syncorejs 0.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 (227) hide show
  1. package/README.md +30 -0
  2. package/dist/_vendor/core/_virtual/_rolldown/runtime.mjs +27 -0
  3. package/dist/_vendor/core/cli.d.mts +5 -0
  4. package/dist/_vendor/core/cli.d.mts.map +1 -0
  5. package/dist/_vendor/core/cli.mjs +1196 -0
  6. package/dist/_vendor/core/cli.mjs.map +1 -0
  7. package/dist/_vendor/core/index.d.mts +7 -0
  8. package/dist/_vendor/core/index.mjs +25 -0
  9. package/dist/_vendor/core/index.mjs.map +1 -0
  10. package/dist/_vendor/core/runtime/devtools.d.mts +15 -0
  11. package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -0
  12. package/dist/_vendor/core/runtime/devtools.mjs +300 -0
  13. package/dist/_vendor/core/runtime/devtools.mjs.map +1 -0
  14. package/dist/_vendor/core/runtime/functions.d.mts +123 -0
  15. package/dist/_vendor/core/runtime/functions.d.mts.map +1 -0
  16. package/dist/_vendor/core/runtime/functions.mjs +71 -0
  17. package/dist/_vendor/core/runtime/functions.mjs.map +1 -0
  18. package/dist/_vendor/core/runtime/id.d.mts +13 -0
  19. package/dist/_vendor/core/runtime/id.d.mts.map +1 -0
  20. package/dist/_vendor/core/runtime/id.mjs +28 -0
  21. package/dist/_vendor/core/runtime/id.mjs.map +1 -0
  22. package/dist/_vendor/core/runtime/runtime.d.mts +370 -0
  23. package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -0
  24. package/dist/_vendor/core/runtime/runtime.mjs +1143 -0
  25. package/dist/_vendor/core/runtime/runtime.mjs.map +1 -0
  26. package/dist/_vendor/devtools-protocol/index.d.ts +230 -0
  27. package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -0
  28. package/dist/_vendor/devtools-protocol/index.js +0 -0
  29. package/dist/_vendor/next/config.d.ts +17 -0
  30. package/dist/_vendor/next/config.d.ts.map +1 -0
  31. package/dist/_vendor/next/config.js +73 -0
  32. package/dist/_vendor/next/config.js.map +1 -0
  33. package/dist/_vendor/next/index.d.ts +80 -0
  34. package/dist/_vendor/next/index.d.ts.map +1 -0
  35. package/dist/_vendor/next/index.js +81 -0
  36. package/dist/_vendor/next/index.js.map +1 -0
  37. package/dist/_vendor/platform-expo/index.d.ts +97 -0
  38. package/dist/_vendor/platform-expo/index.d.ts.map +1 -0
  39. package/dist/_vendor/platform-expo/index.js +197 -0
  40. package/dist/_vendor/platform-expo/index.js.map +1 -0
  41. package/dist/_vendor/platform-expo/react.d.ts +26 -0
  42. package/dist/_vendor/platform-expo/react.d.ts.map +1 -0
  43. package/dist/_vendor/platform-expo/react.js +30 -0
  44. package/dist/_vendor/platform-expo/react.js.map +1 -0
  45. package/dist/_vendor/platform-node/index.d.mts +145 -0
  46. package/dist/_vendor/platform-node/index.d.mts.map +1 -0
  47. package/dist/_vendor/platform-node/index.mjs +405 -0
  48. package/dist/_vendor/platform-node/index.mjs.map +1 -0
  49. package/dist/_vendor/platform-node/ipc-react.d.mts +25 -0
  50. package/dist/_vendor/platform-node/ipc-react.d.mts.map +1 -0
  51. package/dist/_vendor/platform-node/ipc-react.mjs +21 -0
  52. package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -0
  53. package/dist/_vendor/platform-node/ipc.d.mts +75 -0
  54. package/dist/_vendor/platform-node/ipc.d.mts.map +1 -0
  55. package/dist/_vendor/platform-node/ipc.mjs +343 -0
  56. package/dist/_vendor/platform-node/ipc.mjs.map +1 -0
  57. package/dist/_vendor/platform-web/index.d.ts +123 -0
  58. package/dist/_vendor/platform-web/index.d.ts.map +1 -0
  59. package/dist/_vendor/platform-web/index.js +309 -0
  60. package/dist/_vendor/platform-web/index.js.map +1 -0
  61. package/dist/_vendor/platform-web/indexeddb.d.ts +25 -0
  62. package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -0
  63. package/dist/_vendor/platform-web/indexeddb.js +125 -0
  64. package/dist/_vendor/platform-web/indexeddb.js.map +1 -0
  65. package/dist/_vendor/platform-web/opfs.d.ts +27 -0
  66. package/dist/_vendor/platform-web/opfs.d.ts.map +1 -0
  67. package/dist/_vendor/platform-web/opfs.js +146 -0
  68. package/dist/_vendor/platform-web/opfs.js.map +1 -0
  69. package/dist/_vendor/platform-web/persistence.d.ts +27 -0
  70. package/dist/_vendor/platform-web/persistence.d.ts.map +1 -0
  71. package/dist/_vendor/platform-web/persistence.js +23 -0
  72. package/dist/_vendor/platform-web/persistence.js.map +1 -0
  73. package/dist/_vendor/platform-web/react.d.ts +35 -0
  74. package/dist/_vendor/platform-web/react.d.ts.map +1 -0
  75. package/dist/_vendor/platform-web/react.js +42 -0
  76. package/dist/_vendor/platform-web/react.js.map +1 -0
  77. package/dist/_vendor/platform-web/sqljs.js +133 -0
  78. package/dist/_vendor/platform-web/sqljs.js.map +1 -0
  79. package/dist/_vendor/platform-web/worker.d.ts +78 -0
  80. package/dist/_vendor/platform-web/worker.d.ts.map +1 -0
  81. package/dist/_vendor/platform-web/worker.js +307 -0
  82. package/dist/_vendor/platform-web/worker.js.map +1 -0
  83. package/dist/_vendor/react/index.d.ts +58 -0
  84. package/dist/_vendor/react/index.d.ts.map +1 -0
  85. package/dist/_vendor/react/index.js +151 -0
  86. package/dist/_vendor/react/index.js.map +1 -0
  87. package/dist/_vendor/schema/definition.d.ts +98 -0
  88. package/dist/_vendor/schema/definition.d.ts.map +1 -0
  89. package/dist/_vendor/schema/definition.js +84 -0
  90. package/dist/_vendor/schema/definition.js.map +1 -0
  91. package/dist/_vendor/schema/index.d.ts +4 -0
  92. package/dist/_vendor/schema/index.js +4 -0
  93. package/dist/_vendor/schema/planner.d.ts +42 -0
  94. package/dist/_vendor/schema/planner.d.ts.map +1 -0
  95. package/dist/_vendor/schema/planner.js +131 -0
  96. package/dist/_vendor/schema/planner.js.map +1 -0
  97. package/dist/_vendor/schema/validators.d.ts +194 -0
  98. package/dist/_vendor/schema/validators.d.ts.map +1 -0
  99. package/dist/_vendor/schema/validators.js +158 -0
  100. package/dist/_vendor/schema/validators.js.map +1 -0
  101. package/dist/_vendor/svelte/index.d.ts +43 -0
  102. package/dist/_vendor/svelte/index.d.ts.map +1 -0
  103. package/dist/_vendor/svelte/index.js +75 -0
  104. package/dist/_vendor/svelte/index.js.map +1 -0
  105. package/dist/browser-react.d.ts +2 -0
  106. package/dist/browser-react.js +2 -0
  107. package/dist/browser.d.ts +12 -0
  108. package/dist/browser.d.ts.map +1 -0
  109. package/dist/browser.js +10 -0
  110. package/dist/browser.js.map +1 -0
  111. package/dist/cli.d.ts +2 -0
  112. package/dist/cli.js +11 -0
  113. package/dist/cli.js.map +1 -0
  114. package/dist/core/src/cli.d.ts +5 -0
  115. package/dist/core/src/cli.d.ts.map +1 -0
  116. package/dist/core/src/cli.js +1196 -0
  117. package/dist/core/src/cli.js.map +1 -0
  118. package/dist/core/src/index.js +7 -0
  119. package/dist/core/src/runtime/devtools.d.ts +7 -0
  120. package/dist/core/src/runtime/devtools.d.ts.map +1 -0
  121. package/dist/core/src/runtime/devtools.js +300 -0
  122. package/dist/core/src/runtime/devtools.js.map +1 -0
  123. package/dist/core/src/runtime/functions.d.ts +123 -0
  124. package/dist/core/src/runtime/functions.d.ts.map +1 -0
  125. package/dist/core/src/runtime/functions.js +71 -0
  126. package/dist/core/src/runtime/functions.js.map +1 -0
  127. package/dist/core/src/runtime/id.d.ts +13 -0
  128. package/dist/core/src/runtime/id.d.ts.map +1 -0
  129. package/dist/core/src/runtime/id.js +28 -0
  130. package/dist/core/src/runtime/id.js.map +1 -0
  131. package/dist/core/src/runtime/runtime.d.ts +371 -0
  132. package/dist/core/src/runtime/runtime.d.ts.map +1 -0
  133. package/dist/core/src/runtime/runtime.js +1143 -0
  134. package/dist/core/src/runtime/runtime.js.map +1 -0
  135. package/dist/devtools-protocol/src/index.d.ts +201 -0
  136. package/dist/devtools-protocol/src/index.d.ts.map +1 -0
  137. package/dist/expo-react.d.ts +2 -0
  138. package/dist/expo-react.js +2 -0
  139. package/dist/expo.d.ts +2 -0
  140. package/dist/expo.js +2 -0
  141. package/dist/index.d.ts +7 -0
  142. package/dist/index.js +8 -0
  143. package/dist/next/src/config.d.ts +17 -0
  144. package/dist/next/src/config.d.ts.map +1 -0
  145. package/dist/next/src/config.js +73 -0
  146. package/dist/next/src/config.js.map +1 -0
  147. package/dist/next/src/index.d.ts +80 -0
  148. package/dist/next/src/index.d.ts.map +1 -0
  149. package/dist/next/src/index.js +82 -0
  150. package/dist/next/src/index.js.map +1 -0
  151. package/dist/next-config.d.ts +2 -0
  152. package/dist/next-config.js +2 -0
  153. package/dist/next.d.ts +3 -0
  154. package/dist/next.js +3 -0
  155. package/dist/node-ipc-react.d.ts +2 -0
  156. package/dist/node-ipc-react.js +2 -0
  157. package/dist/node-ipc.d.ts +2 -0
  158. package/dist/node-ipc.js +2 -0
  159. package/dist/node.d.ts +4 -0
  160. package/dist/node.js +3 -0
  161. package/dist/platform-expo/src/index.d.ts +96 -0
  162. package/dist/platform-expo/src/index.d.ts.map +1 -0
  163. package/dist/platform-expo/src/index.js +198 -0
  164. package/dist/platform-expo/src/index.js.map +1 -0
  165. package/dist/platform-expo/src/react.d.ts +26 -0
  166. package/dist/platform-expo/src/react.d.ts.map +1 -0
  167. package/dist/platform-expo/src/react.js +30 -0
  168. package/dist/platform-expo/src/react.js.map +1 -0
  169. package/dist/platform-node/src/index.d.ts +145 -0
  170. package/dist/platform-node/src/index.d.ts.map +1 -0
  171. package/dist/platform-node/src/index.js +407 -0
  172. package/dist/platform-node/src/index.js.map +1 -0
  173. package/dist/platform-node/src/ipc-react.d.ts +25 -0
  174. package/dist/platform-node/src/ipc-react.d.ts.map +1 -0
  175. package/dist/platform-node/src/ipc-react.js +21 -0
  176. package/dist/platform-node/src/ipc-react.js.map +1 -0
  177. package/dist/platform-node/src/ipc.d.ts +76 -0
  178. package/dist/platform-node/src/ipc.d.ts.map +1 -0
  179. package/dist/platform-node/src/ipc.js +344 -0
  180. package/dist/platform-node/src/ipc.js.map +1 -0
  181. package/dist/platform-web/src/index.d.ts +106 -0
  182. package/dist/platform-web/src/index.d.ts.map +1 -0
  183. package/dist/platform-web/src/index.js +311 -0
  184. package/dist/platform-web/src/index.js.map +1 -0
  185. package/dist/platform-web/src/indexeddb.js +125 -0
  186. package/dist/platform-web/src/indexeddb.js.map +1 -0
  187. package/dist/platform-web/src/opfs.js +146 -0
  188. package/dist/platform-web/src/opfs.js.map +1 -0
  189. package/dist/platform-web/src/persistence.d.ts +20 -0
  190. package/dist/platform-web/src/persistence.d.ts.map +1 -0
  191. package/dist/platform-web/src/persistence.js +23 -0
  192. package/dist/platform-web/src/persistence.js.map +1 -0
  193. package/dist/platform-web/src/react.d.ts +35 -0
  194. package/dist/platform-web/src/react.d.ts.map +1 -0
  195. package/dist/platform-web/src/react.js +42 -0
  196. package/dist/platform-web/src/react.js.map +1 -0
  197. package/dist/platform-web/src/sqljs.js +133 -0
  198. package/dist/platform-web/src/sqljs.js.map +1 -0
  199. package/dist/platform-web/src/worker.d.ts +79 -0
  200. package/dist/platform-web/src/worker.d.ts.map +1 -0
  201. package/dist/platform-web/src/worker.js +308 -0
  202. package/dist/platform-web/src/worker.js.map +1 -0
  203. package/dist/react/src/index.d.ts +59 -0
  204. package/dist/react/src/index.d.ts.map +1 -0
  205. package/dist/react/src/index.js +151 -0
  206. package/dist/react/src/index.js.map +1 -0
  207. package/dist/react.d.ts +2 -0
  208. package/dist/react.js +2 -0
  209. package/dist/schema/src/definition.d.ts +98 -0
  210. package/dist/schema/src/definition.d.ts.map +1 -0
  211. package/dist/schema/src/definition.js +84 -0
  212. package/dist/schema/src/definition.js.map +1 -0
  213. package/dist/schema/src/planner.d.ts +42 -0
  214. package/dist/schema/src/planner.d.ts.map +1 -0
  215. package/dist/schema/src/planner.js +131 -0
  216. package/dist/schema/src/planner.js.map +1 -0
  217. package/dist/schema/src/validators.d.ts +194 -0
  218. package/dist/schema/src/validators.d.ts.map +1 -0
  219. package/dist/schema/src/validators.js +158 -0
  220. package/dist/schema/src/validators.js.map +1 -0
  221. package/dist/svelte/src/index.d.ts +44 -0
  222. package/dist/svelte/src/index.d.ts.map +1 -0
  223. package/dist/svelte/src/index.js +75 -0
  224. package/dist/svelte/src/index.js.map +1 -0
  225. package/dist/svelte.d.ts +2 -0
  226. package/dist/svelte.js +2 -0
  227. package/package.json +152 -0
@@ -0,0 +1,309 @@
1
+ import { SyncoreIndexedDbPersistence } from "./indexeddb.js";
2
+ import { SyncoreOpfsPersistence } from "./opfs.js";
3
+ import { createWebPersistence, isOpfsAvailable } from "./persistence.js";
4
+ import { SqlJsDriver } from "./sqljs.js";
5
+ import { SyncoreWebWorkerClient, attachWebWorkerRuntime, createManagedWebWorkerClient, createSyncoreWebWorkerClient, createWebWorkerClient } from "./worker.js";
6
+ import { SyncoreRuntime, createDevtoolsRequestHandler } from "../core/index.mjs";
7
+ //#region src/index.ts
8
+ /**
9
+ * Create a full Syncore runtime directly in the browser.
10
+ *
11
+ * Most React apps should use a worker runtime instead so queries and SQLite work
12
+ * stay off the main thread.
13
+ */
14
+ async function createWebSyncoreRuntime(options) {
15
+ const persistence = options.persistence ?? await createWebPersistence({
16
+ ...options.persistenceMode ? { mode: options.persistenceMode } : {},
17
+ ...options.persistenceDatabaseName ? { indexedDbDatabaseName: options.persistenceDatabaseName } : {},
18
+ opfsRootDirectoryName: options.opfsRootDirectoryName ?? options.databaseName ?? "syncore"
19
+ });
20
+ const driver = options.driver ?? await SqlJsDriver.create({
21
+ databaseName: options.databaseName ?? "syncore",
22
+ persistence,
23
+ ...options.wasmUrl ? { wasmUrl: options.wasmUrl } : {},
24
+ ...options.locateFile ? { locateFile: options.locateFile } : {}
25
+ });
26
+ const storage = options.storage ?? new BrowserFileStorageAdapter(persistence, options.storageNamespace ?? options.databaseName ?? "syncore");
27
+ const appName = resolveWebAppName();
28
+ const origin = resolveWebOrigin();
29
+ const sessionLabel = resolveWebSessionLabel();
30
+ const autoDevtools = options.devtools === void 0 && shouldAutoConnectDevtools() ? (() => {
31
+ const sinkOptions = { url: resolveDefaultDevtoolsUrl() };
32
+ if (appName) sinkOptions.appName = appName;
33
+ if (origin) sinkOptions.origin = origin;
34
+ if (sessionLabel) sinkOptions.sessionLabel = sessionLabel;
35
+ return createBrowserWebSocketDevtoolsSink(sinkOptions);
36
+ })() : void 0;
37
+ const resolvedDevtools = options.devtools === false ? void 0 : options.devtools ?? autoDevtools;
38
+ const runtime = new SyncoreRuntime({
39
+ schema: options.schema,
40
+ functions: options.functions,
41
+ driver,
42
+ storage,
43
+ platform: options.platform ?? "browser",
44
+ ...options.capabilities ? { capabilities: options.capabilities } : {},
45
+ ...resolvedDevtools ? { devtools: resolvedDevtools } : {},
46
+ ...options.experimentalPlugins ? { experimentalPlugins: options.experimentalPlugins } : {},
47
+ ...options.scheduler ? { scheduler: options.scheduler } : {}
48
+ });
49
+ if (autoDevtools) {
50
+ autoDevtools.attachRuntime(() => runtime.getDevtoolsSnapshot());
51
+ autoDevtools.attachRequestHandler(createDevtoolsRequestHandler({
52
+ driver,
53
+ schema: options.schema,
54
+ functions: options.functions,
55
+ runtime
56
+ }));
57
+ }
58
+ return runtime;
59
+ }
60
+ /**
61
+ * Attach a Syncore runtime to a browser Worker endpoint.
62
+ */
63
+ function createWebWorkerRuntime(options) {
64
+ return attachWebWorkerRuntime({
65
+ endpoint: options.endpoint,
66
+ createRuntime: () => createWebSyncoreRuntime(options)
67
+ });
68
+ }
69
+ /**
70
+ * Attach a Syncore runtime to a browser Worker endpoint.
71
+ */
72
+ function createBrowserWorkerRuntime(options) {
73
+ return createWebWorkerRuntime(options);
74
+ }
75
+ /**
76
+ * Create a client directly from a browser Syncore runtime.
77
+ */
78
+ function createWebSyncoreClient(runtime) {
79
+ return runtime.createClient();
80
+ }
81
+ /**
82
+ * Create a full Syncore runtime directly in the browser.
83
+ */
84
+ function createBrowserSyncoreRuntime(options) {
85
+ return createWebSyncoreRuntime(options);
86
+ }
87
+ /**
88
+ * Create a client directly from a browser Syncore runtime.
89
+ */
90
+ function createBrowserSyncoreClient(runtime) {
91
+ return createWebSyncoreClient(runtime);
92
+ }
93
+ function createBrowserWebSocketDevtoolsSink(options) {
94
+ let socket;
95
+ let disposed = false;
96
+ let connectTimer;
97
+ let getSnapshot;
98
+ let onRequest;
99
+ const pendingMessages = [];
100
+ let latestHello;
101
+ const connect = () => {
102
+ if (disposed || typeof WebSocket === "undefined") return;
103
+ socket = new WebSocket(options.url);
104
+ socket.onopen = () => {
105
+ if (latestHello) sendNow({
106
+ type: "hello",
107
+ runtimeId: latestHello.runtimeId,
108
+ platform: latestHello.platform,
109
+ ...options.appName ? { appName: options.appName } : {},
110
+ ...options.origin ? { origin: options.origin } : {},
111
+ ...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {}
112
+ });
113
+ if (getSnapshot) sendNow({
114
+ type: "snapshot",
115
+ snapshot: withSnapshotMeta(getSnapshot(), options)
116
+ });
117
+ flushPendingMessages();
118
+ };
119
+ socket.onmessage = (event) => {
120
+ if (typeof event.data !== "string") return;
121
+ const message = JSON.parse(event.data);
122
+ if (message.type === "ping") send({ type: "pong" });
123
+ else if (message.type === "request" && onRequest) onRequest(message.payload).then((responsePayload) => {
124
+ const runtimeId = latestHello?.runtimeId ?? getSnapshot?.().runtimeId;
125
+ if (!runtimeId) return;
126
+ send({
127
+ type: "response",
128
+ requestId: message.requestId,
129
+ runtimeId,
130
+ payload: responsePayload
131
+ });
132
+ }).catch((err) => {
133
+ const runtimeId = latestHello?.runtimeId ?? getSnapshot?.().runtimeId;
134
+ if (!runtimeId) return;
135
+ send({
136
+ type: "response",
137
+ requestId: message.requestId,
138
+ runtimeId,
139
+ payload: {
140
+ kind: "error",
141
+ message: err instanceof Error ? err.message : "Unknown error"
142
+ }
143
+ });
144
+ });
145
+ };
146
+ socket.onclose = scheduleReconnect;
147
+ socket.onerror = () => {
148
+ socket?.close();
149
+ };
150
+ };
151
+ const scheduleReconnect = () => {
152
+ if (disposed || connectTimer) return;
153
+ connectTimer = setTimeout(() => {
154
+ connectTimer = void 0;
155
+ connect();
156
+ }, options.reconnectDelayMs ?? 1200);
157
+ };
158
+ const sendNow = (message) => {
159
+ if (socket?.readyState === WebSocket.OPEN) socket.send(JSON.stringify(message));
160
+ };
161
+ const flushPendingMessages = () => {
162
+ while (pendingMessages.length > 0) {
163
+ const nextMessage = pendingMessages.shift();
164
+ if (nextMessage) sendNow(nextMessage);
165
+ }
166
+ };
167
+ const send = (message) => {
168
+ if (socket?.readyState === WebSocket.OPEN) {
169
+ sendNow(message);
170
+ return;
171
+ }
172
+ pendingMessages.push(message);
173
+ };
174
+ connect();
175
+ return {
176
+ emit(event) {
177
+ if (event.type === "runtime.connected") {
178
+ latestHello = {
179
+ runtimeId: event.runtimeId,
180
+ platform: event.platform
181
+ };
182
+ send({
183
+ type: "hello",
184
+ runtimeId: event.runtimeId,
185
+ platform: event.platform,
186
+ ...options.appName ? { appName: options.appName } : {},
187
+ ...options.origin ? { origin: options.origin } : {},
188
+ ...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {}
189
+ });
190
+ }
191
+ send({
192
+ type: "event",
193
+ event
194
+ });
195
+ if (getSnapshot) send({
196
+ type: "snapshot",
197
+ snapshot: withSnapshotMeta(getSnapshot(), options)
198
+ });
199
+ },
200
+ attachRuntime(snapshotGetter) {
201
+ getSnapshot = snapshotGetter;
202
+ if (socket?.readyState === WebSocket.OPEN) send({
203
+ type: "snapshot",
204
+ snapshot: withSnapshotMeta(getSnapshot(), options)
205
+ });
206
+ },
207
+ attachRequestHandler(handler) {
208
+ onRequest = handler;
209
+ },
210
+ dispose() {
211
+ disposed = true;
212
+ if (connectTimer) clearTimeout(connectTimer);
213
+ socket?.close();
214
+ }
215
+ };
216
+ }
217
+ function withSnapshotMeta(snapshot, options) {
218
+ return {
219
+ ...snapshot,
220
+ ...options.appName ? { appName: options.appName } : {},
221
+ ...options.origin ? { origin: options.origin } : {},
222
+ ...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {}
223
+ };
224
+ }
225
+ function shouldAutoConnectDevtools() {
226
+ if (typeof globalThis === "undefined") return false;
227
+ try {
228
+ return globalThis.location?.hostname === "localhost" || globalThis.location?.hostname === "127.0.0.1" ? true : Boolean(globalThis.location?.hostname?.endsWith?.(".local"));
229
+ } catch {
230
+ return false;
231
+ }
232
+ }
233
+ function resolveDefaultDevtoolsUrl() {
234
+ return "ws://127.0.0.1:4311";
235
+ }
236
+ function resolveWebOrigin() {
237
+ try {
238
+ return globalThis.location?.origin;
239
+ } catch {
240
+ return;
241
+ }
242
+ }
243
+ function resolveWebAppName() {
244
+ try {
245
+ return globalThis.location?.hostname ?? globalThis.document?.title ?? void 0;
246
+ } catch {
247
+ return;
248
+ }
249
+ }
250
+ function resolveWebSessionLabel() {
251
+ try {
252
+ if (typeof navigator === "undefined") return;
253
+ return navigator.userAgent.includes("Firefox") ? "Firefox" : navigator.userAgent.includes("Chrome") ? "Chrome" : navigator.userAgent.includes("Safari") ? "Safari" : navigator.userAgent;
254
+ } catch {
255
+ return;
256
+ }
257
+ }
258
+ /**
259
+ * Browser file/blob storage built on top of Syncore web persistence.
260
+ */
261
+ var BrowserFileStorageAdapter = class {
262
+ constructor(persistence, namespace) {
263
+ this.persistence = persistence;
264
+ this.namespace = namespace;
265
+ }
266
+ async put(id, input) {
267
+ const bytes = normalizeBinary(input.data);
268
+ await this.persistence.putFile(this.namespace, id, bytes, input.contentType ?? null);
269
+ return {
270
+ id,
271
+ path: `${this.persistence.storageProtocol}://${this.namespace}/${id}`,
272
+ size: bytes.byteLength,
273
+ contentType: input.contentType ?? null
274
+ };
275
+ }
276
+ async get(id) {
277
+ const file = await this.persistence.getFile(this.namespace, id);
278
+ if (!file) return null;
279
+ return {
280
+ id,
281
+ path: `${this.persistence.storageProtocol}://${this.namespace}/${id}`,
282
+ size: file.size,
283
+ contentType: file.contentType
284
+ };
285
+ }
286
+ async read(id) {
287
+ return (await this.persistence.getFile(this.namespace, id))?.bytes ?? null;
288
+ }
289
+ async delete(id) {
290
+ await this.persistence.deleteFile(this.namespace, id);
291
+ }
292
+ async list() {
293
+ return (await this.persistence.listFiles(this.namespace)).map((file) => ({
294
+ id: file.id,
295
+ path: `${this.persistence.storageProtocol}://${this.namespace}/${file.id}`,
296
+ size: file.size,
297
+ contentType: file.contentType
298
+ }));
299
+ }
300
+ };
301
+ function normalizeBinary(data) {
302
+ if (typeof data === "string") return new TextEncoder().encode(data);
303
+ if (data instanceof Uint8Array) return data;
304
+ return new Uint8Array(data);
305
+ }
306
+ //#endregion
307
+ export { BrowserFileStorageAdapter, SyncoreIndexedDbPersistence, SyncoreOpfsPersistence, SyncoreWebWorkerClient, attachWebWorkerRuntime, createBrowserSyncoreClient, createBrowserSyncoreRuntime, createBrowserWebSocketDevtoolsSink, createBrowserWorkerRuntime, createManagedWebWorkerClient, createSyncoreWebWorkerClient, createWebPersistence, createWebSyncoreClient, createWebSyncoreRuntime, createWebWorkerClient, createWebWorkerRuntime, isOpfsAvailable };
308
+
309
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n type AnySyncoreSchema,\n createDevtoolsRequestHandler,\n type DevtoolsRequestHandler,\n type DevtoolsSink,\n SyncoreRuntime,\n type SchedulerOptions,\n type SyncoreCapabilities,\n type SyncoreExperimentalPlugin,\n type SyncoreRuntimeOptions,\n type SyncoreStorageAdapter,\n type StorageObject,\n type StorageWriteInput\n} from \"@syncore/core\";\nimport {\n type SyncoreDevtoolsMessage,\n type SyncoreDevtoolsRequest,\n type SyncoreDevtoolsSnapshot\n} from \"@syncore/devtools-protocol\";\nimport {\n createWebPersistence,\n type SyncoreWebPersistence,\n type WebPersistenceMode\n} from \"./persistence.js\";\nimport { SqlJsDriver } from \"./sqljs.js\";\nimport {\n attachWebWorkerRuntime,\n type SyncoreWorkerMessageEndpoint\n} from \"./worker.js\";\nexport * from \"./worker.js\";\nexport * from \"./persistence.js\";\nexport * from \"./indexeddb.js\";\nexport * from \"./opfs.js\";\n\nexport type WebSyncoreSchema = AnySyncoreSchema;\nexport type BrowserSyncoreSchema = WebSyncoreSchema;\n\n/**\n * Options for constructing a browser Syncore runtime.\n *\n * Use this when you want to host the full runtime in a browser tab or worker.\n */\nexport interface CreateWebRuntimeOptions {\n /** The schema for the local Syncore app. */\n schema: WebSyncoreSchema;\n\n /** The generated function registry for the local Syncore app. */\n functions: SyncoreRuntimeOptions<WebSyncoreSchema>[\"functions\"];\n\n /** Optional platform capabilities exposed to function handlers. */\n capabilities?: SyncoreCapabilities;\n\n /** Optional custom SQL driver. Defaults to SQL.js with local persistence. */\n driver?: SyncoreRuntimeOptions<WebSyncoreSchema>[\"driver\"];\n\n /** Optional custom file/blob storage adapter. */\n storage?: SyncoreStorageAdapter;\n\n /** Optional experimental plugins for runtime hooks. */\n experimentalPlugins?: Array<SyncoreExperimentalPlugin<WebSyncoreSchema>>;\n\n /** Optional explicit persistence implementation. */\n persistence?: SyncoreWebPersistence;\n\n /** Which browser persistence mode to use when Syncore creates one for you. */\n persistenceMode?: WebPersistenceMode;\n\n /** Logical database name for SQL.js and local storage namespaces. */\n databaseName?: string;\n\n /** Optional IndexedDB database name for persistence metadata. */\n persistenceDatabaseName?: string;\n\n /** Optional OPFS directory name for persistent files. */\n opfsRootDirectoryName?: string;\n\n /** Optional namespace for file/blob storage. */\n storageNamespace?: string;\n\n /** Optional direct wasm URL for SQL.js. */\n wasmUrl?: string;\n\n /** Optional callback for resolving SQL.js support files. */\n locateFile?: (fileName: string) => string;\n\n /** Optional runtime platform label shown in devtools snapshots. */\n platform?: string;\n\n /** Optional devtools sink used during development. */\n devtools?: DevtoolsSink | false;\n\n /** Optional scheduler configuration for jobs and recurring work. */\n scheduler?: SchedulerOptions;\n}\n\n/**\n * Options for hosting a Syncore runtime inside a browser Worker.\n */\nexport interface CreateWebWorkerRuntimeOptions extends CreateWebRuntimeOptions {\n /** The message endpoint exposed by the current worker global. */\n endpoint: SyncoreWorkerMessageEndpoint;\n}\n\n/**\n * Options for constructing a browser Syncore runtime.\n */\nexport type CreateBrowserRuntimeOptions = CreateWebRuntimeOptions;\n\n/**\n * Options for hosting a Syncore runtime inside a browser Worker.\n */\nexport type CreateBrowserWorkerRuntimeOptions = CreateWebWorkerRuntimeOptions;\n\n/**\n * Create a full Syncore runtime directly in the browser.\n *\n * Most React apps should use a worker runtime instead so queries and SQLite work\n * stay off the main thread.\n */\nexport async function createWebSyncoreRuntime(\n options: CreateWebRuntimeOptions\n): Promise<SyncoreRuntime<WebSyncoreSchema>> {\n const persistence =\n options.persistence ??\n (await createWebPersistence({\n ...(options.persistenceMode ? { mode: options.persistenceMode } : {}),\n ...(options.persistenceDatabaseName\n ? { indexedDbDatabaseName: options.persistenceDatabaseName }\n : {}),\n opfsRootDirectoryName:\n options.opfsRootDirectoryName ?? options.databaseName ?? \"syncore\"\n }));\n const driver =\n options.driver ??\n (await SqlJsDriver.create({\n databaseName: options.databaseName ?? \"syncore\",\n persistence,\n ...(options.wasmUrl ? { wasmUrl: options.wasmUrl } : {}),\n ...(options.locateFile ? { locateFile: options.locateFile } : {})\n }));\n const storage =\n options.storage ??\n new BrowserFileStorageAdapter(\n persistence,\n options.storageNamespace ?? options.databaseName ?? \"syncore\"\n );\n const appName = resolveWebAppName();\n const origin = resolveWebOrigin();\n const sessionLabel = resolveWebSessionLabel();\n const autoDevtools =\n options.devtools === undefined && shouldAutoConnectDevtools()\n ? (() => {\n const sinkOptions: BrowserWebSocketDevtoolsSinkOptions = {\n url: resolveDefaultDevtoolsUrl()\n };\n if (appName) {\n sinkOptions.appName = appName;\n }\n if (origin) {\n sinkOptions.origin = origin;\n }\n if (sessionLabel) {\n sinkOptions.sessionLabel = sessionLabel;\n }\n return createBrowserWebSocketDevtoolsSink(sinkOptions);\n })()\n : undefined;\n const resolvedDevtools =\n options.devtools === false ? undefined : (options.devtools ?? autoDevtools);\n\n const runtime = new SyncoreRuntime({\n schema: options.schema,\n functions: options.functions,\n driver,\n storage,\n platform: options.platform ?? \"browser\",\n ...(options.capabilities ? { capabilities: options.capabilities } : {}),\n ...(resolvedDevtools ? { devtools: resolvedDevtools } : {}),\n ...(options.experimentalPlugins\n ? { experimentalPlugins: options.experimentalPlugins }\n : {}),\n ...(options.scheduler ? { scheduler: options.scheduler } : {})\n });\n\n if (autoDevtools) {\n autoDevtools.attachRuntime(() => runtime.getDevtoolsSnapshot());\n autoDevtools.attachRequestHandler(\n createDevtoolsRequestHandler({\n driver,\n schema: options.schema,\n functions: options.functions,\n runtime\n })\n );\n }\n\n return runtime;\n}\n\n/**\n * Attach a Syncore runtime to a browser Worker endpoint.\n */\nexport function createWebWorkerRuntime(options: CreateWebWorkerRuntimeOptions) {\n return attachWebWorkerRuntime({\n endpoint: options.endpoint,\n createRuntime: () => createWebSyncoreRuntime(options)\n });\n}\n\n/**\n * Attach a Syncore runtime to a browser Worker endpoint.\n */\nexport function createBrowserWorkerRuntime(\n options: CreateBrowserWorkerRuntimeOptions\n) {\n return createWebWorkerRuntime(options);\n}\n\n/**\n * Create a client directly from a browser Syncore runtime.\n */\nexport function createWebSyncoreClient(\n runtime: SyncoreRuntime<WebSyncoreSchema>\n) {\n return runtime.createClient();\n}\n\n/**\n * Create a full Syncore runtime directly in the browser.\n */\nexport function createBrowserSyncoreRuntime(\n options: CreateBrowserRuntimeOptions\n) {\n return createWebSyncoreRuntime(options);\n}\n\n/**\n * Create a client directly from a browser Syncore runtime.\n */\nexport function createBrowserSyncoreClient(\n runtime: SyncoreRuntime<BrowserSyncoreSchema>\n) {\n return createWebSyncoreClient(runtime);\n}\n\nexport interface BrowserWebSocketDevtoolsSinkOptions {\n url: string;\n reconnectDelayMs?: number;\n appName?: string;\n origin?: string;\n sessionLabel?: string;\n}\n\nexport interface BrowserWebSocketDevtoolsSink extends DevtoolsSink {\n attachRuntime(getSnapshot: () => SyncoreDevtoolsSnapshot): void;\n attachRequestHandler(handler: DevtoolsRequestHandler): void;\n dispose(): void;\n}\n\nexport function createBrowserWebSocketDevtoolsSink(\n options: BrowserWebSocketDevtoolsSinkOptions\n): BrowserWebSocketDevtoolsSink {\n let socket: WebSocket | undefined;\n let disposed = false;\n let connectTimer: ReturnType<typeof setTimeout> | undefined;\n let getSnapshot: (() => SyncoreDevtoolsSnapshot) | undefined;\n let onRequest: DevtoolsRequestHandler | undefined;\n const pendingMessages: SyncoreDevtoolsMessage[] = [];\n let latestHello:\n | {\n runtimeId: string;\n platform: string;\n }\n | undefined;\n\n const connect = () => {\n if (disposed || typeof WebSocket === \"undefined\") {\n return;\n }\n socket = new WebSocket(options.url);\n socket.onopen = () => {\n if (latestHello) {\n sendNow({\n type: \"hello\",\n runtimeId: latestHello.runtimeId,\n platform: latestHello.platform,\n ...(options.appName ? { appName: options.appName } : {}),\n ...(options.origin ? { origin: options.origin } : {}),\n ...(options.sessionLabel\n ? { sessionLabel: options.sessionLabel }\n : {})\n });\n }\n if (getSnapshot) {\n sendNow({\n type: \"snapshot\",\n snapshot: withSnapshotMeta(getSnapshot(), options)\n });\n }\n flushPendingMessages();\n };\n socket.onmessage = (event) => {\n if (typeof event.data !== \"string\") {\n return;\n }\n const message = JSON.parse(event.data) as\n | SyncoreDevtoolsMessage\n | SyncoreDevtoolsRequest;\n if (message.type === \"ping\") {\n send({ type: \"pong\" });\n } else if (message.type === \"request\" && onRequest) {\n onRequest(message.payload)\n .then((responsePayload) => {\n const runtimeId =\n latestHello?.runtimeId ?? getSnapshot?.().runtimeId;\n if (!runtimeId) {\n return;\n }\n send({\n type: \"response\",\n requestId: message.requestId,\n runtimeId,\n payload: responsePayload\n });\n })\n .catch((err) => {\n const runtimeId =\n latestHello?.runtimeId ?? getSnapshot?.().runtimeId;\n if (!runtimeId) {\n return;\n }\n send({\n type: \"response\",\n requestId: message.requestId,\n runtimeId,\n payload: {\n kind: \"error\",\n message: err instanceof Error ? err.message : \"Unknown error\"\n }\n });\n });\n }\n };\n socket.onclose = scheduleReconnect;\n socket.onerror = () => {\n socket?.close();\n };\n };\n\n const scheduleReconnect = () => {\n if (disposed || connectTimer) {\n return;\n }\n connectTimer = setTimeout(() => {\n connectTimer = undefined;\n connect();\n }, options.reconnectDelayMs ?? 1200);\n };\n\n const sendNow = (message: SyncoreDevtoolsMessage) => {\n if (socket?.readyState === WebSocket.OPEN) {\n socket.send(JSON.stringify(message));\n }\n };\n\n const flushPendingMessages = () => {\n while (pendingMessages.length > 0) {\n const nextMessage = pendingMessages.shift();\n if (nextMessage) {\n sendNow(nextMessage);\n }\n }\n };\n\n const send = (message: SyncoreDevtoolsMessage) => {\n if (socket?.readyState === WebSocket.OPEN) {\n sendNow(message);\n return;\n }\n pendingMessages.push(message);\n };\n\n connect();\n\n return {\n emit(event) {\n if (event.type === \"runtime.connected\") {\n latestHello = {\n runtimeId: event.runtimeId,\n platform: event.platform\n };\n send({\n type: \"hello\",\n runtimeId: event.runtimeId,\n platform: event.platform,\n ...(options.appName ? { appName: options.appName } : {}),\n ...(options.origin ? { origin: options.origin } : {}),\n ...(options.sessionLabel\n ? { sessionLabel: options.sessionLabel }\n : {})\n });\n }\n send({ type: \"event\", event });\n if (getSnapshot) {\n send({\n type: \"snapshot\",\n snapshot: withSnapshotMeta(getSnapshot(), options)\n });\n }\n },\n attachRuntime(snapshotGetter) {\n getSnapshot = snapshotGetter;\n if (socket?.readyState === WebSocket.OPEN) {\n send({\n type: \"snapshot\",\n snapshot: withSnapshotMeta(getSnapshot(), options)\n });\n }\n },\n attachRequestHandler(handler) {\n onRequest = handler;\n },\n dispose() {\n disposed = true;\n if (connectTimer) {\n clearTimeout(connectTimer);\n }\n socket?.close();\n }\n };\n}\n\nfunction withSnapshotMeta(\n snapshot: SyncoreDevtoolsSnapshot,\n options: BrowserWebSocketDevtoolsSinkOptions\n): SyncoreDevtoolsSnapshot {\n return {\n ...snapshot,\n ...(options.appName ? { appName: options.appName } : {}),\n ...(options.origin ? { origin: options.origin } : {}),\n ...(options.sessionLabel ? { sessionLabel: options.sessionLabel } : {})\n };\n}\n\nfunction shouldAutoConnectDevtools(): boolean {\n if (typeof globalThis === \"undefined\") {\n return false;\n }\n try {\n return globalThis.location?.hostname === \"localhost\" ||\n globalThis.location?.hostname === \"127.0.0.1\"\n ? true\n : Boolean(globalThis.location?.hostname?.endsWith?.(\".local\"));\n } catch {\n return false;\n }\n}\n\nfunction resolveDefaultDevtoolsUrl(): string {\n return \"ws://127.0.0.1:4311\";\n}\n\nfunction resolveWebOrigin(): string | undefined {\n try {\n return globalThis.location?.origin;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveWebAppName(): string | undefined {\n try {\n return (\n globalThis.location?.hostname ?? globalThis.document?.title ?? undefined\n );\n } catch {\n return undefined;\n }\n}\n\nfunction resolveWebSessionLabel(): string | undefined {\n try {\n if (typeof navigator === \"undefined\") {\n return undefined;\n }\n return navigator.userAgent.includes(\"Firefox\")\n ? \"Firefox\"\n : navigator.userAgent.includes(\"Chrome\")\n ? \"Chrome\"\n : navigator.userAgent.includes(\"Safari\")\n ? \"Safari\"\n : navigator.userAgent;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Browser file/blob storage built on top of Syncore web persistence.\n */\nexport class BrowserFileStorageAdapter implements SyncoreStorageAdapter {\n constructor(\n private readonly persistence: SyncoreWebPersistence,\n private readonly namespace: string\n ) {}\n\n async put(id: string, input: StorageWriteInput): Promise<StorageObject> {\n const bytes = normalizeBinary(input.data);\n await this.persistence.putFile(\n this.namespace,\n id,\n bytes,\n input.contentType ?? null\n );\n return {\n id,\n path: `${this.persistence.storageProtocol}://${this.namespace}/${id}`,\n size: bytes.byteLength,\n contentType: input.contentType ?? null\n };\n }\n\n async get(id: string): Promise<StorageObject | null> {\n const file = await this.persistence.getFile(this.namespace, id);\n if (!file) {\n return null;\n }\n return {\n id,\n path: `${this.persistence.storageProtocol}://${this.namespace}/${id}`,\n size: file.size,\n contentType: file.contentType\n };\n }\n\n async read(id: string): Promise<Uint8Array | null> {\n const file = await this.persistence.getFile(this.namespace, id);\n return file?.bytes ?? null;\n }\n\n async delete(id: string): Promise<void> {\n await this.persistence.deleteFile(this.namespace, id);\n }\n\n async list(): Promise<StorageObject[]> {\n const files = await this.persistence.listFiles(this.namespace);\n return files.map((file) => ({\n id: file.id,\n path: `${this.persistence.storageProtocol}://${this.namespace}/${file.id}`,\n size: file.size,\n contentType: file.contentType\n }));\n }\n}\n\nfunction normalizeBinary(data: StorageWriteInput[\"data\"]): Uint8Array {\n if (typeof data === \"string\") {\n return new TextEncoder().encode(data);\n }\n if (data instanceof Uint8Array) {\n return data;\n }\n return new Uint8Array(data);\n}\n"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { StoredWebFile, SyncoreWebPersistence } from "./persistence.js";
2
+
3
+ //#region src/indexeddb.d.ts
4
+ interface IndexedDbPersistenceOptions {
5
+ databaseName?: string;
6
+ }
7
+ declare class SyncoreIndexedDbPersistence implements SyncoreWebPersistence {
8
+ readonly storageProtocol: "idb";
9
+ private readonly databaseName;
10
+ constructor(options?: IndexedDbPersistenceOptions);
11
+ loadDatabase(key: string): Promise<Uint8Array | null>;
12
+ saveDatabase(key: string, bytes: Uint8Array): Promise<void>;
13
+ getFile(namespace: string, id: string): Promise<StoredWebFile | null>;
14
+ putFile(namespace: string, id: string, bytes: Uint8Array, contentType: string | null): Promise<void>;
15
+ deleteFile(namespace: string, id: string): Promise<void>;
16
+ listFiles(namespace: string): Promise<StoredWebFile[]>;
17
+ private getDatabase;
18
+ private getRecord;
19
+ private putRecord;
20
+ private deleteRecord;
21
+ private listRecords;
22
+ }
23
+ //#endregion
24
+ export { IndexedDbPersistenceOptions, SyncoreIndexedDbPersistence };
25
+ //# sourceMappingURL=indexeddb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb.d.ts","names":[],"sources":["../src/indexeddb.ts"],"mappings":";;;UAEiB,2BAAA;EACf,YAAA;AAAA;AAAA,cAiBW,2BAAA,YAAuC,qBAAA;EAAA,SACzC,eAAA;EAAA,iBACQ,YAAA;cAEL,OAAA,GAAU,2BAAA;EAIhB,YAAA,CAAa,GAAA,WAAc,OAAA,CAAQ,UAAA;EAQnC,YAAA,CAAa,GAAA,UAAa,KAAA,EAAO,UAAA,GAAa,OAAA;EAQ9C,OAAA,CACJ,SAAA,UACA,EAAA,WACC,OAAA,CAAQ,aAAA;EAgBL,OAAA,CACJ,SAAA,UACA,EAAA,UACA,KAAA,EAAO,UAAA,EACP,WAAA,kBACC,OAAA;EAUG,UAAA,CAAW,SAAA,UAAmB,EAAA,WAAa,OAAA;EAI3C,SAAA,CAAU,SAAA,WAAoB,OAAA,CAAQ,aAAA;EAAA,QAa9B,WAAA;EAAA,QAuBA,SAAA;EAAA,QAkBA,SAAA;EAAA,QAkBA,YAAA;EAAA,QAkBA,WAAA;AAAA"}
@@ -0,0 +1,125 @@
1
+ //#region src/indexeddb.ts
2
+ var SyncoreIndexedDbPersistence = class {
3
+ storageProtocol = "idb";
4
+ databaseName;
5
+ constructor(options) {
6
+ this.databaseName = options?.databaseName ?? "syncore-web";
7
+ }
8
+ async loadDatabase(key) {
9
+ const record = await this.getRecord("databases", key);
10
+ if (!record) return null;
11
+ return new Uint8Array(record.bytes);
12
+ }
13
+ async saveDatabase(key, bytes) {
14
+ await this.putRecord("databases", {
15
+ key,
16
+ bytes: sliceToArrayBuffer(bytes),
17
+ updatedAt: Date.now()
18
+ });
19
+ }
20
+ async getFile(namespace, id) {
21
+ const record = await this.getRecord("files", createNamespacedKey(namespace, id));
22
+ if (!record) return null;
23
+ return {
24
+ id,
25
+ bytes: new Uint8Array(record.bytes),
26
+ contentType: record.contentType,
27
+ size: record.size
28
+ };
29
+ }
30
+ async putFile(namespace, id, bytes, contentType) {
31
+ await this.putRecord("files", {
32
+ key: createNamespacedKey(namespace, id),
33
+ bytes: sliceToArrayBuffer(bytes),
34
+ contentType,
35
+ size: bytes.byteLength,
36
+ updatedAt: Date.now()
37
+ });
38
+ }
39
+ async deleteFile(namespace, id) {
40
+ await this.deleteRecord("files", createNamespacedKey(namespace, id));
41
+ }
42
+ async listFiles(namespace) {
43
+ const prefix = `${namespace}:`;
44
+ return (await this.listRecords("files")).filter((record) => record.key.startsWith(prefix)).map((record) => ({
45
+ id: record.key.slice(prefix.length),
46
+ bytes: new Uint8Array(record.bytes),
47
+ contentType: record.contentType,
48
+ size: record.size
49
+ }));
50
+ }
51
+ async getDatabase() {
52
+ const indexedDb = globalThis.indexedDB;
53
+ if (!indexedDb) throw new Error("IndexedDB is not available in this environment.");
54
+ return new Promise((resolve, reject) => {
55
+ const request = indexedDb.open(this.databaseName, 1);
56
+ request.onupgradeneeded = () => {
57
+ const database = request.result;
58
+ if (!database.objectStoreNames.contains("databases")) database.createObjectStore("databases", { keyPath: "key" });
59
+ if (!database.objectStoreNames.contains("files")) database.createObjectStore("files", { keyPath: "key" });
60
+ };
61
+ request.onsuccess = () => resolve(request.result);
62
+ request.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error("Failed to open IndexedDB."));
63
+ });
64
+ }
65
+ async getRecord(storeName, key) {
66
+ const database = await this.getDatabase();
67
+ try {
68
+ return await new Promise((resolve, reject) => {
69
+ const request = database.transaction(storeName, "readonly").objectStore(storeName).get(key);
70
+ request.onsuccess = () => resolve(request.result ?? null);
71
+ request.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error(`Failed to read ${storeName}/${key}.`));
72
+ });
73
+ } finally {
74
+ database.close();
75
+ }
76
+ }
77
+ async putRecord(storeName, record) {
78
+ const database = await this.getDatabase();
79
+ try {
80
+ await new Promise((resolve, reject) => {
81
+ const transaction = database.transaction(storeName, "readwrite");
82
+ transaction.oncomplete = () => resolve();
83
+ transaction.onerror = () => reject(transaction.error ?? /* @__PURE__ */ new Error(`Failed to write ${storeName}/${record.key}.`));
84
+ transaction.objectStore(storeName).put(record);
85
+ });
86
+ } finally {
87
+ database.close();
88
+ }
89
+ }
90
+ async deleteRecord(storeName, key) {
91
+ const database = await this.getDatabase();
92
+ try {
93
+ await new Promise((resolve, reject) => {
94
+ const transaction = database.transaction(storeName, "readwrite");
95
+ transaction.oncomplete = () => resolve();
96
+ transaction.onerror = () => reject(transaction.error ?? /* @__PURE__ */ new Error(`Failed to delete ${storeName}/${key}.`));
97
+ transaction.objectStore(storeName).delete(key);
98
+ });
99
+ } finally {
100
+ database.close();
101
+ }
102
+ }
103
+ async listRecords(storeName) {
104
+ const database = await this.getDatabase();
105
+ try {
106
+ return await new Promise((resolve, reject) => {
107
+ const request = database.transaction(storeName, "readonly").objectStore(storeName).getAll();
108
+ request.onsuccess = () => resolve(request.result ?? []);
109
+ request.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error(`Failed to list records from ${storeName}.`));
110
+ });
111
+ } finally {
112
+ database.close();
113
+ }
114
+ }
115
+ };
116
+ function createNamespacedKey(namespace, id) {
117
+ return `${namespace}:${id}`;
118
+ }
119
+ function sliceToArrayBuffer(bytes) {
120
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
121
+ }
122
+ //#endregion
123
+ export { SyncoreIndexedDbPersistence };
124
+
125
+ //# sourceMappingURL=indexeddb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb.js","names":[],"sources":["../src/indexeddb.ts"],"sourcesContent":["import type { SyncoreWebPersistence, StoredWebFile } from \"./persistence.js\";\r\n\r\nexport interface IndexedDbPersistenceOptions {\r\n databaseName?: string;\r\n}\r\n\r\ntype StoredDatabaseRecord = {\r\n key: string;\r\n bytes: ArrayBuffer;\r\n updatedAt: number;\r\n};\r\n\r\ntype StoredFileRecord = {\r\n key: string;\r\n bytes: ArrayBuffer;\r\n contentType: string | null;\r\n size: number;\r\n updatedAt: number;\r\n};\r\n\r\nexport class SyncoreIndexedDbPersistence implements SyncoreWebPersistence {\r\n readonly storageProtocol = \"idb\" as const;\r\n private readonly databaseName: string;\r\n\r\n constructor(options?: IndexedDbPersistenceOptions) {\r\n this.databaseName = options?.databaseName ?? \"syncore-web\";\r\n }\r\n\r\n async loadDatabase(key: string): Promise<Uint8Array | null> {\r\n const record = await this.getRecord<StoredDatabaseRecord>(\"databases\", key);\r\n if (!record) {\r\n return null;\r\n }\r\n return new Uint8Array(record.bytes);\r\n }\r\n\r\n async saveDatabase(key: string, bytes: Uint8Array): Promise<void> {\r\n await this.putRecord<StoredDatabaseRecord>(\"databases\", {\r\n key,\r\n bytes: sliceToArrayBuffer(bytes),\r\n updatedAt: Date.now()\r\n });\r\n }\r\n\r\n async getFile(\r\n namespace: string,\r\n id: string\r\n ): Promise<StoredWebFile | null> {\r\n const record = await this.getRecord<StoredFileRecord>(\r\n \"files\",\r\n createNamespacedKey(namespace, id)\r\n );\r\n if (!record) {\r\n return null;\r\n }\r\n return {\r\n id,\r\n bytes: new Uint8Array(record.bytes),\r\n contentType: record.contentType,\r\n size: record.size\r\n };\r\n }\r\n\r\n async putFile(\r\n namespace: string,\r\n id: string,\r\n bytes: Uint8Array,\r\n contentType: string | null\r\n ): Promise<void> {\r\n await this.putRecord<StoredFileRecord>(\"files\", {\r\n key: createNamespacedKey(namespace, id),\r\n bytes: sliceToArrayBuffer(bytes),\r\n contentType,\r\n size: bytes.byteLength,\r\n updatedAt: Date.now()\r\n });\r\n }\r\n\r\n async deleteFile(namespace: string, id: string): Promise<void> {\r\n await this.deleteRecord(\"files\", createNamespacedKey(namespace, id));\r\n }\r\n\r\n async listFiles(namespace: string): Promise<StoredWebFile[]> {\r\n const prefix = `${namespace}:`;\r\n const records = await this.listRecords<StoredFileRecord>(\"files\");\r\n return records\r\n .filter((record) => record.key.startsWith(prefix))\r\n .map((record) => ({\r\n id: record.key.slice(prefix.length),\r\n bytes: new Uint8Array(record.bytes),\r\n contentType: record.contentType,\r\n size: record.size\r\n }));\r\n }\r\n\r\n private async getDatabase(): Promise<IDBDatabase> {\r\n const indexedDb = globalThis.indexedDB;\r\n if (!indexedDb) {\r\n throw new Error(\"IndexedDB is not available in this environment.\");\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDb.open(this.databaseName, 1);\r\n request.onupgradeneeded = () => {\r\n const database = request.result;\r\n if (!database.objectStoreNames.contains(\"databases\")) {\r\n database.createObjectStore(\"databases\", { keyPath: \"key\" });\r\n }\r\n if (!database.objectStoreNames.contains(\"files\")) {\r\n database.createObjectStore(\"files\", { keyPath: \"key\" });\r\n }\r\n };\r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () =>\r\n reject(request.error ?? new Error(\"Failed to open IndexedDB.\"));\r\n });\r\n }\r\n\r\n private async getRecord<TRecord>(\r\n storeName: \"databases\" | \"files\",\r\n key: string\r\n ): Promise<TRecord | null> {\r\n const database = await this.getDatabase();\r\n try {\r\n return await new Promise<TRecord | null>((resolve, reject) => {\r\n const transaction = database.transaction(storeName, \"readonly\");\r\n const request = transaction.objectStore(storeName).get(key);\r\n request.onsuccess = () => resolve((request.result as TRecord | undefined) ?? null);\r\n request.onerror = () =>\r\n reject(request.error ?? new Error(`Failed to read ${storeName}/${key}.`));\r\n });\r\n } finally {\r\n database.close();\r\n }\r\n }\r\n\r\n private async putRecord<TRecord extends { key: string }>(\r\n storeName: \"databases\" | \"files\",\r\n record: TRecord\r\n ): Promise<void> {\r\n const database = await this.getDatabase();\r\n try {\r\n await new Promise<void>((resolve, reject) => {\r\n const transaction = database.transaction(storeName, \"readwrite\");\r\n transaction.oncomplete = () => resolve();\r\n transaction.onerror = () =>\r\n reject(transaction.error ?? new Error(`Failed to write ${storeName}/${record.key}.`));\r\n transaction.objectStore(storeName).put(record);\r\n });\r\n } finally {\r\n database.close();\r\n }\r\n }\r\n\r\n private async deleteRecord(\r\n storeName: \"databases\" | \"files\",\r\n key: string\r\n ): Promise<void> {\r\n const database = await this.getDatabase();\r\n try {\r\n await new Promise<void>((resolve, reject) => {\r\n const transaction = database.transaction(storeName, \"readwrite\");\r\n transaction.oncomplete = () => resolve();\r\n transaction.onerror = () =>\r\n reject(transaction.error ?? new Error(`Failed to delete ${storeName}/${key}.`));\r\n transaction.objectStore(storeName).delete(key);\r\n });\r\n } finally {\r\n database.close();\r\n }\r\n }\r\n\r\n private async listRecords<TRecord>(\r\n storeName: \"databases\" | \"files\"\r\n ): Promise<TRecord[]> {\r\n const database = await this.getDatabase();\r\n try {\r\n return await new Promise<TRecord[]>((resolve, reject) => {\r\n const transaction = database.transaction(storeName, \"readonly\");\r\n const request = transaction.objectStore(storeName).getAll();\r\n request.onsuccess = () => resolve((request.result as TRecord[] | undefined) ?? []);\r\n request.onerror = () =>\r\n reject(request.error ?? new Error(`Failed to list records from ${storeName}.`));\r\n });\r\n } finally {\r\n database.close();\r\n }\r\n }\r\n}\r\n\r\nfunction createNamespacedKey(namespace: string, id: string): string {\r\n return `${namespace}:${id}`;\r\n}\r\n\r\nfunction sliceToArrayBuffer(bytes: Uint8Array): ArrayBuffer {\r\n return bytes.buffer.slice(\r\n bytes.byteOffset,\r\n bytes.byteOffset + bytes.byteLength\r\n ) as ArrayBuffer;\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { StoredWebFile, SyncoreWebPersistence } from "./persistence.js";
2
+
3
+ //#region src/opfs.d.ts
4
+ interface OpfsPersistenceOptions {
5
+ rootDirectoryName?: string;
6
+ }
7
+ declare class SyncoreOpfsPersistence implements SyncoreWebPersistence {
8
+ private readonly options;
9
+ readonly storageProtocol: "opfs";
10
+ private rootDirectoryPromise;
11
+ constructor(options?: OpfsPersistenceOptions);
12
+ loadDatabase(key: string): Promise<Uint8Array | null>;
13
+ saveDatabase(key: string, bytes: Uint8Array): Promise<void>;
14
+ getFile(namespace: string, id: string): Promise<StoredWebFile | null>;
15
+ putFile(namespace: string, id: string, bytes: Uint8Array, contentType: string | null): Promise<void>;
16
+ deleteFile(namespace: string, id: string): Promise<void>;
17
+ listFiles(namespace: string): Promise<StoredWebFile[]>;
18
+ private ensureDirectory;
19
+ private getOptionalDirectory;
20
+ private getOptionalFileHandle;
21
+ private getOptionalFileHandleFromDirectory;
22
+ private readMetadata;
23
+ private getRootDirectory;
24
+ }
25
+ //#endregion
26
+ export { OpfsPersistenceOptions, SyncoreOpfsPersistence };
27
+ //# sourceMappingURL=opfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opfs.d.ts","names":[],"sources":["../src/opfs.ts"],"mappings":";;;UAEiB,sBAAA;EACf,iBAAA;AAAA;AAAA,cAWW,sBAAA,YAAkC,qBAAA;EAAA,iBAIhB,OAAA;EAAA,SAHpB,eAAA;EAAA,QACD,oBAAA;cAEqB,OAAA,GAAS,sBAAA;EAEhC,YAAA,CAAa,GAAA,WAAc,OAAA,CAAQ,UAAA;EAWnC,YAAA,CAAa,GAAA,UAAa,KAAA,EAAO,UAAA,GAAa,OAAA;EAU9C,OAAA,CAAQ,SAAA,UAAmB,EAAA,WAAa,OAAA,CAAQ,aAAA;EA0BhD,OAAA,CACJ,SAAA,UACA,EAAA,UACA,KAAA,EAAO,UAAA,EACP,WAAA,kBACC,OAAA;EAcG,UAAA,CAAW,SAAA,UAAmB,EAAA,WAAa,OAAA;EAW3C,SAAA,CAAU,SAAA,WAAoB,OAAA,CAAQ,aAAA;EAAA,QA4B9B,eAAA;EAAA,QAUA,oBAAA;EAAA,QAiBA,qBAAA;EAAA,QAWA,kCAAA;EAAA,QAcA,YAAA;EAAA,QAaA,gBAAA;AAAA"}