Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: let users add custom parameters #1978

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/typescript-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ const stream = new ShapeStream({
table: `foo`,
})

// You can also add custom headers and URL parameters
const streamWithParams = new ShapeStream({
url: `${BASE_URL}/v1/shape`,
table: `foo`,
headers: {
'Authorization': 'Bearer token'
},
params: {
'custom-param': 'value'
}
})

stream.subscribe(messages => {
// messages is an array with one or more row updates
// and the stream will wait for all subscribers to process them
Expand Down
37 changes: 37 additions & 0 deletions packages/typescript-client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ import {
REPLICA_PARAM,
} from './constants'

const RESERVED_PARAMS = new Set([
DATABASE_ID_QUERY_PARAM,
COLUMNS_QUERY_PARAM,
LIVE_CACHE_BUSTER_QUERY_PARAM,
SHAPE_HANDLE_QUERY_PARAM,
LIVE_QUERY_PARAM,
OFFSET_QUERY_PARAM,
TABLE_QUERY_PARAM,
WHERE_QUERY_PARAM,
REPLICA_PARAM,
])

type Replica = `full` | `default`

/**
Expand Down Expand Up @@ -98,6 +110,12 @@ export interface ShapeStreamOptions<T = never> {
*/
headers?: Record<string, string>

/**
* Additional request parameters to attach to the URL.
* These will be merged with Electric's standard parameters.
*/
params?: Record<string, string>

/**
* Automatically fetch updates to the Shape. If you just want to sync the current
* shape and stop, pass false.
Expand Down Expand Up @@ -246,6 +264,25 @@ export class ShapeStream<T extends Row<unknown> = Row>
this.options.subscribe
) {
const fetchUrl = new URL(url)

// Add any custom parameters first
if (this.options.params) {
// Check for reserved parameter names
const reservedParams = Object.keys(this.options.params).filter(
(key) => RESERVED_PARAMS.has(key)
)
if (reservedParams.length > 0) {
throw new Error(
`Cannot use reserved Electric parameter names in custom params: ${reservedParams.join(`, `)}`
)
}

for (const [key, value] of Object.entries(this.options.params)) {
fetchUrl.searchParams.set(key, value)
}
}

// Add Electric's internal parameters
if (table) fetchUrl.searchParams.set(TABLE_QUERY_PARAM, table)
if (where) fetchUrl.searchParams.set(WHERE_QUERY_PARAM, where)
if (columns && columns.length > 0)
Expand Down
57 changes: 52 additions & 5 deletions website/docs/api/clients/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,69 @@ export interface ShapeStreamOptions<T = never> {
headers?: Record<string, string>

/**
* Alternatively you can override the fetch function.
* Additional request parameters to attach to the URL.
* These will be merged with Electric's standard parameters.
* Note: You cannot use Electric's reserved parameter names
* (table, where, columns, offset, etc.).
*/
fetchClient?: typeof fetch
params?: Record<string, string>

/**
* Automatically fetch updates to the Shape. If you just want to sync the current
* shape and stop, pass false.
*/
subscribe?: boolean

backoffOptions?: BackoffOptions
parser?: Parser<T>
/**
* Signal to abort the stream.
*/
signal?: AbortSignal

/**
* Custom fetch client implementation.
*/
fetchClient?: typeof fetch

/**
* Custom parser for handling specific data types.
*/
parser?: Parser<T>

backoffOptions?: BackoffOptions
}
```

Note that certain parameter names are reserved for Electric's internal use and cannot be used in custom params:
- `table`
- `where`
- `columns`
- `offset`
- `handle`
- `live`
- `cursor`
- `database_id`
- `replica`

Attempting to use these reserved names will throw an error.

Example usage with custom headers and parameters:

```ts
const stream = new ShapeStream({
url: 'http://localhost:3000/v1/shape',
table: 'items',
// Add authentication header
headers: {
'Authorization': 'Bearer token'
},
// Add custom URL parameters
params: {
'tenant': 'acme-corp',
'version': '1.0'
}
})
```

#### Messages

A `ShapeStream` consumes and emits a stream of messages. These messages can either be a `ChangeMessage` representing a change to the shape data:
Expand All @@ -148,7 +195,7 @@ export type ChangeMessage<T extends Row<unknown> = Row> = {
headers: Header & { operation: `insert` | `update` | `delete` }
offset: Offset
}
````
```

Or a `ControlMessage`, representing an instruction to the client, as [documented here](../http#control-messages).

Expand Down