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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +358 -0
  3. package/dist/core/BaseModel.d.ts +76 -0
  4. package/dist/core/BaseModel.js +505 -0
  5. package/dist/core/BaseSSEConnection.d.ts +31 -0
  6. package/dist/core/BaseSSEConnection.js +91 -0
  7. package/dist/core/BatchModelLoader.d.ts +27 -0
  8. package/dist/core/BatchModelLoader.js +70 -0
  9. package/dist/core/CompoundIndexFetcher.d.ts +46 -0
  10. package/dist/core/CompoundIndexFetcher.js +177 -0
  11. package/dist/core/Database.d.ts +303 -0
  12. package/dist/core/Database.js +837 -0
  13. package/dist/core/LazyCollection.d.ts +168 -0
  14. package/dist/core/LazyCollection.js +403 -0
  15. package/dist/core/LazyOwnedCollection.d.ts +35 -0
  16. package/dist/core/LazyOwnedCollection.js +66 -0
  17. package/dist/core/MemoryAdapter.d.ts +67 -0
  18. package/dist/core/MemoryAdapter.js +243 -0
  19. package/dist/core/ModelRegistry.d.ts +64 -0
  20. package/dist/core/ModelRegistry.js +217 -0
  21. package/dist/core/ModelStream.d.ts +33 -0
  22. package/dist/core/ModelStream.js +68 -0
  23. package/dist/core/ObjectPool.d.ts +113 -0
  24. package/dist/core/ObjectPool.js +339 -0
  25. package/dist/core/Store.d.ts +40 -0
  26. package/dist/core/Store.js +73 -0
  27. package/dist/core/StoreManager.d.ts +839 -0
  28. package/dist/core/StoreManager.js +2034 -0
  29. package/dist/core/SyncConnection.d.ts +105 -0
  30. package/dist/core/SyncConnection.js +348 -0
  31. package/dist/core/Transaction.d.ts +114 -0
  32. package/dist/core/Transaction.js +147 -0
  33. package/dist/core/TransactionQueue.d.ts +110 -0
  34. package/dist/core/TransactionQueue.js +601 -0
  35. package/dist/core/decorators.d.ts +66 -0
  36. package/dist/core/decorators.js +278 -0
  37. package/dist/core/hash.d.ts +6 -0
  38. package/dist/core/hash.js +12 -0
  39. package/dist/core/index.d.ts +16 -0
  40. package/dist/core/index.js +18 -0
  41. package/dist/core/internal.d.ts +27 -0
  42. package/dist/core/internal.js +25 -0
  43. package/dist/core/observability.d.ts +21 -0
  44. package/dist/core/observability.js +66 -0
  45. package/dist/core/refAccessors.d.ts +43 -0
  46. package/dist/core/refAccessors.js +80 -0
  47. package/dist/core/serializers.d.ts +2 -0
  48. package/dist/core/serializers.js +2 -0
  49. package/dist/core/types.d.ts +320 -0
  50. package/dist/core/types.js +84 -0
  51. package/dist/react/index.d.ts +82 -0
  52. package/dist/react/index.js +373 -0
  53. package/dist/schema/builders.d.ts +29 -0
  54. package/dist/schema/builders.js +81 -0
  55. package/dist/schema/compile.d.ts +28 -0
  56. package/dist/schema/compile.js +334 -0
  57. package/dist/schema/createStore.d.ts +235 -0
  58. package/dist/schema/createStore.js +264 -0
  59. package/dist/schema/extend.d.ts +46 -0
  60. package/dist/schema/extend.js +6 -0
  61. package/dist/schema/index.d.ts +13 -0
  62. package/dist/schema/index.js +8 -0
  63. package/dist/schema/infer.d.ts +102 -0
  64. package/dist/schema/infer.js +1 -0
  65. package/dist/schema/types.d.ts +76 -0
  66. package/dist/schema/types.js +1 -0
  67. package/dist/schema/zod.d.ts +90 -0
  68. package/dist/schema/zod.js +101 -0
  69. 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
+ }