@syncular/testkit 0.0.6-96 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/audit.d.ts +22 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/audit.js +40 -0
  4. package/dist/audit.js.map +1 -0
  5. package/dist/client-bridge.d.ts +77 -0
  6. package/dist/client-bridge.d.ts.map +1 -0
  7. package/dist/client-bridge.js +540 -0
  8. package/dist/client-bridge.js.map +1 -0
  9. package/dist/deterministic.js.map +1 -1
  10. package/dist/disposable.js.map +1 -1
  11. package/dist/faults.d.ts +14 -2
  12. package/dist/faults.d.ts.map +1 -1
  13. package/dist/faults.js +104 -42
  14. package/dist/faults.js.map +1 -1
  15. package/dist/hono-node-server.js +1 -1
  16. package/dist/hono-node-server.js.map +1 -1
  17. package/dist/http-fixtures.d.ts +1 -30
  18. package/dist/http-fixtures.d.ts.map +1 -1
  19. package/dist/http-fixtures.js +5 -65
  20. package/dist/http-fixtures.js.map +1 -1
  21. package/dist/index.d.ts +2 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/project-scoped-tasks.d.ts.map +1 -1
  26. package/dist/project-scoped-tasks.js +6 -4
  27. package/dist/project-scoped-tasks.js.map +1 -1
  28. package/dist/realtime-ws.js.map +1 -1
  29. package/dist/runtime-process.js.map +1 -1
  30. package/dist/sync-builders.d.ts +5 -3
  31. package/dist/sync-builders.d.ts.map +1 -1
  32. package/dist/sync-builders.js +9 -3
  33. package/dist/sync-builders.js.map +1 -1
  34. package/dist/sync-http.js.map +1 -1
  35. package/dist/sync-parse.js.map +1 -1
  36. package/dist/sync-response.d.ts +3 -4
  37. package/dist/sync-response.d.ts.map +1 -1
  38. package/dist/sync-response.js.map +1 -1
  39. package/package.json +14 -15
  40. package/src/audit.ts +74 -0
  41. package/src/client-bridge.ts +841 -0
  42. package/src/faults.ts +178 -55
  43. package/src/hono-node-server.ts +1 -1
  44. package/src/http-fixtures.ts +6 -127
  45. package/src/index.ts +2 -4
  46. package/src/project-scoped-tasks.ts +6 -4
  47. package/src/sync-builders.ts +14 -6
  48. package/src/sync-response.ts +3 -5
  49. package/dist/assertions.d.ts +0 -61
  50. package/dist/assertions.d.ts.map +0 -1
  51. package/dist/assertions.js +0 -239
  52. package/dist/assertions.js.map +0 -1
  53. package/dist/fixtures.d.ts +0 -104
  54. package/dist/fixtures.d.ts.map +0 -1
  55. package/dist/fixtures.js +0 -558
  56. package/dist/fixtures.js.map +0 -1
  57. package/dist/resources.d.ts +0 -25
  58. package/dist/resources.d.ts.map +0 -1
  59. package/dist/resources.js +0 -64
  60. package/dist/resources.js.map +0 -1
  61. package/dist/scenario-flow.d.ts +0 -39
  62. package/dist/scenario-flow.d.ts.map +0 -1
  63. package/dist/scenario-flow.js +0 -41
  64. package/dist/scenario-flow.js.map +0 -1
  65. package/src/assertions.ts +0 -432
  66. package/src/fixtures.ts +0 -867
  67. package/src/resources.ts +0 -186
  68. package/src/scenario-flow.ts +0 -143
@@ -0,0 +1,22 @@
1
+ export interface RedactedAuditChange {
2
+ redaction?: {
3
+ payload?: unknown;
4
+ reason?: unknown;
5
+ };
6
+ rowJson?: unknown;
7
+ scopes?: unknown;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface RedactedAuditDebugExport {
11
+ commits?: Array<{
12
+ changes?: RedactedAuditChange[];
13
+ [key: string]: unknown;
14
+ }>;
15
+ [key: string]: unknown;
16
+ }
17
+ export declare function assertAuditChangeRedacted(change: RedactedAuditChange, message?: string): void;
18
+ export declare function assertAuditJsonExcludes(value: unknown, forbiddenNeedles: readonly string[], message?: string): void;
19
+ export declare function assertAuditDebugExportRedacted(value: RedactedAuditDebugExport, forbiddenNeedles?: readonly string[], message?: string): void;
20
+ export declare function readJsonResponse<T>(response: Response): Promise<T>;
21
+ export declare function readTextResponse(response: Response): Promise<string>;
22
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;QAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC,CAAC;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,SAAyC,GAC/C,IAAI,CAeN;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,OAAO,SAAwC,GAC9C,IAAI,CAQN;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,wBAAwB,EAC/B,gBAAgB,GAAE,SAAS,MAAM,EAAO,EACxC,OAAO,SAA+C,GACrD,IAAI,CAON;AAED,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAExE;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E"}
package/dist/audit.js ADDED
@@ -0,0 +1,40 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ export function assertAuditChangeRedacted(change, message = 'Expected audit change to be redacted') {
3
+ if ('rowJson' in change) {
4
+ throw new Error(`${message}: rowJson must be omitted`);
5
+ }
6
+ if ('scopes' in change) {
7
+ throw new Error(`${message}: raw scopes must be omitted`);
8
+ }
9
+ if (!isDeepStrictEqual(change.redaction, {
10
+ payload: 'omitted',
11
+ reason: 'audit_redacted_by_default',
12
+ })) {
13
+ throw new Error(`${message}: missing canonical redaction marker`);
14
+ }
15
+ }
16
+ export function assertAuditJsonExcludes(value, forbiddenNeedles, message = 'Audit JSON leaked forbidden content') {
17
+ const serialized = JSON.stringify(value);
18
+ for (const needle of forbiddenNeedles) {
19
+ if (!needle)
20
+ continue;
21
+ if (serialized.includes(needle)) {
22
+ throw new Error(`${message}: ${needle}`);
23
+ }
24
+ }
25
+ }
26
+ export function assertAuditDebugExportRedacted(value, forbiddenNeedles = [], message = 'Expected audit debug export to be redacted') {
27
+ for (const commit of value.commits ?? []) {
28
+ for (const change of commit.changes ?? []) {
29
+ assertAuditChangeRedacted(change, message);
30
+ }
31
+ }
32
+ assertAuditJsonExcludes(value, forbiddenNeedles, message);
33
+ }
34
+ export async function readJsonResponse(response) {
35
+ return (await response.json());
36
+ }
37
+ export async function readTextResponse(response) {
38
+ return await response.text();
39
+ }
40
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAoB9C,MAAM,UAAU,yBAAyB,CACvC,MAA2B,EAC3B,OAAO,GAAG,sCAAsC;IAEhD,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,2BAA2B,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,8BAA8B,CAAC,CAAC;IAC5D,CAAC;IACD,IACE,CAAC,iBAAiB,CAAC,MAAM,CAAC,SAAS,EAAE;QACnC,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,2BAA2B;KACpC,CAAC,EACF,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,sCAAsC,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAc,EACd,gBAAmC,EACnC,OAAO,GAAG,qCAAqC;IAE/C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACtC,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,MAAM,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,KAA+B,EAC/B,gBAAgB,GAAsB,EAAE,EACxC,OAAO,GAAG,4CAA4C;IAEtD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACzC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YAC1C,yBAAyB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,uBAAuB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAI,QAAkB;IAC1D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAkB;IACvD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { SyncularAuthLeaseRecord, SyncularBridge, SyncularBridgeMutationBatch, SyncularBridgeQueryRequest, SyncularBridgeQueryResult, SyncularBridgeStatus, SyncularClientEventMap, SyncularClientEventSink, SyncularClientEventType, SyncularConflictResolution, SyncularConflictSummary, SyncularDiagnosticSnapshot, SyncularPresenceEntry, SyncularSubscriptionSpec, SyncularSyncResult } from '@syncular/client';
2
+ import type { SyncAuthLeaseIssueRequest, SyncOperation } from '@syncular/core';
3
+ import type { AsyncDisposableResource } from './disposable';
4
+ export type ClientBridgeSeed = Record<string, readonly Record<string, unknown>[]>;
5
+ export type ClientBridgeTauriInvoke = <TResult>(command: string, args?: Record<string, unknown>) => Promise<TResult>;
6
+ export type ClientBridgeTauriListen = <TPayload>(event: string, handler: (event: {
7
+ payload: TPayload;
8
+ }) => void) => Promise<() => void>;
9
+ export type ClientBridgeNativeEventSubscription = (() => void) | {
10
+ remove(): void;
11
+ };
12
+ export interface ClientBridgeNativeModule {
13
+ executeSql<Row extends Record<string, unknown> = Record<string, unknown>>(request: SyncularBridgeQueryRequest): Promise<SyncularBridgeQueryResult<Row>> | SyncularBridgeQueryResult<Row>;
14
+ applyMutationsCommit(batch: SyncularBridgeMutationBatch): Promise<string> | string;
15
+ applyLeasedMutationsCommit?(batch: SyncularBridgeMutationBatch): Promise<string> | string;
16
+ sync?(): Promise<SyncularSyncResult>;
17
+ resumeFromBackground?(): Promise<SyncularSyncResult>;
18
+ start?(): Promise<void>;
19
+ stop?(): Promise<void>;
20
+ setSubscriptions?(subscriptions: readonly SyncularSubscriptionSpec[]): Promise<void>;
21
+ getStatus?(): SyncularBridgeStatus;
22
+ issueAuthLease?(request: SyncAuthLeaseIssueRequest): Promise<SyncularAuthLeaseRecord>;
23
+ upsertAuthLease?(lease: SyncularAuthLeaseRecord): Promise<void>;
24
+ authLease?(leaseId: string): Promise<SyncularAuthLeaseRecord | null>;
25
+ activeAuthLeases?(actorId?: string | null, nowMs?: number): Promise<SyncularAuthLeaseRecord[]>;
26
+ diagnosticSnapshot?(): Promise<SyncularDiagnosticSnapshot>;
27
+ addListener?<T extends SyncularClientEventType>(event: T, listener: SyncularClientEventSink<T>): ClientBridgeNativeEventSubscription;
28
+ getPresence?<TMetadata = Record<string, unknown>>(scopeKey: string): SyncularPresenceEntry<TMetadata>[];
29
+ joinPresence?(scopeKey: string, metadata?: Record<string, unknown>): void;
30
+ leavePresence?(scopeKey: string): void;
31
+ updatePresenceMetadata?(scopeKey: string, metadata: Record<string, unknown>): void;
32
+ conflictSummaries?(): Promise<SyncularConflictSummary[]>;
33
+ retryConflictKeepLocal?(id: string): Promise<string>;
34
+ resolveConflict?(id: string, resolution: SyncularConflictResolution): Promise<void>;
35
+ }
36
+ export interface CreateClientBridgeHarnessOptions {
37
+ seed?: ClientBridgeSeed;
38
+ idColumn?: string;
39
+ actorId?: string;
40
+ clientId?: string;
41
+ }
42
+ export interface ClientBridgeInvocation {
43
+ command: string;
44
+ args: Record<string, unknown> | undefined;
45
+ }
46
+ export interface ClientBridgeSqlQuery extends SyncularBridgeQueryRequest {
47
+ }
48
+ export interface ClientBridgeHarness {
49
+ bridge: SyncularBridge;
50
+ tauri: {
51
+ invoke: ClientBridgeTauriInvoke;
52
+ listen: ClientBridgeTauriListen;
53
+ invocations(): ClientBridgeInvocation[];
54
+ };
55
+ reactNative: {
56
+ module: ClientBridgeNativeModule;
57
+ };
58
+ queries(): ClientBridgeSqlQuery[];
59
+ batches(): SyncularBridgeMutationBatch[];
60
+ leasedBatches(): SyncularBridgeMutationBatch[];
61
+ operations(): SyncOperation[];
62
+ syncCount(): number;
63
+ listenerCount(event: SyncularClientEventType): number;
64
+ rows(table: string): Record<string, unknown>[];
65
+ setRows(table: string, rows: readonly Record<string, unknown>[]): void;
66
+ setStatus(status: SyncularBridgeStatus): void;
67
+ setConflicts(conflicts: readonly SyncularConflictSummary[]): void;
68
+ authLease(leaseId: string): SyncularAuthLeaseRecord | null;
69
+ authLeases(): SyncularAuthLeaseRecord[];
70
+ diagnosticSnapshot(): SyncularDiagnosticSnapshot;
71
+ emit<T extends SyncularClientEventType>(event: T, payload: SyncularClientEventMap[T]): void;
72
+ emitRowsChanged(event: SyncularClientEventMap['rowsChanged']): void;
73
+ presence<TMetadata = Record<string, unknown>>(scopeKey: string): SyncularPresenceEntry<TMetadata>[];
74
+ close(): void;
75
+ }
76
+ export declare function createClientBridgeHarness(options?: CreateClientBridgeHarnessOptions): Promise<AsyncDisposableResource<ClientBridgeHarness>>;
77
+ //# sourceMappingURL=client-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-bridge.d.ts","sourceRoot":"","sources":["../src/client-bridge.ts"],"names":[],"mappings":"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"}