@syncular/testkit 0.0.6-96 → 0.1.0

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 (71) 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 +2 -2
  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 +6 -66
  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 +14 -16
  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 +1 -1
  29. package/dist/realtime-ws.js.map +1 -1
  30. package/dist/runtime-process.js +1 -1
  31. package/dist/runtime-process.js.map +1 -1
  32. package/dist/sync-builders.d.ts +5 -3
  33. package/dist/sync-builders.d.ts.map +1 -1
  34. package/dist/sync-builders.js +9 -3
  35. package/dist/sync-builders.js.map +1 -1
  36. package/dist/sync-http.js +1 -1
  37. package/dist/sync-http.js.map +1 -1
  38. package/dist/sync-parse.js.map +1 -1
  39. package/dist/sync-response.d.ts +3 -4
  40. package/dist/sync-response.d.ts.map +1 -1
  41. package/dist/sync-response.js.map +1 -1
  42. package/package.json +15 -16
  43. package/src/audit.ts +74 -0
  44. package/src/client-bridge.ts +841 -0
  45. package/src/faults.ts +178 -55
  46. package/src/hono-node-server.ts +1 -1
  47. package/src/http-fixtures.ts +6 -127
  48. package/src/index.ts +2 -4
  49. package/src/project-scoped-tasks.ts +6 -4
  50. package/src/sync-builders.ts +14 -6
  51. package/src/sync-response.ts +3 -5
  52. package/dist/assertions.d.ts +0 -61
  53. package/dist/assertions.d.ts.map +0 -1
  54. package/dist/assertions.js +0 -239
  55. package/dist/assertions.js.map +0 -1
  56. package/dist/fixtures.d.ts +0 -104
  57. package/dist/fixtures.d.ts.map +0 -1
  58. package/dist/fixtures.js +0 -558
  59. package/dist/fixtures.js.map +0 -1
  60. package/dist/resources.d.ts +0 -25
  61. package/dist/resources.d.ts.map +0 -1
  62. package/dist/resources.js +0 -64
  63. package/dist/resources.js.map +0 -1
  64. package/dist/scenario-flow.d.ts +0 -39
  65. package/dist/scenario-flow.d.ts.map +0 -1
  66. package/dist/scenario-flow.js +0 -41
  67. package/dist/scenario-flow.js.map +0 -1
  68. package/src/assertions.ts +0 -432
  69. package/src/fixtures.ts +0 -867
  70. package/src/resources.ts +0 -186
  71. 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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"}