diff --git a/.changeset/yellow-knives-behave.md b/.changeset/yellow-knives-behave.md new file mode 100644 index 000000000..59b3f1109 --- /dev/null +++ b/.changeset/yellow-knives-behave.md @@ -0,0 +1,6 @@ +--- +'@powersync/service-core': patch +'@powersync/service-image': patch +--- + +Protocol: Allow `null` as stream parameter. diff --git a/packages/service-core/src/util/protocol-types.ts b/packages/service-core/src/util/protocol-types.ts index 21e5716c2..4a6410b4c 100644 --- a/packages/service-core/src/util/protocol-types.ts +++ b/packages/service-core/src/util/protocol-types.ts @@ -1,5 +1,5 @@ import * as t from 'ts-codec'; -import { BucketDescription, BucketPriority, SqliteJsonRow } from '@powersync/service-sync-rules'; +import { BucketPriority, SqliteJsonRow } from '@powersync/service-sync-rules'; import { JsonContainer } from '@powersync/service-jsonbig'; export const BucketRequest = t.object({ @@ -24,7 +24,7 @@ export const RequestedStreamSubscription = t.object({ /** * An optional dictionary of parameters to pass to this specific stream. */ - parameters: t.record(t.any).optional(), + parameters: t.union(t.record(t.any), t.Null), /** * Set when the client wishes to re-assign a different priority to this stream. * diff --git a/packages/service-core/test/src/util/protocol_types.test.ts b/packages/service-core/test/src/util/protocol_types.test.ts new file mode 100644 index 000000000..a86013e7c --- /dev/null +++ b/packages/service-core/test/src/util/protocol_types.test.ts @@ -0,0 +1,43 @@ +import { StreamingSyncRequest } from '@/index.js'; +import { schema } from '@powersync/lib-services-framework'; +import { describe, test, expect, it } from 'vitest'; + +describe('protocol types', () => { + describe('StreamingSyncRequest', () => { + const validator = schema.createTsCodecValidator(StreamingSyncRequest, { allowAdditional: true }); + + test('with streams', () => { + expect( + validator.validate({ + buckets: [], + include_checksum: true, + raw_data: true, + binary_data: true, + client_id: '0da33a94-c140-4b42-b3b3-a1df3b1352a3', + parameters: {}, + streams: { + include_defaults: true, + subscriptions: [{ stream: 'does_not_exist', parameters: null, override_priority: null }] + } + } as any) + ).toMatchObject({ valid: true }); + }); + + test('does not allow missing parameters', () => { + expect( + validator.validate({ + buckets: [], + include_checksum: true, + raw_data: true, + binary_data: true, + client_id: '0da33a94-c140-4b42-b3b3-a1df3b1352a3', + parameters: {}, + streams: { + include_defaults: true, + subscriptions: [{ stream: 'a', override_priority: null }] + } + } as any) + ).toMatchObject({ valid: false }); + }); + }); +}); diff --git a/packages/sync-rules/src/streams/stream.ts b/packages/sync-rules/src/streams/stream.ts index 612175574..0197b83d2 100644 --- a/packages/sync-rules/src/streams/stream.ts +++ b/packages/sync-rules/src/streams/stream.ts @@ -3,7 +3,6 @@ import { BucketInclusionReason, BucketPriority, DEFAULT_BUCKET_PRIORITY } from ' import { BucketParameterQuerier, PendingQueriers } from '../BucketParameterQuerier.js'; import { BucketSource, BucketSourceType, ResultSetDescription } from '../BucketSource.js'; import { ColumnDefinition } from '../ExpressionType.js'; -import { CompatibilityContext } from '../compatibility.js'; import { SourceTableInterface } from '../SourceTableInterface.js'; import { GetQuerierOptions, RequestedStream } from '../SqlSyncRules.js'; import { TablePattern } from '../TablePattern.js'; @@ -17,7 +16,6 @@ import { SqliteRow, TableRow } from '../types.js'; -import { applyRowContext } from '../utils.js'; import { StreamVariant } from './variant.js'; export class SyncStream implements BucketSource {