@procedures/store 0.0.0-stage → 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.
Files changed (115) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +65 -2
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/errors.d.ts +16 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/errors.js +18 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/index.d.ts +19 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +19 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/module.d.ts +23 -0
  14. package/dist/module.d.ts.map +1 -0
  15. package/dist/module.js +26 -0
  16. package/dist/module.js.map +1 -0
  17. package/dist/procedures.d.ts +13 -0
  18. package/dist/procedures.d.ts.map +1 -0
  19. package/dist/procedures.js +14 -0
  20. package/dist/procedures.js.map +1 -0
  21. package/dist/program-store/attach.d.ts +20 -0
  22. package/dist/program-store/attach.d.ts.map +1 -0
  23. package/dist/program-store/attach.js +36 -0
  24. package/dist/program-store/attach.js.map +1 -0
  25. package/dist/program-store/collection.d.ts +19 -0
  26. package/dist/program-store/collection.d.ts.map +1 -0
  27. package/dist/program-store/collection.js +34 -0
  28. package/dist/program-store/collection.js.map +1 -0
  29. package/dist/program-store/file.d.ts +29 -0
  30. package/dist/program-store/file.d.ts.map +1 -0
  31. package/dist/program-store/file.js +156 -0
  32. package/dist/program-store/file.js.map +1 -0
  33. package/dist/program-store/index.d.ts +11 -0
  34. package/dist/program-store/index.d.ts.map +1 -0
  35. package/dist/program-store/index.js +10 -0
  36. package/dist/program-store/index.js.map +1 -0
  37. package/dist/program-store/memory.d.ts +15 -0
  38. package/dist/program-store/memory.d.ts.map +1 -0
  39. package/dist/program-store/memory.js +25 -0
  40. package/dist/program-store/memory.js.map +1 -0
  41. package/dist/program-store/procedures.d.ts +23 -0
  42. package/dist/program-store/procedures.d.ts.map +1 -0
  43. package/dist/program-store/procedures.js +228 -0
  44. package/dist/program-store/procedures.js.map +1 -0
  45. package/dist/program-store/types.d.ts +50 -0
  46. package/dist/program-store/types.d.ts.map +1 -0
  47. package/dist/program-store/types.js +41 -0
  48. package/dist/program-store/types.js.map +1 -0
  49. package/dist/register.d.ts +7 -0
  50. package/dist/register.d.ts.map +1 -0
  51. package/dist/register.js +9 -0
  52. package/dist/register.js.map +1 -0
  53. package/dist/storage/adapter.d.ts +148 -0
  54. package/dist/storage/adapter.d.ts.map +1 -0
  55. package/dist/storage/adapter.js +214 -0
  56. package/dist/storage/adapter.js.map +1 -0
  57. package/dist/storage/api.d.ts +125 -0
  58. package/dist/storage/api.d.ts.map +1 -0
  59. package/dist/storage/api.js +220 -0
  60. package/dist/storage/api.js.map +1 -0
  61. package/dist/storage/factory.d.ts +134 -0
  62. package/dist/storage/factory.d.ts.map +1 -0
  63. package/dist/storage/factory.js +166 -0
  64. package/dist/storage/factory.js.map +1 -0
  65. package/dist/storage/hybrid.d.ts +193 -0
  66. package/dist/storage/hybrid.d.ts.map +1 -0
  67. package/dist/storage/hybrid.js +519 -0
  68. package/dist/storage/hybrid.js.map +1 -0
  69. package/dist/storage/index.d.ts +21 -0
  70. package/dist/storage/index.d.ts.map +1 -0
  71. package/dist/storage/index.js +20 -0
  72. package/dist/storage/index.js.map +1 -0
  73. package/dist/storage/procedures.d.ts +14 -0
  74. package/dist/storage/procedures.d.ts.map +1 -0
  75. package/dist/storage/procedures.js +101 -0
  76. package/dist/storage/procedures.js.map +1 -0
  77. package/dist/storage/serialization.d.ts +123 -0
  78. package/dist/storage/serialization.d.ts.map +1 -0
  79. package/dist/storage/serialization.js +216 -0
  80. package/dist/storage/serialization.js.map +1 -0
  81. package/dist/storage/synced-registry.d.ts +246 -0
  82. package/dist/storage/synced-registry.d.ts.map +1 -0
  83. package/dist/storage/synced-registry.js +575 -0
  84. package/dist/storage/synced-registry.js.map +1 -0
  85. package/dist/storage/types.d.ts +130 -0
  86. package/dist/storage/types.d.ts.map +1 -0
  87. package/dist/storage/types.js +8 -0
  88. package/dist/storage/types.js.map +1 -0
  89. package/dist/types.d.ts +7 -0
  90. package/dist/types.d.ts.map +1 -0
  91. package/dist/types.js +7 -0
  92. package/dist/types.js.map +1 -0
  93. package/package.json +78 -3
  94. package/src/errors.ts +20 -0
  95. package/src/index.ts +19 -0
  96. package/src/module.ts +30 -0
  97. package/src/procedures.ts +17 -0
  98. package/src/program-store/attach.ts +46 -0
  99. package/src/program-store/collection.ts +39 -0
  100. package/src/program-store/file.ts +157 -0
  101. package/src/program-store/index.ts +17 -0
  102. package/src/program-store/memory.ts +30 -0
  103. package/src/program-store/procedures.ts +351 -0
  104. package/src/program-store/types.ts +78 -0
  105. package/src/register.ts +11 -0
  106. package/src/storage/adapter.ts +273 -0
  107. package/src/storage/api.ts +335 -0
  108. package/src/storage/factory.ts +268 -0
  109. package/src/storage/hybrid.ts +676 -0
  110. package/src/storage/index.ts +61 -0
  111. package/src/storage/procedures.ts +149 -0
  112. package/src/storage/serialization.ts +283 -0
  113. package/src/storage/synced-registry.ts +698 -0
  114. package/src/storage/types.ts +180 -0
  115. package/src/types.ts +7 -0
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Synced Procedure Registry
3
+ *
4
+ * Wraps ProcedureRegistry with storage synchronization capabilities.
5
+ * Enables procedure persistence and sync across backends.
6
+ */
7
+ import type { CollectionStorage } from "@procedures/collections";
8
+ import { ProcedureRegistry } from "@procedures/client";
9
+ import type { AnyProcedure, ProcedurePath, RegistrationOptions } from "@procedures/client";
10
+ import type { SerializedProcedure, SyncedRegistryOptions, SyncResult, SyncStatus, SyncDirection, HandlerLoader, HandlerReference } from "./types.js";
11
+ import { ProcedureStorageAdapter } from "./adapter.js";
12
+ /**
13
+ * Extended registration options with persistence flag.
14
+ */
15
+ export interface SyncedRegistrationOptions extends RegistrationOptions {
16
+ /** Whether to persist this procedure to storage (default: true) */
17
+ persist?: boolean | undefined;
18
+ /**
19
+ * The module and export of the handler. The stored record keeps it, so another process can
20
+ * load the handler (with an allowlisted handler loader) when it pulls the record.
21
+ */
22
+ handlerRef?: HandlerReference | undefined;
23
+ }
24
+ /**
25
+ * The synced registry that wraps a registry, if one does. The `procedure.store`, `load`,
26
+ * `sync` and `remote` procedures use it.
27
+ *
28
+ * @param registry - A procedure registry
29
+ * @returns The synced registry of the newest wrapper that is not closed, or undefined
30
+ */
31
+ export declare function getProcedureStore(registry: ProcedureRegistry): SyncedProcedureRegistry | undefined;
32
+ /**
33
+ * Procedure registry with storage synchronization.
34
+ *
35
+ * Wraps an existing ProcedureRegistry and adds:
36
+ * - Automatic persistence on register (write-through/write-back)
37
+ * - Sync from storage on demand
38
+ * - Conflict resolution
39
+ * - Connection management for remote storage
40
+ *
41
+ * A pull compares the `storedAt` of each record with the one of the last sync, and a local
42
+ * change counter for each path. A change on one side only is not a conflict: the changed side
43
+ * wins. A change on both sides (or a path with no sync yet) is a conflict, and the
44
+ * `conflictResolution` option decides. A record with no handler never replaces a procedure
45
+ * that has one: the procedure keeps its handler and takes the record's metadata.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const registry = new SyncedProcedureRegistry(
50
+ * PROCEDURE_REGISTRY,
51
+ * storageAdapter,
52
+ * {
53
+ * writeStrategy: 'write-through',
54
+ * conflictResolution: 'remote',
55
+ * }
56
+ * );
57
+ *
58
+ * // Sync from storage on startup
59
+ * await registry.syncFromStorage();
60
+ *
61
+ * // Register with auto-persistence
62
+ * registry.register(myProcedure, { persist: true });
63
+ *
64
+ * // Manual sync
65
+ * const result = await registry.sync('both');
66
+ * ```
67
+ */
68
+ export declare class SyncedProcedureRegistry {
69
+ private readonly baseRegistry;
70
+ private readonly adapter;
71
+ private readonly options;
72
+ /** Pending changes for write-back strategy */
73
+ private pendingChanges;
74
+ /** Pending deletes for write-back strategy (deep dive DATA-8: they were never deleted) */
75
+ private pendingDeletes;
76
+ /** The handler reference of each path, for the stored records */
77
+ private readonly handlerRefs;
78
+ /** The `storedAt` of the record of each path at its last push or pull */
79
+ private readonly syncedAt;
80
+ /** A counter of local changes for each path, and its value at the last push or pull */
81
+ private readonly localVersion;
82
+ private readonly syncedVersion;
83
+ /** Write-through stores that have not finished */
84
+ private readonly inFlight;
85
+ /** Whether currently connected to remote storage */
86
+ private connected;
87
+ /** Remote endpoint (if connected) */
88
+ private endpoint;
89
+ /** Last sync timestamp */
90
+ private lastSyncTime;
91
+ /** Whether currently syncing */
92
+ private syncing;
93
+ /** Auto-sync interval handle */
94
+ private syncIntervalHandle;
95
+ constructor(baseRegistry: ProcedureRegistry, storage: CollectionStorage<SerializedProcedure>, options?: Partial<SyncedRegistryOptions>);
96
+ /**
97
+ * Register a procedure with optional persistence.
98
+ *
99
+ * The record has the path where the procedure is registered: with a `pathPrefix`, the
100
+ * prefixed path. (Before, the record had the path without the prefix: deep dive CORE-8.)
101
+ *
102
+ * @param procedure - Procedure to register
103
+ * @param options - Registration options including persist flag
104
+ */
105
+ register(procedure: AnyProcedure, options?: SyncedRegistrationOptions): void;
106
+ /**
107
+ * Unregister a procedure. Its record is deleted from storage: now (write-through), or at the
108
+ * next flush (write-back).
109
+ *
110
+ * @param path - Procedure path
111
+ * @returns True if procedure was removed
112
+ */
113
+ unregister(path: ProcedurePath): boolean;
114
+ /**
115
+ * Get a procedure by path.
116
+ */
117
+ get(path: ProcedurePath): AnyProcedure | undefined;
118
+ /**
119
+ * Check if a procedure exists.
120
+ */
121
+ has(path: ProcedurePath): boolean;
122
+ /**
123
+ * Get all registered procedures.
124
+ */
125
+ getAll(): AnyProcedure[];
126
+ /**
127
+ * Get procedures by prefix.
128
+ */
129
+ getByPrefix(prefix: ProcedurePath): AnyProcedure[];
130
+ /**
131
+ * Get count of registered procedures.
132
+ */
133
+ get size(): number;
134
+ /**
135
+ * Sync from storage to registry.
136
+ * Loads procedures from storage and merges with registry.
137
+ *
138
+ * @param filter - Pull only the records for which this function gives true (default: all)
139
+ * @returns Sync result with counts and conflicts
140
+ */
141
+ syncFromStorage(filter?: (record: SerializedProcedure) => boolean): Promise<SyncResult>;
142
+ /**
143
+ * Sync from registry to storage.
144
+ * Persists all registered procedures to storage, each with its handler reference.
145
+ *
146
+ * @returns Sync result
147
+ */
148
+ syncToStorage(): Promise<SyncResult>;
149
+ /**
150
+ * Full bidirectional sync.
151
+ *
152
+ * @param direction - Sync direction (push/pull/both)
153
+ * @returns Sync result
154
+ */
155
+ sync(direction?: SyncDirection): Promise<SyncResult>;
156
+ /**
157
+ * Flush pending changes to storage: the queued writes and deletes of the write-back strategy.
158
+ *
159
+ * @returns The number of records written or deleted
160
+ */
161
+ flushPending(): Promise<number>;
162
+ /**
163
+ * Store the registered procedure at a path now, whatever the write strategy.
164
+ *
165
+ * @param path - Procedure path
166
+ * @param options - A handler reference for the record
167
+ * @returns The stored record, or undefined when no procedure is registered at the path
168
+ */
169
+ storeProcedure(path: ProcedurePath, options?: {
170
+ handlerRef?: HandlerReference | undefined;
171
+ }): Promise<SerializedProcedure | undefined>;
172
+ /**
173
+ * Wait for the write-through writes that have started.
174
+ */
175
+ flushWrites(): Promise<void>;
176
+ /**
177
+ * Record a remote endpoint, and optionally pull from storage. This method does not change the
178
+ * storage: give the registry an `ApiStorage` for the endpoint when you make it.
179
+ *
180
+ * @param endpoint - Remote endpoint URL
181
+ * @param options - Connection options
182
+ */
183
+ connect(endpoint: string, options?: {
184
+ syncOnConnect?: boolean;
185
+ }): Promise<void>;
186
+ /**
187
+ * Disconnect from remote storage.
188
+ */
189
+ disconnect(): void;
190
+ /**
191
+ * Get current sync status.
192
+ */
193
+ getStatus(): SyncStatus;
194
+ /**
195
+ * Start auto-sync at specified interval.
196
+ *
197
+ * @param intervalMs - Sync interval in milliseconds
198
+ */
199
+ startAutoSync(intervalMs: number): void;
200
+ /**
201
+ * Stop auto-sync.
202
+ */
203
+ stopAutoSync(): void;
204
+ /**
205
+ * Resolve a conflict between local and remote procedures.
206
+ *
207
+ * @param path - Procedure path
208
+ * @param local - Local procedure
209
+ * @param remote - Remote procedure
210
+ * @returns Conflict info if not automatically resolved
211
+ */
212
+ private resolveConflict;
213
+ /**
214
+ * The remote version of a procedure. When the remote record gives no handler (a stub), the
215
+ * local handler and schemas stay, and the remote metadata applies.
216
+ */
217
+ private keepHandler;
218
+ /** Record a local change of a path. */
219
+ private touch;
220
+ /** True when the path changed locally since its last push or pull. */
221
+ private isDirty;
222
+ /** Record that storage and the registry agree on a path. */
223
+ private markSynced;
224
+ /** Store records for procedures, each with its handler reference, and mark them synced. */
225
+ private storeRecords;
226
+ /** Delete records, and forget their sync state. */
227
+ private removeRecords;
228
+ private track;
229
+ /**
230
+ * Get the base registry.
231
+ */
232
+ getBaseRegistry(): ProcedureRegistry;
233
+ /**
234
+ * Get the storage adapter.
235
+ */
236
+ getAdapter(): ProcedureStorageAdapter;
237
+ /**
238
+ * Get the handler loader.
239
+ */
240
+ getHandlerLoader(): HandlerLoader | undefined;
241
+ /**
242
+ * Close the synced registry and cleanup resources.
243
+ */
244
+ close(): Promise<void>;
245
+ }
246
+ //# sourceMappingURL=synced-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synced-registry.d.ts","sourceRoot":"","sources":["../../src/storage/synced-registry.ts"],"names":[],"mappings":"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"}