@syncular/testkit 0.1.3 → 0.2.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.
- package/README.md +210 -0
- package/dist/client.d.ts +68 -0
- package/dist/client.js +145 -0
- package/dist/clock.d.ts +24 -0
- package/dist/clock.js +32 -0
- package/dist/create-test-sync.d.ts +67 -0
- package/dist/create-test-sync.js +90 -0
- package/dist/faults.d.ts +52 -50
- package/dist/faults.js +74 -192
- package/dist/index.d.ts +17 -11
- package/dist/index.js +18 -11
- package/dist/react.d.ts +10 -0
- package/dist/react.js +41 -0
- package/dist/server.d.ts +44 -4
- package/dist/server.js +68 -4
- package/package.json +41 -57
- package/src/client.ts +218 -0
- package/src/clock.ts +45 -0
- package/src/create-test-sync.ts +158 -0
- package/src/faults.ts +77 -338
- package/src/index.ts +44 -10
- package/src/react.ts +46 -0
- package/src/server.ts +102 -3
- package/dist/audit.d.ts +0 -22
- package/dist/audit.d.ts.map +0 -1
- package/dist/audit.js +0 -40
- package/dist/audit.js.map +0 -1
- package/dist/client-bridge.d.ts +0 -77
- package/dist/client-bridge.d.ts.map +0 -1
- package/dist/client-bridge.js +0 -540
- package/dist/client-bridge.js.map +0 -1
- package/dist/deterministic.d.ts +0 -31
- package/dist/deterministic.d.ts.map +0 -1
- package/dist/deterministic.js +0 -69
- package/dist/deterministic.js.map +0 -1
- package/dist/disposable.d.ts +0 -10
- package/dist/disposable.d.ts.map +0 -1
- package/dist/disposable.js +0 -28
- package/dist/disposable.js.map +0 -1
- package/dist/faults.d.ts.map +0 -1
- package/dist/faults.js.map +0 -1
- package/dist/hono-node-server.d.ts +0 -20
- package/dist/hono-node-server.d.ts.map +0 -1
- package/dist/hono-node-server.js +0 -90
- package/dist/hono-node-server.js.map +0 -1
- package/dist/http-fixtures.d.ts +0 -32
- package/dist/http-fixtures.d.ts.map +0 -1
- package/dist/http-fixtures.js +0 -117
- package/dist/http-fixtures.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/project-scoped-tasks.d.ts +0 -40
- package/dist/project-scoped-tasks.d.ts.map +0 -1
- package/dist/project-scoped-tasks.js +0 -247
- package/dist/project-scoped-tasks.js.map +0 -1
- package/dist/realtime-ws.d.ts +0 -48
- package/dist/realtime-ws.d.ts.map +0 -1
- package/dist/realtime-ws.js +0 -203
- package/dist/realtime-ws.js.map +0 -1
- package/dist/runtime-process.d.ts +0 -14
- package/dist/runtime-process.d.ts.map +0 -1
- package/dist/runtime-process.js +0 -99
- package/dist/runtime-process.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/sync-builders.d.ts +0 -48
- package/dist/sync-builders.d.ts.map +0 -1
- package/dist/sync-builders.js +0 -66
- package/dist/sync-builders.js.map +0 -1
- package/dist/sync-http.d.ts +0 -48
- package/dist/sync-http.d.ts.map +0 -1
- package/dist/sync-http.js +0 -43
- package/dist/sync-http.js.map +0 -1
- package/dist/sync-parse.d.ts +0 -8
- package/dist/sync-parse.d.ts.map +0 -1
- package/dist/sync-parse.js +0 -38
- package/dist/sync-parse.js.map +0 -1
- package/dist/sync-response.d.ts +0 -6
- package/dist/sync-response.d.ts.map +0 -1
- package/dist/sync-response.js +0 -19
- package/dist/sync-response.js.map +0 -1
- package/src/audit.ts +0 -74
- package/src/client-bridge.ts +0 -841
- package/src/deterministic.ts +0 -121
- package/src/disposable.ts +0 -50
- package/src/hono-node-server.ts +0 -144
- package/src/http-fixtures.ts +0 -187
- package/src/project-scoped-tasks.ts +0 -351
- package/src/realtime-ws.ts +0 -354
- package/src/runtime-process.ts +0 -159
- package/src/sync-builders.ts +0 -136
- package/src/sync-http.ts +0 -117
- package/src/sync-parse.ts +0 -86
- package/src/sync-response.ts +0 -43
package/src/runtime-process.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import type { ChildProcess } from 'node:child_process';
|
|
2
|
-
import {
|
|
3
|
-
type AsyncDisposableResource,
|
|
4
|
-
createAsyncDisposableResource,
|
|
5
|
-
type ResourceRunner,
|
|
6
|
-
withAsyncDisposableFactory,
|
|
7
|
-
} from './disposable';
|
|
8
|
-
|
|
9
|
-
export interface WaitForJsonPortOptions {
|
|
10
|
-
timeoutMs?: number;
|
|
11
|
-
processName?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function waitForJsonPortFromStdout(
|
|
15
|
-
process: ChildProcess,
|
|
16
|
-
options: WaitForJsonPortOptions = {}
|
|
17
|
-
): Promise<number> {
|
|
18
|
-
const timeoutMs = options.timeoutMs ?? 30_000;
|
|
19
|
-
const processName = options.processName ?? 'Child process';
|
|
20
|
-
|
|
21
|
-
return new Promise<number>((resolve, reject) => {
|
|
22
|
-
const stdout = process.stdout;
|
|
23
|
-
const stderr = process.stderr;
|
|
24
|
-
|
|
25
|
-
if (!stdout || !stderr) {
|
|
26
|
-
reject(new Error(`${processName} has no stdout/stderr pipes`));
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let stdoutBuffer = '';
|
|
31
|
-
let stderrBuffer = '';
|
|
32
|
-
|
|
33
|
-
const cleanup = () => {
|
|
34
|
-
clearTimeout(timeout);
|
|
35
|
-
stdout.off('data', onStdoutData);
|
|
36
|
-
stderr.off('data', onStderrData);
|
|
37
|
-
process.off('exit', onExit);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const resolvePort = (port: number) => {
|
|
41
|
-
cleanup();
|
|
42
|
-
resolve(port);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const rejectWith = (error: Error) => {
|
|
46
|
-
cleanup();
|
|
47
|
-
reject(error);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const onStdoutData = (chunk: Buffer | string) => {
|
|
51
|
-
stdoutBuffer += chunk.toString();
|
|
52
|
-
|
|
53
|
-
const lines = stdoutBuffer.split('\n');
|
|
54
|
-
stdoutBuffer = lines.pop() ?? '';
|
|
55
|
-
|
|
56
|
-
for (const line of lines) {
|
|
57
|
-
const trimmed = line.trim();
|
|
58
|
-
if (!trimmed) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const parsed = JSON.parse(trimmed) as { port?: number };
|
|
64
|
-
if (parsed.port && parsed.port > 0) {
|
|
65
|
-
resolvePort(parsed.port);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
} catch {
|
|
69
|
-
// keep reading until a valid JSON line is emitted
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const onStderrData = (chunk: Buffer | string) => {
|
|
75
|
-
stderrBuffer += chunk.toString();
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const onExit = (code: number | null, signal: NodeJS.Signals | null) => {
|
|
79
|
-
rejectWith(
|
|
80
|
-
new Error(
|
|
81
|
-
`${processName} exited before reporting port (code=${String(code)} signal=${String(signal)})\nstderr: ${stderrBuffer}`
|
|
82
|
-
)
|
|
83
|
-
);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const timeout = setTimeout(() => {
|
|
87
|
-
rejectWith(
|
|
88
|
-
new Error(
|
|
89
|
-
`${processName} startup timed out after ${timeoutMs}ms\nstderr: ${stderrBuffer}`
|
|
90
|
-
)
|
|
91
|
-
);
|
|
92
|
-
}, timeoutMs);
|
|
93
|
-
|
|
94
|
-
stdout.on('data', onStdoutData);
|
|
95
|
-
stderr.on('data', onStderrData);
|
|
96
|
-
process.on('exit', onExit);
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface StopChildProcessOptions {
|
|
101
|
-
gracePeriodMs?: number;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function stopChildProcess(
|
|
105
|
-
process: ChildProcess,
|
|
106
|
-
options: StopChildProcessOptions = {}
|
|
107
|
-
): Promise<void> {
|
|
108
|
-
if (process.exitCode != null) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const gracePeriodMs = options.gracePeriodMs ?? 5000;
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
process.kill('SIGTERM');
|
|
116
|
-
} catch {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
await new Promise<void>((resolve) => {
|
|
121
|
-
const onExit = () => {
|
|
122
|
-
clearTimeout(timeout);
|
|
123
|
-
process.off('exit', onExit);
|
|
124
|
-
resolve();
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const timeout = setTimeout(() => {
|
|
128
|
-
try {
|
|
129
|
-
process.kill('SIGKILL');
|
|
130
|
-
} catch {
|
|
131
|
-
// ignore
|
|
132
|
-
}
|
|
133
|
-
process.off('exit', onExit);
|
|
134
|
-
resolve();
|
|
135
|
-
}, gracePeriodMs);
|
|
136
|
-
|
|
137
|
-
process.on('exit', onExit);
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function createChildProcessResource(
|
|
142
|
-
process: ChildProcess,
|
|
143
|
-
options: StopChildProcessOptions = {}
|
|
144
|
-
): AsyncDisposableResource<ChildProcess> {
|
|
145
|
-
return createAsyncDisposableResource(process, () =>
|
|
146
|
-
stopChildProcess(process, options)
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export async function withChildProcess<TResult>(
|
|
151
|
-
process: ChildProcess,
|
|
152
|
-
run: ResourceRunner<ChildProcess, TResult>,
|
|
153
|
-
options: StopChildProcessOptions = {}
|
|
154
|
-
): Promise<TResult> {
|
|
155
|
-
return withAsyncDisposableFactory(
|
|
156
|
-
async () => createChildProcessResource(process, options),
|
|
157
|
-
run
|
|
158
|
-
);
|
|
159
|
-
}
|
package/src/sync-builders.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
SyncCombinedRequest,
|
|
3
|
-
SyncOperation,
|
|
4
|
-
SyncPullRequest,
|
|
5
|
-
SyncPushBatchRequest,
|
|
6
|
-
SyncSubscriptionRequest,
|
|
7
|
-
} from '@syncular/core';
|
|
8
|
-
|
|
9
|
-
export interface CreateSyncUpsertOperationOptions {
|
|
10
|
-
table: string;
|
|
11
|
-
rowId: string;
|
|
12
|
-
payload: Record<string, unknown>;
|
|
13
|
-
baseVersion?: number | null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function createSyncUpsertOperation(
|
|
17
|
-
options: CreateSyncUpsertOperationOptions
|
|
18
|
-
): SyncOperation {
|
|
19
|
-
return {
|
|
20
|
-
table: options.table,
|
|
21
|
-
row_id: options.rowId,
|
|
22
|
-
op: 'upsert',
|
|
23
|
-
payload: options.payload,
|
|
24
|
-
base_version: options.baseVersion ?? null,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface CreateSyncDeleteOperationOptions {
|
|
29
|
-
table: string;
|
|
30
|
-
rowId: string;
|
|
31
|
-
baseVersion?: number | null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function createSyncDeleteOperation(
|
|
35
|
-
options: CreateSyncDeleteOperationOptions
|
|
36
|
-
): SyncOperation {
|
|
37
|
-
return {
|
|
38
|
-
table: options.table,
|
|
39
|
-
row_id: options.rowId,
|
|
40
|
-
op: 'delete',
|
|
41
|
-
payload: null,
|
|
42
|
-
base_version: options.baseVersion ?? null,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface CreateSyncSubscriptionOptions {
|
|
47
|
-
id: string;
|
|
48
|
-
table: string;
|
|
49
|
-
scopes: SyncSubscriptionRequest['scopes'];
|
|
50
|
-
params?: SyncSubscriptionRequest['params'];
|
|
51
|
-
cursor?: number;
|
|
52
|
-
bootstrapState?: SyncSubscriptionRequest['bootstrapState'];
|
|
53
|
-
crdtStateVectors?: SyncSubscriptionRequest['crdtStateVectors'];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function createSyncSubscription(
|
|
57
|
-
options: CreateSyncSubscriptionOptions
|
|
58
|
-
): SyncSubscriptionRequest {
|
|
59
|
-
return {
|
|
60
|
-
id: options.id,
|
|
61
|
-
table: options.table,
|
|
62
|
-
scopes: options.scopes,
|
|
63
|
-
...(options.params ? { params: options.params } : {}),
|
|
64
|
-
cursor: options.cursor ?? 0,
|
|
65
|
-
bootstrapState: options.bootstrapState ?? null,
|
|
66
|
-
crdtStateVectors: options.crdtStateVectors ?? [],
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface CreateSyncPushRequestOptions {
|
|
71
|
-
clientId: string;
|
|
72
|
-
clientCommitId: string;
|
|
73
|
-
operations: SyncOperation[];
|
|
74
|
-
schemaVersion?: number;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function createSyncPushRequest(
|
|
78
|
-
options: CreateSyncPushRequestOptions
|
|
79
|
-
): SyncPushBatchRequest {
|
|
80
|
-
return {
|
|
81
|
-
clientId: options.clientId,
|
|
82
|
-
commits: [
|
|
83
|
-
{
|
|
84
|
-
clientCommitId: options.clientCommitId,
|
|
85
|
-
operations: options.operations,
|
|
86
|
-
schemaVersion: options.schemaVersion ?? 1,
|
|
87
|
-
},
|
|
88
|
-
],
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface CreateSyncPullRequestOptions {
|
|
93
|
-
clientId: string;
|
|
94
|
-
schemaVersion?: number;
|
|
95
|
-
subscriptions: SyncSubscriptionRequest[];
|
|
96
|
-
limitCommits?: number;
|
|
97
|
-
limitSnapshotRows?: number;
|
|
98
|
-
maxSnapshotPages?: number;
|
|
99
|
-
dedupeRows?: boolean;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function createSyncPullRequest(
|
|
103
|
-
options: CreateSyncPullRequestOptions
|
|
104
|
-
): SyncPullRequest {
|
|
105
|
-
return {
|
|
106
|
-
clientId: options.clientId,
|
|
107
|
-
schemaVersion: options.schemaVersion ?? 1,
|
|
108
|
-
subscriptions: options.subscriptions,
|
|
109
|
-
limitCommits: options.limitCommits ?? 50,
|
|
110
|
-
...(options.limitSnapshotRows !== undefined
|
|
111
|
-
? { limitSnapshotRows: options.limitSnapshotRows }
|
|
112
|
-
: {}),
|
|
113
|
-
...(options.maxSnapshotPages !== undefined
|
|
114
|
-
? { maxSnapshotPages: options.maxSnapshotPages }
|
|
115
|
-
: {}),
|
|
116
|
-
...(options.dedupeRows !== undefined
|
|
117
|
-
? { dedupeRows: options.dedupeRows }
|
|
118
|
-
: {}),
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface CreateSyncCombinedRequestOptions {
|
|
123
|
-
clientId: string;
|
|
124
|
-
push?: Omit<SyncPushBatchRequest, 'clientId'>;
|
|
125
|
-
pull?: Omit<SyncPullRequest, 'clientId'>;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function createSyncCombinedRequest(
|
|
129
|
-
options: CreateSyncCombinedRequestOptions
|
|
130
|
-
): SyncCombinedRequest {
|
|
131
|
-
return {
|
|
132
|
-
clientId: options.clientId,
|
|
133
|
-
...(options.push ? { push: options.push } : {}),
|
|
134
|
-
...(options.pull ? { pull: options.pull } : {}),
|
|
135
|
-
};
|
|
136
|
-
}
|
package/src/sync-http.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
SyncCombinedRequest,
|
|
3
|
-
SyncCombinedResponse,
|
|
4
|
-
SyncPullRequest,
|
|
5
|
-
SyncPullResponse,
|
|
6
|
-
SyncPushRequest,
|
|
7
|
-
SyncPushResponse,
|
|
8
|
-
} from '@syncular/core';
|
|
9
|
-
import {
|
|
10
|
-
parseSyncCombinedResponse,
|
|
11
|
-
parseSyncPullResponse,
|
|
12
|
-
parseSyncPushResponse,
|
|
13
|
-
} from './sync-parse';
|
|
14
|
-
|
|
15
|
-
export interface JsonActorHeadersOptions {
|
|
16
|
-
actorId: string;
|
|
17
|
-
actorHeader?: string;
|
|
18
|
-
extraHeaders?: Record<string, string>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createJsonActorHeaders(
|
|
22
|
-
options: JsonActorHeadersOptions
|
|
23
|
-
): Record<string, string> {
|
|
24
|
-
return {
|
|
25
|
-
'content-type': 'application/json',
|
|
26
|
-
[options.actorHeader ?? 'x-actor-id']: options.actorId,
|
|
27
|
-
...options.extraHeaders,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface PostJsonWithActorOptions<TBody> {
|
|
32
|
-
fetch: typeof globalThis.fetch;
|
|
33
|
-
url: string;
|
|
34
|
-
actorId: string;
|
|
35
|
-
actorHeader?: string;
|
|
36
|
-
extraHeaders?: Record<string, string>;
|
|
37
|
-
body: TBody;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface PostJsonWithActorResult<TResponse> {
|
|
41
|
-
response: Response;
|
|
42
|
-
json: TResponse;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function postJsonWithActor<TBody, TResponse>(
|
|
46
|
-
options: PostJsonWithActorOptions<TBody>
|
|
47
|
-
): Promise<PostJsonWithActorResult<TResponse>> {
|
|
48
|
-
const response = await options.fetch(options.url, {
|
|
49
|
-
method: 'POST',
|
|
50
|
-
headers: createJsonActorHeaders({
|
|
51
|
-
actorId: options.actorId,
|
|
52
|
-
actorHeader: options.actorHeader,
|
|
53
|
-
extraHeaders: options.extraHeaders,
|
|
54
|
-
}),
|
|
55
|
-
body: JSON.stringify(options.body),
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const json = (await response.json()) as TResponse;
|
|
59
|
-
return { response, json };
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface PostSyncCombinedRequestOptions {
|
|
63
|
-
fetch: typeof globalThis.fetch;
|
|
64
|
-
url: string;
|
|
65
|
-
actorId: string;
|
|
66
|
-
actorHeader?: string;
|
|
67
|
-
extraHeaders?: Record<string, string>;
|
|
68
|
-
body: SyncCombinedRequest;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export async function postSyncCombinedRequest(
|
|
72
|
-
options: PostSyncCombinedRequestOptions
|
|
73
|
-
): Promise<PostJsonWithActorResult<SyncCombinedResponse>> {
|
|
74
|
-
const result = await postJsonWithActor<SyncCombinedRequest, unknown>(options);
|
|
75
|
-
return {
|
|
76
|
-
response: result.response,
|
|
77
|
-
json: parseSyncCombinedResponse(result.json),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface PostSyncPushRequestOptions {
|
|
82
|
-
fetch: typeof globalThis.fetch;
|
|
83
|
-
url: string;
|
|
84
|
-
actorId: string;
|
|
85
|
-
actorHeader?: string;
|
|
86
|
-
extraHeaders?: Record<string, string>;
|
|
87
|
-
body: SyncPushRequest;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export async function postSyncPushRequest(
|
|
91
|
-
options: PostSyncPushRequestOptions
|
|
92
|
-
): Promise<PostJsonWithActorResult<SyncPushResponse>> {
|
|
93
|
-
const result = await postJsonWithActor<SyncPushRequest, unknown>(options);
|
|
94
|
-
return {
|
|
95
|
-
response: result.response,
|
|
96
|
-
json: parseSyncPushResponse(result.json),
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface PostSyncPullRequestOptions {
|
|
101
|
-
fetch: typeof globalThis.fetch;
|
|
102
|
-
url: string;
|
|
103
|
-
actorId: string;
|
|
104
|
-
actorHeader?: string;
|
|
105
|
-
extraHeaders?: Record<string, string>;
|
|
106
|
-
body: SyncPullRequest;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export async function postSyncPullRequest(
|
|
110
|
-
options: PostSyncPullRequestOptions
|
|
111
|
-
): Promise<PostJsonWithActorResult<SyncPullResponse>> {
|
|
112
|
-
const result = await postJsonWithActor<SyncPullRequest, unknown>(options);
|
|
113
|
-
return {
|
|
114
|
-
response: result.response,
|
|
115
|
-
json: parseSyncPullResponse(result.json),
|
|
116
|
-
};
|
|
117
|
-
}
|
package/src/sync-parse.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type SyncCombinedResponse,
|
|
3
|
-
SyncCombinedResponseSchema,
|
|
4
|
-
type SyncPullResponse,
|
|
5
|
-
SyncPullResponseSchema,
|
|
6
|
-
type SyncPushResponse,
|
|
7
|
-
SyncPushResponseSchema,
|
|
8
|
-
} from '@syncular/core';
|
|
9
|
-
|
|
10
|
-
interface ParseIssue {
|
|
11
|
-
path: ReadonlyArray<PropertyKey>;
|
|
12
|
-
message: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type ParseResult<T> =
|
|
16
|
-
| { success: true; data: T }
|
|
17
|
-
| { success: false; error: { issues: ReadonlyArray<ParseIssue> } };
|
|
18
|
-
|
|
19
|
-
function formatIssue(issue: ParseIssue): string {
|
|
20
|
-
const path =
|
|
21
|
-
issue.path.length > 0
|
|
22
|
-
? issue.path
|
|
23
|
-
.map((segment) =>
|
|
24
|
-
typeof segment === 'symbol' ? segment.toString() : String(segment)
|
|
25
|
-
)
|
|
26
|
-
.join('.')
|
|
27
|
-
: 'root';
|
|
28
|
-
return `${path}: ${issue.message}`;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function formatIssues(issues: ReadonlyArray<ParseIssue>): string {
|
|
32
|
-
return issues.map((issue) => formatIssue(issue)).join('; ');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function parseOrThrow<T>(
|
|
36
|
-
label: string,
|
|
37
|
-
value: unknown,
|
|
38
|
-
parse: (input: unknown) => ParseResult<T>
|
|
39
|
-
): T {
|
|
40
|
-
const parsed = parse(value);
|
|
41
|
-
if (parsed.success) {
|
|
42
|
-
return parsed.data;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
throw new Error(
|
|
46
|
-
`${label} validation failed: ${formatIssues(parsed.error.issues)}`
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function parseSyncCombinedResponse(
|
|
51
|
-
value: unknown
|
|
52
|
-
): SyncCombinedResponse {
|
|
53
|
-
return parseOrThrow('SyncCombinedResponse', value, (input) =>
|
|
54
|
-
SyncCombinedResponseSchema.safeParse(input)
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function parseSyncPushResponse(value: unknown): SyncPushResponse {
|
|
59
|
-
return parseOrThrow('SyncPushResponse', value, (input) =>
|
|
60
|
-
SyncPushResponseSchema.safeParse(input)
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function parseSyncPullResponse(value: unknown): SyncPullResponse {
|
|
65
|
-
return parseOrThrow('SyncPullResponse', value, (input) =>
|
|
66
|
-
SyncPullResponseSchema.safeParse(input)
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export async function readSyncCombinedResponse(
|
|
71
|
-
response: Response
|
|
72
|
-
): Promise<SyncCombinedResponse> {
|
|
73
|
-
return parseSyncCombinedResponse(await response.json());
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export async function readSyncPushResponse(
|
|
77
|
-
response: Response
|
|
78
|
-
): Promise<SyncPushResponse> {
|
|
79
|
-
return parseSyncPushResponse(await response.json());
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export async function readSyncPullResponse(
|
|
83
|
-
response: Response
|
|
84
|
-
): Promise<SyncPullResponse> {
|
|
85
|
-
return parseSyncPullResponse(await response.json());
|
|
86
|
-
}
|
package/src/sync-response.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isRecord,
|
|
3
|
-
type SyncChange,
|
|
4
|
-
type SyncPullResponse,
|
|
5
|
-
} from '@syncular/core';
|
|
6
|
-
|
|
7
|
-
export type SyncSubscriptionRecord = Pick<
|
|
8
|
-
SyncPullResponse['subscriptions'][number],
|
|
9
|
-
'id' | 'commits'
|
|
10
|
-
>;
|
|
11
|
-
|
|
12
|
-
export function subscriptionChanges(
|
|
13
|
-
subscriptions: SyncSubscriptionRecord[] | undefined,
|
|
14
|
-
subscriptionId: string
|
|
15
|
-
): SyncChange[] {
|
|
16
|
-
const subscription = subscriptions?.find(
|
|
17
|
-
(item) => item.id === subscriptionId
|
|
18
|
-
);
|
|
19
|
-
if (!subscription) {
|
|
20
|
-
return [];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return subscription.commits?.flatMap((commit) => commit.changes) ?? [];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function findSubscriptionChange(
|
|
27
|
-
subscriptions: SyncSubscriptionRecord[] | undefined,
|
|
28
|
-
subscriptionId: string,
|
|
29
|
-
rowId: string
|
|
30
|
-
): SyncChange | undefined {
|
|
31
|
-
const changes = subscriptionChanges(subscriptions, subscriptionId);
|
|
32
|
-
return changes.find((change) => change.row_id === rowId);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function subscriptionChangeRow(
|
|
36
|
-
change: SyncChange | undefined
|
|
37
|
-
): Record<string, unknown> | undefined {
|
|
38
|
-
if (!change) {
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return isRecord(change.row_json) ? change.row_json : undefined;
|
|
43
|
-
}
|