@yydb/yydb 0.0.12 → 0.0.15

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 (53) hide show
  1. package/README.md +86 -86
  2. package/dist/api/database.d.ts +40 -0
  3. package/dist/api/database.js +16 -0
  4. package/dist/cli/cli.js +28 -1
  5. package/dist/cli/info-cmd.js +30 -1
  6. package/dist/cli/verify-cmd.d.ts +11 -0
  7. package/dist/cli/verify-cmd.js +73 -0
  8. package/dist/database.d.ts +50 -0
  9. package/dist/database.js +181 -0
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/micro.d.ts +63 -0
  13. package/dist/micro.js +160 -0
  14. package/dist/native/binding.d.ts +8 -0
  15. package/dist/native.d.ts +9 -0
  16. package/dist/native.js +32 -0
  17. package/dist/node/cli/cli.d.ts +1 -0
  18. package/dist/node/cli/cli.js +25 -0
  19. package/dist/node/cli/info-cmd.d.ts +3 -0
  20. package/dist/node/cli/info-cmd.js +10 -0
  21. package/dist/node/cli/init-cmd.d.ts +3 -0
  22. package/dist/node/cli/init-cmd.js +18 -0
  23. package/dist/node/cli/options.d.ts +4 -0
  24. package/dist/node/cli/options.js +14 -0
  25. package/dist/node/cli/serve-cmd.d.ts +3 -0
  26. package/dist/node/cli/serve-cmd.js +14 -0
  27. package/dist/node/cli/version-cmd.d.ts +3 -0
  28. package/dist/node/cli/version-cmd.js +8 -0
  29. package/dist/node/cli.d.ts +2 -0
  30. package/dist/node/cli.js +6 -0
  31. package/dist/node/database.d.ts +50 -0
  32. package/dist/node/database.js +173 -0
  33. package/dist/node/index.d.ts +7 -0
  34. package/dist/node/index.js +5 -0
  35. package/dist/node/native.d.ts +9 -0
  36. package/dist/node/native.js +32 -0
  37. package/dist/node/resolve-bin.d.ts +15 -0
  38. package/dist/node/resolve-bin.js +62 -0
  39. package/dist/resolve-bin.d.ts +15 -0
  40. package/dist/resolve-bin.js +62 -0
  41. package/dist/shared/errors.d.ts +62 -15
  42. package/dist/shared/errors.js +64 -41
  43. package/dist/shared/wasm-envelope.d.ts +41 -0
  44. package/dist/shared/wasm-envelope.js +56 -0
  45. package/dist/udf-types.d.ts +26 -0
  46. package/dist/udf-types.js +16 -0
  47. package/dist/wasm/binding.d.ts +1 -0
  48. package/dist/wasm/binding.js +1 -0
  49. package/dist/wasm/database.d.ts +54 -0
  50. package/dist/wasm/database.js +118 -0
  51. package/dist/wasm/index.d.ts +8 -0
  52. package/dist/wasm/index.js +5 -0
  53. package/package.json +40 -40
@@ -0,0 +1,5 @@
1
+ export { Database } from './database.js';
2
+ export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from '@yydb/yydb-client';
3
+ export { defineMicro, MicroSessionRegistry } from '../shared/micro.js';
4
+ export { nativeBindingName, platformKey, resolveYydbBinary, resolveYydbCli } from './resolve-bin.js';
5
+ export * from '../shared/vos.js';
@@ -0,0 +1,9 @@
1
+ export interface YydbNative {
2
+ version(): string;
3
+ serve(dbPath: string, bind: string, insecureBind?: boolean): void;
4
+ initDb(dbPath: string, schemaVersion: number, schemaDocument?: string | null): void;
5
+ infoText(dbPath: string): string;
6
+ readSchemaFile(schemaPath: string): string;
7
+ }
8
+ /** Load the platform native binding used by the `yydb` CLI. */
9
+ export declare function loadNative(): YydbNative;
@@ -0,0 +1,32 @@
1
+ import { createRequire } from 'node:module';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { platformKey } from './resolve-bin.js';
5
+ function loadModule(specifier) {
6
+ const require = createRequire(import.meta.url);
7
+ const loaded = require(specifier);
8
+ return (loaded.default ?? loaded);
9
+ }
10
+ /** Load the platform native binding used by the `yydb` CLI. */
11
+ export function loadNative() {
12
+ const fromEnv = process.env.YYDB_NATIVE?.trim();
13
+ if (fromEnv) {
14
+ const bindingPath = path.resolve(fromEnv);
15
+ if (!fs.existsSync(bindingPath)) {
16
+ throw new Error(`YYDB_NATIVE points to missing binding: ${fromEnv}`);
17
+ }
18
+ return loadModule(bindingPath);
19
+ }
20
+ const key = platformKey();
21
+ if (!key) {
22
+ throw new Error(`YYDB native binding not available for ${process.platform}-${process.arch}`);
23
+ }
24
+ const pkg = `@yydb/yydb-${key}`;
25
+ try {
26
+ return loadModule(pkg);
27
+ }
28
+ catch (error) {
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ throw new Error(`YYDB native binding not found. Reinstall @yydb/yydb with optional dependencies, set YYDB_NATIVE, or stage ${pkg}. ${message}`);
31
+ }
32
+ }
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ export type PlatformKey = 'win32-x64' | 'linux-x64' | 'darwin-x64' | 'darwin-arm64';
3
+ /** Map Node platform/arch to optionalDependency package suffix. */
4
+ export declare function platformKey(platform?: NodeJS.Platform, arch?: NodeJS.Architecture): PlatformKey | null;
5
+ /** Native binding filename inside each `@yydb/yydb-<platform>` package `lib/`. */
6
+ export declare function nativeBindingName(key: PlatformKey): string;
7
+ /**
8
+ * Resolve the TypeScript `yydb` CLI entry script.
9
+ * Order: `YYDB_CLI` → this package `dist/cli.js`.
10
+ */
11
+ export declare function resolveYydbCli(): string;
12
+ /**
13
+ * @deprecated Use {@link resolveYydbCli}. Kept for callers that still import this name.
14
+ */
15
+ export declare function resolveYydbBinary(): string;
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ /** Map Node platform/arch to optionalDependency package suffix. */
5
+ export function platformKey(platform = process.platform, arch = process.arch) {
6
+ if (platform === 'win32' && arch === 'x64')
7
+ return 'win32-x64';
8
+ if (platform === 'linux' && arch === 'x64')
9
+ return 'linux-x64';
10
+ if (platform === 'darwin' && arch === 'x64')
11
+ return 'darwin-x64';
12
+ if (platform === 'darwin' && arch === 'arm64')
13
+ return 'darwin-arm64';
14
+ return null;
15
+ }
16
+ /** Native binding filename inside each `@yydb/yydb-<platform>` package `lib/`. */
17
+ export function nativeBindingName(key) {
18
+ switch (key) {
19
+ case 'win32-x64':
20
+ return 'yydb-win32-x64-msvc.node';
21
+ case 'linux-x64':
22
+ return 'yydb-linux-x64-gnu.node';
23
+ case 'darwin-x64':
24
+ return 'yydb-darwin-x64.node';
25
+ case 'darwin-arm64':
26
+ return 'yydb-darwin-arm64.node';
27
+ }
28
+ }
29
+ function existsFile(filePath) {
30
+ try {
31
+ fs.accessSync(filePath, fs.constants.F_OK);
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ /**
39
+ * Resolve the TypeScript `yydb` CLI entry script.
40
+ * Order: `YYDB_CLI` → this package `dist/cli.js`.
41
+ */
42
+ export function resolveYydbCli() {
43
+ const fromEnv = process.env.YYDB_CLI?.trim();
44
+ if (fromEnv) {
45
+ if (!existsFile(fromEnv)) {
46
+ throw new Error(`YYDB_CLI points to missing script: ${fromEnv}`);
47
+ }
48
+ return path.resolve(fromEnv);
49
+ }
50
+ const here = path.dirname(fileURLToPath(import.meta.url));
51
+ const candidate = path.join(here, 'cli.js');
52
+ if (!existsFile(candidate)) {
53
+ throw new Error('YYDB CLI script not found. Build `@yydb/yydb` (`pnpm --filter @yydb/yydb build`) or set YYDB_CLI.');
54
+ }
55
+ return candidate;
56
+ }
57
+ /**
58
+ * @deprecated Use {@link resolveYydbCli}. Kept for callers that still import this name.
59
+ */
60
+ export function resolveYydbBinary() {
61
+ return resolveYydbCli();
62
+ }
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ export type PlatformKey = 'win32-x64' | 'linux-x64' | 'darwin-x64' | 'darwin-arm64';
3
+ /** Map Node platform/arch to optionalDependency package suffix. */
4
+ export declare function platformKey(platform?: NodeJS.Platform, arch?: NodeJS.Architecture): PlatformKey | null;
5
+ /** Native binding filename inside each `@yydb/yydb-<platform>` package `lib/`. */
6
+ export declare function nativeBindingName(key: PlatformKey): string;
7
+ /**
8
+ * Resolve the TypeScript `yydb` CLI entry script.
9
+ * Order: `YYDB_CLI` → this package `dist/cli.js`.
10
+ */
11
+ export declare function resolveYydbCli(): string;
12
+ /**
13
+ * @deprecated Use {@link resolveYydbCli}. Kept for callers that still import this name.
14
+ */
15
+ export declare function resolveYydbBinary(): string;
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ /** Map Node platform/arch to optionalDependency package suffix. */
5
+ export function platformKey(platform = process.platform, arch = process.arch) {
6
+ if (platform === 'win32' && arch === 'x64')
7
+ return 'win32-x64';
8
+ if (platform === 'linux' && arch === 'x64')
9
+ return 'linux-x64';
10
+ if (platform === 'darwin' && arch === 'x64')
11
+ return 'darwin-x64';
12
+ if (platform === 'darwin' && arch === 'arm64')
13
+ return 'darwin-arm64';
14
+ return null;
15
+ }
16
+ /** Native binding filename inside each `@yydb/yydb-<platform>` package `lib/`. */
17
+ export function nativeBindingName(key) {
18
+ switch (key) {
19
+ case 'win32-x64':
20
+ return 'yydb-win32-x64-msvc.node';
21
+ case 'linux-x64':
22
+ return 'yydb-linux-x64-gnu.node';
23
+ case 'darwin-x64':
24
+ return 'yydb-darwin-x64.node';
25
+ case 'darwin-arm64':
26
+ return 'yydb-darwin-arm64.node';
27
+ }
28
+ }
29
+ function existsFile(filePath) {
30
+ try {
31
+ fs.accessSync(filePath, fs.constants.F_OK);
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ /**
39
+ * Resolve the TypeScript `yydb` CLI entry script.
40
+ * Order: `YYDB_CLI` → this package `dist/cli.js`.
41
+ */
42
+ export function resolveYydbCli() {
43
+ const fromEnv = process.env.YYDB_CLI?.trim();
44
+ if (fromEnv) {
45
+ if (!existsFile(fromEnv)) {
46
+ throw new Error(`YYDB_CLI points to missing script: ${fromEnv}`);
47
+ }
48
+ return path.resolve(fromEnv);
49
+ }
50
+ const here = path.dirname(fileURLToPath(import.meta.url));
51
+ const candidate = path.join(here, 'cli.js');
52
+ if (!existsFile(candidate)) {
53
+ throw new Error('YYDB CLI script not found. Build `@yydb/yydb` (`pnpm --filter @yydb/yydb build`) or set YYDB_CLI.');
54
+ }
55
+ return candidate;
56
+ }
57
+ /**
58
+ * @deprecated Use {@link resolveYydbCli}. Kept for callers that still import this name.
59
+ */
60
+ export function resolveYydbBinary() {
61
+ return resolveYydbCli();
62
+ }
@@ -2,12 +2,57 @@
2
2
  * Host-facing YYDB error surface.
3
3
  *
4
4
  * Every public failure carries a stable `code`: engine codes come from the
5
- * Rust core (`yydb.schema.invalid`, …) over N-API or the wire, client codes
6
- * are minted locally with the `yydb.client.` prefix. Branch on `code` —
7
- * `message` is display text only.
5
+ * Rust core (`yydb.schema.invalid`, …) over N-API or the wire; client codes
6
+ * are minted locally with the `yydb.client.` prefix. **Branch on `code`** —
7
+ * `message` is display text only and must never be used for retry decisions.
8
+ *
9
+ * ## Where codes live
10
+ *
11
+ * Engine codes live in Rust (`yydb_types::Error` variants → DiagnosticEnvelope).
12
+ * The TS side no longer keeps a hardcoded engine-code table — when Rust gains a
13
+ * new variant, hosts pick up the new code string via {@link fromDiagnosticJson}
14
+ * without any TS change. Client codes (`yydb.client.*`) are minted only on the
15
+ * host side and remain available as constants below.
16
+ */
17
+ /**
18
+ * Client-side error codes that never originate from Rust.
19
+ *
20
+ * Engine codes (`yydb.schema.*`, `yydb.udf.*`, `yydb.io`, …) are emitted by
21
+ * Rust and should be matched via string literals or from the diagnostic JSON
22
+ * envelope — they are intentionally not duplicated here.
23
+ */
24
+ export declare const YydbClientErrorCodes: {
25
+ /** serve() endpoint is empty or invalid. */
26
+ readonly clientInvalidEndpoint: "yydb.client.invalid_endpoint";
27
+ /** connect() socket / transport layer failure. */
28
+ readonly clientTransportFailure: "yydb.client.transport_failure";
29
+ /** Server replied with a request id we did not send. */
30
+ readonly clientRequestIdMismatch: "yydb.client.request_id_mismatch";
31
+ /** Server replied with a msg_type we did not request. */
32
+ readonly clientUnexpectedResponse: "yydb.client.unexpected_response";
33
+ /** Could not parse an Error frame body from the wire. */
34
+ readonly clientDecodeFailure: "yydb.client.decode_failure";
35
+ /** The YYDB session is already closed. */
36
+ readonly sessionClosed: "yydb.session.closed";
37
+ };
38
+ /**
39
+ * @deprecated Engine codes moved to Rust — use string literals or match on
40
+ * {@link YydbError.code} returned from {@link fromDiagnosticJson}. This table
41
+ * exists only for transition; new engine error variants will **not** be added here.
8
42
  */
9
- /** Stable codes known to the TypeScript hosts. */
10
43
  export declare const YydbErrorCodes: {
44
+ /** serve() endpoint is empty or invalid. */
45
+ readonly clientInvalidEndpoint: "yydb.client.invalid_endpoint";
46
+ /** connect() socket / transport layer failure. */
47
+ readonly clientTransportFailure: "yydb.client.transport_failure";
48
+ /** Server replied with a request id we did not send. */
49
+ readonly clientRequestIdMismatch: "yydb.client.request_id_mismatch";
50
+ /** Server replied with a msg_type we did not request. */
51
+ readonly clientUnexpectedResponse: "yydb.client.unexpected_response";
52
+ /** Could not parse an Error frame body from the wire. */
53
+ readonly clientDecodeFailure: "yydb.client.decode_failure";
54
+ /** The YYDB session is already closed. */
55
+ readonly sessionClosed: "yydb.session.closed";
11
56
  readonly io: "yydb.io";
12
57
  readonly corrupt: "yydb.corrupt";
13
58
  readonly schemaConflict: "yydb.schema.conflict";
@@ -25,21 +70,23 @@ export declare const YydbErrorCodes: {
25
70
  readonly fencingMismatch: "yydb.fencing.mismatch";
26
71
  readonly leaseExpired: "yydb.lease.expired";
27
72
  readonly quotaExceeded: "yydb.quota.exceeded";
28
- readonly sessionClosed: "yydb.session.closed";
29
- readonly clientInvalidEndpoint: "yydb.client.invalid_endpoint";
30
- readonly clientTransportFailure: "yydb.client.transport_failure";
31
- readonly clientRequestIdMismatch: "yydb.client.request_id_mismatch";
32
- readonly clientUnexpectedResponse: "yydb.client.unexpected_response";
33
- readonly clientDecodeFailure: "yydb.client.decode_failure";
34
73
  };
35
- /** A known code, or any future code the engine introduces. */
36
- export type YydbErrorCode = (typeof YydbErrorCodes)[keyof typeof YydbErrorCodes] | (string & {});
37
- /** Whether `code` may be retried with the same arguments. */
38
- export declare function isRetryableYydbCode(code: string): boolean;
74
+ /** Any stable YYDB error code string — engine, client, or future variant. */
75
+ export type YydbErrorCode = string;
39
76
  /** Options carried by a {@link YydbError}. */
40
77
  export interface YydbErrorOptions {
41
78
  /** Operation that failed (`schemaGet`, `kvPut`, `query`, …). */
42
79
  operation?: string;
80
+ /**
81
+ * Whether the caller may retry with the same arguments.
82
+ *
83
+ * When omitted, constructor defaults to `false` (conservative). Callers
84
+ * that mint their own errors (especially client-local retryable ones like
85
+ * `yydb.client.transport_failure`) **must** set this explicitly. Engine
86
+ * errors coming through {@link fromDiagnosticJson} always carry the Rust-
87
+ * authoritative `retryable` value and override the default.
88
+ */
89
+ retryable?: boolean;
43
90
  /** Structured parameters for catalog templating (when present). */
44
91
  params?: Readonly<Record<string, string>>;
45
92
  /** Underlying failure when this error wraps one. */
@@ -47,7 +94,7 @@ export interface YydbErrorOptions {
47
94
  }
48
95
  /** YYDB failure with a stable machine-readable {@link YydbError.code}. */
49
96
  export declare class YydbError extends Error {
50
- /** Stable code — engine code or `yydb.client.*`. */
97
+ /** Stable code — engine code (from Rust) or `yydb.client.*`. */
51
98
  readonly code: string;
52
99
  /** Operation that failed. */
53
100
  readonly operation: string;
@@ -2,12 +2,46 @@
2
2
  * Host-facing YYDB error surface.
3
3
  *
4
4
  * Every public failure carries a stable `code`: engine codes come from the
5
- * Rust core (`yydb.schema.invalid`, …) over N-API or the wire, client codes
6
- * are minted locally with the `yydb.client.` prefix. Branch on `code` —
7
- * `message` is display text only.
5
+ * Rust core (`yydb.schema.invalid`, …) over N-API or the wire; client codes
6
+ * are minted locally with the `yydb.client.` prefix. **Branch on `code`** —
7
+ * `message` is display text only and must never be used for retry decisions.
8
+ *
9
+ * ## Where codes live
10
+ *
11
+ * Engine codes live in Rust (`yydb_types::Error` variants → DiagnosticEnvelope).
12
+ * The TS side no longer keeps a hardcoded engine-code table — when Rust gains a
13
+ * new variant, hosts pick up the new code string via {@link fromDiagnosticJson}
14
+ * without any TS change. Client codes (`yydb.client.*`) are minted only on the
15
+ * host side and remain available as constants below.
16
+ */
17
+ /**
18
+ * Client-side error codes that never originate from Rust.
19
+ *
20
+ * Engine codes (`yydb.schema.*`, `yydb.udf.*`, `yydb.io`, …) are emitted by
21
+ * Rust and should be matched via string literals or from the diagnostic JSON
22
+ * envelope — they are intentionally not duplicated here.
23
+ */
24
+ export const YydbClientErrorCodes = {
25
+ /** serve() endpoint is empty or invalid. */
26
+ clientInvalidEndpoint: 'yydb.client.invalid_endpoint',
27
+ /** connect() socket / transport layer failure. */
28
+ clientTransportFailure: 'yydb.client.transport_failure',
29
+ /** Server replied with a request id we did not send. */
30
+ clientRequestIdMismatch: 'yydb.client.request_id_mismatch',
31
+ /** Server replied with a msg_type we did not request. */
32
+ clientUnexpectedResponse: 'yydb.client.unexpected_response',
33
+ /** Could not parse an Error frame body from the wire. */
34
+ clientDecodeFailure: 'yydb.client.decode_failure',
35
+ /** The YYDB session is already closed. */
36
+ sessionClosed: 'yydb.session.closed',
37
+ };
38
+ /**
39
+ * @deprecated Engine codes moved to Rust — use string literals or match on
40
+ * {@link YydbError.code} returned from {@link fromDiagnosticJson}. This table
41
+ * exists only for transition; new engine error variants will **not** be added here.
8
42
  */
9
- /** Stable codes known to the TypeScript hosts. */
10
43
  export const YydbErrorCodes = {
44
+ // Engine codes (deprecated)
11
45
  io: 'yydb.io',
12
46
  corrupt: 'yydb.corrupt',
13
47
  schemaConflict: 'yydb.schema.conflict',
@@ -25,30 +59,12 @@ export const YydbErrorCodes = {
25
59
  fencingMismatch: 'yydb.fencing.mismatch',
26
60
  leaseExpired: 'yydb.lease.expired',
27
61
  quotaExceeded: 'yydb.quota.exceeded',
28
- sessionClosed: 'yydb.session.closed',
29
- clientInvalidEndpoint: 'yydb.client.invalid_endpoint',
30
- clientTransportFailure: 'yydb.client.transport_failure',
31
- clientRequestIdMismatch: 'yydb.client.request_id_mismatch',
32
- clientUnexpectedResponse: 'yydb.client.unexpected_response',
33
- clientDecodeFailure: 'yydb.client.decode_failure',
62
+ // Client codes (still canonical for client-local errors)
63
+ ...YydbClientErrorCodes,
34
64
  };
35
- /**
36
- * Codes where retrying the same operation can legitimately succeed: a socket or
37
- * lease hiccup, or a compare-and-set that lost a benign race. Every other code
38
- * needs the caller to change input, schema, or wiring first.
39
- */
40
- const RETRYABLE_CODES = new Set([
41
- YydbErrorCodes.clientTransportFailure,
42
- YydbErrorCodes.casConflict,
43
- YydbErrorCodes.leaseUnavailable,
44
- ]);
45
- /** Whether `code` may be retried with the same arguments. */
46
- export function isRetryableYydbCode(code) {
47
- return RETRYABLE_CODES.has(code);
48
- }
49
65
  /** YYDB failure with a stable machine-readable {@link YydbError.code}. */
50
66
  export class YydbError extends Error {
51
- /** Stable code — engine code or `yydb.client.*`. */
67
+ /** Stable code — engine code (from Rust) or `yydb.client.*`. */
52
68
  code;
53
69
  /** Operation that failed. */
54
70
  operation;
@@ -61,8 +77,10 @@ export class YydbError extends Error {
61
77
  this.name = 'YydbError';
62
78
  this.code = code;
63
79
  this.operation = options.operation ?? 'unknown';
64
- this.retryable = isRetryableYydbCode(code);
65
- this.params = options.params;
80
+ this.retryable = options.retryable ?? false;
81
+ if (options.params !== undefined) {
82
+ this.params = options.params;
83
+ }
66
84
  }
67
85
  /**
68
86
  * Parse the diagnostic JSON that N-API and WASM surfaces embed in their
@@ -106,23 +124,28 @@ export class YydbError extends Error {
106
124
  else {
107
125
  return null;
108
126
  }
109
- const code = typeof obj.code === 'string' ? obj.code : null;
110
- const message = typeof obj.message === 'string' ? obj.message : '';
127
+ // WASM envelopes nest the diagnostic under `{ ok, error: {...} }`.
128
+ let diag = obj;
129
+ if (typeof obj['ok'] === 'boolean' && !obj['ok'] && obj['error'] && typeof obj['error'] === 'object') {
130
+ diag = obj['error'];
131
+ }
132
+ const code = typeof diag['code'] === 'string' ? diag['code'] : null;
133
+ const message = typeof diag['message'] === 'string' ? diag['message'] : '';
111
134
  if (!code)
112
135
  return null;
113
- const operation = typeof obj.operation === 'string' ? obj.operation : undefined;
114
- const retryable = typeof obj.retryable === 'boolean' ? obj.retryable : undefined;
115
- const params = obj.params && typeof obj.params === 'object'
116
- ? obj.params
136
+ const operation = typeof diag['operation'] === 'string' ? diag['operation'] : undefined;
137
+ const retryable = typeof diag['retryable'] === 'boolean' ? diag['retryable'] : undefined;
138
+ const params = diag['params'] && typeof diag['params'] === 'object'
139
+ ? diag['params']
117
140
  : undefined;
118
- const err = new YydbError(code, message, {
119
- operation,
120
- params,
121
- });
122
- if (typeof retryable === 'boolean') {
123
- err.retryable = retryable;
124
- }
125
- return err;
141
+ const opts = {};
142
+ if (operation !== undefined)
143
+ opts.operation = operation;
144
+ if (retryable !== undefined)
145
+ opts.retryable = retryable;
146
+ if (params !== undefined)
147
+ opts.params = params;
148
+ return new YydbError(code, message, opts);
126
149
  }
127
150
  }
128
151
  /** Narrowing helper so callers can branch without `instanceof` imports. */
@@ -0,0 +1,41 @@
1
+ /** Parsed `{ ok, rows, error, code }` envelope from wasm VOS calls. */
2
+ export type WasmRowsResult = {
3
+ ok: boolean;
4
+ rows: Record<string, unknown>[];
5
+ error: string | null;
6
+ code: string | null;
7
+ };
8
+ /** Parsed `{ ok, schema, error, code }` envelope from wasm `getSchema`. */
9
+ export type WasmSchemaResult = {
10
+ ok: boolean;
11
+ schema: {
12
+ version: number;
13
+ document: string;
14
+ } | null;
15
+ error: string | null;
16
+ code: string | null;
17
+ };
18
+ /** Parsed `{ ok, value, error, code }` envelope from wasm `get`. */
19
+ export type WasmKvGetResult = {
20
+ ok: boolean;
21
+ value: number[] | null;
22
+ error: string | null;
23
+ code: string | null;
24
+ };
25
+ /** Parsed `{ ok, value, error, code }` envelope from wasm `callScalar`. */
26
+ export type WasmScalarResult = {
27
+ ok: boolean;
28
+ value: string | number | boolean | null;
29
+ error: string | null;
30
+ code: string | null;
31
+ };
32
+ export type WireScalarValue = string | number | boolean | null;
33
+ export type SchemaVersion = {
34
+ version: number;
35
+ document: string;
36
+ };
37
+ export declare function parseWasmRowsResult(payload: string, operation: string): WasmRowsResult;
38
+ export declare function parseWasmUnitResult(payload: string, operation: string): void;
39
+ export declare function parseWasmSchemaResult(payload: string, operation: string): SchemaVersion | null;
40
+ export declare function parseWasmScalarResult(payload: string, operation: string): WireScalarValue;
41
+ export declare function parseWasmKvGetResult(payload: string, operation: string): Uint8Array | null;
@@ -0,0 +1,56 @@
1
+ import { YydbError, YydbErrorCodes } from '@yydb/yydb-client';
2
+ function parseJson(payload, operation) {
3
+ try {
4
+ return JSON.parse(payload);
5
+ }
6
+ catch (cause) {
7
+ throw new YydbError(YydbErrorCodes.clientDecodeFailure, `${operation}: invalid JSON envelope`, { operation, cause });
8
+ }
9
+ }
10
+ /**
11
+ * Build the error for a failed wasm envelope. The Rust core always sends a
12
+ * stable `code`; a missing one means the wasm artifact is stale, which is a
13
+ * decode failure rather than an engine failure.
14
+ */
15
+ function envelopeError(envelope, operation) {
16
+ const code = envelope.code ?? YydbErrorCodes.clientDecodeFailure;
17
+ const message = envelope.error ?? `${operation}: wasm envelope carried no message`;
18
+ return new YydbError(code, message, { operation });
19
+ }
20
+ export function parseWasmRowsResult(payload, operation) {
21
+ const parsed = parseJson(payload, operation);
22
+ if (!parsed.ok) {
23
+ throw envelopeError(parsed, operation);
24
+ }
25
+ return parsed;
26
+ }
27
+ export function parseWasmUnitResult(payload, operation) {
28
+ const parsed = parseJson(payload, operation);
29
+ if (!parsed.ok) {
30
+ throw envelopeError(parsed, operation);
31
+ }
32
+ }
33
+ export function parseWasmSchemaResult(payload, operation) {
34
+ const parsed = parseJson(payload, operation);
35
+ if (!parsed.ok) {
36
+ throw envelopeError(parsed, operation);
37
+ }
38
+ return parsed.schema;
39
+ }
40
+ export function parseWasmScalarResult(payload, operation) {
41
+ const parsed = parseJson(payload, operation);
42
+ if (!parsed.ok) {
43
+ throw envelopeError(parsed, operation);
44
+ }
45
+ return parsed.value;
46
+ }
47
+ export function parseWasmKvGetResult(payload, operation) {
48
+ const parsed = parseJson(payload, operation);
49
+ if (!parsed.ok) {
50
+ throw envelopeError(parsed, operation);
51
+ }
52
+ if (parsed.value === null) {
53
+ return null;
54
+ }
55
+ return Uint8Array.from(parsed.value);
56
+ }
@@ -0,0 +1,26 @@
1
+ /** Phase-1 scalar UDF wire kinds aligned with `yydb-udf`. */
2
+ export type UdfScalarKind = 'i64' | 'bool' | 'text' | 'null';
3
+ /** Runtime type descriptor used in `defineMicro` contracts. */
4
+ export interface UdfTypeDescriptor<T = unknown> {
5
+ readonly kind: UdfScalarKind;
6
+ /** Phantom type for author-side inference only. */
7
+ readonly _type?: T;
8
+ }
9
+ /** `i64` argument or return descriptor. */
10
+ export declare function i64(): UdfTypeDescriptor<number>;
11
+ /** `bool` argument or return descriptor. */
12
+ export declare function bool(): UdfTypeDescriptor<boolean>;
13
+ /** `text` argument or return descriptor. */
14
+ export declare function text(): UdfTypeDescriptor<string>;
15
+ /** `null` return descriptor. */
16
+ export declare function nullType(): UdfTypeDescriptor<null>;
17
+ /** Maps descriptor tuple types to positional argument types. */
18
+ export type InferUdfArgs<T extends readonly UdfTypeDescriptor[]> = {
19
+ [K in keyof T]: T[K] extends UdfTypeDescriptor<infer V> ? V : never;
20
+ };
21
+ /** Maps a return descriptor to its value type. */
22
+ export type InferUdfReturn<T extends UdfTypeDescriptor> = T extends UdfTypeDescriptor<infer V> ? V : never;
23
+ /** Session micro effect surface (Phase 1: pure only). */
24
+ export type MicroEffect = 'pure';
25
+ /** Invocation mode stored with the definition for future batch host calls. */
26
+ export type MicroInvocationMode = 'scalar' | 'batch';
@@ -0,0 +1,16 @@
1
+ /** `i64` argument or return descriptor. */
2
+ export function i64() {
3
+ return { kind: 'i64' };
4
+ }
5
+ /** `bool` argument or return descriptor. */
6
+ export function bool() {
7
+ return { kind: 'bool' };
8
+ }
9
+ /** `text` argument or return descriptor. */
10
+ export function text() {
11
+ return { kind: 'text' };
12
+ }
13
+ /** `null` return descriptor. */
14
+ export function nullType() {
15
+ return { kind: 'null' };
16
+ }
@@ -0,0 +1 @@
1
+ export { checkSchema, createMemorySession, initWasm, introspectSchema, openPersistentSession, queryMemory, resetWasmBindingForTests, yydbVersion, type CheckSchemaResult, type InitWasmOptions, type WasmInitInput, type WasmSession, } from '@yydb/yydb-unknown-wasm32';
@@ -0,0 +1 @@
1
+ export { checkSchema, createMemorySession, initWasm, introspectSchema, openPersistentSession, queryMemory, resetWasmBindingForTests, yydbVersion, } from '@yydb/yydb-unknown-wasm32';
@@ -0,0 +1,54 @@
1
+ import { defineMicro as buildMicro, type DefinedMicro, type MicroHandle } from '../shared/micro.js';
2
+ import type { UdfScalarDescriptor } from '../shared/udf-types.js';
3
+ import { type SchemaVersion } from '../shared/wasm-envelope.js';
4
+ import { type CheckSchemaResult, type InitWasmOptions } from './binding.js';
5
+ export type WasmOpenOptions = InitWasmOptions;
6
+ /**
7
+ * Browser-facing YYDB handle backed by an in-process wasm session.
8
+ * Use `open` for OPFS-backed paths and `openInMemory` for ephemeral state.
9
+ */
10
+ export declare class Database {
11
+ readonly path: string;
12
+ private session;
13
+ private readonly kind;
14
+ private readonly microRegistry;
15
+ private constructor();
16
+ /** Open an OPFS-backed database at `path` (for example `app.yydb`). */
17
+ static open(path: string, options?: WasmOpenOptions): Promise<Database>;
18
+ /** Open a stateful in-memory database session. */
19
+ static openInMemory(options?: WasmOpenOptions): Promise<Database>;
20
+ /** Library version from the wasm binding. */
21
+ version(): string;
22
+ /** Engine version string (Node API parity). */
23
+ serverVersion(): Promise<string>;
24
+ /** Database info text (`path=…\\n…`), matching the YY wire `Info` reply. */
25
+ info(): Promise<string>;
26
+ /** Parse and validate a VOS schema document without opening a session. */
27
+ checkSchema(source: string): CheckSchemaResult;
28
+ /** Persist schema document. `version` is accepted for Node API parity; wasm uses the document body. */
29
+ ensureSchema(_version: number, document: string): Promise<void>;
30
+ getSchema(): Promise<SchemaVersion | null>;
31
+ get(key: string): Promise<Uint8Array | null>;
32
+ put(key: string, value: Uint8Array | string): Promise<void>;
33
+ /** VOS read pipeline (for example `User.filter(x => x.active).collect()`). */
34
+ query(source: string): Record<string, unknown>[];
35
+ /** Unit-valued VOS write programs (for example `User { … }.insert()`). */
36
+ execute(source: string): void;
37
+ /**
38
+ * Build a typed session-local micro definition. Does not register it with
39
+ * the engine until `registerMicro` is called.
40
+ */
41
+ defineMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: Parameters<typeof buildMicro<TArgs, TReturn>>[0]): DefinedMicro<TArgs, TReturn>;
42
+ /**
43
+ * Install a `defineMicro` definition into the current session registry and
44
+ * sync metadata to the embedded engine. Host micros are session-local.
45
+ */
46
+ registerMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: DefinedMicro<TArgs, TReturn>): Promise<MicroHandle>;
47
+ /** Invoke a registered scalar UDF on the embedded engine. */
48
+ callScalar(name: string, version: number, args: readonly (string | number | boolean | null)[]): Promise<string | number | boolean | null>;
49
+ /** Whether this handle owns a persistent OPFS session. */
50
+ isPersistent(): boolean;
51
+ /** Close the embedded session. Idempotent; further calls fail with `yydb.session.closed`. */
52
+ close(): Promise<void>;
53
+ private requireSession;
54
+ }