@tursodatabase/sync-common 0.2.0-pre.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.
- package/README.md +8 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/run.d.ts +4 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +121 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## About
|
|
2
|
+
|
|
3
|
+
This package is the Turso Sync common JS library which is shared between final builds for Node and Browser.
|
|
4
|
+
|
|
5
|
+
Do not use this package directly - instead you must use `@tursodatabase/sync` or `@tursodatabase/sync-browser`.
|
|
6
|
+
|
|
7
|
+
> **⚠️ Warning:** This software is ALPHA, only use for development, testing, and experimentation. We are working to make it production ready, but do not use it for critical data right now.
|
|
8
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { run, memoryIO } from "./run.js";
|
|
2
|
+
import { SyncOpts, ProtocolIo, RunOpts, DatabaseRowMutation, DatabaseRowStatement, DatabaseRowTransformResult } from "./types.js";
|
|
3
|
+
export { run, memoryIO, };
|
|
4
|
+
export type { SyncOpts, ProtocolIo, RunOpts, DatabaseRowMutation, DatabaseRowStatement, DatabaseRowTransformResult };
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAEjI,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,CAAA;AACzB,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,CAAA"}
|
package/dist/index.js
ADDED
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA2FpE,wBAAgB,QAAQ,IAAI,UAAU,CAUrC;AAGD,wBAAsB,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAoBlG"}
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const GENERATOR_RESUME_IO = 0;
|
|
3
|
+
const GENERATOR_RESUME_DONE = 1;
|
|
4
|
+
function trackPromise(p) {
|
|
5
|
+
let status = { promise: null, finished: false };
|
|
6
|
+
status.promise = p.finally(() => status.finished = true);
|
|
7
|
+
return status;
|
|
8
|
+
}
|
|
9
|
+
function timeoutMs(ms) {
|
|
10
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
11
|
+
}
|
|
12
|
+
async function process(opts, io, request) {
|
|
13
|
+
const requestType = request.request();
|
|
14
|
+
const completion = request.completion();
|
|
15
|
+
if (requestType.type == 'Http') {
|
|
16
|
+
try {
|
|
17
|
+
let headers = opts.headers;
|
|
18
|
+
if (requestType.headers != null && requestType.headers.length > 0) {
|
|
19
|
+
headers = { ...opts.headers };
|
|
20
|
+
for (let header of requestType.headers) {
|
|
21
|
+
headers[header[0]] = header[1];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const response = await fetch(`${opts.url}${requestType.path}`, {
|
|
25
|
+
method: requestType.method,
|
|
26
|
+
headers: headers,
|
|
27
|
+
body: requestType.body != null ? new Uint8Array(requestType.body) : null,
|
|
28
|
+
});
|
|
29
|
+
completion.status(response.status);
|
|
30
|
+
const reader = response.body.getReader();
|
|
31
|
+
while (true) {
|
|
32
|
+
const { done, value } = await reader.read();
|
|
33
|
+
if (done) {
|
|
34
|
+
completion.done();
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
completion.pushBuffer(value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
completion.poison(`fetch error: ${error}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (requestType.type == 'FullRead') {
|
|
45
|
+
try {
|
|
46
|
+
const metadata = await io.read(requestType.path);
|
|
47
|
+
if (metadata != null) {
|
|
48
|
+
completion.pushBuffer(metadata);
|
|
49
|
+
}
|
|
50
|
+
completion.done();
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
completion.poison(`metadata read error: ${error}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (requestType.type == 'FullWrite') {
|
|
57
|
+
try {
|
|
58
|
+
await io.write(requestType.path, requestType.content);
|
|
59
|
+
completion.done();
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
completion.poison(`metadata write error: ${error}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (requestType.type == 'Transform') {
|
|
66
|
+
if (opts.transform == null) {
|
|
67
|
+
completion.poison("transform is not set");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const results = [];
|
|
71
|
+
for (const mutation of requestType.mutations) {
|
|
72
|
+
const result = opts.transform(mutation);
|
|
73
|
+
if (result == null) {
|
|
74
|
+
results.push({ type: 'Keep' });
|
|
75
|
+
}
|
|
76
|
+
else if (result.operation == 'skip') {
|
|
77
|
+
results.push({ type: 'Skip' });
|
|
78
|
+
}
|
|
79
|
+
else if (result.operation == 'rewrite') {
|
|
80
|
+
results.push({ type: 'Rewrite', stmt: result.stmt });
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
completion.poison("unexpected transform operation");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
completion.pushTransform(results);
|
|
88
|
+
completion.done();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function memoryIO() {
|
|
92
|
+
let values = new Map();
|
|
93
|
+
return {
|
|
94
|
+
async read(path) {
|
|
95
|
+
return values.get(path);
|
|
96
|
+
},
|
|
97
|
+
async write(path, data) {
|
|
98
|
+
values.set(path, data);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
;
|
|
103
|
+
export async function run(opts, io, engine, generator) {
|
|
104
|
+
let tasks = [];
|
|
105
|
+
while (true) {
|
|
106
|
+
const { type, ...rest } = await generator.resumeAsync(null);
|
|
107
|
+
if (type == 'Done') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (type == 'SyncEngineStats') {
|
|
111
|
+
return rest;
|
|
112
|
+
}
|
|
113
|
+
for (let request = engine.protocolIo(); request != null; request = engine.protocolIo()) {
|
|
114
|
+
tasks.push(trackPromise(process(opts, io, request)));
|
|
115
|
+
}
|
|
116
|
+
const tasksRace = tasks.length == 0 ? Promise.resolve() : Promise.race([timeoutMs(opts.preemptionMs), ...tasks.map(t => t.promise)]);
|
|
117
|
+
await Promise.all([engine.ioLoopAsync(), tasksRace]);
|
|
118
|
+
tasks = tasks.filter(t => !t.finished);
|
|
119
|
+
}
|
|
120
|
+
return generator.take();
|
|
121
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare const enum DatabaseChangeType {
|
|
2
|
+
Insert = 0,
|
|
3
|
+
Update = 1,
|
|
4
|
+
Delete = 2
|
|
5
|
+
}
|
|
6
|
+
export interface DatabaseRowMutation {
|
|
7
|
+
changeTime: number;
|
|
8
|
+
tableName: string;
|
|
9
|
+
id: number;
|
|
10
|
+
changeType: DatabaseChangeType;
|
|
11
|
+
before?: Record<string, any>;
|
|
12
|
+
after?: Record<string, any>;
|
|
13
|
+
updates?: Record<string, any>;
|
|
14
|
+
}
|
|
15
|
+
export type DatabaseRowTransformResult = {
|
|
16
|
+
operation: 'skip';
|
|
17
|
+
} | {
|
|
18
|
+
operation: 'rewrite';
|
|
19
|
+
stmt: DatabaseRowStatement;
|
|
20
|
+
} | null;
|
|
21
|
+
export type Transform = (arg: DatabaseRowMutation) => DatabaseRowTransformResult;
|
|
22
|
+
export interface RunOpts {
|
|
23
|
+
preemptionMs: number;
|
|
24
|
+
url: string;
|
|
25
|
+
headers: {
|
|
26
|
+
[K: string]: string;
|
|
27
|
+
};
|
|
28
|
+
transform?: Transform;
|
|
29
|
+
}
|
|
30
|
+
export interface ProtocolIo {
|
|
31
|
+
read(path: string): Promise<Buffer | Uint8Array | null>;
|
|
32
|
+
write(path: string, content: Buffer | Uint8Array): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface SyncOpts {
|
|
35
|
+
path: string;
|
|
36
|
+
clientName?: string;
|
|
37
|
+
url: string;
|
|
38
|
+
authToken?: string;
|
|
39
|
+
encryptionKey?: string;
|
|
40
|
+
tablesIgnore?: string[];
|
|
41
|
+
transform?: Transform;
|
|
42
|
+
tracing?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface DatabaseRowStatement {
|
|
45
|
+
sql: string;
|
|
46
|
+
values: Array<any>;
|
|
47
|
+
}
|
|
48
|
+
export type GeneratorResponse = {
|
|
49
|
+
type: 'IO';
|
|
50
|
+
} | {
|
|
51
|
+
type: 'Done';
|
|
52
|
+
} | {
|
|
53
|
+
type: 'SyncEngineStats';
|
|
54
|
+
operations: number;
|
|
55
|
+
mainWal: number;
|
|
56
|
+
revertWal: number;
|
|
57
|
+
lastPullUnixTime: number;
|
|
58
|
+
lastPushUnixTime: number | null;
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,CAAC,KAAK,MAAM,kBAAkB;IACxC,MAAM,IAAI;IACV,MAAM,IAAI;IACV,MAAM,IAAI;CACb;AAED,MAAM,WAAW,mBAAmB;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,kBAAkB,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAChC;AAED,MAAM,MAAM,0BAA0B,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAAG,IAAI,CAAC;AAC7H,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,0BAA0B,CAAC;AACjF,MAAM,WAAW,OAAO;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;CACrB;AAED,MAAM,MAAM,iBAAiB,GACvB;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tursodatabase/sync-common",
|
|
3
|
+
"version": "0.2.0-pre.1",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/tursodatabase/turso"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"packageManager": "yarn@4.9.2",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/**",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.9.2"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"tsc-build": "npm exec tsc",
|
|
22
|
+
"build": "npm run tsc-build",
|
|
23
|
+
"test": "echo 'no tests'"
|
|
24
|
+
}
|
|
25
|
+
}
|