From b394d04251e248e1b0535ab583ed7ef40e286c09 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Fri, 15 Nov 2024 17:37:23 -0700 Subject: [PATCH 1/4] fix: do validation for params off constructor so it can throw before starting --- packages/typescript-client/src/client.ts | 29 ++++++++++++++++++- .../test/__snapshots__/client.test.ts.snap | 3 ++ .../typescript-client/test/client.test.ts | 14 +++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 packages/typescript-client/test/__snapshots__/client.test.ts.snap diff --git a/packages/typescript-client/src/client.ts b/packages/typescript-client/src/client.ts index 57c0695596..32aadd0df1 100644 --- a/packages/typescript-client/src/client.ts +++ b/packages/typescript-client/src/client.ts @@ -45,6 +45,19 @@ const RESERVED_PARAMS = new Set([ type Replica = `full` | `default` +type ReservedParamKeys = + | typeof DATABASE_ID_QUERY_PARAM + | typeof COLUMNS_QUERY_PARAM + | typeof LIVE_CACHE_BUSTER_QUERY_PARAM + | typeof SHAPE_HANDLE_QUERY_PARAM + | typeof LIVE_QUERY_PARAM + | typeof OFFSET_QUERY_PARAM + | typeof TABLE_QUERY_PARAM + | typeof WHERE_QUERY_PARAM + | typeof REPLICA_PARAM + +type ParamsRecord = Omit, ReservedParamKeys> + /** * Options for constructing a ShapeStream. */ @@ -113,8 +126,10 @@ export interface ShapeStreamOptions { /** * 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, handle, live, cursor, database_id, replica). */ - params?: Record + params?: ParamsRecord /** * Automatically fetch updates to the Shape. If you just want to sync the current @@ -517,5 +532,17 @@ function validateOptions(options: Partial>): void { `shapeHandle is required if this isn't an initial fetch (i.e. offset > -1)` ) } + + // Check for reserved parameter names + if (options.params) { + const reservedParams = Object.keys(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(`, `)}` + ) + } + } return } diff --git a/packages/typescript-client/test/__snapshots__/client.test.ts.snap b/packages/typescript-client/test/__snapshots__/client.test.ts.snap new file mode 100644 index 0000000000..f8675636b5 --- /dev/null +++ b/packages/typescript-client/test/__snapshots__/client.test.ts.snap @@ -0,0 +1,3 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Shape > should throw on a reserved parameter 1`] = `[Error: Cannot use reserved Electric parameter names in custom params: database_id]`; diff --git a/packages/typescript-client/test/client.test.ts b/packages/typescript-client/test/client.test.ts index 168447a160..a608819f00 100644 --- a/packages/typescript-client/test/client.test.ts +++ b/packages/typescript-client/test/client.test.ts @@ -23,6 +23,20 @@ describe(`Shape`, () => { expect(shape.lastSynced()).toBeLessThanOrEqual(Date.now() - start) }) + it.only(`should throw on a reserved parameter`, async () => { + console.log(`hi`) + expect(() => { + const shapeStream = new ShapeStream({ + url: `${BASE_URL}/v1/shape`, + table: `foo`, + params: { + database_id: `foo`, + }, + }) + new Shape(shapeStream) + }).toThrowErrorMatchingSnapshot() + }) + it(`should notify with the initial value`, async ({ issuesTableUrl, insertIssues, From 22c1dcfa5b5cf2fc9e753631ec0f67b99ddde770 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 18 Nov 2024 14:04:51 -0700 Subject: [PATCH 2/4] Remove only --- packages/typescript-client/test/client.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/typescript-client/test/client.test.ts b/packages/typescript-client/test/client.test.ts index a608819f00..5c994af0d8 100644 --- a/packages/typescript-client/test/client.test.ts +++ b/packages/typescript-client/test/client.test.ts @@ -23,8 +23,7 @@ describe(`Shape`, () => { expect(shape.lastSynced()).toBeLessThanOrEqual(Date.now() - start) }) - it.only(`should throw on a reserved parameter`, async () => { - console.log(`hi`) + it(`should throw on a reserved parameter`, async () => { expect(() => { const shapeStream = new ShapeStream({ url: `${BASE_URL}/v1/shape`, From 77a68ba960fa65e3e54a1a17a86921b93518290e Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 18 Nov 2024 14:09:10 -0700 Subject: [PATCH 3/4] style --- packages/typescript-client/src/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/typescript-client/src/client.ts b/packages/typescript-client/src/client.ts index 32aadd0df1..c37976e419 100644 --- a/packages/typescript-client/src/client.ts +++ b/packages/typescript-client/src/client.ts @@ -535,8 +535,8 @@ function validateOptions(options: Partial>): void { // Check for reserved parameter names if (options.params) { - const reservedParams = Object.keys(options.params).filter( - (key) => RESERVED_PARAMS.has(key) + const reservedParams = Object.keys(options.params).filter((key) => + RESERVED_PARAMS.has(key) ) if (reservedParams.length > 0) { throw new Error( From 4b36367279f56395f7f526620db17ab52d1230b4 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 18 Nov 2024 14:14:38 -0700 Subject: [PATCH 4/4] add config.d.ts --- examples/nextjs-example/.sst/platform/config.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/nextjs-example/.sst/platform/config.d.ts b/examples/nextjs-example/.sst/platform/config.d.ts index 08a1c1a1c1..012a6e7551 100644 --- a/examples/nextjs-example/.sst/platform/config.d.ts +++ b/examples/nextjs-example/.sst/platform/config.d.ts @@ -2,22 +2,22 @@ import "./src/global.d.ts" import "../types.generated" import { AppInput, App, Config } from "./src/config" import * as _neon from "@sst-provider/neon"; -import * as _cloudflare from "@pulumi/cloudflare"; import * as _aws from "@pulumi/aws"; +import * as _cloudflare from "@pulumi/cloudflare"; declare global { // @ts-expect-error export import neon = _neon // @ts-expect-error - export import cloudflare = _cloudflare - // @ts-expect-error export import aws = _aws + // @ts-expect-error + export import cloudflare = _cloudflare interface Providers { providers?: { "neon"?: (_neon.ProviderArgs & { version?: string }) | boolean | string; - "cloudflare"?: (_cloudflare.ProviderArgs & { version?: string }) | boolean | string; "aws"?: (_aws.ProviderArgs & { version?: string }) | boolean | string; + "cloudflare"?: (_cloudflare.ProviderArgs & { version?: string }) | boolean | string; } } export const $config: (