@oliphaunt/wasix-ts 0.1.0 → 0.2.1

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 (180) hide show
  1. package/ARCHITECTURE.md +55 -32
  2. package/CHANGELOG.md +38 -0
  3. package/README.md +19 -387
  4. package/THIRD_PARTY_NOTICES.md +5 -5
  5. package/lib/browser.d.ts +2 -0
  6. package/lib/browser.js +6 -0
  7. package/lib/{database.d.ts → core/database.d.ts} +4 -4
  8. package/lib/{database.js → core/database.js} +1 -1
  9. package/lib/core/open-config.d.ts +5 -0
  10. package/lib/core/open-config.js +28 -0
  11. package/lib/{public.d.ts → core/public.d.ts} +3 -3
  12. package/lib/{public.js → core/public.js} +2 -2
  13. package/lib/{types.d.ts → core/types.d.ts} +19 -43
  14. package/lib/direct.node.d.ts +2 -2
  15. package/lib/direct.node.js +2 -2
  16. package/lib/host/index.d.mts +1 -1
  17. package/lib/host/index.mjs +1 -1
  18. package/lib/host/provenance.json +1 -1
  19. package/lib/host/wasmer_js_bg.wasm +0 -0
  20. package/lib/hosts/browser/browser-public.d.ts +8 -0
  21. package/lib/hosts/browser/browser-public.js +1 -0
  22. package/lib/{client-common.d.ts → hosts/browser/client-common.d.ts} +3 -3
  23. package/lib/hosts/browser/client-common.js +17 -0
  24. package/lib/{client.d.ts → hosts/browser/client.d.ts} +1 -1
  25. package/lib/{client.js → hosts/browser/client.js} +5 -3
  26. package/lib/{direct-client-common.d.ts → hosts/browser/direct-client-common.d.ts} +9 -8
  27. package/lib/{direct-client-common.js → hosts/browser/direct-client-common.js} +17 -31
  28. package/lib/hosts/browser/initialize.d.ts +5 -0
  29. package/lib/hosts/browser/initialize.js +67 -0
  30. package/lib/{internal-common.d.ts → hosts/browser/internal-common.d.ts} +3 -3
  31. package/lib/{internal-common.js → hosts/browser/internal-common.js} +3 -3
  32. package/lib/{tool-worker-common.d.ts → hosts/browser/tool-worker-common.d.ts} +3 -3
  33. package/lib/{tool-worker-common.js → hosts/browser/tool-worker-common.js} +2 -2
  34. package/lib/{tool-worker.js → hosts/browser/tool-worker.js} +1 -1
  35. package/lib/{wasix-runtime.d.ts → hosts/browser/wasix-runtime.d.ts} +3 -3
  36. package/lib/{wasix-runtime.js → hosts/browser/wasix-runtime.js} +41 -25
  37. package/lib/{worker-client.d.ts → hosts/browser/worker-client.d.ts} +1 -1
  38. package/lib/{worker-client.js → hosts/browser/worker-client.js} +5 -4
  39. package/lib/{worker.js → hosts/browser/worker.js} +2 -2
  40. package/lib/{direct-client.d.ts → hosts/node-api/direct-client.d.ts} +1 -1
  41. package/lib/{direct-client.js → hosts/node-api/direct-client.js} +1 -1
  42. package/lib/{native-addon.d.ts → hosts/node-api/native-addon.d.ts} +28 -6
  43. package/lib/{native-addon.js → hosts/node-api/native-addon.js} +4 -5
  44. package/lib/hosts/node-api/native-public.d.ts +8 -0
  45. package/lib/hosts/node-api/native-public.js +1 -0
  46. package/lib/{native-server.d.ts → hosts/node-api/native-server.d.ts} +1 -1
  47. package/lib/{native-server.js → hosts/node-api/native-server.js} +3 -2
  48. package/lib/{native-session.d.ts → hosts/node-api/native-session.d.ts} +14 -4
  49. package/lib/{native-session.js → hosts/node-api/native-session.js} +93 -108
  50. package/lib/{node-actor.d.ts → hosts/node-api/node-actor.d.ts} +2 -2
  51. package/lib/{node-actor.js → hosts/node-api/node-actor.js} +1 -1
  52. package/lib/{node-client-common.d.ts → hosts/node-api/node-client-common.d.ts} +3 -3
  53. package/lib/{node-client-common.js → hosts/node-api/node-client-common.js} +4 -4
  54. package/lib/{node-client.d.ts → hosts/node-api/node-client.d.ts} +1 -1
  55. package/lib/{node-client.js → hosts/node-api/node-client.js} +1 -1
  56. package/lib/{node-direct.d.ts → hosts/node-api/node-direct.d.ts} +2 -2
  57. package/lib/{node-direct.js → hosts/node-api/node-direct.js} +1 -1
  58. package/lib/{node-worker-port.d.ts → hosts/node-api/node-worker-port.d.ts} +1 -1
  59. package/lib/{node-worker.js → hosts/node-api/node-worker.js} +1 -1
  60. package/lib/{worker-node-client.d.ts → hosts/node-api/worker-node-client.d.ts} +1 -1
  61. package/lib/{worker-node-client.js → hosts/node-api/worker-node-client.js} +5 -18
  62. package/lib/index.bun.d.ts +2 -2
  63. package/lib/index.bun.js +2 -2
  64. package/lib/index.d.ts +2 -2
  65. package/lib/index.deno.d.ts +2 -2
  66. package/lib/index.deno.js +2 -2
  67. package/lib/index.js +2 -2
  68. package/lib/index.node.d.ts +2 -2
  69. package/lib/index.node.js +2 -2
  70. package/lib/internal.d.ts +4 -4
  71. package/lib/internal.js +24 -4
  72. package/lib/internal.node.d.ts +4 -4
  73. package/lib/internal.node.js +2 -2
  74. package/lib/native-only.d.ts +1 -0
  75. package/lib/native-only.js +2 -0
  76. package/lib/protocol/protocol.d.ts +1 -0
  77. package/lib/protocol/protocol.js +1 -0
  78. package/lib/protocol/query.d.ts +1 -0
  79. package/lib/protocol/query.js +1 -0
  80. package/lib/{archive.d.ts → resources/archive.d.ts} +1 -1
  81. package/lib/{descriptor-validation.d.ts → resources/descriptor-validation.d.ts} +2 -2
  82. package/lib/{descriptor-validation.js → resources/descriptor-validation.js} +1 -1
  83. package/lib/{extension-descriptor.d.ts → resources/extension-descriptor.d.ts} +2 -2
  84. package/lib/{extensions.d.ts → resources/extensions.d.ts} +13 -6
  85. package/lib/{extensions.js → resources/extensions.js} +80 -155
  86. package/lib/resources/icu-descriptor.d.ts +3 -0
  87. package/lib/resources/icu-descriptor.js +16 -0
  88. package/lib/{runtime-descriptor.d.ts → resources/runtime-descriptor.d.ts} +1 -1
  89. package/lib/{runtime-descriptor.js → resources/runtime-descriptor.js} +1 -24
  90. package/lib/{tool-runtime.d.ts → resources/tool-runtime.d.ts} +8 -2
  91. package/lib/server.node.d.ts +1 -1
  92. package/lib/server.node.js +1 -1
  93. package/lib/{database-root.d.ts → storage/database-root.d.ts} +8 -0
  94. package/lib/{database-root.js → storage/database-root.js} +6 -0
  95. package/lib/storage/incremental-storage.d.ts +3 -3
  96. package/lib/storage/incremental-storage.js +2 -2
  97. package/lib/storage/indexed-db-provider.d.ts +2 -2
  98. package/lib/storage/indexed-db-provider.js +3 -3
  99. package/lib/storage/indexed-db.d.ts +2 -2
  100. package/lib/storage/indexed-db.js +1 -1
  101. package/lib/storage/node.d.ts +2 -2
  102. package/lib/storage/node.js +1 -1
  103. package/lib/storage/opfs-pool.d.ts +2 -2
  104. package/lib/storage/opfs-pool.js +4 -4
  105. package/lib/storage/opfs-provider.d.ts +2 -2
  106. package/lib/storage/opfs-provider.js +1 -1
  107. package/lib/storage/opfs.d.ts +2 -2
  108. package/lib/storage/opfs.js +1 -1
  109. package/lib/{physical-archive.js → storage/physical-archive.js} +4 -4
  110. package/lib/storage/restore-cleanup.d.ts +1 -1
  111. package/lib/storage/restore-cleanup.js +1 -1
  112. package/lib/{storage-provider.d.ts → storage/storage-provider.d.ts} +5 -11
  113. package/lib/{storage-provider.js → storage/storage-provider.js} +8 -13
  114. package/lib/{storage-snapshot.d.ts → storage/storage-snapshot.d.ts} +2 -2
  115. package/lib/{storage.d.ts → storage/types.d.ts} +8 -7
  116. package/lib/storage/web-lock.js +1 -1
  117. package/lib/worker-entry.bun.d.ts +2 -2
  118. package/lib/worker-entry.bun.js +2 -2
  119. package/lib/worker-entry.d.ts +2 -2
  120. package/lib/worker-entry.deno.d.ts +2 -2
  121. package/lib/worker-entry.deno.js +2 -2
  122. package/lib/worker-entry.js +2 -2
  123. package/lib/worker-entry.node.d.ts +2 -2
  124. package/lib/worker-entry.node.js +2 -2
  125. package/lib/{rpc.d.ts → workers/rpc.d.ts} +14 -34
  126. package/lib/{rpc.js → workers/rpc.js} +4 -4
  127. package/lib/{worker-dispatch.d.ts → workers/worker-dispatch.d.ts} +1 -1
  128. package/lib/{worker-dispatch.js → workers/worker-dispatch.js} +2 -2
  129. package/lib/{worker-rpc.d.ts → workers/worker-rpc.d.ts} +3 -3
  130. package/lib/{worker-rpc.js → workers/worker-rpc.js} +8 -12
  131. package/package.json +66 -30
  132. package/lib/client-common.js +0 -36
  133. package/lib/icu-descriptor.d.ts +0 -3
  134. package/lib/icu-descriptor.js +0 -92
  135. package/lib/protocol.d.ts +0 -1
  136. package/lib/protocol.js +0 -1
  137. package/lib/query.d.ts +0 -1
  138. package/lib/query.js +0 -1
  139. package/node_modules/@oliphaunt/js-core/README.md +0 -7
  140. package/node_modules/@oliphaunt/js-core/dist/commonjs/protocol.d.ts +0 -1
  141. package/node_modules/@oliphaunt/js-core/dist/commonjs/protocol.js +0 -22
  142. package/node_modules/@oliphaunt/js-core/dist/commonjs/query.d.ts +0 -255
  143. package/node_modules/@oliphaunt/js-core/dist/commonjs/query.js +0 -2068
  144. package/node_modules/@oliphaunt/js-core/dist/module/package.json +0 -3
  145. package/node_modules/@oliphaunt/js-core/dist/module/protocol.d.ts +0 -1
  146. package/node_modules/@oliphaunt/js-core/dist/module/protocol.js +0 -19
  147. package/node_modules/@oliphaunt/js-core/dist/module/query.d.ts +0 -255
  148. package/node_modules/@oliphaunt/js-core/dist/module/query.js +0 -2039
  149. package/node_modules/@oliphaunt/js-core/package.json +0 -21
  150. /package/lib/{errors.d.ts → core/errors.d.ts} +0 -0
  151. /package/lib/{errors.js → core/errors.js} +0 -0
  152. /package/lib/{startup-config.d.ts → core/startup-config.d.ts} +0 -0
  153. /package/lib/{startup-config.js → core/startup-config.js} +0 -0
  154. /package/lib/{types.js → core/types.js} +0 -0
  155. /package/lib/{tool-worker.d.ts → hosts/browser/tool-worker.d.ts} +0 -0
  156. /package/lib/{worker.d.ts → hosts/browser/worker.d.ts} +0 -0
  157. /package/lib/{host-runtime.d.ts → hosts/node-api/host-runtime.d.ts} +0 -0
  158. /package/lib/{host-runtime.js → hosts/node-api/host-runtime.js} +0 -0
  159. /package/lib/{node-worker-options.d.ts → hosts/node-api/node-worker-options.d.ts} +0 -0
  160. /package/lib/{node-worker-options.js → hosts/node-api/node-worker-options.js} +0 -0
  161. /package/lib/{node-worker-port.js → hosts/node-api/node-worker-port.js} +0 -0
  162. /package/lib/{node-worker.d.ts → hosts/node-api/node-worker.d.ts} +0 -0
  163. /package/lib/{byte-channel.d.ts → protocol/byte-channel.d.ts} +0 -0
  164. /package/lib/{byte-channel.js → protocol/byte-channel.js} +0 -0
  165. /package/lib/{pgwire-connection.d.ts → protocol/pgwire-connection.d.ts} +0 -0
  166. /package/lib/{pgwire-connection.js → protocol/pgwire-connection.js} +0 -0
  167. /package/lib/{pgwire.d.ts → protocol/pgwire.d.ts} +0 -0
  168. /package/lib/{pgwire.js → protocol/pgwire.js} +0 -0
  169. /package/lib/{archive.js → resources/archive.js} +0 -0
  170. /package/lib/{asset-source.d.ts → resources/asset-source.d.ts} +0 -0
  171. /package/lib/{asset-source.js → resources/asset-source.js} +0 -0
  172. /package/lib/{extension-descriptor.js → resources/extension-descriptor.js} +0 -0
  173. /package/lib/{tool-runtime.js → resources/tool-runtime.js} +0 -0
  174. /package/lib/{zstd.d.ts → resources/zstd.d.ts} +0 -0
  175. /package/lib/{zstd.js → resources/zstd.js} +0 -0
  176. /package/lib/{physical-archive.d.ts → storage/physical-archive.d.ts} +0 -0
  177. /package/lib/{storage-snapshot.js → storage/storage-snapshot.js} +0 -0
  178. /package/lib/{storage.js → storage/types.js} +0 -0
  179. /package/lib/{worker-transfer.d.ts → workers/worker-transfer.d.ts} +0 -0
  180. /package/lib/{worker-transfer.js → workers/worker-transfer.js} +0 -0
@@ -1,18 +1,24 @@
1
- import { WasixStorageError, } from './errors.js';
2
- import { loadNativeWasixAddon, } from './native-addon.js';
3
- import { normalizeWasixDatabaseIdentity, } from './database.js';
4
- import { validateWasixToolDescriptor } from './tool-runtime.js';
1
+ import { createRequire } from 'node:module';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { readFile } from 'node:fs/promises';
5
+ import { installPackageAssetReader } from '../../resources/asset-source.js';
6
+ import { loadAsset } from '../../resources/archive.js';
7
+ import { assertSha256, loadIcuData, loadSeedBytes } from '../../resources/extensions.js';
8
+ import { WasixStorageError, } from '../../core/errors.js';
9
+ import { loadNativeWasixAddon, nativeTarget, } from './native-addon.js';
10
+ import { normalizeWasixDatabaseIdentity, } from '../../core/database.js';
11
+ import { validateWasixToolDescriptor } from '../../resources/tool-runtime.js';
12
+ installPackageAssetReader(readFile);
5
13
  /** @internal A synchronous Rust Oliphaunt owned by the importing JavaScript realm. */
6
14
  export class NativeWasixSession {
7
15
  identity;
8
16
  terminalState;
9
- #addon;
10
17
  #handle;
11
18
  #runtimeVersion;
12
19
  #closed = false;
13
20
  #closeAttempt;
14
- constructor(addon, handle, identity, runtimeVersion) {
15
- this.#addon = addon;
21
+ constructor(handle, identity, runtimeVersion) {
16
22
  this.#handle = handle;
17
23
  this.identity = identity;
18
24
  this.#runtimeVersion = runtimeVersion;
@@ -35,9 +41,12 @@ export class NativeWasixSession {
35
41
  throw new TypeError(`@oliphaunt/wasix-ts ${provider} storage is browser-only`);
36
42
  }
37
43
  try {
38
- const handle = addon.NativeWasixDatabase.open(nativeOptions);
44
+ const handle = addon.NativeWasixDatabase.open({
45
+ ...nativeOptions,
46
+ ...(await loadNativeResources(options)),
47
+ });
39
48
  validateDatabaseHandle(handle);
40
- return new NativeWasixSession(addon, handle, normalizeWasixDatabaseIdentity(options.username, options.database), options.runtime.version);
49
+ return new NativeWasixSession(handle, normalizeWasixDatabaseIdentity(options.username, options.database), options.runtime.version);
41
50
  }
42
51
  catch (error) {
43
52
  throw mapNativeError(error);
@@ -90,25 +99,20 @@ export class NativeWasixSession {
90
99
  }
91
100
  async runTool(options) {
92
101
  this.#assertOpen();
93
- if (options.runtimeVersion !== '' && options.runtimeVersion !== this.#runtimeVersion) {
94
- throw new Error(`WASIX tools runtime ${options.runtimeVersion} is incompatible with database runtime ${this.#runtimeVersion}`);
95
- }
96
- validateWasixToolDescriptor(options.tool);
97
- const expectedIdentity = `${options.tool.sha256}:${options.tool.size}`;
98
- if (this.#addon.toolIdentity(options.tool.name) !== expectedIdentity) {
99
- throw new Error(`WASIX ${options.tool.name} descriptor does not match the tool embedded in the native addon`);
100
- }
102
+ const assets = await loadNativeToolAssets(this.#runtimeVersion, options);
101
103
  if (options.tool.name === 'pg_dump') {
102
104
  try {
103
- return toolProcessResult(this.#handle.pgDump(userPgDumpArguments(options.args, this.identity)));
105
+ return toolProcessResult(this.#handle.pgDump(options.args, assets));
104
106
  }
105
107
  catch (error) {
106
108
  throw this.#mapFailure(error);
107
109
  }
108
110
  }
109
- const parsed = userPsqlArguments(options.args, options.stdin, this.identity);
111
+ const script = options.stdin === undefined
112
+ ? undefined
113
+ : new TextDecoder('utf-8', { fatal: true }).decode(options.stdin);
110
114
  try {
111
- return toolProcessResult(this.#handle.psql(parsed.args, parsed.command, parsed.script));
115
+ return toolProcessResult(this.#handle.psql(options.args, assets, options.command, script));
112
116
  }
113
117
  catch (error) {
114
118
  throw this.#mapFailure(error);
@@ -146,13 +150,11 @@ export class NativeWasixSession {
146
150
  export class NativeWasixActorSession {
147
151
  identity;
148
152
  terminalState;
149
- #addon;
150
153
  #handle;
151
154
  #runtimeVersion;
152
155
  #closed = false;
153
156
  #closeAttempt;
154
- constructor(addon, handle, identity, runtimeVersion) {
155
- this.#addon = addon;
157
+ constructor(handle, identity, runtimeVersion) {
156
158
  this.#handle = handle;
157
159
  this.identity = identity;
158
160
  this.#runtimeVersion = runtimeVersion;
@@ -161,9 +163,12 @@ export class NativeWasixActorSession {
161
163
  static async open(options) {
162
164
  const addon = requireCompatibleNativeWasixAddon(options);
163
165
  try {
164
- const handle = await addon.NativeWasixActorDatabase.open(nativeWasixOpenOptions(options, nativeStorage(options)));
166
+ const handle = await addon.NativeWasixActorDatabase.open({
167
+ ...nativeWasixOpenOptions(options, nativeStorage(options)),
168
+ ...(await loadNativeResources(options)),
169
+ });
165
170
  validateActorDatabaseHandle(handle);
166
- return new NativeWasixActorSession(addon, handle, normalizeWasixDatabaseIdentity(options.username, options.database), options.runtime.version);
171
+ return new NativeWasixActorSession(handle, normalizeWasixDatabaseIdentity(options.username, options.database), options.runtime.version);
167
172
  }
168
173
  catch (error) {
169
174
  throw mapNativeError(error);
@@ -209,13 +214,15 @@ export class NativeWasixActorSession {
209
214
  }
210
215
  async runTool(options) {
211
216
  this.#assertOpen();
212
- validateNativeToolCall(this.#addon, this.#runtimeVersion, options);
217
+ const assets = await loadNativeToolAssets(this.#runtimeVersion, options);
213
218
  try {
214
219
  if (options.tool.name === 'pg_dump') {
215
- return toolProcessResult(await this.#handle.pgDump(userPgDumpArguments(options.args, this.identity)));
220
+ return toolProcessResult(await this.#handle.pgDump(options.args, assets));
216
221
  }
217
- const parsed = userPsqlArguments(options.args, options.stdin, this.identity);
218
- return toolProcessResult(await this.#handle.psql(parsed.args, parsed.command, parsed.script));
222
+ const script = options.stdin === undefined
223
+ ? undefined
224
+ : new TextDecoder('utf-8', { fatal: true }).decode(options.stdin);
225
+ return toolProcessResult(await this.#handle.psql(options.args, assets, options.command, script));
219
226
  }
220
227
  catch (error) {
221
228
  throw this.#mapFailure(error);
@@ -342,33 +349,29 @@ export function requireCompatibleNativeWasixAddon(options) {
342
349
  options.runtime.version !== addon.runtimeVersion()) {
343
350
  throw new Error(`WASIX runtime ${options.runtime.version} is incompatible with native runtime ${addon.runtimeVersion()}`);
344
351
  }
345
- if (options.icu !== undefined &&
346
- options.icu.compatibility.runtimeVersion !== options.runtime.version) {
347
- throw new Error('WASIX ICU descriptor is incompatible with the selected native runtime');
348
- }
349
- requireEmbeddedPayloadIdentity(addon, 'runtimeArchive', options.runtime.runtimeArchive, 'runtime archive');
350
- requireEmbeddedPayloadIdentity(addon, 'standardSeedArchive', options.runtime.standardSeedArchive, 'standard cluster seed archive');
351
- requireEmbeddedPayloadIdentity(addon, 'standardSeedManifest', options.runtime.standardSeedManifest, 'standard cluster seed manifest');
352
- if (options.icu !== undefined) {
353
- requireEmbeddedPayloadIdentity(addon, 'icuDataArchive', options.icu.dataArchive, 'ICU data archive');
354
- requireEmbeddedPayloadIdentity(addon, 'icuSeedArchive', options.icu.clusterSeedArchive, 'ICU cluster seed archive');
355
- requireEmbeddedPayloadIdentity(addon, 'icuSeedManifest', options.icu.clusterSeedManifest, 'ICU cluster seed manifest');
356
- }
357
352
  for (const [sqlName, carrier] of Object.entries(options.extensionCarriers)) {
358
353
  if (carrier.sqlName !== sqlName) {
359
354
  throw new Error(`WASIX extension carrier key ${sqlName} does not match ${carrier.sqlName}`);
360
355
  }
361
- const expectedIdentity = `${carrier.sha256}:${carrier.size}`;
362
- if (addon.extensionIdentity(sqlName) !== expectedIdentity) {
363
- throw new Error(`WASIX extension ${sqlName} descriptor does not match the archive embedded in the native addon`);
356
+ if (carrier.product !== 'oliphaunt-extension-contrib-pg18')
357
+ continue;
358
+ if (carrier.version !== addon.runtimeVersion()) {
359
+ throw new Error(`WASIX contrib extension ${sqlName} version ${carrier.version} is incompatible with native runtime ${addon.runtimeVersion()}`);
364
360
  }
365
361
  }
366
362
  return addon;
367
363
  }
368
- function requireEmbeddedPayloadIdentity(addon, component, descriptor, label) {
369
- if (addon.payloadIdentity(component) !== `${descriptor.sha256}:${descriptor.size}`) {
370
- throw new Error(`WASIX ${label} descriptor does not match the native addon payload`);
371
- }
364
+ export async function loadNativeResources(options) {
365
+ const [seed, icuData] = await Promise.all([
366
+ options.seed === undefined ? undefined : loadSeedBytes(options.seed),
367
+ options.icu === undefined ? undefined : loadIcuData(options.icu),
368
+ ]);
369
+ return {
370
+ ...(seed === undefined ? {} : { seed }),
371
+ ...(icuData === undefined
372
+ ? {}
373
+ : { icuData: { data: icuData.data, manifest: icuData.manifest } }),
374
+ };
372
375
  }
373
376
  /** @internal Project already-validated TS config onto the narrow native ABI. */
374
377
  export function nativeWasixOpenOptions(options, storage) {
@@ -379,9 +382,37 @@ export function nativeWasixOpenOptions(options, storage) {
379
382
  username: identity.username,
380
383
  database: identity.database,
381
384
  startupGucs: { ...options.startupGUCs },
382
- extensions: [...options.extensions],
385
+ extensions: [...new Set([...options.extensions, ...Object.keys(options.extensionCarriers)])],
386
+ extensionPackages: nativeExtensionPackages(options),
383
387
  };
384
388
  }
389
+ function nativeExtensionPackages(options) {
390
+ return Object.values(options.extensionCarriers)
391
+ .filter((carrier) => carrier.product !== 'oliphaunt-extension-contrib-pg18')
392
+ .map((carrier) => {
393
+ if (typeof carrier.source !== 'string' || !carrier.source.startsWith('file:')) {
394
+ throw new Error(`WASIX extension ${carrier.sqlName} requires an installed package on native hosts`);
395
+ }
396
+ const archive = fileURLToPath(carrier.source);
397
+ // Generated portable carriers own extensions/<sql-name>/extension.tar.zst.
398
+ const packageJson = join(dirname(dirname(dirname(archive))), 'package.json');
399
+ const name = `@oliphaunt/${carrier.product.slice('oliphaunt-'.length)}-wasix`;
400
+ const needsAot = carrier.install.nativeModule !== null || carrier.install.nativeModules.length > 0;
401
+ const target = nativeTarget(process.platform, process.arch, 'glibc').id;
402
+ const aotPackageJson = needsAot
403
+ ? createRequire(packageJson).resolve(`${name}-${target}/package.json`)
404
+ : undefined;
405
+ return {
406
+ sqlName: carrier.sqlName,
407
+ product: carrier.product,
408
+ version: carrier.version,
409
+ archiveSha256: carrier.sha256,
410
+ archiveSize: carrier.size,
411
+ packageJson,
412
+ ...(aotPackageJson === undefined ? {} : { aotPackageJson }),
413
+ };
414
+ });
415
+ }
385
416
  function nativeStorage(options) {
386
417
  if (options.storage.kind === 'memory')
387
418
  return { kind: 'memory' };
@@ -391,15 +422,22 @@ function nativeStorage(options) {
391
422
  const provider = options.storage.kind === 'indexed-db' ? 'IndexedDB' : 'OPFS';
392
423
  throw new TypeError(`@oliphaunt/wasix-ts ${provider} storage is browser-only`);
393
424
  }
394
- function validateNativeToolCall(addon, runtimeVersion, options) {
425
+ async function loadNativeToolAssets(runtimeVersion, options) {
395
426
  if (options.runtimeVersion !== '' && options.runtimeVersion !== runtimeVersion) {
396
427
  throw new Error(`WASIX tools runtime ${options.runtimeVersion} is incompatible with database runtime ${runtimeVersion}`);
397
428
  }
398
429
  validateWasixToolDescriptor(options.tool);
399
- const expectedIdentity = `${options.tool.sha256}:${options.tool.size}`;
400
- if (addon.toolIdentity(options.tool.name) !== expectedIdentity) {
401
- throw new Error(`WASIX ${options.tool.name} descriptor does not match the tool embedded in the native addon`);
402
- }
430
+ if (!options.tool.aot)
431
+ throw new Error('WASIX native tools require the installed target AOT carrier');
432
+ const [wasm, aot, manifest] = await Promise.all([
433
+ loadAsset(options.tool.source, 'WASIX tool module'),
434
+ loadAsset(options.tool.aot.source, 'WASIX tool AOT'),
435
+ loadAsset(options.tool.aot.manifest, 'WASIX tools AOT manifest'),
436
+ ]);
437
+ if (wasm.length !== options.tool.size)
438
+ throw new Error('WASIX tool module size mismatch');
439
+ await assertSha256(wasm, options.tool.sha256, 'WASIX tool module');
440
+ return { wasm, aot, manifest: new TextDecoder('utf-8', { fatal: true }).decode(manifest) };
403
441
  }
404
442
  function validateDatabaseHandle(handle) {
405
443
  if (typeof handle !== 'object' ||
@@ -446,59 +484,6 @@ function toolProcessResult(result) {
446
484
  stderr: binaryView(result.stderr),
447
485
  };
448
486
  }
449
- function userPgDumpArguments(args, identity) {
450
- const suffix = [
451
- '--encoding=UTF8',
452
- '--no-password',
453
- `--username=${identity.username}`,
454
- '--host=127.0.0.1',
455
- '--port=65432',
456
- `--dbname=${identity.database}`,
457
- ];
458
- return stripManagedSuffix('pg_dump', args, suffix);
459
- }
460
- function userPsqlArguments(args, stdin, identity) {
461
- const managed = [
462
- '--no-psqlrc',
463
- '--no-password',
464
- '--set=ON_ERROR_STOP=1',
465
- `--username=${identity.username}`,
466
- '--host=127.0.0.1',
467
- '--port=65432',
468
- `--dbname=${identity.database}`,
469
- ];
470
- const start = findExactSequence(args, managed);
471
- if (start < 0)
472
- throw new Error('Oliphaunt WASIX psql call has an invalid managed argument set');
473
- const user = args.slice(0, start);
474
- const input = args.slice(start + managed.length);
475
- if (input.length === 0)
476
- return { args: user };
477
- if (input.length === 2 && input[0] === '--command' && input[1] !== undefined) {
478
- return { args: user, command: input[1] };
479
- }
480
- if (input.length === 1 && input[0] === '--file=-' && stdin !== undefined) {
481
- return {
482
- args: user,
483
- script: new TextDecoder('utf-8', { fatal: true }).decode(stdin),
484
- };
485
- }
486
- throw new Error('Oliphaunt WASIX psql call has invalid managed input arguments');
487
- }
488
- function stripManagedSuffix(tool, args, suffix) {
489
- if (args.length < suffix.length ||
490
- !suffix.every((argument, index) => args[args.length - suffix.length + index] === argument)) {
491
- throw new Error(`Oliphaunt WASIX ${tool} call has an invalid managed argument set`);
492
- }
493
- return args.slice(0, -suffix.length);
494
- }
495
- function findExactSequence(values, expected) {
496
- for (let start = values.length - expected.length; start >= 0; start -= 1) {
497
- if (expected.every((value, offset) => values[start + offset] === value))
498
- return start;
499
- }
500
- return -1;
501
- }
502
487
  /** @internal Translate only the exact tagged native storage contract. */
503
488
  export function mapNativeError(error) {
504
489
  if (error instanceof WasixStorageError)
@@ -539,7 +524,7 @@ function nativeStorageError(error) {
539
524
  return undefined;
540
525
  const candidate = error;
541
526
  if (candidate.oliphauntWasixError !== 'storage' ||
542
- candidate.oliphauntWasixAddonAbi !== 1 ||
527
+ candidate.oliphauntWasixAddonAbi !== 3 ||
543
528
  !memberOf(candidate.code, STORAGE_CODES) ||
544
529
  !memberOf(candidate.commitState, STORAGE_COMMIT_STATES) ||
545
530
  !memberOf(candidate.phase, STORAGE_PHASES)) {
@@ -1,6 +1,6 @@
1
1
  import { NativeWasixActorSession } from './native-session.js';
2
- import type { SerializedOpenOptions } from './rpc.js';
3
- import type { OliphauntDatabase } from './types.js';
2
+ import type { SerializedOpenOptions } from '../../workers/rpc.js';
3
+ import type { OliphauntDatabase } from '../../core/types.js';
4
4
  /** @internal Open one Rust-owner actor without blocking the importing event loop. */
5
5
  export declare function openNodeActorSession(options: SerializedOpenOptions): Promise<NativeWasixActorSession>;
6
6
  /** @internal Open the public database contract over the native Rust owner. */
@@ -1,4 +1,4 @@
1
- import { WasixDatabaseImpl } from './database.js';
1
+ import { WasixDatabaseImpl } from '../../core/database.js';
2
2
  import { NativeWasixActorSession } from './native-session.js';
3
3
  /** @internal Open one Rust-owner actor without blocking the importing event loop. */
4
4
  export async function openNodeActorSession(options) {
@@ -1,6 +1,6 @@
1
- import type { SerializedOpenOptions } from './rpc.js';
2
- import type { PersistentWasixStorage } from './storage.js';
3
- import type { BinaryInput } from './types.js';
1
+ import type { SerializedOpenOptions } from '../../workers/rpc.js';
2
+ import type { PersistentWasixStorage } from '../../storage/types.js';
3
+ import type { BinaryInput } from '../../core/types.js';
4
4
  /** @internal Restore a physical archive through the Rust WASIX implementation. */
5
5
  export declare function restoreNodeWasix(storage: PersistentWasixStorage, bytes: BinaryInput): Promise<void>;
6
6
  /** @internal Restore synchronously in the importing realm for `/direct`. */
@@ -1,20 +1,20 @@
1
1
  import { isAbsolute, resolve } from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
- import { serializeOpenConfig } from './client-common.js';
3
+ import { serializeOpenConfig } from '../../core/open-config.js';
4
4
  import { hostRuntime } from './host-runtime.js';
5
5
  import { restoreNativeWasix, restoreNativeWasixDirect } from './native-session.js';
6
- import { toUint8Array } from './query.js';
6
+ import { toUint8Array } from '../../protocol/query.js';
7
7
  /** @internal Restore a physical archive through the Rust WASIX implementation. */
8
8
  export async function restoreNodeWasix(storage, bytes) {
9
9
  const options = serializeOpenConfig({ storage });
10
10
  requireNodeStorage(options);
11
- return restoreNativeWasix(options, toUint8Array(bytes).slice());
11
+ return restoreNativeWasix(options, toUint8Array(bytes));
12
12
  }
13
13
  /** @internal Restore synchronously in the importing realm for `/direct`. */
14
14
  export async function restoreNodeWasixDirect(storage, bytes) {
15
15
  const options = serializeOpenConfig({ storage });
16
16
  requireNodeStorage(options);
17
- return restoreNativeWasixDirect(options, toUint8Array(bytes).slice());
17
+ return restoreNativeWasixDirect(options, toUint8Array(bytes));
18
18
  }
19
19
  /** @internal Validate and normalize storage shared by direct and Worker entrypoints. */
20
20
  export function requireNodeStorage(options) {
@@ -1,4 +1,4 @@
1
- import type { OliphauntClient, OliphauntDatabase, OpenConfig } from './types.js';
1
+ import type { OliphauntClient, OliphauntDatabase, OpenConfig } from './native-public.js';
2
2
  /** Open PostgreSQL on a dedicated Rust owner while keeping the caller event loop responsive. */
3
3
  export declare function openWasix(config?: OpenConfig): Promise<OliphauntDatabase>;
4
4
  export declare const Oliphaunt: OliphauntClient;
@@ -1,4 +1,4 @@
1
- import { serializeOpenConfig } from './client-common.js';
1
+ import { serializeOpenConfig } from '../../core/open-config.js';
2
2
  import { requireNodeStorage, restoreNodeWasix } from './node-client-common.js';
3
3
  import { openNodeActor } from './node-actor.js';
4
4
  /** Open PostgreSQL on a dedicated Rust owner while keeping the caller event loop responsive. */
@@ -1,6 +1,6 @@
1
1
  import { NativeWasixSession } from './native-session.js';
2
- import type { SerializedOpenOptions } from './rpc.js';
3
- import type { OliphauntDatabase } from './types.js';
2
+ import type { SerializedOpenOptions } from '../../workers/rpc.js';
3
+ import type { OliphauntDatabase } from '../../core/types.js';
4
4
  /** @internal Own one synchronous Rust WASIX session in the current JS realm. */
5
5
  export declare function openNodeDirectSession(options: SerializedOpenOptions): Promise<NativeWasixSession>;
6
6
  /** @internal Open the public database contract in the current Node realm. */
@@ -1,4 +1,4 @@
1
- import { WasixDatabaseImpl } from './database.js';
1
+ import { WasixDatabaseImpl } from '../../core/database.js';
2
2
  import { NativeWasixSession } from './native-session.js';
3
3
  /** @internal Own one synchronous Rust WASIX session in the current JS realm. */
4
4
  export async function openNodeDirectSession(options) {
@@ -1,4 +1,4 @@
1
1
  import type { Worker } from 'node:worker_threads';
2
- import type { WasixWorkerPort } from './worker-rpc.js';
2
+ import type { WasixWorkerPort } from '../../workers/worker-rpc.js';
3
3
  /** @internal Adapt Node-compatible Worker events to the shared RPC transport. */
4
4
  export declare function nodeWorkerPort(worker: Worker, runtimeName?: string): WasixWorkerPort;
@@ -2,7 +2,7 @@ import { parentPort } from 'node:worker_threads';
2
2
  import { hostRuntimeName } from './host-runtime.js';
3
3
  import { openNodeDirectSession } from './node-direct.js';
4
4
  import { restoreNativeWasixStorageDirect } from './native-session.js';
5
- import { createWorkerSessionDispatcher } from './worker-dispatch.js';
5
+ import { createWorkerSessionDispatcher } from '../../workers/worker-dispatch.js';
6
6
  if (parentPort === null) {
7
7
  throw new Error(`@oliphaunt/wasix-ts ${hostRuntimeName()} host must run inside a Worker`);
8
8
  }
@@ -1,4 +1,4 @@
1
- import type { OliphauntClient, OliphauntDatabase, OpenConfig } from './types.js';
1
+ import type { OliphauntClient, OliphauntDatabase, OpenConfig } from './native-public.js';
2
2
  /** Open PostgreSQL in a package-owned Node-compatible Worker realm. */
3
3
  export declare function openWasix(config?: OpenConfig): Promise<OliphauntDatabase>;
4
4
  export declare const Oliphaunt: OliphauntClient;
@@ -1,15 +1,14 @@
1
1
  import { Worker } from 'node:worker_threads';
2
- import { serializeOpenConfig } from './client-common.js';
2
+ import { serializeOpenConfig } from '../../core/open-config.js';
3
3
  import { hostRuntimeName } from './host-runtime.js';
4
4
  import { requireNodeStorage } from './node-client-common.js';
5
5
  import { nodeWorkerExecArgv } from './node-worker-options.js';
6
6
  import { nodeWorkerPort } from './node-worker-port.js';
7
- import { openWasixWithWorker, restoreWasixWithWorker } from './worker-rpc.js';
7
+ import { openWasixWithWorker, restoreWasixWithWorker, } from '../../workers/worker-rpc.js';
8
8
  /** Open PostgreSQL in a package-owned Node-compatible Worker realm. */
9
9
  export async function openWasix(config = {}) {
10
- // The native Worker owns release-embedded runtime assets. Do not structured-
11
- // clone caller-provided WebAssembly archives that the N-API path will never
12
- // read; retain their exact identity metadata for compatibility validation.
10
+ // Runtime and contrib assets are embedded in the addon; external extensions
11
+ // still need their installed package URLs in the Worker.
13
12
  const openOptions = withoutNativeAssetPayloads(serializeOpenConfig(config));
14
13
  return openWasixWithWorker(createNodeWorker, openOptions, requireNodeStorage, false);
15
14
  }
@@ -33,23 +32,11 @@ function withoutNativeAssetPayloads(options) {
33
32
  runtime: {
34
33
  ...options.runtime,
35
34
  runtimeArchive: { ...options.runtime.runtimeArchive, source },
36
- standardSeedArchive: { ...options.runtime.standardSeedArchive, source },
37
- standardSeedManifest: { ...options.runtime.standardSeedManifest, source },
38
35
  manifest: { ...options.runtime.manifest, source },
39
36
  },
40
- ...(options.icu === undefined
41
- ? {}
42
- : {
43
- icu: {
44
- ...options.icu,
45
- dataArchive: { ...options.icu.dataArchive, source },
46
- clusterSeedArchive: { ...options.icu.clusterSeedArchive, source },
47
- clusterSeedManifest: { ...options.icu.clusterSeedManifest, source },
48
- },
49
- }),
50
37
  extensionCarriers: Object.fromEntries(Object.entries(options.extensionCarriers).map(([sqlName, carrier]) => [
51
38
  sqlName,
52
- { ...carrier, source },
39
+ carrier.product === 'oliphaunt-extension-contrib-pg18' ? { ...carrier, source } : carrier,
53
40
  ])),
54
41
  };
55
42
  }
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './node-client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/node-api/node-client.js';
2
+ export * from './hosts/node-api/native-public.js';
package/lib/index.bun.js CHANGED
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './node-client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/node-api/node-client.js';
2
+ export * from './hosts/node-api/native-public.js';
package/lib/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/browser/client.js';
2
+ export * from './hosts/browser/browser-public.js';
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './node-client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/node-api/node-client.js';
2
+ export * from './hosts/node-api/native-public.js';
package/lib/index.deno.js CHANGED
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './node-client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/node-api/node-client.js';
2
+ export * from './hosts/node-api/native-public.js';
package/lib/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/browser/client.js';
2
+ export * from './hosts/browser/browser-public.js';
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './node-client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/node-api/node-client.js';
2
+ export * from './hosts/node-api/native-public.js';
package/lib/index.node.js CHANGED
@@ -1,2 +1,2 @@
1
- export { Oliphaunt, Oliphaunt as default } from './node-client.js';
2
- export * from './public.js';
1
+ export { Oliphaunt, Oliphaunt as default } from './hosts/node-api/node-client.js';
2
+ export * from './hosts/node-api/native-public.js';
package/lib/internal.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { OliphauntDatabase } from './types.js';
2
- import { type WasixToolProcessOptions, type WasixToolProcessResult } from './internal-common.js';
3
- export { getWasixDatabaseIdentity } from './database.js';
4
- export type { WasixToolDescriptor, WasixToolProcessOptions, WasixToolProcessResult, } from './internal-common.js';
1
+ import type { OliphauntDatabase } from './core/types.js';
2
+ import { type WasixToolProcessOptions, type WasixToolProcessResult } from './hosts/browser/internal-common.js';
3
+ export { getWasixDatabaseIdentity } from './core/database.js';
4
+ export type { WasixToolDescriptor, WasixToolProcessOptions, WasixToolProcessResult, } from './hosts/browser/internal-common.js';
5
5
  export declare function runWasixToolProcess(database: OliphauntDatabase, options: WasixToolProcessOptions): Promise<WasixToolProcessResult>;
package/lib/internal.js CHANGED
@@ -1,13 +1,33 @@
1
- import { runWasixToolProcess as runTool, } from './internal-common.js';
2
- export { getWasixDatabaseIdentity } from './database.js';
1
+ import { runWasixToolProcess as runTool, } from './hosts/browser/internal-common.js';
2
+ import { getWasixDatabaseIdentity } from './core/database.js';
3
+ export { getWasixDatabaseIdentity } from './core/database.js';
3
4
  export function runWasixToolProcess(database, options) {
4
- return runTool(database, options, createBrowserToolWorker);
5
+ const identity = getWasixDatabaseIdentity(database);
6
+ const managed = options.tool.name === 'pg_dump'
7
+ ? ['--encoding=UTF8', '--no-password']
8
+ : ['--no-psqlrc', '--no-password', '--set=ON_ERROR_STOP=1'];
9
+ return runTool(database, {
10
+ ...options,
11
+ args: [
12
+ ...options.args,
13
+ ...managed,
14
+ `--username=${identity.username}`,
15
+ '--host=127.0.0.1',
16
+ '--port=65432',
17
+ `--dbname=${identity.database}`,
18
+ ...(options.command !== undefined
19
+ ? ['--command', options.command]
20
+ : options.stdin !== undefined
21
+ ? ['--file=-']
22
+ : []),
23
+ ],
24
+ }, createBrowserToolWorker);
5
25
  }
6
26
  function createBrowserToolWorker() {
7
27
  if (typeof Worker === 'undefined') {
8
28
  throw new Error('WASIX tools require Web Workers');
9
29
  }
10
- const worker = new Worker(new URL('./tool-worker.js', import.meta.url), {
30
+ const worker = new Worker(new URL('./hosts/browser/tool-worker.js', import.meta.url), {
11
31
  type: 'module',
12
32
  name: 'oliphaunt-wasix-tool',
13
33
  });
@@ -1,5 +1,5 @@
1
- import type { OliphauntDatabase } from './types.js';
2
- import type { WasixToolProcessOptions, WasixToolProcessResult } from './internal-common.js';
3
- export { getWasixDatabaseIdentity } from './database.js';
4
- export type { WasixToolDescriptor, WasixToolProcessOptions, WasixToolProcessResult, } from './internal-common.js';
1
+ import type { OliphauntDatabase } from './core/types.js';
2
+ import type { WasixToolProcessOptions, WasixToolProcessResult } from './hosts/browser/internal-common.js';
3
+ export { getWasixDatabaseIdentity } from './core/database.js';
4
+ export type { WasixToolDescriptor, WasixToolProcessOptions, WasixToolProcessResult, } from './hosts/browser/internal-common.js';
5
5
  export declare function runWasixToolProcess(database: OliphauntDatabase, options: WasixToolProcessOptions): Promise<WasixToolProcessResult>;
@@ -1,5 +1,5 @@
1
- import { tryRunWasixNativeToolProcess } from './database.js';
2
- export { getWasixDatabaseIdentity } from './database.js';
1
+ import { tryRunWasixNativeToolProcess } from './core/database.js';
2
+ export { getWasixDatabaseIdentity } from './core/database.js';
3
3
  export function runWasixToolProcess(database, options) {
4
4
  const native = tryRunWasixNativeToolProcess(database, options);
5
5
  if (native !== undefined)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ throw new Error('This @oliphaunt/wasix-ts entrypoint requires Node.js, Bun, or Deno; use @oliphaunt/wasix-ts/browser in a browser');
2
+ export {};
@@ -0,0 +1 @@
1
+ export * from '@oliphaunt/ts-query/protocol';
@@ -0,0 +1 @@
1
+ export * from '@oliphaunt/ts-query/protocol';
@@ -0,0 +1 @@
1
+ export * from '@oliphaunt/ts-query/query';
@@ -0,0 +1 @@
1
+ export * from '@oliphaunt/ts-query/query';
@@ -1,4 +1,4 @@
1
- import type { SerializedAssetSource } from './rpc.js';
1
+ import type { SerializedAssetSource } from '../workers/rpc.js';
2
2
  export type DirectoryFiles = Record<string, Uint8Array>;
3
3
  export type ExtractedArchive = {
4
4
  files: Map<string, Uint8Array>;
@@ -1,5 +1,5 @@
1
- import type { SerializedAssetSource } from './rpc.js';
2
- import type { WasixAssetSource } from './types.js';
1
+ import type { SerializedAssetSource } from '../workers/rpc.js';
2
+ import type { WasixAssetSource } from '../core/types.js';
3
3
  export declare function requireExactObject(value: unknown, fields: readonly string[], label: string): Record<string, unknown>;
4
4
  export declare function requireString(value: unknown, label: string): string;
5
5
  export declare function requireVersion(value: unknown, label: string): string;