zerodrift 1.0.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/LICENSE +21 -0
- package/README.md +358 -0
- package/dist/core/BaseModel.d.ts +76 -0
- package/dist/core/BaseModel.js +505 -0
- package/dist/core/BaseSSEConnection.d.ts +31 -0
- package/dist/core/BaseSSEConnection.js +91 -0
- package/dist/core/BatchModelLoader.d.ts +27 -0
- package/dist/core/BatchModelLoader.js +70 -0
- package/dist/core/CompoundIndexFetcher.d.ts +46 -0
- package/dist/core/CompoundIndexFetcher.js +177 -0
- package/dist/core/Database.d.ts +303 -0
- package/dist/core/Database.js +837 -0
- package/dist/core/LazyCollection.d.ts +168 -0
- package/dist/core/LazyCollection.js +403 -0
- package/dist/core/LazyOwnedCollection.d.ts +35 -0
- package/dist/core/LazyOwnedCollection.js +66 -0
- package/dist/core/MemoryAdapter.d.ts +67 -0
- package/dist/core/MemoryAdapter.js +243 -0
- package/dist/core/ModelRegistry.d.ts +64 -0
- package/dist/core/ModelRegistry.js +217 -0
- package/dist/core/ModelStream.d.ts +33 -0
- package/dist/core/ModelStream.js +68 -0
- package/dist/core/ObjectPool.d.ts +113 -0
- package/dist/core/ObjectPool.js +339 -0
- package/dist/core/Store.d.ts +40 -0
- package/dist/core/Store.js +73 -0
- package/dist/core/StoreManager.d.ts +839 -0
- package/dist/core/StoreManager.js +2034 -0
- package/dist/core/SyncConnection.d.ts +105 -0
- package/dist/core/SyncConnection.js +348 -0
- package/dist/core/Transaction.d.ts +114 -0
- package/dist/core/Transaction.js +147 -0
- package/dist/core/TransactionQueue.d.ts +110 -0
- package/dist/core/TransactionQueue.js +601 -0
- package/dist/core/decorators.d.ts +66 -0
- package/dist/core/decorators.js +278 -0
- package/dist/core/hash.d.ts +6 -0
- package/dist/core/hash.js +12 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.js +18 -0
- package/dist/core/internal.d.ts +27 -0
- package/dist/core/internal.js +25 -0
- package/dist/core/observability.d.ts +21 -0
- package/dist/core/observability.js +66 -0
- package/dist/core/refAccessors.d.ts +43 -0
- package/dist/core/refAccessors.js +80 -0
- package/dist/core/serializers.d.ts +2 -0
- package/dist/core/serializers.js +2 -0
- package/dist/core/types.d.ts +320 -0
- package/dist/core/types.js +84 -0
- package/dist/react/index.d.ts +82 -0
- package/dist/react/index.js +373 -0
- package/dist/schema/builders.d.ts +29 -0
- package/dist/schema/builders.js +81 -0
- package/dist/schema/compile.d.ts +28 -0
- package/dist/schema/compile.js +334 -0
- package/dist/schema/createStore.d.ts +235 -0
- package/dist/schema/createStore.js +264 -0
- package/dist/schema/extend.d.ts +46 -0
- package/dist/schema/extend.js +6 -0
- package/dist/schema/index.d.ts +13 -0
- package/dist/schema/index.js +8 -0
- package/dist/schema/infer.d.ts +102 -0
- package/dist/schema/infer.js +1 -0
- package/dist/schema/types.d.ts +76 -0
- package/dist/schema/types.js +1 -0
- package/dist/schema/zod.d.ts +90 -0
- package/dist/schema/zod.js +101 -0
- package/package.json +99 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { fields, entity, rebuildFieldBuilder } from "./builders";
|
|
2
|
+
const PRIMITIVE_KIND = new Map([
|
|
3
|
+
["string", fields.string],
|
|
4
|
+
["number", fields.number],
|
|
5
|
+
["int", fields.number],
|
|
6
|
+
["boolean", fields.boolean],
|
|
7
|
+
["date", fields.date],
|
|
8
|
+
]);
|
|
9
|
+
/**
|
|
10
|
+
* Convert any Zod schema into the equivalent schema-first `FieldBuilder`.
|
|
11
|
+
* Handles the common nullable / optional / default modifiers; anything more
|
|
12
|
+
* structured (objects, arrays, unions, enums) collapses to `s.json<T>()` so
|
|
13
|
+
* the runtime stores the raw value and the TS type still flows from Zod.
|
|
14
|
+
*
|
|
15
|
+
* Zod is an optional peer dependency — calling this function requires the
|
|
16
|
+
* caller to have installed `zod`.
|
|
17
|
+
*/
|
|
18
|
+
export function fromZod(zSchema) {
|
|
19
|
+
let current = zSchema;
|
|
20
|
+
let nullable = false;
|
|
21
|
+
let optional = false;
|
|
22
|
+
let defaultValue = undefined;
|
|
23
|
+
while (true) {
|
|
24
|
+
const { type, innerType, defaultValue: inner } = current._zod.def;
|
|
25
|
+
if (type === "nullable" && innerType != null) {
|
|
26
|
+
nullable = true;
|
|
27
|
+
current = innerType;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (type === "optional" && innerType != null) {
|
|
31
|
+
optional = true;
|
|
32
|
+
current = innerType;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (type === "default" && innerType != null) {
|
|
36
|
+
defaultValue = inner;
|
|
37
|
+
current = innerType;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
const factory = PRIMITIVE_KIND.get(current._zod.def.type) ?? fields.json;
|
|
43
|
+
let builder = factory();
|
|
44
|
+
if (defaultValue !== undefined) {
|
|
45
|
+
builder = builder.default(defaultValue);
|
|
46
|
+
}
|
|
47
|
+
if (nullable) {
|
|
48
|
+
builder = builder.nullable();
|
|
49
|
+
}
|
|
50
|
+
if (optional) {
|
|
51
|
+
builder = rebuildFieldBuilder({
|
|
52
|
+
...builder.meta,
|
|
53
|
+
optional: true,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return builder;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Convert a `z.object({ ... })` into an `EntityDef`. Each key on the Zod
|
|
60
|
+
* object becomes a field via `fromZod`, then `opts.fields[key]` (if
|
|
61
|
+
* present) is applied — either chained onto the auto-derived builder, or
|
|
62
|
+
* used as a full replacement.
|
|
63
|
+
*
|
|
64
|
+
* The override map is captured via a `const`-modified generic so per-field
|
|
65
|
+
* metadata (`.indexed()`, refId target, …) flows into the returned
|
|
66
|
+
* `EntityDef` — `IndexedFieldKeys`, `getByIndex`, `peekByIndex`, and the
|
|
67
|
+
* typed React hooks all see Zod-built entities the same way they see
|
|
68
|
+
* hand-written ones.
|
|
69
|
+
*
|
|
70
|
+
* `F` is inferred from the provided `fields` map while an intersected
|
|
71
|
+
* override-map type supplies allowed keys and key-specific contextual typing
|
|
72
|
+
* for the `(auto) => ...` parameter. When no `fields` map is provided, `F`
|
|
73
|
+
* defaults to an empty record so untouched Zod fields stay on the auto-derived
|
|
74
|
+
* `FieldBuilder<z.infer<...>>` path.
|
|
75
|
+
* `EntityFromZodOpts<Z>` keeps the strict union for users who pre-type
|
|
76
|
+
* their opts variables.
|
|
77
|
+
*
|
|
78
|
+
* Only single-record entities are produced; relations still belong in the
|
|
79
|
+
* schema's `links` block. Treat the Zod object as the source of field
|
|
80
|
+
* shape and validation; `link(...)` remains the source of truth for the
|
|
81
|
+
* graph.
|
|
82
|
+
*/
|
|
83
|
+
export function entityFromZod(zSchema, opts) {
|
|
84
|
+
const overrides = (opts.fields ?? {});
|
|
85
|
+
const fieldsRecord = {};
|
|
86
|
+
for (const [key, fieldSchema] of Object.entries(zSchema.shape)) {
|
|
87
|
+
const auto = key === "id" ? fields.id() : fromZod(fieldSchema);
|
|
88
|
+
const override = overrides[key];
|
|
89
|
+
fieldsRecord[key] =
|
|
90
|
+
typeof override === "function"
|
|
91
|
+
? override(auto)
|
|
92
|
+
: (override ?? auto);
|
|
93
|
+
}
|
|
94
|
+
return entity({
|
|
95
|
+
loadStrategy: opts.loadStrategy,
|
|
96
|
+
usedForPartialIndexes: opts.usedForPartialIndexes,
|
|
97
|
+
name: opts.name,
|
|
98
|
+
version: opts.version,
|
|
99
|
+
fields: fieldsRecord,
|
|
100
|
+
});
|
|
101
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zerodrift",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "A TypeScript local-first sync engine: synchronous in-memory reads, optimistic writes, realtime SSE sync, offline IndexedDB persistence. Runs in the browser and in Node.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "selasijean <selasijean@gmail.com>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/selasijean/zerodrift.git"
|
|
11
|
+
},
|
|
12
|
+
"workspaces": [
|
|
13
|
+
"examples/webapp"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/selasijean/zerodrift#readme",
|
|
16
|
+
"bugs": "https://github.com/selasijean/zerodrift/issues",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"local-first",
|
|
19
|
+
"sync",
|
|
20
|
+
"offline",
|
|
21
|
+
"optimistic",
|
|
22
|
+
"indexeddb",
|
|
23
|
+
"sse",
|
|
24
|
+
"mobx",
|
|
25
|
+
"realtime",
|
|
26
|
+
"crdt-alternative"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./dist/core/index.js",
|
|
30
|
+
"module": "./dist/core/index.js",
|
|
31
|
+
"types": "./dist/core/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/core/index.d.ts",
|
|
35
|
+
"default": "./dist/core/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./react": {
|
|
38
|
+
"types": "./dist/react/index.d.ts",
|
|
39
|
+
"default": "./dist/react/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./schema": {
|
|
42
|
+
"types": "./dist/schema/index.d.ts",
|
|
43
|
+
"default": "./dist/schema/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./internal": {
|
|
46
|
+
"types": "./dist/core/internal.d.ts",
|
|
47
|
+
"default": "./dist/core/internal.js"
|
|
48
|
+
},
|
|
49
|
+
"./package.json": "./package.json"
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"dist"
|
|
53
|
+
],
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18"
|
|
56
|
+
},
|
|
57
|
+
"sideEffects": false,
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc -p tsconfig.build.json",
|
|
60
|
+
"clean": "rm -rf dist",
|
|
61
|
+
"prepack": "npm run clean && npm run build",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"test:watch": "vitest",
|
|
64
|
+
"test:coverage": "vitest run --coverage",
|
|
65
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\" \"__tests__/**/*.ts\""
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"mobx": "^6.15.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"react": ">=18.0.0",
|
|
72
|
+
"zod": ">=4.0.0"
|
|
73
|
+
},
|
|
74
|
+
"peerDependenciesMeta": {
|
|
75
|
+
"react": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"zod": {
|
|
79
|
+
"optional": true
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"devDependencies": {
|
|
83
|
+
"@eslint/js": "^10.0.1",
|
|
84
|
+
"@swc/core": "^1.15.24",
|
|
85
|
+
"@types/react": "^19.2.14",
|
|
86
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
87
|
+
"eslint": "^10.2.0",
|
|
88
|
+
"eslint-config-prettier": "^10.1.8",
|
|
89
|
+
"fake-indexeddb": "^6.2.5",
|
|
90
|
+
"jsdom": "^29.0.2",
|
|
91
|
+
"prettier": "^3.8.3",
|
|
92
|
+
"react": "^19.2.5",
|
|
93
|
+
"typescript": "^6.0.2",
|
|
94
|
+
"typescript-eslint": "^8.58.2",
|
|
95
|
+
"unplugin-swc": "^1.5.9",
|
|
96
|
+
"vitest": "^4.1.4",
|
|
97
|
+
"zod": "^4.4.3"
|
|
98
|
+
}
|
|
99
|
+
}
|