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,146 @@
1
+ //#region src/opfs.ts
2
+ var SyncoreOpfsPersistence = class {
3
+ storageProtocol = "opfs";
4
+ rootDirectoryPromise;
5
+ constructor(options = {}) {
6
+ this.options = options;
7
+ }
8
+ async loadDatabase(key) {
9
+ const handle = await this.getOptionalFileHandle(["databases"], `${encodePathComponent(key)}.sqlite`);
10
+ if (!handle) return null;
11
+ return readFileBytes(handle);
12
+ }
13
+ async saveDatabase(key, bytes) {
14
+ await writeBytes(await (await this.ensureDirectory(["databases"])).getFileHandle(`${encodePathComponent(key)}.sqlite`, { create: true }), bytes);
15
+ }
16
+ async getFile(namespace, id) {
17
+ const directory = await this.getOptionalDirectory(["files", encodePathComponent(namespace)]);
18
+ if (!directory) return null;
19
+ const fileName = `${encodePathComponent(id)}.bin`;
20
+ const metadataName = `${encodePathComponent(id)}.meta.json`;
21
+ const fileHandle = await this.getOptionalFileHandleFromDirectory(directory, fileName);
22
+ if (!fileHandle) return null;
23
+ const [bytes, metadata] = await Promise.all([readFileBytes(fileHandle), this.readMetadata(directory, metadataName)]);
24
+ return {
25
+ id,
26
+ bytes,
27
+ size: bytes.byteLength,
28
+ contentType: metadata?.contentType ?? null
29
+ };
30
+ }
31
+ async putFile(namespace, id, bytes, contentType) {
32
+ const directory = await this.ensureDirectory(["files", encodePathComponent(namespace)]);
33
+ const encodedId = encodePathComponent(id);
34
+ await writeBytes(await directory.getFileHandle(`${encodedId}.bin`, { create: true }), bytes);
35
+ await writeText(await directory.getFileHandle(`${encodedId}.meta.json`, { create: true }), JSON.stringify({ contentType }));
36
+ }
37
+ async deleteFile(namespace, id) {
38
+ const directory = await this.getOptionalDirectory(["files", encodePathComponent(namespace)]);
39
+ if (!directory) return;
40
+ const encodedId = encodePathComponent(id);
41
+ await removeEntryIfExists(directory, `${encodedId}.bin`);
42
+ await removeEntryIfExists(directory, `${encodedId}.meta.json`);
43
+ }
44
+ async listFiles(namespace) {
45
+ const directory = await this.getOptionalDirectory(["files", encodePathComponent(namespace)]);
46
+ if (!directory) return [];
47
+ const files = [];
48
+ const iterableDirectory = directory;
49
+ for await (const [name, handle] of iterableDirectory.entries()) {
50
+ if (handle.kind !== "file" || !name.endsWith(".bin")) continue;
51
+ const encodedId = name.slice(0, -4);
52
+ const id = decodeURIComponent(encodedId);
53
+ const bytes = await readFileBytes(handle);
54
+ const metadata = await this.readMetadata(directory, `${encodedId}.meta.json`);
55
+ files.push({
56
+ id,
57
+ bytes,
58
+ size: bytes.byteLength,
59
+ contentType: metadata?.contentType ?? null
60
+ });
61
+ }
62
+ return files;
63
+ }
64
+ async ensureDirectory(pathSegments) {
65
+ let directory = await this.getRootDirectory();
66
+ for (const segment of pathSegments) directory = await directory.getDirectoryHandle(segment, { create: true });
67
+ return directory;
68
+ }
69
+ async getOptionalDirectory(pathSegments) {
70
+ try {
71
+ let directory = await this.getRootDirectory();
72
+ for (const segment of pathSegments) directory = await directory.getDirectoryHandle(segment);
73
+ return directory;
74
+ } catch (error) {
75
+ if (isNotFoundError(error)) return null;
76
+ throw error;
77
+ }
78
+ }
79
+ async getOptionalFileHandle(pathSegments, fileName) {
80
+ const directory = await this.getOptionalDirectory(pathSegments);
81
+ if (!directory) return null;
82
+ return this.getOptionalFileHandleFromDirectory(directory, fileName);
83
+ }
84
+ async getOptionalFileHandleFromDirectory(directory, fileName) {
85
+ try {
86
+ return await directory.getFileHandle(fileName);
87
+ } catch (error) {
88
+ if (isNotFoundError(error)) return null;
89
+ throw error;
90
+ }
91
+ }
92
+ async readMetadata(directory, fileName) {
93
+ const handle = await this.getOptionalFileHandleFromDirectory(directory, fileName);
94
+ if (!handle) return null;
95
+ const bytes = await readFileBytes(handle);
96
+ return JSON.parse(new TextDecoder().decode(bytes));
97
+ }
98
+ async getRootDirectory() {
99
+ if (!this.rootDirectoryPromise) this.rootDirectoryPromise = (async () => {
100
+ const storageManager = getOpfsStorageManager();
101
+ if (!storageManager?.getDirectory) throw new Error("OPFS is not available in this environment.");
102
+ return (await storageManager.getDirectory()).getDirectoryHandle(this.options.rootDirectoryName ?? "syncore", { create: true });
103
+ })();
104
+ return this.rootDirectoryPromise;
105
+ }
106
+ };
107
+ async function readFileBytes(handle) {
108
+ const file = await handle.getFile();
109
+ return new Uint8Array(await file.arrayBuffer());
110
+ }
111
+ async function writeBytes(handle, bytes) {
112
+ const writable = await handle.createWritable();
113
+ try {
114
+ await writable.write(sliceToArrayBuffer(bytes));
115
+ await writable.truncate(bytes.byteLength);
116
+ } finally {
117
+ await writable.close();
118
+ }
119
+ }
120
+ async function writeText(handle, value) {
121
+ await writeBytes(handle, new TextEncoder().encode(value));
122
+ }
123
+ async function removeEntryIfExists(directory, name) {
124
+ try {
125
+ await directory.removeEntry(name);
126
+ } catch (error) {
127
+ if (!isNotFoundError(error)) throw error;
128
+ }
129
+ }
130
+ function encodePathComponent(value) {
131
+ return encodeURIComponent(value);
132
+ }
133
+ function sliceToArrayBuffer(bytes) {
134
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
135
+ }
136
+ function getOpfsStorageManager() {
137
+ if (typeof navigator === "undefined") return;
138
+ return navigator.storage;
139
+ }
140
+ function isNotFoundError(error) {
141
+ return typeof error === "object" && error !== null && "name" in error && error.name === "NotFoundError";
142
+ }
143
+ //#endregion
144
+ export { SyncoreOpfsPersistence };
145
+
146
+ //# sourceMappingURL=opfs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opfs.js","names":[],"sources":["../src/opfs.ts"],"sourcesContent":["import type { SyncoreWebPersistence, StoredWebFile } from \"./persistence.js\";\r\n\r\nexport interface OpfsPersistenceOptions {\r\n rootDirectoryName?: string;\r\n}\r\n\r\ntype StoredFileMetadata = {\r\n contentType: string | null;\r\n};\r\n\r\ntype OpfsStorageManager = StorageManager & {\r\n getDirectory?: () => Promise<FileSystemDirectoryHandle>;\r\n};\r\n\r\nexport class SyncoreOpfsPersistence implements SyncoreWebPersistence {\r\n readonly storageProtocol = \"opfs\" as const;\r\n private rootDirectoryPromise: Promise<FileSystemDirectoryHandle> | undefined;\r\n\r\n constructor(private readonly options: OpfsPersistenceOptions = {}) {}\r\n\r\n async loadDatabase(key: string): Promise<Uint8Array | null> {\r\n const handle = await this.getOptionalFileHandle(\r\n [\"databases\"],\r\n `${encodePathComponent(key)}.sqlite`\r\n );\r\n if (!handle) {\r\n return null;\r\n }\r\n return readFileBytes(handle);\r\n }\r\n\r\n async saveDatabase(key: string, bytes: Uint8Array): Promise<void> {\r\n const directory = await this.ensureDirectory([\"databases\"]);\r\n await writeBytes(\r\n await directory.getFileHandle(`${encodePathComponent(key)}.sqlite`, {\r\n create: true\r\n }),\r\n bytes\r\n );\r\n }\r\n\r\n async getFile(namespace: string, id: string): Promise<StoredWebFile | null> {\r\n const directory = await this.getOptionalDirectory([\"files\", encodePathComponent(namespace)]);\r\n if (!directory) {\r\n return null;\r\n }\r\n\r\n const fileName = `${encodePathComponent(id)}.bin`;\r\n const metadataName = `${encodePathComponent(id)}.meta.json`;\r\n const fileHandle = await this.getOptionalFileHandleFromDirectory(directory, fileName);\r\n if (!fileHandle) {\r\n return null;\r\n }\r\n\r\n const [bytes, metadata] = await Promise.all([\r\n readFileBytes(fileHandle),\r\n this.readMetadata(directory, metadataName)\r\n ]);\r\n\r\n return {\r\n id,\r\n bytes,\r\n size: bytes.byteLength,\r\n contentType: metadata?.contentType ?? null\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 const directory = await this.ensureDirectory([\"files\", encodePathComponent(namespace)]);\r\n const encodedId = encodePathComponent(id);\r\n\r\n await writeBytes(\r\n await directory.getFileHandle(`${encodedId}.bin`, { create: true }),\r\n bytes\r\n );\r\n await writeText(\r\n await directory.getFileHandle(`${encodedId}.meta.json`, { create: true }),\r\n JSON.stringify({ contentType } satisfies StoredFileMetadata)\r\n );\r\n }\r\n\r\n async deleteFile(namespace: string, id: string): Promise<void> {\r\n const directory = await this.getOptionalDirectory([\"files\", encodePathComponent(namespace)]);\r\n if (!directory) {\r\n return;\r\n }\r\n\r\n const encodedId = encodePathComponent(id);\r\n await removeEntryIfExists(directory, `${encodedId}.bin`);\r\n await removeEntryIfExists(directory, `${encodedId}.meta.json`);\r\n }\r\n\r\n async listFiles(namespace: string): Promise<StoredWebFile[]> {\r\n const directory = await this.getOptionalDirectory([\"files\", encodePathComponent(namespace)]);\r\n if (!directory) {\r\n return [];\r\n }\r\n\r\n const files: StoredWebFile[] = [];\r\n const iterableDirectory = directory as FileSystemDirectoryHandle & {\r\n entries(): AsyncIterable<[string, FileSystemHandle]>;\r\n };\r\n for await (const [name, handle] of iterableDirectory.entries()) {\r\n if (handle.kind !== \"file\" || !name.endsWith(\".bin\")) {\r\n continue;\r\n }\r\n const encodedId = name.slice(0, -4);\r\n const id = decodeURIComponent(encodedId);\r\n const bytes = await readFileBytes(handle as FileSystemFileHandle);\r\n const metadata = await this.readMetadata(directory, `${encodedId}.meta.json`);\r\n files.push({\r\n id,\r\n bytes,\r\n size: bytes.byteLength,\r\n contentType: metadata?.contentType ?? null\r\n });\r\n }\r\n return files;\r\n }\r\n\r\n private async ensureDirectory(\r\n pathSegments: string[]\r\n ): Promise<FileSystemDirectoryHandle> {\r\n let directory = await this.getRootDirectory();\r\n for (const segment of pathSegments) {\r\n directory = await directory.getDirectoryHandle(segment, { create: true });\r\n }\r\n return directory;\r\n }\r\n\r\n private async getOptionalDirectory(\r\n pathSegments: string[]\r\n ): Promise<FileSystemDirectoryHandle | null> {\r\n try {\r\n let directory = await this.getRootDirectory();\r\n for (const segment of pathSegments) {\r\n directory = await directory.getDirectoryHandle(segment);\r\n }\r\n return directory;\r\n } catch (error) {\r\n if (isNotFoundError(error)) {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n private async getOptionalFileHandle(\r\n pathSegments: string[],\r\n fileName: string\r\n ): Promise<FileSystemFileHandle | null> {\r\n const directory = await this.getOptionalDirectory(pathSegments);\r\n if (!directory) {\r\n return null;\r\n }\r\n return this.getOptionalFileHandleFromDirectory(directory, fileName);\r\n }\r\n\r\n private async getOptionalFileHandleFromDirectory(\r\n directory: FileSystemDirectoryHandle,\r\n fileName: string\r\n ): Promise<FileSystemFileHandle | null> {\r\n try {\r\n return await directory.getFileHandle(fileName);\r\n } catch (error) {\r\n if (isNotFoundError(error)) {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n private async readMetadata(\r\n directory: FileSystemDirectoryHandle,\r\n fileName: string\r\n ): Promise<StoredFileMetadata | null> {\r\n const handle = await this.getOptionalFileHandleFromDirectory(directory, fileName);\r\n if (!handle) {\r\n return null;\r\n }\r\n\r\n const bytes = await readFileBytes(handle);\r\n return JSON.parse(new TextDecoder().decode(bytes)) as StoredFileMetadata;\r\n }\r\n\r\n private async getRootDirectory(): Promise<FileSystemDirectoryHandle> {\r\n if (!this.rootDirectoryPromise) {\r\n this.rootDirectoryPromise = (async () => {\r\n const storageManager = getOpfsStorageManager();\r\n if (!storageManager?.getDirectory) {\r\n throw new Error(\"OPFS is not available in this environment.\");\r\n }\r\n const root = await storageManager.getDirectory();\r\n return root.getDirectoryHandle(\r\n this.options.rootDirectoryName ?? \"syncore\",\r\n { create: true }\r\n );\r\n })();\r\n }\r\n return this.rootDirectoryPromise;\r\n }\r\n}\r\n\r\nasync function readFileBytes(handle: FileSystemFileHandle): Promise<Uint8Array> {\r\n const file = await handle.getFile();\r\n return new Uint8Array(await file.arrayBuffer());\r\n}\r\n\r\nasync function writeBytes(\r\n handle: FileSystemFileHandle,\r\n bytes: Uint8Array\r\n): Promise<void> {\r\n const writable = await handle.createWritable();\r\n try {\r\n await writable.write(sliceToArrayBuffer(bytes));\r\n await writable.truncate(bytes.byteLength);\r\n } finally {\r\n await writable.close();\r\n }\r\n}\r\n\r\nasync function writeText(\r\n handle: FileSystemFileHandle,\r\n value: string\r\n): Promise<void> {\r\n await writeBytes(handle, new TextEncoder().encode(value));\r\n}\r\n\r\nasync function removeEntryIfExists(\r\n directory: FileSystemDirectoryHandle,\r\n name: string\r\n): Promise<void> {\r\n try {\r\n await directory.removeEntry(name);\r\n } catch (error) {\r\n if (!isNotFoundError(error)) {\r\n throw error;\r\n }\r\n }\r\n}\r\n\r\nfunction encodePathComponent(value: string): string {\r\n return encodeURIComponent(value);\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\r\nfunction getOpfsStorageManager(): OpfsStorageManager | undefined {\r\n if (typeof navigator === \"undefined\") {\r\n return undefined;\r\n }\r\n return navigator.storage as OpfsStorageManager | undefined;\r\n}\r\n\r\nfunction isNotFoundError(error: unknown): boolean {\r\n return (\r\n typeof error === \"object\" &&\r\n error !== null &&\r\n \"name\" in error &&\r\n error.name === \"NotFoundError\"\r\n );\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ //#region src/persistence.d.ts
2
+ interface StoredWebFile {
3
+ id: string;
4
+ bytes: Uint8Array;
5
+ contentType: string | null;
6
+ size: number;
7
+ }
8
+ interface SyncoreWebPersistence {
9
+ readonly storageProtocol: "idb" | "opfs";
10
+ loadDatabase(key: string): Promise<Uint8Array | null>;
11
+ saveDatabase(key: string, bytes: Uint8Array): Promise<void>;
12
+ getFile(namespace: string, id: string): Promise<StoredWebFile | null>;
13
+ putFile(namespace: string, id: string, bytes: Uint8Array, contentType: string | null): Promise<void>;
14
+ deleteFile(namespace: string, id: string): Promise<void>;
15
+ listFiles(namespace: string): Promise<StoredWebFile[]>;
16
+ }
17
+ type WebPersistenceMode = "auto" | "indexeddb" | "opfs";
18
+ interface CreateWebPersistenceOptions {
19
+ mode?: WebPersistenceMode;
20
+ indexedDbDatabaseName?: string;
21
+ opfsRootDirectoryName?: string;
22
+ }
23
+ declare function createWebPersistence(options?: CreateWebPersistenceOptions): Promise<SyncoreWebPersistence>;
24
+ declare function isOpfsAvailable(): boolean;
25
+ //#endregion
26
+ export { CreateWebPersistenceOptions, StoredWebFile, SyncoreWebPersistence, WebPersistenceMode, createWebPersistence, isOpfsAvailable };
27
+ //# sourceMappingURL=persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.d.ts","names":[],"sources":["../src/persistence.ts"],"mappings":";UAGiB,aAAA;EACf,EAAA;EACA,KAAA,EAAO,UAAA;EACP,WAAA;EACA,IAAA;AAAA;AAAA,UAGe,qBAAA;EAAA,SACN,eAAA;EACT,YAAA,CAAa,GAAA,WAAc,OAAA,CAAQ,UAAA;EACnC,YAAA,CAAa,GAAA,UAAa,KAAA,EAAO,UAAA,GAAa,OAAA;EAC9C,OAAA,CAAQ,SAAA,UAAmB,EAAA,WAAa,OAAA,CAAQ,aAAA;EAChD,OAAA,CACE,SAAA,UACA,EAAA,UACA,KAAA,EAAO,UAAA,EACP,WAAA,kBACC,OAAA;EACH,UAAA,CAAW,SAAA,UAAmB,EAAA,WAAa,OAAA;EAC3C,SAAA,CAAU,SAAA,WAAoB,OAAA,CAAQ,aAAA;AAAA;AAAA,KAG5B,kBAAA;AAAA,UAEK,2BAAA;EACf,IAAA,GAAO,kBAAA;EACP,qBAAA;EACA,qBAAA;AAAA;AAAA,iBAGoB,oBAAA,CACpB,OAAA,GAAS,2BAAA,GACR,OAAA,CAAQ,qBAAA;AAAA,iBA6BK,eAAA,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { SyncoreIndexedDbPersistence } from "./indexeddb.js";
2
+ import { SyncoreOpfsPersistence } from "./opfs.js";
3
+ //#region src/persistence.ts
4
+ async function createWebPersistence(options = {}) {
5
+ const mode = options.mode ?? "auto";
6
+ if (mode === "opfs") {
7
+ if (!isOpfsAvailable()) throw new Error("OPFS is not available in this environment.");
8
+ return new SyncoreOpfsPersistence(options.opfsRootDirectoryName ? { rootDirectoryName: options.opfsRootDirectoryName } : void 0);
9
+ }
10
+ if (mode === "auto" && isOpfsAvailable()) return new SyncoreOpfsPersistence(options.opfsRootDirectoryName ? { rootDirectoryName: options.opfsRootDirectoryName } : void 0);
11
+ return new SyncoreIndexedDbPersistence(options.indexedDbDatabaseName ? { databaseName: options.indexedDbDatabaseName } : void 0);
12
+ }
13
+ function isOpfsAvailable() {
14
+ return Boolean(getOpfsStorageManager()?.getDirectory);
15
+ }
16
+ function getOpfsStorageManager() {
17
+ if (typeof navigator === "undefined") return;
18
+ return navigator.storage;
19
+ }
20
+ //#endregion
21
+ export { createWebPersistence, isOpfsAvailable };
22
+
23
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","names":[],"sources":["../src/persistence.ts"],"sourcesContent":["import { SyncoreIndexedDbPersistence } from \"./indexeddb.js\";\r\nimport { SyncoreOpfsPersistence } from \"./opfs.js\";\r\n\r\nexport interface StoredWebFile {\r\n id: string;\r\n bytes: Uint8Array;\r\n contentType: string | null;\r\n size: number;\r\n}\r\n\r\nexport interface SyncoreWebPersistence {\r\n readonly storageProtocol: \"idb\" | \"opfs\";\r\n loadDatabase(key: string): Promise<Uint8Array | null>;\r\n saveDatabase(key: string, bytes: Uint8Array): Promise<void>;\r\n getFile(namespace: string, id: string): Promise<StoredWebFile | null>;\r\n putFile(\r\n namespace: string,\r\n id: string,\r\n bytes: Uint8Array,\r\n contentType: string | null\r\n ): Promise<void>;\r\n deleteFile(namespace: string, id: string): Promise<void>;\r\n listFiles(namespace: string): Promise<StoredWebFile[]>;\r\n}\r\n\r\nexport type WebPersistenceMode = \"auto\" | \"indexeddb\" | \"opfs\";\r\n\r\nexport interface CreateWebPersistenceOptions {\r\n mode?: WebPersistenceMode;\r\n indexedDbDatabaseName?: string;\r\n opfsRootDirectoryName?: string;\r\n}\r\n\r\nexport async function createWebPersistence(\r\n options: CreateWebPersistenceOptions = {}\r\n): Promise<SyncoreWebPersistence> {\r\n const mode = options.mode ?? \"auto\";\r\n\r\n if (mode === \"opfs\") {\r\n if (!isOpfsAvailable()) {\r\n throw new Error(\"OPFS is not available in this environment.\");\r\n }\r\n return new SyncoreOpfsPersistence(\r\n options.opfsRootDirectoryName\r\n ? { rootDirectoryName: options.opfsRootDirectoryName }\r\n : undefined\r\n );\r\n }\r\n\r\n if (mode === \"auto\" && isOpfsAvailable()) {\r\n return new SyncoreOpfsPersistence(\r\n options.opfsRootDirectoryName\r\n ? { rootDirectoryName: options.opfsRootDirectoryName }\r\n : undefined\r\n );\r\n }\r\n\r\n return new SyncoreIndexedDbPersistence(\r\n options.indexedDbDatabaseName\r\n ? { databaseName: options.indexedDbDatabaseName }\r\n : undefined\r\n );\r\n}\r\n\r\nexport function isOpfsAvailable(): boolean {\r\n return Boolean(getOpfsStorageManager()?.getDirectory);\r\n}\r\n\r\ntype OpfsStorageManager = StorageManager & {\r\n getDirectory?: () => Promise<FileSystemDirectoryHandle>;\r\n};\r\n\r\nfunction getOpfsStorageManager(): OpfsStorageManager | undefined {\r\n if (typeof navigator === \"undefined\") {\r\n return undefined;\r\n }\r\n return navigator.storage as OpfsStorageManager | undefined;\r\n}\r\n"],"mappings":";;;AAiCA,eAAsB,qBACpB,UAAuC,EAAE,EACT;CAChC,MAAM,OAAO,QAAQ,QAAQ;AAE7B,KAAI,SAAS,QAAQ;AACnB,MAAI,CAAC,iBAAiB,CACpB,OAAM,IAAI,MAAM,6CAA6C;AAE/D,SAAO,IAAI,uBACT,QAAQ,wBACJ,EAAE,mBAAmB,QAAQ,uBAAuB,GACpD,KAAA,EACL;;AAGH,KAAI,SAAS,UAAU,iBAAiB,CACtC,QAAO,IAAI,uBACT,QAAQ,wBACJ,EAAE,mBAAmB,QAAQ,uBAAuB,GACpD,KAAA,EACL;AAGH,QAAO,IAAI,4BACT,QAAQ,wBACJ,EAAE,cAAc,QAAQ,uBAAuB,GAC/C,KAAA,EACL;;AAGH,SAAgB,kBAA2B;AACzC,QAAO,QAAQ,uBAAuB,EAAE,aAAa;;AAOvD,SAAS,wBAAwD;AAC/D,KAAI,OAAO,cAAc,YACvB;AAEF,QAAO,UAAU"}
@@ -0,0 +1,35 @@
1
+ import { CreateWebWorkerClientProviderOptions } from "./worker.js";
2
+ import { ReactNode } from "react";
3
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
4
+
5
+ //#region src/react.d.ts
6
+ /**
7
+ * Props for {@link SyncoreWebProvider}.
8
+ */
9
+ interface SyncoreWebProviderProps extends CreateWebWorkerClientProviderOptions {
10
+ /** The React subtree that should receive the Syncore client. */
11
+ children: ReactNode;
12
+ /** Optional fallback content rendered before the worker client is ready. */
13
+ fallback?: ReactNode;
14
+ }
15
+ /**
16
+ * Props for {@link SyncoreBrowserProvider}.
17
+ */
18
+ type SyncoreBrowserProviderProps = SyncoreWebProviderProps;
19
+ /**
20
+ * Start a worker-backed Syncore client and provide it to React descendants.
21
+ */
22
+ declare function SyncoreWebProvider({
23
+ children,
24
+ workerUrl,
25
+ workerType,
26
+ workerName,
27
+ fallback
28
+ }: SyncoreWebProviderProps): ReactNode;
29
+ /**
30
+ * Start a worker-backed Syncore client and provide it to React descendants.
31
+ */
32
+ declare function SyncoreBrowserProvider(props: SyncoreBrowserProviderProps): react_jsx_runtime0.JSX.Element;
33
+ //#endregion
34
+ export { SyncoreBrowserProvider, SyncoreBrowserProviderProps, SyncoreWebProvider, SyncoreWebProviderProps };
35
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","names":[],"sources":["../src/react.tsx"],"mappings":";;;;;;;;UAYiB,uBAAA,SAAgC,oCAAA;EAAR;EAEvC,QAAA,EAAU,SAAA;EAAA;EAGV,QAAA,GAAW,SAAA;AAAA;;;;KAMD,2BAAA,GAA8B,uBAAA;;;;iBAK1B,kBAAA,CAAA;EACd,QAAA;EACA,SAAA;EACA,UAAA;EACA,UAAA;EACA;AAAA,GACC,uBAAA,GAA0B,SAAA;;AAX7B;;iBAyCgB,sBAAA,CAAuB,KAAA,EAAO,2BAAA,GAA2B,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -0,0 +1,42 @@
1
+ import { createSyncoreWebWorkerClient } from "./worker.js";
2
+ import { useEffect, useState } from "react";
3
+ import { SyncoreProvider } from "../react/index.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/react.tsx
6
+ /**
7
+ * Start a worker-backed Syncore client and provide it to React descendants.
8
+ */
9
+ function SyncoreWebProvider({ children, workerUrl, workerType, workerName, fallback = null }) {
10
+ const [managedClient, setManagedClient] = useState(null);
11
+ useEffect(() => {
12
+ const nextClient = createSyncoreWebWorkerClient({
13
+ workerUrl,
14
+ ...workerType ? { workerType } : {},
15
+ ...workerName ? { workerName } : {}
16
+ });
17
+ setManagedClient(nextClient);
18
+ return () => {
19
+ nextClient.dispose();
20
+ setManagedClient(null);
21
+ };
22
+ }, [
23
+ workerName,
24
+ workerType,
25
+ workerUrl
26
+ ]);
27
+ if (!managedClient) return fallback;
28
+ return /* @__PURE__ */ jsx(SyncoreProvider, {
29
+ client: managedClient.client,
30
+ children
31
+ });
32
+ }
33
+ /**
34
+ * Start a worker-backed Syncore client and provide it to React descendants.
35
+ */
36
+ function SyncoreBrowserProvider(props) {
37
+ return /* @__PURE__ */ jsx(SyncoreWebProvider, { ...props });
38
+ }
39
+ //#endregion
40
+ export { SyncoreBrowserProvider, SyncoreWebProvider };
41
+
42
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\r\nimport type { ReactNode } from \"react\";\r\nimport { SyncoreProvider } from \"@syncore/react\";\r\nimport {\r\n createSyncoreWebWorkerClient,\r\n type CreateWebWorkerClientProviderOptions,\r\n type ManagedWebWorkerClient\r\n} from \"./worker.js\";\r\n\r\n/**\r\n * Props for {@link SyncoreWebProvider}.\r\n */\r\nexport interface SyncoreWebProviderProps extends CreateWebWorkerClientProviderOptions {\r\n /** The React subtree that should receive the Syncore client. */\r\n children: ReactNode;\r\n\r\n /** Optional fallback content rendered before the worker client is ready. */\r\n fallback?: ReactNode;\r\n}\r\n\r\n/**\r\n * Props for {@link SyncoreBrowserProvider}.\r\n */\r\nexport type SyncoreBrowserProviderProps = SyncoreWebProviderProps;\r\n\r\n/**\r\n * Start a worker-backed Syncore client and provide it to React descendants.\r\n */\r\nexport function SyncoreWebProvider({\r\n children,\r\n workerUrl,\r\n workerType,\r\n workerName,\r\n fallback = null\r\n}: SyncoreWebProviderProps): ReactNode {\r\n const [managedClient, setManagedClient] =\r\n useState<ManagedWebWorkerClient | null>(null);\r\n\r\n useEffect(() => {\r\n const nextClient = createSyncoreWebWorkerClient({\r\n workerUrl,\r\n ...(workerType ? { workerType } : {}),\r\n ...(workerName ? { workerName } : {})\r\n });\r\n setManagedClient(nextClient);\r\n\r\n return () => {\r\n nextClient.dispose();\r\n setManagedClient(null);\r\n };\r\n }, [workerName, workerType, workerUrl]);\r\n\r\n if (!managedClient) {\r\n return fallback;\r\n }\r\n\r\n return (\r\n <SyncoreProvider client={managedClient.client}>{children}</SyncoreProvider>\r\n );\r\n}\r\n\r\n/**\r\n * Start a worker-backed Syncore client and provide it to React descendants.\r\n */\r\nexport function SyncoreBrowserProvider(props: SyncoreBrowserProviderProps) {\r\n return <SyncoreWebProvider {...props} />;\r\n}\r\n"],"mappings":";;;;;;;;AA4BA,SAAgB,mBAAmB,EACjC,UACA,WACA,YACA,YACA,WAAW,QAC0B;CACrC,MAAM,CAAC,eAAe,oBACpB,SAAwC,KAAK;AAE/C,iBAAgB;EACd,MAAM,aAAa,6BAA6B;GAC9C;GACA,GAAI,aAAa,EAAE,YAAY,GAAG,EAAE;GACpC,GAAI,aAAa,EAAE,YAAY,GAAG,EAAE;GACrC,CAAC;AACF,mBAAiB,WAAW;AAE5B,eAAa;AACX,cAAW,SAAS;AACpB,oBAAiB,KAAK;;IAEvB;EAAC;EAAY;EAAY;EAAU,CAAC;AAEvC,KAAI,CAAC,cACH,QAAO;AAGT,QACE,oBAAC,iBAAD;EAAiB,QAAQ,cAAc;EAAS;EAA2B,CAAA;;;;;AAO/E,SAAgB,uBAAuB,OAAoC;AACzE,QAAO,oBAAC,oBAAD,EAAoB,GAAI,OAAS,CAAA"}
@@ -0,0 +1,133 @@
1
+ import { SyncoreIndexedDbPersistence } from "./indexeddb.js";
2
+ import initSqlJs from "sql.js";
3
+ //#region src/sqljs.ts
4
+ var SqlJsDriver = class SqlJsDriver {
5
+ transactionDepth = 0;
6
+ closed = false;
7
+ constructor(database, persistence, databaseName) {
8
+ this.database = database;
9
+ this.persistence = persistence;
10
+ this.databaseName = databaseName;
11
+ }
12
+ static async create(options) {
13
+ const persistence = options.persistence ?? new SyncoreIndexedDbPersistence();
14
+ const SQL = await initSqlJs(typeof window === "undefined" && !options.locateFile && !options.wasmUrl ? void 0 : { locateFile: options.locateFile ?? (() => options.wasmUrl ?? "/sql-wasm.wasm") });
15
+ const existingBytes = await persistence.loadDatabase(options.databaseName);
16
+ return new SqlJsDriver(existingBytes ? new SQL.Database(existingBytes) : new SQL.Database(), persistence, options.databaseName);
17
+ }
18
+ async exec(sql) {
19
+ this.ensureOpen();
20
+ this.database.run(sql);
21
+ await this.persistIfNeeded();
22
+ }
23
+ async run(sql, params = []) {
24
+ this.ensureOpen();
25
+ const statement = this.database.prepare(sql);
26
+ try {
27
+ statement.run(normalizeParams(params));
28
+ const lastInsertRowid = readScalarNumber(this.database, "SELECT last_insert_rowid()");
29
+ const result = {
30
+ changes: this.database.getRowsModified(),
31
+ ...lastInsertRowid !== null ? { lastInsertRowid } : {}
32
+ };
33
+ await this.persistIfNeeded();
34
+ return result;
35
+ } finally {
36
+ statement.free();
37
+ }
38
+ }
39
+ async get(sql, params = []) {
40
+ this.ensureOpen();
41
+ const statement = this.database.prepare(sql);
42
+ try {
43
+ statement.bind(normalizeParams(params));
44
+ if (!statement.step()) return;
45
+ return statement.getAsObject();
46
+ } finally {
47
+ statement.free();
48
+ }
49
+ }
50
+ async all(sql, params = []) {
51
+ this.ensureOpen();
52
+ const statement = this.database.prepare(sql);
53
+ try {
54
+ statement.bind(normalizeParams(params));
55
+ const rows = [];
56
+ while (statement.step()) rows.push(statement.getAsObject());
57
+ return rows;
58
+ } finally {
59
+ statement.free();
60
+ }
61
+ }
62
+ async withTransaction(callback) {
63
+ this.ensureOpen();
64
+ if (this.transactionDepth > 0) return this.withSavepoint(`nested_${this.transactionDepth}`, callback);
65
+ this.transactionDepth += 1;
66
+ this.database.run("BEGIN IMMEDIATE");
67
+ try {
68
+ const result = await callback();
69
+ this.database.run("COMMIT");
70
+ await this.persistNow();
71
+ return result;
72
+ } catch (error) {
73
+ this.database.run("ROLLBACK");
74
+ throw error;
75
+ } finally {
76
+ this.transactionDepth -= 1;
77
+ }
78
+ }
79
+ async withSavepoint(name, callback) {
80
+ this.ensureOpen();
81
+ const safeName = name.replaceAll(/[^a-zA-Z0-9_]/g, "_");
82
+ this.database.run(`SAVEPOINT ${safeName}`);
83
+ this.transactionDepth += 1;
84
+ try {
85
+ const result = await callback();
86
+ this.database.run(`RELEASE SAVEPOINT ${safeName}`);
87
+ return result;
88
+ } catch (error) {
89
+ this.database.run(`ROLLBACK TO SAVEPOINT ${safeName}`);
90
+ this.database.run(`RELEASE SAVEPOINT ${safeName}`);
91
+ throw error;
92
+ } finally {
93
+ this.transactionDepth -= 1;
94
+ }
95
+ }
96
+ async close() {
97
+ if (this.closed) return;
98
+ await this.persistNow();
99
+ this.database.close();
100
+ this.closed = true;
101
+ }
102
+ async persistIfNeeded() {
103
+ if (this.transactionDepth === 0) await this.persistNow();
104
+ }
105
+ async persistNow() {
106
+ this.ensureOpen();
107
+ await this.persistence.saveDatabase(this.databaseName, this.database.export());
108
+ }
109
+ ensureOpen() {
110
+ if (this.closed) throw new Error("The sql.js driver is already closed.");
111
+ }
112
+ };
113
+ function normalizeParams(values) {
114
+ return values.map((value) => {
115
+ if (typeof value === "boolean") return value ? 1 : 0;
116
+ if (value === null || typeof value === "number" || typeof value === "string" || value instanceof Uint8Array) return value;
117
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
118
+ return JSON.stringify(value);
119
+ });
120
+ }
121
+ function readScalarNumber(database, sql) {
122
+ const firstValue = (database.exec(sql)[0]?.values[0])?.[0];
123
+ if (typeof firstValue === "number") return firstValue;
124
+ if (typeof firstValue === "string") {
125
+ const parsed = Number(firstValue);
126
+ return Number.isNaN(parsed) ? null : parsed;
127
+ }
128
+ return null;
129
+ }
130
+ //#endregion
131
+ export { SqlJsDriver };
132
+
133
+ //# sourceMappingURL=sqljs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqljs.js","names":[],"sources":["../src/sqljs.ts"],"sourcesContent":["import initSqlJs from \"sql.js\";\r\nimport type { RunResult, SyncoreSqlDriver } from \"@syncore/core\";\r\nimport { SyncoreIndexedDbPersistence } from \"./indexeddb.js\";\r\nimport type { SyncoreWebPersistence } from \"./persistence.js\";\r\n\r\ntype SqlJsDatabase = initSqlJs.Database;\r\ntype SqlJsValue = initSqlJs.SqlValue;\r\n\r\nexport interface CreateSqlJsDriverOptions {\r\n databaseName: string;\r\n persistence?: SyncoreWebPersistence;\r\n wasmUrl?: string;\r\n locateFile?: (fileName: string) => string;\r\n}\r\n\r\nexport class SqlJsDriver implements SyncoreSqlDriver {\r\n private transactionDepth = 0;\r\n private closed = false;\r\n\r\n constructor(\r\n private readonly database: SqlJsDatabase,\r\n private readonly persistence: SyncoreWebPersistence,\r\n private readonly databaseName: string\r\n ) {}\r\n\r\n static async create(options: CreateSqlJsDriverOptions): Promise<SqlJsDriver> {\r\n const persistence =\r\n options.persistence ?? new SyncoreIndexedDbPersistence();\r\n const SQL = await initSqlJs(\r\n typeof window === \"undefined\" && !options.locateFile && !options.wasmUrl\r\n ? undefined\r\n : {\r\n locateFile:\r\n options.locateFile ?? (() => options.wasmUrl ?? \"/sql-wasm.wasm\")\r\n }\r\n );\r\n const existingBytes = await persistence.loadDatabase(options.databaseName);\r\n const database = existingBytes\r\n ? new SQL.Database(existingBytes)\r\n : new SQL.Database();\r\n return new SqlJsDriver(database, persistence, options.databaseName);\r\n }\r\n\r\n async exec(sql: string): Promise<void> {\r\n this.ensureOpen();\r\n this.database.run(sql);\r\n await this.persistIfNeeded();\r\n }\r\n\r\n async run(sql: string, params: unknown[] = []): Promise<RunResult> {\r\n this.ensureOpen();\r\n const statement = this.database.prepare(sql);\r\n try {\r\n statement.run(normalizeParams(params));\r\n const lastInsertRowid = readScalarNumber(\r\n this.database,\r\n \"SELECT last_insert_rowid()\"\r\n );\r\n const result = {\r\n changes: this.database.getRowsModified(),\r\n ...(lastInsertRowid !== null ? { lastInsertRowid } : {})\r\n };\r\n await this.persistIfNeeded();\r\n return result;\r\n } finally {\r\n statement.free();\r\n }\r\n }\r\n\r\n async get<T>(sql: string, params: unknown[] = []): Promise<T | undefined> {\r\n this.ensureOpen();\r\n const statement = this.database.prepare(sql);\r\n try {\r\n statement.bind(normalizeParams(params));\r\n if (!statement.step()) {\r\n return undefined;\r\n }\r\n return statement.getAsObject() as T;\r\n } finally {\r\n statement.free();\r\n }\r\n }\r\n\r\n async all<T>(sql: string, params: unknown[] = []): Promise<T[]> {\r\n this.ensureOpen();\r\n const statement = this.database.prepare(sql);\r\n try {\r\n statement.bind(normalizeParams(params));\r\n const rows: T[] = [];\r\n while (statement.step()) {\r\n rows.push(statement.getAsObject() as T);\r\n }\r\n return rows;\r\n } finally {\r\n statement.free();\r\n }\r\n }\r\n\r\n async withTransaction<T>(callback: () => Promise<T>): Promise<T> {\r\n this.ensureOpen();\r\n if (this.transactionDepth > 0) {\r\n return this.withSavepoint(`nested_${this.transactionDepth}`, callback);\r\n }\r\n\r\n this.transactionDepth += 1;\r\n this.database.run(\"BEGIN IMMEDIATE\");\r\n try {\r\n const result = await callback();\r\n this.database.run(\"COMMIT\");\r\n await this.persistNow();\r\n return result;\r\n } catch (error) {\r\n this.database.run(\"ROLLBACK\");\r\n throw error;\r\n } finally {\r\n this.transactionDepth -= 1;\r\n }\r\n }\r\n\r\n async withSavepoint<T>(name: string, callback: () => Promise<T>): Promise<T> {\r\n this.ensureOpen();\r\n const safeName = name.replaceAll(/[^a-zA-Z0-9_]/g, \"_\");\r\n this.database.run(`SAVEPOINT ${safeName}`);\r\n this.transactionDepth += 1;\r\n try {\r\n const result = await callback();\r\n this.database.run(`RELEASE SAVEPOINT ${safeName}`);\r\n return result;\r\n } catch (error) {\r\n this.database.run(`ROLLBACK TO SAVEPOINT ${safeName}`);\r\n this.database.run(`RELEASE SAVEPOINT ${safeName}`);\r\n throw error;\r\n } finally {\r\n this.transactionDepth -= 1;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this.closed) {\r\n return;\r\n }\r\n await this.persistNow();\r\n this.database.close();\r\n this.closed = true;\r\n }\r\n\r\n private async persistIfNeeded(): Promise<void> {\r\n if (this.transactionDepth === 0) {\r\n await this.persistNow();\r\n }\r\n }\r\n\r\n private async persistNow(): Promise<void> {\r\n this.ensureOpen();\r\n await this.persistence.saveDatabase(\r\n this.databaseName,\r\n this.database.export()\r\n );\r\n }\r\n\r\n private ensureOpen(): void {\r\n if (this.closed) {\r\n throw new Error(\"The sql.js driver is already closed.\");\r\n }\r\n }\r\n}\r\n\r\nfunction normalizeParams(values: unknown[]): SqlJsValue[] {\r\n return values.map((value) => {\r\n if (typeof value === \"boolean\") {\r\n return value ? 1 : 0;\r\n }\r\n if (\r\n value === null ||\r\n typeof value === \"number\" ||\r\n typeof value === \"string\" ||\r\n value instanceof Uint8Array\r\n ) {\r\n return value;\r\n }\r\n if (value instanceof ArrayBuffer) {\r\n return new Uint8Array(value);\r\n }\r\n return JSON.stringify(value);\r\n });\r\n}\r\n\r\nfunction readScalarNumber(database: SqlJsDatabase, sql: string): number | null {\r\n const rows = database.exec(sql);\r\n const firstSet = rows[0];\r\n const firstRow = firstSet?.values[0];\r\n const firstValue = firstRow?.[0];\r\n if (typeof firstValue === \"number\") {\r\n return firstValue;\r\n }\r\n if (typeof firstValue === \"string\") {\r\n const parsed = Number(firstValue);\r\n return Number.isNaN(parsed) ? null : parsed;\r\n }\r\n return null;\r\n}\r\n"],"mappings":";;;AAeA,IAAa,cAAb,MAAa,YAAwC;CACnD,mBAA2B;CAC3B,SAAiB;CAEjB,YACE,UACA,aACA,cACA;AAHiB,OAAA,WAAA;AACA,OAAA,cAAA;AACA,OAAA,eAAA;;CAGnB,aAAa,OAAO,SAAyD;EAC3E,MAAM,cACJ,QAAQ,eAAe,IAAI,6BAA6B;EAC1D,MAAM,MAAM,MAAM,UAChB,OAAO,WAAW,eAAe,CAAC,QAAQ,cAAc,CAAC,QAAQ,UAC7D,KAAA,IACA,EACE,YACE,QAAQ,qBAAqB,QAAQ,WAAW,mBACnD,CACN;EACD,MAAM,gBAAgB,MAAM,YAAY,aAAa,QAAQ,aAAa;AAI1E,SAAO,IAAI,YAHM,gBACb,IAAI,IAAI,SAAS,cAAc,GAC/B,IAAI,IAAI,UAAU,EACW,aAAa,QAAQ,aAAa;;CAGrE,MAAM,KAAK,KAA4B;AACrC,OAAK,YAAY;AACjB,OAAK,SAAS,IAAI,IAAI;AACtB,QAAM,KAAK,iBAAiB;;CAG9B,MAAM,IAAI,KAAa,SAAoB,EAAE,EAAsB;AACjE,OAAK,YAAY;EACjB,MAAM,YAAY,KAAK,SAAS,QAAQ,IAAI;AAC5C,MAAI;AACF,aAAU,IAAI,gBAAgB,OAAO,CAAC;GACtC,MAAM,kBAAkB,iBACtB,KAAK,UACL,6BACD;GACD,MAAM,SAAS;IACb,SAAS,KAAK,SAAS,iBAAiB;IACxC,GAAI,oBAAoB,OAAO,EAAE,iBAAiB,GAAG,EAAE;IACxD;AACD,SAAM,KAAK,iBAAiB;AAC5B,UAAO;YACC;AACR,aAAU,MAAM;;;CAIpB,MAAM,IAAO,KAAa,SAAoB,EAAE,EAA0B;AACxE,OAAK,YAAY;EACjB,MAAM,YAAY,KAAK,SAAS,QAAQ,IAAI;AAC5C,MAAI;AACF,aAAU,KAAK,gBAAgB,OAAO,CAAC;AACvC,OAAI,CAAC,UAAU,MAAM,CACnB;AAEF,UAAO,UAAU,aAAa;YACtB;AACR,aAAU,MAAM;;;CAIpB,MAAM,IAAO,KAAa,SAAoB,EAAE,EAAgB;AAC9D,OAAK,YAAY;EACjB,MAAM,YAAY,KAAK,SAAS,QAAQ,IAAI;AAC5C,MAAI;AACF,aAAU,KAAK,gBAAgB,OAAO,CAAC;GACvC,MAAM,OAAY,EAAE;AACpB,UAAO,UAAU,MAAM,CACrB,MAAK,KAAK,UAAU,aAAa,CAAM;AAEzC,UAAO;YACC;AACR,aAAU,MAAM;;;CAIpB,MAAM,gBAAmB,UAAwC;AAC/D,OAAK,YAAY;AACjB,MAAI,KAAK,mBAAmB,EAC1B,QAAO,KAAK,cAAc,UAAU,KAAK,oBAAoB,SAAS;AAGxE,OAAK,oBAAoB;AACzB,OAAK,SAAS,IAAI,kBAAkB;AACpC,MAAI;GACF,MAAM,SAAS,MAAM,UAAU;AAC/B,QAAK,SAAS,IAAI,SAAS;AAC3B,SAAM,KAAK,YAAY;AACvB,UAAO;WACA,OAAO;AACd,QAAK,SAAS,IAAI,WAAW;AAC7B,SAAM;YACE;AACR,QAAK,oBAAoB;;;CAI7B,MAAM,cAAiB,MAAc,UAAwC;AAC3E,OAAK,YAAY;EACjB,MAAM,WAAW,KAAK,WAAW,kBAAkB,IAAI;AACvD,OAAK,SAAS,IAAI,aAAa,WAAW;AAC1C,OAAK,oBAAoB;AACzB,MAAI;GACF,MAAM,SAAS,MAAM,UAAU;AAC/B,QAAK,SAAS,IAAI,qBAAqB,WAAW;AAClD,UAAO;WACA,OAAO;AACd,QAAK,SAAS,IAAI,yBAAyB,WAAW;AACtD,QAAK,SAAS,IAAI,qBAAqB,WAAW;AAClD,SAAM;YACE;AACR,QAAK,oBAAoB;;;CAI7B,MAAM,QAAuB;AAC3B,MAAI,KAAK,OACP;AAEF,QAAM,KAAK,YAAY;AACvB,OAAK,SAAS,OAAO;AACrB,OAAK,SAAS;;CAGhB,MAAc,kBAAiC;AAC7C,MAAI,KAAK,qBAAqB,EAC5B,OAAM,KAAK,YAAY;;CAI3B,MAAc,aAA4B;AACxC,OAAK,YAAY;AACjB,QAAM,KAAK,YAAY,aACrB,KAAK,cACL,KAAK,SAAS,QAAQ,CACvB;;CAGH,aAA2B;AACzB,MAAI,KAAK,OACP,OAAM,IAAI,MAAM,uCAAuC;;;AAK7D,SAAS,gBAAgB,QAAiC;AACxD,QAAO,OAAO,KAAK,UAAU;AAC3B,MAAI,OAAO,UAAU,UACnB,QAAO,QAAQ,IAAI;AAErB,MACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,WAEjB,QAAO;AAET,MAAI,iBAAiB,YACnB,QAAO,IAAI,WAAW,MAAM;AAE9B,SAAO,KAAK,UAAU,MAAM;GAC5B;;AAGJ,SAAS,iBAAiB,UAAyB,KAA4B;CAI7E,MAAM,cAHO,SAAS,KAAK,IAAI,CACT,IACK,OAAO,MACJ;AAC9B,KAAI,OAAO,eAAe,SACxB,QAAO;AAET,KAAI,OAAO,eAAe,UAAU;EAClC,MAAM,SAAS,OAAO,WAAW;AACjC,SAAO,OAAO,MAAM,OAAO,GAAG,OAAO;;AAEvC,QAAO"}
@@ -0,0 +1,78 @@
1
+ import { AnySyncoreSchema, FunctionReference, SyncoreClient, SyncoreRuntime, SyncoreWatch } from "../core/index.d.mts";
2
+
3
+ //#region src/worker.d.ts
4
+ type WebWorkerSyncoreSchema = AnySyncoreSchema;
5
+ interface SyncoreWorkerMessageEndpoint {
6
+ postMessage(message: unknown): void;
7
+ addEventListener(type: "message", listener: (event: MessageEvent<unknown>) => void): void;
8
+ removeEventListener(type: "message", listener: (event: MessageEvent<unknown>) => void): void;
9
+ }
10
+ type WorkerQueryWatch<TValue> = SyncoreWatch<TValue> & {
11
+ dispose(): void;
12
+ };
13
+ type OptionalArgsTuple<TArgs> = Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];
14
+ declare class SyncoreWebWorkerClient implements SyncoreClient {
15
+ private readonly endpoint;
16
+ private readonly pendingRequests;
17
+ private readonly watchRecordsByKey;
18
+ private readonly watchKeyBySubscriptionId;
19
+ private disposed;
20
+ private readonly handleMessage;
21
+ constructor(endpoint: SyncoreWorkerMessageEndpoint);
22
+ query<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
23
+ mutation<TArgs, TResult>(reference: FunctionReference<"mutation", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
24
+ action<TArgs, TResult>(reference: FunctionReference<"action", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
25
+ watchQuery<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): WorkerQueryWatch<TResult>;
26
+ dispose(): void;
27
+ private invoke;
28
+ private rejectAllPending;
29
+ private ensureNotDisposed;
30
+ }
31
+ interface AttachWebWorkerRuntimeOptions {
32
+ endpoint: SyncoreWorkerMessageEndpoint;
33
+ createRuntime: (() => Promise<SyncoreRuntime<WebWorkerSyncoreSchema>>) | (() => SyncoreRuntime<WebWorkerSyncoreSchema>);
34
+ }
35
+ interface AttachedWebWorkerRuntime {
36
+ ready: Promise<void>;
37
+ dispose(): Promise<void>;
38
+ }
39
+ /**
40
+ * A worker-backed browser client plus the Worker instance it owns.
41
+ */
42
+ interface ManagedWebWorkerClient {
43
+ client: SyncoreWebWorkerClient;
44
+ worker: Worker;
45
+ dispose(): void;
46
+ }
47
+ /**
48
+ * Options for creating a worker-backed Syncore client in the browser.
49
+ */
50
+ interface CreateWebWorkerClientProviderOptions {
51
+ /** The worker module URL passed to `new Worker(...)`. */
52
+ workerUrl: URL | string;
53
+ /** Optional worker type, defaults to `module`. */
54
+ workerType?: WorkerOptions["type"];
55
+ /** Optional name shown in browser devtools. */
56
+ workerName?: string;
57
+ }
58
+ /**
59
+ * Create a web worker Syncore client from a low-level message endpoint.
60
+ */
61
+ declare function createWebWorkerClient(endpoint: SyncoreWorkerMessageEndpoint): SyncoreWebWorkerClient;
62
+ /**
63
+ * Create and manage both a browser Worker and the Syncore client that talks to it.
64
+ */
65
+ declare function createManagedWebWorkerClient(options: {
66
+ createWorker: () => Worker;
67
+ }): ManagedWebWorkerClient;
68
+ /**
69
+ * Create a worker-backed Syncore client using the standard Worker constructor.
70
+ */
71
+ declare function createSyncoreWebWorkerClient(options: CreateWebWorkerClientProviderOptions): ManagedWebWorkerClient;
72
+ /**
73
+ * Attach a Syncore runtime implementation to a worker message endpoint.
74
+ */
75
+ declare function attachWebWorkerRuntime(options: AttachWebWorkerRuntimeOptions): AttachedWebWorkerRuntime;
76
+ //#endregion
77
+ export { AttachWebWorkerRuntimeOptions, AttachedWebWorkerRuntime, CreateWebWorkerClientProviderOptions, ManagedWebWorkerClient, SyncoreWebWorkerClient, SyncoreWorkerMessageEndpoint, WebWorkerSyncoreSchema, WorkerQueryWatch, attachWebWorkerRuntime, createManagedWebWorkerClient, createSyncoreWebWorkerClient, createWebWorkerClient };
78
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","names":[],"sources":["../src/worker.ts"],"mappings":";;;KASY,sBAAA,GAAyB,gBAAA;AAAA,UAEpB,4BAAA;EACf,WAAA,CAAY,OAAA;EACZ,gBAAA,CACE,IAAA,aACA,QAAA,GAAW,KAAA,EAAO,YAAA;EAEpB,mBAAA,CACE,IAAA,aACA,QAAA,GAAW,KAAA,EAAO,YAAA;AAAA;AAAA,KAmFV,gBAAA,WAA2B,YAAA,CAAa,MAAA;EAClD,OAAA;AAAA;AAAA,KAGG,iBAAA,UACH,MAAA,uBAA6B,KAAA,IAAS,IAAA,GAAO,KAAA,KAAU,IAAA,EAAM,KAAA;AAAA,cAElD,sBAAA,YAAkC,aAAA;EAAA,iBAuDhB,QAAA;EAAA,iBAtDZ,eAAA;EAAA,iBACA,iBAAA;EAAA,iBACA,wBAAA;EAAA,QACT,QAAA;EAAA,iBAES,aAAA;cAiDY,QAAA,EAAU,4BAAA;EAIvC,KAAA,gBAAA,CACE,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,IAC1B,OAAA,CAAQ,OAAA;EAQX,QAAA,gBAAA,CACE,SAAA,EAAW,iBAAA,aAA8B,KAAA,EAAO,OAAA,MAC7C,IAAA,EAAM,iBAAA,CAAkB,KAAA,IAC1B,OAAA,CAAQ,OAAA;EAQX,MAAA,gBAAA,CACE,SAAA,EAAW,iBAAA,WAA4B,KAAA,EAAO,OAAA,MAC3C,IAAA,EAAM,iBAAA,CAAkB,KAAA,IAC1B,OAAA,CAAQ,OAAA;EAQX,UAAA,gBAAA,CACE,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,IAC1B,gBAAA,CAAiB,OAAA;EA8DpB,OAAA,CAAA;EAAA,QAiBQ,MAAA;EAAA,QAqCA,gBAAA;EAAA,QAOA,iBAAA;AAAA;AAAA,UAOO,6BAAA;EACf,QAAA,EAAU,4BAAA;EACV,aAAA,SACW,OAAA,CAAQ,cAAA,CAAe,sBAAA,aACvB,cAAA,CAAe,sBAAA;AAAA;AAAA,UAGX,wBAAA;EACf,KAAA,EAAO,OAAA;EACP,OAAA,IAAW,OAAA;AAAA;AA/OX;;;AAAA,UAqPe,sBAAA;EACf,MAAA,EAAQ,sBAAA;EACR,MAAA,EAAQ,MAAA;EACR,OAAA;AAAA;;;;UAMe,oCAAA;EA3PuB;EA6PtC,SAAA,EAAW,GAAA;EA7P4C;EAgQvD,UAAA,GAAa,aAAA;EAhQqD;EAmQlE,UAAA;AAAA;;;;iBAMc,qBAAA,CACd,QAAA,EAAU,4BAAA,GACT,sBAAA;;;;iBAOa,4BAAA,CAA6B,OAAA;EAC3C,YAAA,QAAoB,MAAA;AAAA,IAClB,sBAAA;;;;iBAgBY,4BAAA,CACd,OAAA,EAAS,oCAAA,GACR,sBAAA;;;;iBAaa,sBAAA,CACd,OAAA,EAAS,6BAAA,GACR,wBAAA"}