zerodrift 1.0.3 → 1.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 (56) hide show
  1. package/README.md +15 -3
  2. package/dist/core/BaseModel.d.ts +2 -2
  3. package/dist/core/BaseModel.js +4 -4
  4. package/dist/core/BaseSSEConnection.d.ts +9 -3
  5. package/dist/core/BaseSSEConnection.js +23 -3
  6. package/dist/core/CompoundIndexFetcher.d.ts +2 -2
  7. package/dist/core/CompoundIndexFetcher.js +3 -3
  8. package/dist/core/Database.d.ts +2 -1
  9. package/dist/core/Database.js +1 -1
  10. package/dist/core/LazyCollection.d.ts +2 -2
  11. package/dist/core/LazyCollection.js +1 -1
  12. package/dist/core/LazyOwnedCollection.d.ts +2 -2
  13. package/dist/core/LazyOwnedCollection.js +1 -1
  14. package/dist/core/MemoryAdapter.d.ts +1 -1
  15. package/dist/core/MemoryAdapter.js +1 -1
  16. package/dist/core/ModelRegistry.d.ts +1 -1
  17. package/dist/core/ModelRegistry.js +2 -2
  18. package/dist/core/ModelStream.d.ts +4 -4
  19. package/dist/core/ModelStream.js +3 -3
  20. package/dist/core/ObjectPool.d.ts +2 -2
  21. package/dist/core/ObjectPool.js +2 -2
  22. package/dist/core/Store.d.ts +4 -4
  23. package/dist/core/Store.js +1 -1
  24. package/dist/core/StoreManager.d.ts +23 -12
  25. package/dist/core/StoreManager.js +25 -13
  26. package/dist/core/SyncConnection.d.ts +6 -6
  27. package/dist/core/SyncConnection.js +11 -10
  28. package/dist/core/Transaction.d.ts +2 -2
  29. package/dist/core/Transaction.js +1 -1
  30. package/dist/core/TransactionQueue.d.ts +6 -6
  31. package/dist/core/TransactionQueue.js +4 -4
  32. package/dist/core/decorators.d.ts +1 -1
  33. package/dist/core/decorators.js +4 -4
  34. package/dist/core/index.d.ts +16 -16
  35. package/dist/core/index.js +9 -9
  36. package/dist/core/internal.d.ts +13 -13
  37. package/dist/core/internal.js +11 -11
  38. package/dist/core/observability.js +1 -1
  39. package/dist/core/refAccessors.d.ts +2 -2
  40. package/dist/core/types.d.ts +1 -1
  41. package/dist/react/index.d.ts +22 -12
  42. package/dist/react/index.js +31 -23
  43. package/dist/schema/builders.d.ts +1 -1
  44. package/dist/schema/builders.js +1 -1
  45. package/dist/schema/compile.d.ts +1 -1
  46. package/dist/schema/compile.js +6 -6
  47. package/dist/schema/createStore.d.ts +5 -5
  48. package/dist/schema/createStore.js +4 -4
  49. package/dist/schema/extend.d.ts +2 -2
  50. package/dist/schema/index.d.ts +13 -13
  51. package/dist/schema/index.js +7 -7
  52. package/dist/schema/infer.d.ts +10 -1
  53. package/dist/schema/types.d.ts +1 -1
  54. package/dist/schema/zod.d.ts +125 -12
  55. package/dist/schema/zod.js +24 -2
  56. package/package.json +1 -1
@@ -12,10 +12,10 @@
12
12
  *
13
13
  * The undo stack stores "entries" — either a single tx or a batch of txs.
14
14
  */
15
- import { ModelRegistry } from "./ModelRegistry";
16
- import { toError } from "./types";
17
- import { BaseTransaction, UpdateTransaction, CreateTransaction, DeleteTransaction, ArchiveTransaction, } from "./Transaction";
18
- import { TransactionState } from "./types";
15
+ import { ModelRegistry } from "./ModelRegistry.js";
16
+ import { toError } from "./types.js";
17
+ import { BaseTransaction, UpdateTransaction, CreateTransaction, DeleteTransaction, ArchiveTransaction, } from "./Transaction.js";
18
+ import { TransactionState } from "./types.js";
19
19
  const isAction = (e) => !(e instanceof BaseTransaction);
20
20
  export class TransactionQueue {
21
21
  constructor(database, pool, undoLimit = 100) {
@@ -15,7 +15,7 @@
15
15
  * time. The engine reads that metadata later for serialization, hydration,
16
16
  * observability, indexing, and reference resolution.
17
17
  */
18
- import { LoadStrategy } from "./types";
18
+ import { LoadStrategy } from "./types.js";
19
19
  export declare function ClientModel(opts?: {
20
20
  /**
21
21
  * The registry name — what `ModelMeta.name` becomes, what
@@ -15,10 +15,10 @@
15
15
  * time. The engine reads that metadata later for serialization, hydration,
16
16
  * observability, indexing, and reference resolution.
17
17
  */
18
- import { ModelRegistry } from "./ModelRegistry";
19
- import { defineObservableProperty } from "./observability";
20
- import { PropertyType, } from "./types";
21
- import { installBackRefAccessor, installCollectionAccessor, installReferenceAccessor, } from "./refAccessors";
18
+ import { ModelRegistry } from "./ModelRegistry.js";
19
+ import { defineObservableProperty } from "./observability.js";
20
+ import { PropertyType, } from "./types.js";
21
+ import { installBackRefAccessor, installCollectionAccessor, installReferenceAccessor, } from "./refAccessors.js";
22
22
  const pendingByClass = new WeakMap();
23
23
  function getOrCreatePending(ctor) {
24
24
  let entry = pendingByClass.get(ctor);
@@ -1,16 +1,16 @@
1
- export { LoadStrategy, PropertyType, BootstrapPhase, TransactionState, } from "./types";
2
- export { dateSerializer, dateDeserializer } from "./serializers";
3
- export type { PropertyMeta, ModelMeta, FieldTransform, PropertyChange, CommitIntent, CommitRouteResult, CommitRouteHandler, OnModelTouchedHandler, OnDelete, EngineErrorContext, EngineErrorHandler, } from "./types";
4
- export { ClientModel, Property, EphemeralProperty, Reference, LazyReference, ReferenceCollection, LazyReferenceCollection, OwnedCollection, LazyOwnedCollection, BackReference, ReferenceArray, Action, Computed, } from "./decorators";
5
- export { BaseModel } from "./BaseModel";
6
- export { RefCollection, BackRef, CollectionState } from "./LazyCollection";
7
- export { OwnedRefs } from "./LazyOwnedCollection";
8
- export { MemoryAdapter } from "./MemoryAdapter";
9
- export { BootstrapType } from "./Database";
10
- export type { DatabaseMeta, StorageAdapter } from "./Database";
11
- export { StoreManager, RestrictDeleteError } from "./StoreManager";
12
- export type { BootstrapResponse, BootstrapFetcher, BootstrapFetcherOptions, FetcherContext, StoreManagerConfig, TransportConfig, LoadingConfig, PersistenceConfig, HooksConfig, AdvancedConfig, OnDemandConfig, OnDemandFetcher, OnDemandBatchFetcher, ModelStreamConfig, } from "./StoreManager";
13
- export type { UndoableAction } from "./Transaction";
14
- export type { TransactionSender, BatchResponse, UndoableActionHandlers, UndoResult, } from "./TransactionQueue";
15
- export type { SyncAction, DeltaPacket, SyncMessageTransform, } from "./SyncConnection";
16
- export type { ModelUpdate, ModelStreamMessageTransform } from "./ModelStream";
1
+ export { LoadStrategy, PropertyType, BootstrapPhase, TransactionState, } from "./types.js";
2
+ export { dateSerializer, dateDeserializer } from "./serializers.js";
3
+ export type { PropertyMeta, ModelMeta, FieldTransform, PropertyChange, CommitIntent, CommitRouteResult, CommitRouteHandler, OnModelTouchedHandler, OnDelete, EngineErrorContext, EngineErrorHandler, } from "./types.js";
4
+ export { ClientModel, Property, EphemeralProperty, Reference, LazyReference, ReferenceCollection, LazyReferenceCollection, OwnedCollection, LazyOwnedCollection, BackReference, ReferenceArray, Action, Computed, } from "./decorators.js";
5
+ export { BaseModel } from "./BaseModel.js";
6
+ export { RefCollection, BackRef, CollectionState } from "./LazyCollection.js";
7
+ export { OwnedRefs } from "./LazyOwnedCollection.js";
8
+ export { MemoryAdapter } from "./MemoryAdapter.js";
9
+ export { BootstrapType } from "./Database.js";
10
+ export type { DatabaseMeta, StorageAdapter } from "./Database.js";
11
+ export { StoreManager, RestrictDeleteError } from "./StoreManager.js";
12
+ export type { BootstrapResponse, BootstrapFetcher, BootstrapFetcherOptions, FetcherContext, StoreManagerConfig, TransportConfig, LoadingConfig, PersistenceConfig, HooksConfig, AdvancedConfig, OnDemandConfig, OnDemandFetcher, OnDemandBatchFetcher, ModelStreamConfig, } from "./StoreManager.js";
13
+ export type { UndoableAction } from "./Transaction.js";
14
+ export type { TransactionSender, BatchResponse, UndoableActionHandlers, UndoResult, } from "./TransactionQueue.js";
15
+ export type { SyncAction, DeltaPacket, SSEEndpoint, SyncMessageTransform, } from "./SyncConnection.js";
16
+ export type { ModelUpdate, ModelStreamMessageTransform } from "./ModelStream.js";
@@ -1,18 +1,18 @@
1
1
  // `zerodrift` — the curated, stable adopter surface. The engine's runtime
2
2
  // machinery lives behind `zerodrift/internal` (see internal.ts).
3
3
  // ── Enums & serializers ────────────────────────────────────────────────────
4
- export { LoadStrategy, PropertyType, BootstrapPhase, TransactionState, } from "./types";
5
- export { dateSerializer, dateDeserializer } from "./serializers";
4
+ export { LoadStrategy, PropertyType, BootstrapPhase, TransactionState, } from "./types.js";
5
+ export { dateSerializer, dateDeserializer } from "./serializers.js";
6
6
  // ── Model definition ───────────────────────────────────────────────────────
7
- export { ClientModel, Property, EphemeralProperty, Reference, LazyReference, ReferenceCollection, LazyReferenceCollection, OwnedCollection, LazyOwnedCollection, BackReference, ReferenceArray, Action, Computed, } from "./decorators";
8
- export { BaseModel } from "./BaseModel";
7
+ export { ClientModel, Property, EphemeralProperty, Reference, LazyReference, ReferenceCollection, LazyReferenceCollection, OwnedCollection, LazyOwnedCollection, BackReference, ReferenceArray, Action, Computed, } from "./decorators.js";
8
+ export { BaseModel } from "./BaseModel.js";
9
9
  // Relation field types — adopters annotate model fields with these
10
10
  // (`public issues: RefCollection<Issue>`), so they stay on the curated
11
11
  // surface even though their construction is engine-internal.
12
- export { RefCollection, BackRef, CollectionState } from "./LazyCollection";
13
- export { OwnedRefs } from "./LazyOwnedCollection";
12
+ export { RefCollection, BackRef, CollectionState } from "./LazyCollection.js";
13
+ export { OwnedRefs } from "./LazyOwnedCollection.js";
14
14
  // ── Storage ────────────────────────────────────────────────────────────────
15
- export { MemoryAdapter } from "./MemoryAdapter";
16
- export { BootstrapType } from "./Database";
15
+ export { MemoryAdapter } from "./MemoryAdapter.js";
16
+ export { BootstrapType } from "./Database.js";
17
17
  // ── Engine ─────────────────────────────────────────────────────────────────
18
- export { StoreManager, RestrictDeleteError } from "./StoreManager";
18
+ export { StoreManager, RestrictDeleteError } from "./StoreManager.js";
@@ -12,16 +12,16 @@
12
12
  * bump. If you find yourself importing from here in app code, that's usually
13
13
  * a sign the curated surface is missing something — open an issue.
14
14
  */
15
- export { ObjectPool } from "./ObjectPool";
16
- export { Database } from "./Database";
17
- export { ModelRegistry } from "./ModelRegistry";
18
- export { defineObservableProperty } from "./observability";
19
- export { FullStore, PartialStore, ModelStore } from "./Store";
20
- export { BaseTransaction, UpdateTransaction, CreateTransaction, DeleteTransaction, ArchiveTransaction, } from "./Transaction";
21
- export { TransactionQueue } from "./TransactionQueue";
22
- export { SyncConnection } from "./SyncConnection";
23
- export { ModelStream } from "./ModelStream";
24
- export { normalizeConfig } from "./StoreManager";
25
- export type { NormalizedConfig } from "./StoreManager";
26
- export type { IObjectPool, IStoreManager, CoveringPath, } from "./types";
27
- export { DEFAULT_TRANSIENT_INDEX_DEPTH, toError } from "./types";
15
+ export { ObjectPool } from "./ObjectPool.js";
16
+ export { Database } from "./Database.js";
17
+ export { ModelRegistry } from "./ModelRegistry.js";
18
+ export { defineObservableProperty } from "./observability.js";
19
+ export { FullStore, PartialStore, ModelStore } from "./Store.js";
20
+ export { BaseTransaction, UpdateTransaction, CreateTransaction, DeleteTransaction, ArchiveTransaction, } from "./Transaction.js";
21
+ export { TransactionQueue } from "./TransactionQueue.js";
22
+ export { SyncConnection } from "./SyncConnection.js";
23
+ export { ModelStream } from "./ModelStream.js";
24
+ export { normalizeConfig } from "./StoreManager.js";
25
+ export type { NormalizedConfig } from "./StoreManager.js";
26
+ export type { IObjectPool, IStoreManager, CoveringPath, } from "./types.js";
27
+ export { DEFAULT_TRANSIENT_INDEX_DEPTH, toError } from "./types.js";
@@ -12,14 +12,14 @@
12
12
  * bump. If you find yourself importing from here in app code, that's usually
13
13
  * a sign the curated surface is missing something — open an issue.
14
14
  */
15
- export { ObjectPool } from "./ObjectPool";
16
- export { Database } from "./Database";
17
- export { ModelRegistry } from "./ModelRegistry";
18
- export { defineObservableProperty } from "./observability";
19
- export { FullStore, PartialStore, ModelStore } from "./Store";
20
- export { BaseTransaction, UpdateTransaction, CreateTransaction, DeleteTransaction, ArchiveTransaction, } from "./Transaction";
21
- export { TransactionQueue } from "./TransactionQueue";
22
- export { SyncConnection } from "./SyncConnection";
23
- export { ModelStream } from "./ModelStream";
24
- export { normalizeConfig } from "./StoreManager";
25
- export { DEFAULT_TRANSIENT_INDEX_DEPTH, toError } from "./types";
15
+ export { ObjectPool } from "./ObjectPool.js";
16
+ export { Database } from "./Database.js";
17
+ export { ModelRegistry } from "./ModelRegistry.js";
18
+ export { defineObservableProperty } from "./observability.js";
19
+ export { FullStore, PartialStore, ModelStore } from "./Store.js";
20
+ export { BaseTransaction, UpdateTransaction, CreateTransaction, DeleteTransaction, ArchiveTransaction, } from "./Transaction.js";
21
+ export { TransactionQueue } from "./TransactionQueue.js";
22
+ export { SyncConnection } from "./SyncConnection.js";
23
+ export { ModelStream } from "./ModelStream.js";
24
+ export { normalizeConfig } from "./StoreManager.js";
25
+ export { DEFAULT_TRANSIENT_INDEX_DEPTH, toError } from "./types.js";
@@ -19,7 +19,7 @@
19
19
  * the raw stored value (for pre-bootstrap access before observability is on).
20
20
  */
21
21
  import { observable } from "mobx";
22
- import { BaseModel } from "./BaseModel";
22
+ import { BaseModel } from "./BaseModel.js";
23
23
  export function defineObservableProperty(target, propName) {
24
24
  // Raw storage key — holds the value before the MobX box is created
25
25
  const rawKey = `__raw_${propName}`;
@@ -1,5 +1,5 @@
1
- import type { IObjectPool } from "./types";
2
- import type { LazyCollectionBase, BackRef } from "./LazyCollection";
1
+ import type { IObjectPool } from "./types.js";
2
+ import type { LazyCollectionBase, BackRef } from "./LazyCollection.js";
3
3
  export interface RefHolder {
4
4
  store: IObjectPool | null;
5
5
  [key: string]: unknown;
@@ -1,4 +1,4 @@
1
- import type { BaseModel } from "./BaseModel";
1
+ import type { BaseModel } from "./BaseModel.js";
2
2
  /** How a model is loaded into the client. Choose by *when* you need its rows. */
3
3
  export declare enum LoadStrategy {
4
4
  /** Loaded during bootstrap, fully resident, kept current by SSE. The
@@ -7,16 +7,20 @@
7
7
  * `useRecordsByIndex` (or a relation via `useRelation`).
8
8
  */
9
9
  import React from "react";
10
- import { StoreManager, type StoreManagerConfig } from "../core/StoreManager";
11
- import { BootstrapPhase } from "../core/types";
12
- import { LazyCollectionBase, BackRef } from "../core/LazyCollection";
13
- import type { BaseModel } from "../core/BaseModel";
10
+ import { StoreManager, type StoreManagerConfig } from "../core/StoreManager.js";
11
+ import { BootstrapPhase } from "../core/types.js";
12
+ import { LazyCollectionBase, BackRef } from "../core/LazyCollection.js";
13
+ import type { BaseModel } from "../core/BaseModel.js";
14
+ import { type EntityNamespace, type EntityStore, type RecordWithExtensions } from "../schema/createStore.js";
15
+ import type { ExtensionDescriptor } from "../schema/extend.js";
16
+ import type { EntityKey, IndexedFieldKeys } from "../schema/infer.js";
17
+ import type { SchemaDef } from "../schema/types.js";
14
18
  export interface SyncStatus {
15
19
  phase: BootstrapPhase;
16
20
  detail?: string;
17
21
  error?: string;
18
22
  }
19
- export declare function SyncProvider<TContext = unknown>({ config, context, children, fallback, }: {
23
+ export declare function SyncProvider<TContext = unknown, S extends SchemaDef = SchemaDef>({ config, schema, extensions, context, children, fallback, }: {
20
24
  config: StoreManagerConfig<TContext>;
21
25
  /** Live context forwarded to `StoreManager.setContext` — consumed by
22
26
  * `identifierFn` when minting ids for client-side models. Pushed
@@ -25,12 +29,22 @@ export declare function SyncProvider<TContext = unknown>({ config, context, chil
25
29
  children: React.ReactNode;
26
30
  /** Shown while bootstrap is in progress. */
27
31
  fallback?: React.ReactNode;
28
- }): import("react/jsx-runtime").JSX.Element | null;
32
+ } & ({
33
+ schema?: undefined;
34
+ extensions?: undefined;
35
+ } | {
36
+ /** Schema-first wiring. Read the store back with `useStore<typeof schema>()`. */
37
+ schema: S;
38
+ extensions?: readonly ExtensionDescriptor<S>[];
39
+ })): import("react/jsx-runtime").JSX.Element | null;
29
40
  export declare function useSyncEngine(): {
30
41
  sm: StoreManager<any>;
31
42
  status: SyncStatus;
43
+ store?: EntityStore<any, any>;
32
44
  };
33
45
  export declare function useBootstrapStatus(): SyncStatus;
46
+ /** Read the schema-first store from context — `useStore<typeof schema>()`. */
47
+ export declare function useStore<S extends SchemaDef, const Exts extends readonly ExtensionDescriptor<S>[] = readonly []>(): EntityStore<S, Exts>;
34
48
  /**
35
49
  * Uniform async-resource shape for every load-aware hook (`useRecord`,
36
50
  * `useRecords`, `useRecordsByIndex`, `useRelation`). `data` is the payload
@@ -49,17 +63,13 @@ export interface AsyncResource<T> {
49
63
  * the async overload a `Promise<string>`. */
50
64
  export declare function useBatch(): StoreManager["batch"];
51
65
  export declare function useUndoRedo(): {
52
- undo: () => Promise<import("../core").UndoResult | null>;
53
- redo: () => Promise<import("../core").UndoResult | null>;
66
+ undo: () => Promise<import("../core/TransactionQueue.js").UndoResult | null>;
67
+ redo: () => Promise<import("../core/TransactionQueue.js").UndoResult | null>;
54
68
  canUndo: boolean;
55
69
  canRedo: boolean;
56
70
  };
57
71
  export declare function useRelation<T extends BaseModel = BaseModel>(relation: LazyCollectionBase<T> | null | undefined): AsyncResource<T[]>;
58
72
  export declare function useRelation<T extends BaseModel = BaseModel>(relation: BackRef<T> | null | undefined): AsyncResource<T | null>;
59
- import { type EntityNamespace, type RecordWithExtensions } from "../schema/createStore";
60
- import type { ExtensionDescriptor } from "../schema/extend";
61
- import type { EntityKey, IndexedFieldKeys } from "../schema/infer";
62
- import type { SchemaDef } from "../schema/types";
63
73
  type AnyNamespace = EntityNamespace<any, any, any>;
64
74
  type ModelCtor<T extends BaseModel = BaseModel> = abstract new (...args: any[]) => T;
65
75
  type Handle = AnyNamespace | ModelCtor;
@@ -8,22 +8,29 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
8
8
  * `useRecordsByIndex` (or a relation via `useRelation`).
9
9
  */
10
10
  import { createContext, useContext, useState, useEffect, useCallback, useMemo, useRef, useSyncExternalStore, useLayoutEffect, } from "react";
11
- import { StoreManager } from "../core/StoreManager";
12
- import { BootstrapPhase } from "../core/types";
13
- import { BackRef } from "../core/LazyCollection";
14
- import { readFk } from "../core/ObjectPool";
11
+ import { StoreManager } from "../core/StoreManager.js";
12
+ import { BootstrapPhase } from "../core/types.js";
13
+ import { BackRef } from "../core/LazyCollection.js";
14
+ import { readFk } from "../core/ObjectPool.js";
15
+ import { createStore, entityNamespaceRegistryName, } from "../schema/createStore.js";
15
16
  // `<any>` keeps the hooks free of TContext — none of them touch it.
16
17
  const SyncContext = createContext(null);
17
18
  // ---------------------------------------------------------------------------
18
19
  // Provider
19
20
  // ---------------------------------------------------------------------------
20
- export function SyncProvider({ config, context, children, fallback, }) {
21
+ export function SyncProvider({ config, schema, extensions, context, children, fallback, }) {
21
22
  const [status, setStatus] = useState({
22
23
  phase: BootstrapPhase.Idle,
23
24
  });
24
25
  const smRef = useRef(null);
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ const storeRef = useRef(undefined);
25
28
  const cfgRef = useRef(config);
26
29
  cfgRef.current = config;
30
+ const schemaRef = useRef(schema);
31
+ schemaRef.current = schema;
32
+ const extensionsRef = useRef(extensions);
33
+ extensionsRef.current = extensions;
27
34
  // Detect bfcache restores. When a tab is duplicated (or the user navigates
28
35
  // back/forward) the browser may restore the page from its back/forward cache
29
36
  // (bfcache). In that case the JS heap is frozen and thawed — React effects do
@@ -60,6 +67,15 @@ export function SyncProvider({ config, context, children, fallback, }) {
60
67
  if (contextRef.current !== undefined) {
61
68
  sm.setContext(contextRef.current);
62
69
  }
70
+ // createStore registers schema entities into ModelRegistry — must
71
+ // run before bootstrap() so the first fetch sees them.
72
+ if (schemaRef.current != null) {
73
+ storeRef.current = createStore({
74
+ schema: schemaRef.current,
75
+ storeManager: sm,
76
+ extensions: extensionsRef.current,
77
+ });
78
+ }
63
79
  smRef.current = sm;
64
80
  sm.bootstrap().catch((err) => {
65
81
  if (active) {
@@ -70,6 +86,7 @@ export function SyncProvider({ config, context, children, fallback, }) {
70
86
  active = false;
71
87
  sm.teardown();
72
88
  smRef.current = null;
89
+ storeRef.current = undefined;
73
90
  };
74
91
  }, [cfgRef.current.workspaceId]);
75
92
  // Push context updates synchronously so an event handler dispatched in the
@@ -87,7 +104,7 @@ export function SyncProvider({ config, context, children, fallback, }) {
87
104
  fallback != null) {
88
105
  return _jsx(_Fragment, { children: fallback });
89
106
  }
90
- return (_jsx(SyncContext.Provider, { value: { sm: smRef.current, status }, children: children }));
107
+ return (_jsx(SyncContext.Provider, { value: { sm: smRef.current, status, store: storeRef.current }, children: children }));
91
108
  }
92
109
  // ---------------------------------------------------------------------------
93
110
  // Core hook
@@ -102,6 +119,14 @@ export function useSyncEngine() {
102
119
  export function useBootstrapStatus() {
103
120
  return useSyncEngine().status;
104
121
  }
122
+ /** Read the schema-first store from context — `useStore<typeof schema>()`. */
123
+ export function useStore() {
124
+ const ctx = useSyncEngine();
125
+ if (ctx.store == null) {
126
+ throw new Error("useStore() requires <SyncProvider schema={…}>.");
127
+ }
128
+ return ctx.store;
129
+ }
105
130
  /** Subscribe to a model type's pool changes and read a snapshot synchronously.
106
131
  *
107
132
  * `getSnapshot` is intentionally NOT stabilized — useSyncExternalStore calls
@@ -328,23 +353,6 @@ function useStableCallback(callback) {
328
353
  }, [callback]);
329
354
  return stableRef.current;
330
355
  }
331
- // ---------------------------------------------------------------------------
332
- // Public read hooks — keyed by a "handle"
333
- //
334
- // A handle is either a schema namespace (`store.issue`) or a decorator
335
- // model class (`Issue`). Both resolve to a registry name; the record type
336
- // is inferred from whichever form was passed, so the same four hooks serve
337
- // both authoring paths with one vocabulary:
338
- //
339
- // useRecord(handle, id) → AsyncResource<T | null>
340
- // useRecords(handle, ids?) → AsyncResource<T[]>
341
- // useRecordsByIndex(handle, key, v|v[]) → AsyncResource<T[]>
342
- // useRelation(record.relation) → AsyncResource<T[] | T | null>
343
- //
344
- // For namespace handles the index key is constrained to the schema's
345
- // `.indexed()` fields; for class handles it's `string`.
346
- // ---------------------------------------------------------------------------
347
- import { entityNamespaceRegistryName, } from "../schema/createStore";
348
356
  function handleRegistryName(handle) {
349
357
  if (typeof handle === "function") {
350
358
  // Set by @ClientModel (explicit { name } or ctor.name fallback).
@@ -1,4 +1,4 @@
1
- import type { AnyFieldBuilder, AnyLinkDef, EntityDef, FieldBuilder, FieldMeta, LinkDef, SchemaDef } from "./types";
1
+ import type { AnyFieldBuilder, AnyLinkDef, EntityDef, FieldBuilder, FieldMeta, LinkDef, SchemaDef } from "./types.js";
2
2
  export declare function rebuildFieldBuilder<T, M extends FieldMeta>(meta: M): FieldBuilder<T, M>;
3
3
  export declare const fields: {
4
4
  id: () => FieldBuilder<string, FieldMeta & {
@@ -1,4 +1,4 @@
1
- import { dateDeserializer, dateSerializer } from "../core/serializers";
1
+ import { dateDeserializer, dateSerializer } from "../core/serializers.js";
2
2
  function makeBuilder(meta) {
3
3
  return {
4
4
  meta,
@@ -1,4 +1,4 @@
1
- import type { SchemaDef } from "./types";
1
+ import type { SchemaDef } from "./types.js";
2
2
  export interface CompiledSchema {
3
3
  /** Registry names of every entity that was compiled. */
4
4
  modelNames: readonly string[];
@@ -1,9 +1,9 @@
1
- import { BaseModel } from "../core/BaseModel";
2
- import { hashString } from "../core/hash";
3
- import { ModelRegistry } from "../core/ModelRegistry";
4
- import { defineObservableProperty } from "../core/observability";
5
- import { installCollectionAccessor, installReferenceAccessor, } from "../core/refAccessors";
6
- import { PropertyType } from "../core/types";
1
+ import { BaseModel } from "../core/BaseModel.js";
2
+ import { hashString } from "../core/hash.js";
3
+ import { ModelRegistry } from "../core/ModelRegistry.js";
4
+ import { defineObservableProperty } from "../core/observability.js";
5
+ import { installCollectionAccessor, installReferenceAccessor, } from "../core/refAccessors.js";
6
+ import { PropertyType } from "../core/types.js";
7
7
  /**
8
8
  * Compile a `SchemaDef` produced by `defineSchema(...)` into the existing
9
9
  * `ModelRegistry`. Each schema entity becomes a synthetic `BaseModel`
@@ -1,8 +1,8 @@
1
- import type { StoreManager } from "../core/StoreManager";
2
- import type { UndoResult } from "../core/TransactionQueue";
3
- import type { ExtensionDescriptor, MergedExtensionMembers } from "./extend";
4
- import type { EntityKey, IndexedFieldKeys, InferCreateInput, InferEntity, InferUpdateInput } from "./infer";
5
- import type { SchemaDef } from "./types";
1
+ import type { StoreManager } from "../core/StoreManager.js";
2
+ import type { UndoResult } from "../core/TransactionQueue.js";
3
+ import type { ExtensionDescriptor, MergedExtensionMembers } from "./extend.js";
4
+ import type { EntityKey, IndexedFieldKeys, InferCreateInput, InferEntity, InferUpdateInput } from "./infer.js";
5
+ import type { SchemaDef } from "./types.js";
6
6
  /**
7
7
  * Curated subset of `BaseModel` lifecycle methods we expose on records so
8
8
  * imperative "mutate fields then commit" workflows have a typed path. Keeps
@@ -1,8 +1,8 @@
1
1
  import { action, computed } from "mobx";
2
- import { ModelRegistry } from "../core/ModelRegistry";
3
- import { prop } from "../core/ObjectPool";
4
- import { installActionMethod, installComputedAccessor, } from "../core/refAccessors";
5
- import { compileSchema } from "./compile";
2
+ import { ModelRegistry } from "../core/ModelRegistry.js";
3
+ import { prop } from "../core/ObjectPool.js";
4
+ import { installActionMethod, installComputedAccessor, } from "../core/refAccessors.js";
5
+ import { compileSchema } from "./compile.js";
6
6
  /**
7
7
  * Project a `SchemaDef` over a live `StoreManager`. The runtime values are
8
8
  * `BaseModel` instances that structurally satisfy the inferred record type;
@@ -1,5 +1,5 @@
1
- import type { EntityKey, InferEntity } from "./infer";
2
- import type { SchemaDef } from "./types";
1
+ import type { EntityKey, InferEntity } from "./infer.js";
2
+ import type { SchemaDef } from "./types.js";
3
3
  export type ComputedFn<S extends SchemaDef, K extends EntityKey<S>> = (record: InferEntity<S, K>) => unknown;
4
4
  export type ActionFn<S extends SchemaDef, K extends EntityKey<S>> = (record: InferEntity<S, K>, ...args: never[]) => unknown;
5
5
  export interface ExtensionDef<S extends SchemaDef, K extends EntityKey<S>> {
@@ -1,13 +1,13 @@
1
- export { LoadStrategy } from "../core/types";
2
- export { defineSchema, entity, link, fields } from "./builders";
3
- export { fields as s } from "./builders";
4
- export { compileSchema } from "./compile";
5
- export type { CompiledSchema } from "./compile";
6
- export { createStore } from "./createStore";
7
- export type { EntityStore, EntityNamespace, RecordWithExtensions, StoreApi, } from "./createStore";
8
- export { extend } from "./extend";
9
- export type { ActionFn, ComputedFn, ExtensionDef, ExtensionDescriptor, ExtensionMap, MergedExtensionMembers, } from "./extend";
10
- export { fromZod, entityFromZod } from "./zod";
11
- export type { EntityFromZodFieldOverride, EntityFromZodOpts } from "./zod";
12
- export type { EntityDef, FieldBuilder, FieldKind, FieldMeta, LinkDef, LinkFromSpec, LinkToSpec, OnDelete, SchemaDef, } from "./types";
13
- export type { EntityKey, IndexedFieldKeys, InferCreateInput, InferEntity, InferUpdateInput, RelationCollection, } from "./infer";
1
+ export { LoadStrategy } from "../core/types.js";
2
+ export { defineSchema, entity, link, fields } from "./builders.js";
3
+ export { fields as s } from "./builders.js";
4
+ export { compileSchema } from "./compile.js";
5
+ export type { CompiledSchema } from "./compile.js";
6
+ export { createStore } from "./createStore.js";
7
+ export type { EntityStore, EntityNamespace, RecordWithExtensions, StoreApi, } from "./createStore.js";
8
+ export { extend } from "./extend.js";
9
+ export type { ActionFn, ComputedFn, ExtensionDef, ExtensionDescriptor, ExtensionMap, MergedExtensionMembers, } from "./extend.js";
10
+ export { fromZod, entityFromZod, entitiesFromZod } from "./zod.js";
11
+ export type { EntityFromZodFieldOverride, EntityFromZodOpts } from "./zod.js";
12
+ export type { EntityDef, FieldBuilder, FieldKind, FieldMeta, LinkDef, LinkFromSpec, LinkToSpec, OnDelete, SchemaDef, } from "./types.js";
13
+ export type { EntityKey, IndexedFieldKeys, InferCreateInput, InferEntity, InferRecord, InferUpdateInput, RelationCollection, } from "./infer.js";
@@ -1,8 +1,8 @@
1
1
  // Public schema-authoring surface. See agent-docs/RFC-schema-first-authoring.md.
2
- export { LoadStrategy } from "../core/types";
3
- export { defineSchema, entity, link, fields } from "./builders";
4
- export { fields as s } from "./builders";
5
- export { compileSchema } from "./compile";
6
- export { createStore } from "./createStore";
7
- export { extend } from "./extend";
8
- export { fromZod, entityFromZod } from "./zod";
2
+ export { LoadStrategy } from "../core/types.js";
3
+ export { defineSchema, entity, link, fields } from "./builders.js";
4
+ export { fields as s } from "./builders.js";
5
+ export { compileSchema } from "./compile.js";
6
+ export { createStore } from "./createStore.js";
7
+ export { extend } from "./extend.js";
8
+ export { fromZod, entityFromZod, entitiesFromZod } from "./zod.js";
@@ -1,4 +1,4 @@
1
- import type { EntityDef, FieldBuilder, FieldMeta, SchemaDef } from "./types";
1
+ import type { EntityDef, FieldBuilder, FieldMeta, SchemaDef } from "./types.js";
2
2
  type FieldType<F> = F extends FieldBuilder<infer T, FieldMeta> ? T : never;
3
3
  type FieldIsNullable<F> = null extends FieldType<F> ? true : false;
4
4
  type FieldIsIndexed<F> = F extends FieldBuilder<unknown, infer M> ? M extends {
@@ -81,6 +81,15 @@ type ReverseCollections<S extends SchemaDef, K extends EntityKey<S>> = {
81
81
  * with a one-line helper at the call site if they want.
82
82
  */
83
83
  export type InferEntity<S extends SchemaDef, K extends EntityKey<S>> = EntityFieldTypes<S, K> & SingularRelations<S, K> & ReverseCollections<S, K>;
84
+ /**
85
+ * Alias for {@link InferEntity}. Provided so the three record-shape helpers
86
+ * read uniformly at call sites:
87
+ *
88
+ * type Need = InferRecord<typeof schema, "need">;
89
+ * type NeedCreate = InferCreateInput<typeof schema, "need">;
90
+ * type NeedUpdate = InferUpdateInput<typeof schema, "need">;
91
+ */
92
+ export type InferRecord<S extends SchemaDef, K extends EntityKey<S>> = InferEntity<S, K>;
84
93
  /**
85
94
  * A create-input field is optional when the runtime can fill it without
86
95
  * the caller: id-kind (BaseModel auto-assigns a UUID), defaulted fields,
@@ -1,4 +1,4 @@
1
- import type { LoadStrategy, OnDelete } from "../core/types";
1
+ import type { LoadStrategy, OnDelete } from "../core/types.js";
2
2
  export type FieldKind = "id" | "string" | "number" | "boolean" | "date" | "json" | "refId";
3
3
  export interface FieldMeta {
4
4
  kind: FieldKind;