@yydb/yydb 0.0.4 → 0.0.6
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.
- package/README.md +72 -22
- package/dist/{cli → node/cli}/cli.js +1 -1
- package/dist/{database.d.ts → node/database.d.ts} +4 -4
- package/dist/{database.js → node/database.js} +3 -11
- package/dist/node/index.d.ts +7 -0
- package/dist/node/index.js +5 -0
- package/dist/{micro.d.ts → shared/micro.d.ts} +22 -7
- package/dist/{micro.js → shared/micro.js} +77 -44
- package/dist/shared/udf-types.d.ts +34 -0
- package/dist/shared/udf-types.js +14 -0
- package/dist/shared/vos.d.ts +19 -0
- package/dist/shared/vos.js +15 -0
- package/dist/shared/wasm-envelope.d.ts +40 -0
- package/dist/shared/wasm-envelope.js +49 -0
- package/dist/wasm/binding.d.ts +1 -0
- package/dist/wasm/binding.js +1 -0
- package/dist/wasm/database.d.ts +50 -0
- package/dist/wasm/database.js +110 -0
- package/dist/wasm/index.d.ts +8 -0
- package/dist/wasm/index.js +5 -0
- package/package.json +27 -16
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -4
- package/dist/udf-types.d.ts +0 -26
- package/dist/udf-types.js +0 -16
- /package/dist/{cli → node/cli}/cli.d.ts +0 -0
- /package/dist/{cli → node/cli}/info-cmd.d.ts +0 -0
- /package/dist/{cli → node/cli}/info-cmd.js +0 -0
- /package/dist/{cli → node/cli}/init-cmd.d.ts +0 -0
- /package/dist/{cli → node/cli}/init-cmd.js +0 -0
- /package/dist/{cli → node/cli}/options.d.ts +0 -0
- /package/dist/{cli → node/cli}/options.js +0 -0
- /package/dist/{cli → node/cli}/serve-cmd.d.ts +0 -0
- /package/dist/{cli → node/cli}/serve-cmd.js +0 -0
- /package/dist/{cli → node/cli}/version-cmd.d.ts +0 -0
- /package/dist/{cli → node/cli}/version-cmd.js +0 -0
- /package/dist/{cli.d.ts → node/cli.d.ts} +0 -0
- /package/dist/{cli.js → node/cli.js} +0 -0
- /package/dist/{native.d.ts → node/native.d.ts} +0 -0
- /package/dist/{native.js → node/native.js} +0 -0
- /package/dist/{resolve-bin.d.ts → node/resolve-bin.d.ts} +0 -0
- /package/dist/{resolve-bin.js → node/resolve-bin.js} +0 -0
package/README.md
CHANGED
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
# `@yydb/yydb`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Node all-in-one and browser wasm core from one package. On Node.js, `Database.open` starts a private loopback `yydb serve`
|
|
4
|
+
process and talks over the YY wire protocol. In browsers, `@yydb/yydb/wasm` loads an in-process wasm session with KV
|
|
5
|
+
and schema on memory or OPFS paths.
|
|
6
|
+
|
|
7
|
+
For a wire client only (renderer or an app that already runs `yydb serve`), use
|
|
8
|
+
[`@yydb/yydb-client`](https://www.npmjs.com/package/@yydb/yydb-client).
|
|
6
9
|
|
|
7
10
|
[](https://www.npmjs.com/package/@yydb/yydb)
|
|
8
11
|
[](https://www.npmjs.com/package/@yydb/yydb)
|
|
9
12
|
|
|
10
13
|
## Exports
|
|
11
14
|
|
|
12
|
-
| Import
|
|
13
|
-
|
|
14
|
-
| `@yydb/yydb`
|
|
15
|
-
| `@yydb/yydb
|
|
15
|
+
| Import | Runtime | Role |
|
|
16
|
+
|--------|---------|------|
|
|
17
|
+
| `@yydb/yydb` | Node (`node` export condition) | `Database.open`, micro helpers |
|
|
18
|
+
| `@yydb/yydb` | Browser / bundler (`default`) | wasm `Database` |
|
|
19
|
+
| `@yydb/yydb/node` | Node (explicit) | Same as Node default |
|
|
20
|
+
| `@yydb/yydb/wasm` | Browser (explicit) | wasm `Database`, `initWasm`, `checkSchema` |
|
|
21
|
+
| `@yydb/yydb/cli` | Node | CLI (`version`, `init`, `info`, `serve`) |
|
|
16
22
|
|
|
17
|
-
Node.js 18+.
|
|
23
|
+
Node.js 18+. Platform `.node` bindings install via optional dependencies.
|
|
18
24
|
|
|
19
|
-
Schema truth lives in the `.yydb` file via `ensureSchema` and VOS documents.
|
|
25
|
+
Schema truth lives in the `.yydb` file via `ensureSchema` and VOS documents. Wasm sessions mirror KV and schema calls
|
|
26
|
+
on the embedded core.
|
|
20
27
|
|
|
21
|
-
##
|
|
28
|
+
## Node example
|
|
22
29
|
|
|
23
30
|
```ts
|
|
24
|
-
import {Database} from
|
|
31
|
+
import { Database } from '@yydb/yydb';
|
|
25
32
|
|
|
26
|
-
const db = await Database.open(
|
|
33
|
+
const db = await Database.open('./data/app.yydb');
|
|
27
34
|
|
|
28
35
|
await db.ensureSchema(
|
|
29
36
|
1,
|
|
@@ -34,14 +41,54 @@ await db.ensureSchema(
|
|
|
34
41
|
}`,
|
|
35
42
|
);
|
|
36
43
|
|
|
37
|
-
await db.put(
|
|
38
|
-
console.log(await db.get(
|
|
44
|
+
await db.put('theme', 'dark');
|
|
45
|
+
console.log(await db.get('theme'));
|
|
39
46
|
await db.close();
|
|
40
47
|
```
|
|
41
48
|
|
|
42
49
|
The file is created when missing. Schema version and VOS document persist with the data.
|
|
43
50
|
|
|
44
|
-
##
|
|
51
|
+
## Browser example
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { Database } from '@yydb/yydb/wasm';
|
|
55
|
+
|
|
56
|
+
const db = await Database.openInMemory();
|
|
57
|
+
|
|
58
|
+
await db.ensureSchema(
|
|
59
|
+
1,
|
|
60
|
+
`table Setting {
|
|
61
|
+
@@id: uuid,
|
|
62
|
+
key: utf8,
|
|
63
|
+
value: utf8,
|
|
64
|
+
}`,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
await db.put('theme', 'dark');
|
|
68
|
+
console.log(await db.get('theme'));
|
|
69
|
+
db.close();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Use `Database.open('app.yydb')` for OPFS-backed paths in supported browsers.
|
|
73
|
+
|
|
74
|
+
## Wasm API
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const db = await Database.openInMemory();
|
|
78
|
+
// or: const db = await Database.open('app.yydb');
|
|
79
|
+
|
|
80
|
+
await db.ensureSchema(version, vosDocument);
|
|
81
|
+
await db.getSchema();
|
|
82
|
+
await db.put(key, stringOrBytes);
|
|
83
|
+
await db.get(key);
|
|
84
|
+
await db.info();
|
|
85
|
+
await db.serverVersion();
|
|
86
|
+
await db.registerMicro(microDefinition);
|
|
87
|
+
await db.callScalar('double', 1, [21]);
|
|
88
|
+
db.close();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Node API
|
|
45
92
|
|
|
46
93
|
```ts
|
|
47
94
|
const db = await Database.open(path, options?);
|
|
@@ -52,6 +99,8 @@ await db.put(key, stringOrBytes);
|
|
|
52
99
|
await db.get(key);
|
|
53
100
|
await db.info();
|
|
54
101
|
await db.serverVersion();
|
|
102
|
+
await db.registerMicro(microDefinition);
|
|
103
|
+
await db.callScalar('double', 1, [21]);
|
|
55
104
|
await db.close();
|
|
56
105
|
```
|
|
57
106
|
|
|
@@ -60,14 +109,15 @@ arguments). `binary` is a deprecated alias for `cli`.
|
|
|
60
109
|
|
|
61
110
|
## Related packages
|
|
62
111
|
|
|
63
|
-
| Need
|
|
64
|
-
|
|
65
|
-
| Node all-in-one (this package) | **`@yydb/yydb`**
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
112
|
+
| Need | Package |
|
|
113
|
+
|------|---------|
|
|
114
|
+
| Node all-in-one (this package) | **`@yydb/yydb`** or `@yydb/yydb/node` |
|
|
115
|
+
| Browser wasm entry | **`@yydb/yydb/wasm`** |
|
|
116
|
+
| Wire client only | [`@yydb/yydb-client`](https://www.npmjs.com/package/@yydb/yydb-client) |
|
|
117
|
+
| In-process Rust embed | [`yydb`](https://crates.io/crates/yydb) |
|
|
118
|
+
| Agent skills (wire protocol) | [`@yydb/yydb-skills`](https://www.npmjs.com/package/@yydb/yydb-skills) |
|
|
69
119
|
|
|
70
|
-
Electron: main process can use `@yydb/yydb`; renderer code can use `@yydb/yydb-client` against the main-process
|
|
120
|
+
Electron: main process can use `@yydb/yydb/node`; renderer code can use `@yydb/yydb-client` against the main-process
|
|
71
121
|
endpoint.
|
|
72
122
|
|
|
73
123
|
The managed engine listens on `127.0.0.1` with no authentication — keep the endpoint private.
|
|
@@ -6,7 +6,7 @@ import { registerInitCommand } from './init-cmd.js';
|
|
|
6
6
|
import { registerServeCommand } from './serve-cmd.js';
|
|
7
7
|
import { registerVersionCommand } from './version-cmd.js';
|
|
8
8
|
function buildYydbCli() {
|
|
9
|
-
const localesRoot = join(dirname(fileURLToPath(import.meta.url)), '
|
|
9
|
+
const localesRoot = join(dirname(fileURLToPath(import.meta.url)), '../../../locales');
|
|
10
10
|
const cli = createCli('yydb').locales(localesRoot).intro('cli.intro');
|
|
11
11
|
registerVersionCommand(cli);
|
|
12
12
|
registerInitCommand(cli);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineMicro as buildMicro, type DefinedMicro, type MicroHandle } from '
|
|
2
|
-
import type {
|
|
1
|
+
import { defineMicro as buildMicro, type DefinedMicro, type MicroHandle } from '../shared/micro.js';
|
|
2
|
+
import type { UdfScalarDescriptor } from '../shared/udf-types.js';
|
|
3
3
|
export type { SchemaVersion } from '@yydb/yydb-client';
|
|
4
4
|
export interface OpenOptions {
|
|
5
5
|
/** Override CLI script path (tests / special installs). */
|
|
@@ -36,13 +36,13 @@ export declare class Database {
|
|
|
36
36
|
* Build a typed session-local micro definition. Does not register it with
|
|
37
37
|
* the engine until [`registerMicro`](./database.ts) is called.
|
|
38
38
|
*/
|
|
39
|
-
defineMicro<TArgs extends readonly
|
|
39
|
+
defineMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: Parameters<typeof buildMicro<TArgs, TReturn>>[0]): DefinedMicro<TArgs, TReturn>;
|
|
40
40
|
/**
|
|
41
41
|
* Install a [`defineMicro`](./database.ts) definition into the current
|
|
42
42
|
* session registry and sync metadata to the private engine. Host micros are
|
|
43
43
|
* session-local and never written to `.yydb`.
|
|
44
44
|
*/
|
|
45
|
-
registerMicro<TArgs extends readonly
|
|
45
|
+
registerMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: DefinedMicro<TArgs, TReturn>): Promise<MicroHandle>;
|
|
46
46
|
/** Invoke a registered scalar UDF on the private engine. */
|
|
47
47
|
callScalar(name: string, version: number, args: readonly (string | number | boolean | null)[]): Promise<string | number | boolean | null>;
|
|
48
48
|
/** Stop the private engine process. */
|
|
@@ -3,16 +3,8 @@ import fs from 'node:fs';
|
|
|
3
3
|
import net from 'node:net';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { connect } from '@yydb/yydb-client/node';
|
|
6
|
-
import { defineMicro as buildMicro, MicroSessionRegistry } from '
|
|
6
|
+
import { defineMicro as buildMicro, microFingerprint, udfWireKind, MicroSessionRegistry, } from '../shared/micro.js';
|
|
7
7
|
import { resolveYydbCli } from './resolve-bin.js';
|
|
8
|
-
function microFingerprint(name, version) {
|
|
9
|
-
const bytes = new Uint8Array(32);
|
|
10
|
-
const seed = `${name}@${version}`;
|
|
11
|
-
for (let index = 0; index < bytes.byteLength; index += 1) {
|
|
12
|
-
bytes[index] = seed.charCodeAt(index % seed.length) & 0xff;
|
|
13
|
-
}
|
|
14
|
-
return bytes;
|
|
15
|
-
}
|
|
16
8
|
async function freeLoopbackPort() {
|
|
17
9
|
return await new Promise((resolve, reject) => {
|
|
18
10
|
const server = net.createServer();
|
|
@@ -149,8 +141,8 @@ export class Database {
|
|
|
149
141
|
udfVersion: definition.version,
|
|
150
142
|
name: definition.name,
|
|
151
143
|
functionId: handle.functionId,
|
|
152
|
-
args: definition.args.map(
|
|
153
|
-
returns: definition.returns
|
|
144
|
+
args: definition.args.map(udfWireKind),
|
|
145
|
+
returns: udfWireKind(definition.returns),
|
|
154
146
|
fingerprint: microFingerprint(definition.name, definition.version),
|
|
155
147
|
});
|
|
156
148
|
return handle;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Database, type OpenOptions } from './database.js';
|
|
2
|
+
export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from '@yydb/yydb-client';
|
|
3
|
+
export type { YydbErrorCode, YydbErrorOptions } from '@yydb/yydb-client';
|
|
4
|
+
export { defineMicro, type DefinedMicro, type MicroHandle, type TsMicroDefinitionInput, MicroSessionRegistry } from '../shared/micro.js';
|
|
5
|
+
export { type InferUdfArgs, type InferUdfReturn, type MicroEffect, type MicroInvocationMode, type UdfScalarDescriptor, type UdfScalarKind, } from '../shared/udf-types.js';
|
|
6
|
+
export { nativeBindingName, platformKey, resolveYydbBinary, resolveYydbCli } from './resolve-bin.js';
|
|
7
|
+
export * from '../shared/vos.js';
|
|
@@ -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';
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import type { InferUdfArgs, InferUdfReturn, MicroEffect, MicroInvocationMode,
|
|
1
|
+
import type { InferUdfArgs, InferUdfReturn, MicroEffect, MicroInvocationMode, UdfScalarDescriptor } from './udf-types.js';
|
|
2
|
+
import type { AnyTypeDescriptor } from '@voml/vos';
|
|
3
|
+
/** Value shape accepted and produced on the wire micro path. */
|
|
4
|
+
type MicroWireValue = string | number | boolean | null;
|
|
5
|
+
/** Wire kinds a VOS descriptor can map onto (`UdfType::Null` is never a type here). */
|
|
6
|
+
type UdfWireKind = 'i64' | 'bool' | 'text';
|
|
7
|
+
/**
|
|
8
|
+
* Maps a VOS descriptor onto its wire `UdfType` tag.
|
|
9
|
+
*
|
|
10
|
+
* Accepts any VOS descriptor so the runtime layer can reject a kind that
|
|
11
|
+
* slipped past the type layer; throws for everything outside the Phase-1
|
|
12
|
+
* subset instead of letting it reach the engine.
|
|
13
|
+
*/
|
|
14
|
+
export declare function udfWireKind(descriptor: AnyTypeDescriptor): UdfWireKind;
|
|
2
15
|
/** Input accepted by [`Database.defineMicro`](./database.ts). */
|
|
3
|
-
export interface TsMicroDefinitionInput<TArgs extends readonly
|
|
16
|
+
export interface TsMicroDefinitionInput<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor> {
|
|
4
17
|
readonly name: string;
|
|
5
18
|
readonly version: number;
|
|
6
19
|
readonly args: TArgs;
|
|
@@ -11,7 +24,7 @@ export interface TsMicroDefinitionInput<TArgs extends readonly UdfTypeDescriptor
|
|
|
11
24
|
readonly fn: (...args: InferUdfArgs<TArgs>) => InferUdfReturn<TReturn>;
|
|
12
25
|
}
|
|
13
26
|
/** Opaque definition produced by `defineMicro` before session registration. */
|
|
14
|
-
export interface DefinedMicro<TArgs extends readonly
|
|
27
|
+
export interface DefinedMicro<TArgs extends readonly UdfScalarDescriptor[] = readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor = UdfScalarDescriptor> {
|
|
15
28
|
readonly name: string;
|
|
16
29
|
readonly version: number;
|
|
17
30
|
readonly args: TArgs;
|
|
@@ -31,7 +44,7 @@ export interface MicroHandle {
|
|
|
31
44
|
/** Monotonic host implementation version for opaque handle checks. */
|
|
32
45
|
readonly implementationVersion: number;
|
|
33
46
|
}
|
|
34
|
-
type AnyDefinedMicro = DefinedMicro<readonly
|
|
47
|
+
type AnyDefinedMicro = DefinedMicro<readonly UdfScalarDescriptor[], UdfScalarDescriptor>;
|
|
35
48
|
/**
|
|
36
49
|
* Process-local registry for JS functions behind opaque host handles.
|
|
37
50
|
* Rust keeps `host_id + function_id + version`, not the closure.
|
|
@@ -43,7 +56,7 @@ export declare class MicroSessionRegistry {
|
|
|
43
56
|
private readonly byFunctionId;
|
|
44
57
|
constructor(hostId?: number);
|
|
45
58
|
/** Installs a defined micro into the current session registry. */
|
|
46
|
-
register<TArgs extends readonly
|
|
59
|
+
register<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: DefinedMicro<TArgs, TReturn>): MicroHandle;
|
|
47
60
|
/** Returns a registered micro by opaque host handle. */
|
|
48
61
|
resolve(handle: MicroHandle): AnyDefinedMicro | undefined;
|
|
49
62
|
/** Invokes a registered micro from a wire `MicroHostInvoke` payload. */
|
|
@@ -52,12 +65,14 @@ export declare class MicroSessionRegistry {
|
|
|
52
65
|
handleVersion: number;
|
|
53
66
|
functionId: string;
|
|
54
67
|
args: readonly unknown[];
|
|
55
|
-
}):
|
|
68
|
+
}): MicroWireValue;
|
|
56
69
|
/** Invokes a registered scalar micro (host adapter entry point). */
|
|
57
70
|
invokeScalar(handle: MicroHandle, args: unknown[]): unknown;
|
|
58
71
|
/** Lists logical names currently registered in this session. */
|
|
59
72
|
list(): string[];
|
|
60
73
|
}
|
|
61
74
|
/** Builds a session-local micro definition without registering it. */
|
|
62
|
-
export declare function defineMicro<TArgs extends readonly
|
|
75
|
+
export declare function defineMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(input: TsMicroDefinitionInput<TArgs, TReturn>): DefinedMicro<TArgs, TReturn>;
|
|
76
|
+
/** Stable 32-byte fingerprint for a logical micro name and version. */
|
|
77
|
+
export declare function microFingerprint(name: string, version: number): Uint8Array;
|
|
63
78
|
export {};
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps a VOS descriptor onto its wire `UdfType` tag.
|
|
3
|
+
*
|
|
4
|
+
* Accepts any VOS descriptor so the runtime layer can reject a kind that
|
|
5
|
+
* slipped past the type layer; throws for everything outside the Phase-1
|
|
6
|
+
* subset instead of letting it reach the engine.
|
|
7
|
+
*/
|
|
8
|
+
export function udfWireKind(descriptor) {
|
|
9
|
+
switch (descriptor.kind) {
|
|
10
|
+
case 'i64':
|
|
11
|
+
return 'i64';
|
|
12
|
+
case 'bool':
|
|
13
|
+
return 'bool';
|
|
14
|
+
case 'utf8':
|
|
15
|
+
return 'text';
|
|
16
|
+
default:
|
|
17
|
+
throw new Error(`unsupported micro type descriptor: ${descriptor.kind}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
1
20
|
let nextHostId = 1;
|
|
2
21
|
/**
|
|
3
22
|
* Process-local registry for JS functions behind opaque host handles.
|
|
@@ -46,7 +65,12 @@ export class MicroSessionRegistry {
|
|
|
46
65
|
name: '',
|
|
47
66
|
version: 0,
|
|
48
67
|
};
|
|
49
|
-
|
|
68
|
+
const definition = this.resolve(handle);
|
|
69
|
+
if (!definition) {
|
|
70
|
+
throw new Error(`micro not found: ${payload.functionId}`);
|
|
71
|
+
}
|
|
72
|
+
const args = definition.args.map((descriptor, index) => wireToBoundary(descriptor, payload.args[index]));
|
|
73
|
+
return boundaryToWire(definition.returns, this.invokeScalar(handle, args));
|
|
50
74
|
}
|
|
51
75
|
/** Invokes a registered scalar micro (host adapter entry point). */
|
|
52
76
|
invokeScalar(handle, args) {
|
|
@@ -60,9 +84,11 @@ export class MicroSessionRegistry {
|
|
|
60
84
|
if (args.length !== definition.args.length) {
|
|
61
85
|
throw new Error(`micro ${definition.name} arity mismatch: expected ${definition.args.length}, got ${args.length}`);
|
|
62
86
|
}
|
|
63
|
-
|
|
87
|
+
definition.args.forEach((descriptor, index) => {
|
|
88
|
+
validateValue(descriptor, args[index], `micro ${definition.name} arg ${index}`);
|
|
89
|
+
});
|
|
64
90
|
const result = definition.fn(...args);
|
|
65
|
-
|
|
91
|
+
validateValue(definition.returns, result, `micro ${definition.name} return`);
|
|
66
92
|
return result;
|
|
67
93
|
}
|
|
68
94
|
/** Lists logical names currently registered in this session. */
|
|
@@ -87,6 +113,12 @@ export function defineMicro(input) {
|
|
|
87
113
|
if (typeof input.fn !== 'function') {
|
|
88
114
|
throw new Error('micro fn must be a function');
|
|
89
115
|
}
|
|
116
|
+
// Reject descriptors outside the Phase-1 subset while the definition is
|
|
117
|
+
// still session-local, instead of at register time.
|
|
118
|
+
input.args.forEach((descriptor, index) => {
|
|
119
|
+
assertSupportedDescriptor(descriptor, `micro ${input.name} arg ${index}`);
|
|
120
|
+
});
|
|
121
|
+
assertSupportedDescriptor(input.returns, `micro ${input.name} return`);
|
|
90
122
|
return {
|
|
91
123
|
name: input.name,
|
|
92
124
|
version: input.version,
|
|
@@ -99,62 +131,63 @@ export function defineMicro(input) {
|
|
|
99
131
|
fn: input.fn,
|
|
100
132
|
};
|
|
101
133
|
}
|
|
134
|
+
/** Stable 32-byte fingerprint for a logical micro name and version. */
|
|
135
|
+
export function microFingerprint(name, version) {
|
|
136
|
+
const bytes = new Uint8Array(32);
|
|
137
|
+
const seed = `${name}@${version}`;
|
|
138
|
+
for (let index = 0; index < bytes.byteLength; index += 1) {
|
|
139
|
+
bytes[index] = seed.charCodeAt(index % seed.length) & 0xff;
|
|
140
|
+
}
|
|
141
|
+
return bytes;
|
|
142
|
+
}
|
|
102
143
|
function logicalKey(name, version) {
|
|
103
144
|
return `${name}@${version}`;
|
|
104
145
|
}
|
|
105
|
-
function
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (typeof value !== 'number' || !Number.isInteger(value)) {
|
|
112
|
-
throw new Error(`micro ${definition.name} arg ${index} expects i64`);
|
|
113
|
-
}
|
|
114
|
-
break;
|
|
115
|
-
case 'bool':
|
|
116
|
-
if (typeof value !== 'boolean') {
|
|
117
|
-
throw new Error(`micro ${definition.name} arg ${index} expects bool`);
|
|
118
|
-
}
|
|
119
|
-
break;
|
|
120
|
-
case 'text':
|
|
121
|
-
if (typeof value !== 'string') {
|
|
122
|
-
throw new Error(`micro ${definition.name} arg ${index} expects text`);
|
|
123
|
-
}
|
|
124
|
-
break;
|
|
125
|
-
case 'null':
|
|
126
|
-
if (value !== null) {
|
|
127
|
-
throw new Error(`micro ${definition.name} arg ${index} expects null`);
|
|
128
|
-
}
|
|
129
|
-
break;
|
|
130
|
-
default:
|
|
131
|
-
throw new Error(`unsupported micro arg kind: ${kind}`);
|
|
132
|
-
}
|
|
146
|
+
function assertSupportedDescriptor(descriptor, label) {
|
|
147
|
+
try {
|
|
148
|
+
udfWireKind(descriptor);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
throw new Error(`${label} uses a descriptor outside the Phase-1 micro subset`);
|
|
133
152
|
}
|
|
134
153
|
}
|
|
135
|
-
|
|
136
|
-
|
|
154
|
+
/** Boundary value a VOS descriptor carries in the host runtime. */
|
|
155
|
+
function validateValue(descriptor, value, label) {
|
|
156
|
+
switch (udfWireKind(descriptor)) {
|
|
137
157
|
case 'i64':
|
|
138
|
-
if (typeof value !== '
|
|
139
|
-
throw new Error(
|
|
158
|
+
if (typeof value !== 'bigint') {
|
|
159
|
+
throw new Error(`${label} expects VOS \`i64\` (a bigint)`);
|
|
140
160
|
}
|
|
141
161
|
break;
|
|
142
162
|
case 'bool':
|
|
143
163
|
if (typeof value !== 'boolean') {
|
|
144
|
-
throw new Error(
|
|
164
|
+
throw new Error(`${label} expects VOS \`bool\``);
|
|
145
165
|
}
|
|
146
166
|
break;
|
|
147
167
|
case 'text':
|
|
148
168
|
if (typeof value !== 'string') {
|
|
149
|
-
throw new Error(
|
|
169
|
+
throw new Error(`${label} expects VOS \`utf8\` (a string)`);
|
|
150
170
|
}
|
|
151
171
|
break;
|
|
152
|
-
case 'null':
|
|
153
|
-
if (value !== null) {
|
|
154
|
-
throw new Error('micro return expects null');
|
|
155
|
-
}
|
|
156
|
-
break;
|
|
157
|
-
default:
|
|
158
|
-
throw new Error(`unsupported micro return kind: ${descriptor.kind}`);
|
|
159
172
|
}
|
|
160
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Wire value to boundary value. The YY wire carries `i64` as a JS number, so
|
|
176
|
+
* it becomes the VOS `i64` boundary value here rather than in author code.
|
|
177
|
+
*/
|
|
178
|
+
function wireToBoundary(descriptor, value) {
|
|
179
|
+
if (udfWireKind(descriptor) === 'i64' && typeof value === 'number' && Number.isSafeInteger(value)) {
|
|
180
|
+
return BigInt(value);
|
|
181
|
+
}
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
/** Boundary value back to the wire subset; `i64` must still fit a JS number. */
|
|
185
|
+
function boundaryToWire(descriptor, value) {
|
|
186
|
+
if (udfWireKind(descriptor) === 'i64' && typeof value === 'bigint') {
|
|
187
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
188
|
+
throw new Error(`micro return i64 ${value} does not fit the wire number path`);
|
|
189
|
+
}
|
|
190
|
+
return Number(value);
|
|
191
|
+
}
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host micro (UDF) boundary types.
|
|
3
|
+
*
|
|
4
|
+
* Descriptors come straight from `@voml/vos`: `v.i64()`, `v.bool()`, `v.utf8()`.
|
|
5
|
+
* YYDB keeps no scalar descriptor algebra of its own — only the VOS descriptors
|
|
6
|
+
* the Phase-1 UDF boundary accepts.
|
|
7
|
+
*
|
|
8
|
+
* `null` is not a type here. It is a value carried by the wire subset, so it
|
|
9
|
+
* gets no descriptor.
|
|
10
|
+
*
|
|
11
|
+
* This module is types only, so a host test can load it through type stripping.
|
|
12
|
+
* The mapping onto the wire `UdfType` tags lives in `micro.ts`.
|
|
13
|
+
*/
|
|
14
|
+
import type { Infer, TypeDescriptor } from '@voml/vos';
|
|
15
|
+
/** Phase-1 scalar kinds on the YY wire micro path, aligned with `yydb-udf`. */
|
|
16
|
+
export type UdfScalarKind = 'i64' | 'bool' | 'text' | 'null';
|
|
17
|
+
/**
|
|
18
|
+
* VOS descriptors accepted at the Phase-1 host micro boundary.
|
|
19
|
+
*
|
|
20
|
+
* Drawn from the frozen VOS type algebra, so `v.utf16()`, `v.optional(…)`,
|
|
21
|
+
* `v.list(…)` and every non-scalar descriptor are rejected before they reach
|
|
22
|
+
* the wire.
|
|
23
|
+
*/
|
|
24
|
+
export type UdfScalarDescriptor = TypeDescriptor<'i64', bigint> | TypeDescriptor<'bool', boolean> | TypeDescriptor<'utf8', string>;
|
|
25
|
+
/** Maps a descriptor tuple to positional boundary value types. */
|
|
26
|
+
export type InferUdfArgs<T extends readonly UdfScalarDescriptor[]> = {
|
|
27
|
+
[K in keyof T]: Infer<T[K]>;
|
|
28
|
+
};
|
|
29
|
+
/** Maps a return descriptor to its boundary value type. */
|
|
30
|
+
export type InferUdfReturn<T extends UdfScalarDescriptor> = Infer<T>;
|
|
31
|
+
/** Session micro effect surface (Phase 1: pure only). */
|
|
32
|
+
export type MicroEffect = 'pure';
|
|
33
|
+
/** Invocation mode stored with the definition for future batch host calls. */
|
|
34
|
+
export type MicroInvocationMode = 'scalar' | 'batch';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host micro (UDF) boundary types.
|
|
3
|
+
*
|
|
4
|
+
* Descriptors come straight from `@voml/vos`: `v.i64()`, `v.bool()`, `v.utf8()`.
|
|
5
|
+
* YYDB keeps no scalar descriptor algebra of its own — only the VOS descriptors
|
|
6
|
+
* the Phase-1 UDF boundary accepts.
|
|
7
|
+
*
|
|
8
|
+
* `null` is not a type here. It is a value carried by the wire subset, so it
|
|
9
|
+
* gets no descriptor.
|
|
10
|
+
*
|
|
11
|
+
* This module is types only, so a host test can load it through type stripping.
|
|
12
|
+
* The mapping onto the wire `UdfType` tags lives in `micro.ts`.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@yydb/yydb` 对 `@voml/vos` 的 re-export 门。
|
|
3
|
+
*
|
|
4
|
+
* 普通 YYDB 用户只依赖 `@yydb/yydb`,不必再显式安装或引入 `@voml/vos`。
|
|
5
|
+
* 这里只转发 YYDB 作者面需要的 VOS 建模面:`v` builder、descriptor 类型与 `Infer` 推导。
|
|
6
|
+
*
|
|
7
|
+
* 刻意不转发:
|
|
8
|
+
* - VOS source 发射:`@voml/vos` 不生成 `.vos` 文本(descriptor 直接编译 canonical artifact),
|
|
9
|
+
* 源码书写与格式化属于 `@voml/vos-language`。
|
|
10
|
+
* - `checkSource` / `VosDiagnostic`:VOS source 检查与语言层诊断属于 `@voml/vos-language`,
|
|
11
|
+
* 不属于 `@voml/vos` 建模面,也不进 YYDB 作者面。
|
|
12
|
+
*
|
|
13
|
+
* 依赖边界见内部决策文档「VOS + YYDB TypeScript 门面设计」§1.1。
|
|
14
|
+
*/
|
|
15
|
+
export { v } from '@voml/vos';
|
|
16
|
+
export type { VBuiltinName, VItemName, VWrapperName } from '@voml/vos';
|
|
17
|
+
export type { AnyTypeDescriptor, Attribute, BuiltinKind, FieldDescriptor, Infer, RefDescriptor, ReferenceTarget, ScalarKind, TypeDescriptor, WrapperKind, } from '@voml/vos';
|
|
18
|
+
export type { ClassDescriptor, FieldAccess, FieldMap, ItemKind, ItemMetadataKey, NamedFieldMap, NamedItemDescriptor, NamedItemKind, ObjectDescriptor, RowOf, StructuralDescriptor, TableDescriptor, } from '@voml/vos';
|
|
19
|
+
export type { ReferenceKey, VosFileRef } from '@voml/vos';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@yydb/yydb` 对 `@voml/vos` 的 re-export 门。
|
|
3
|
+
*
|
|
4
|
+
* 普通 YYDB 用户只依赖 `@yydb/yydb`,不必再显式安装或引入 `@voml/vos`。
|
|
5
|
+
* 这里只转发 YYDB 作者面需要的 VOS 建模面:`v` builder、descriptor 类型与 `Infer` 推导。
|
|
6
|
+
*
|
|
7
|
+
* 刻意不转发:
|
|
8
|
+
* - VOS source 发射:`@voml/vos` 不生成 `.vos` 文本(descriptor 直接编译 canonical artifact),
|
|
9
|
+
* 源码书写与格式化属于 `@voml/vos-language`。
|
|
10
|
+
* - `checkSource` / `VosDiagnostic`:VOS source 检查与语言层诊断属于 `@voml/vos-language`,
|
|
11
|
+
* 不属于 `@voml/vos` 建模面,也不进 YYDB 作者面。
|
|
12
|
+
*
|
|
13
|
+
* 依赖边界见内部决策文档「VOS + YYDB TypeScript 门面设计」§1.1。
|
|
14
|
+
*/
|
|
15
|
+
export { v } from '@voml/vos';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Parsed `{ ok, rows, error, code }` envelope from wasm unit-valued 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 parseWasmUnitResult(payload: string, operation: string): void;
|
|
38
|
+
export declare function parseWasmSchemaResult(payload: string, operation: string): SchemaVersion | null;
|
|
39
|
+
export declare function parseWasmScalarResult(payload: string, operation: string): WireScalarValue;
|
|
40
|
+
export declare function parseWasmKvGetResult(payload: string, operation: string): Uint8Array | null;
|
|
@@ -0,0 +1,49 @@
|
|
|
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 parseWasmUnitResult(payload, operation) {
|
|
21
|
+
const parsed = parseJson(payload, operation);
|
|
22
|
+
if (!parsed.ok) {
|
|
23
|
+
throw envelopeError(parsed, operation);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function parseWasmSchemaResult(payload, operation) {
|
|
27
|
+
const parsed = parseJson(payload, operation);
|
|
28
|
+
if (!parsed.ok) {
|
|
29
|
+
throw envelopeError(parsed, operation);
|
|
30
|
+
}
|
|
31
|
+
return parsed.schema;
|
|
32
|
+
}
|
|
33
|
+
export function parseWasmScalarResult(payload, operation) {
|
|
34
|
+
const parsed = parseJson(payload, operation);
|
|
35
|
+
if (!parsed.ok) {
|
|
36
|
+
throw envelopeError(parsed, operation);
|
|
37
|
+
}
|
|
38
|
+
return parsed.value;
|
|
39
|
+
}
|
|
40
|
+
export function parseWasmKvGetResult(payload, operation) {
|
|
41
|
+
const parsed = parseJson(payload, operation);
|
|
42
|
+
if (!parsed.ok) {
|
|
43
|
+
throw envelopeError(parsed, operation);
|
|
44
|
+
}
|
|
45
|
+
if (parsed.value === null) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return Uint8Array.from(parsed.value);
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { checkSchema, createMemorySession, initWasm, introspectSchema, openPersistentSession, 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, resetWasmBindingForTests, yydbVersion, } from '@yydb/yydb-unknown-wasm32';
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
/**
|
|
34
|
+
* Build a typed session-local micro definition. Does not register it with
|
|
35
|
+
* the engine until `registerMicro` is called.
|
|
36
|
+
*/
|
|
37
|
+
defineMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: Parameters<typeof buildMicro<TArgs, TReturn>>[0]): DefinedMicro<TArgs, TReturn>;
|
|
38
|
+
/**
|
|
39
|
+
* Install a `defineMicro` definition into the current session registry and
|
|
40
|
+
* sync metadata to the embedded engine. Host micros are session-local.
|
|
41
|
+
*/
|
|
42
|
+
registerMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: DefinedMicro<TArgs, TReturn>): Promise<MicroHandle>;
|
|
43
|
+
/** Invoke a registered scalar UDF on the embedded engine. */
|
|
44
|
+
callScalar(name: string, version: number, args: readonly (string | number | boolean | null)[]): Promise<string | number | boolean | null>;
|
|
45
|
+
/** Whether this handle owns a persistent OPFS session. */
|
|
46
|
+
isPersistent(): boolean;
|
|
47
|
+
/** Close the embedded session. Idempotent; further calls fail with `yydb.session.closed`. */
|
|
48
|
+
close(): Promise<void>;
|
|
49
|
+
private requireSession;
|
|
50
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { encodeMicroRegister, encodeScalarCall, YydbError, YydbErrorCodes } from '@yydb/yydb-client';
|
|
2
|
+
import { defineMicro as buildMicro, microFingerprint, udfWireKind, MicroSessionRegistry, } from '../shared/micro.js';
|
|
3
|
+
import { parseWasmKvGetResult, parseWasmScalarResult, parseWasmSchemaResult, parseWasmUnitResult, } from '../shared/wasm-envelope.js';
|
|
4
|
+
import { checkSchema, createMemorySession, initWasm, openPersistentSession, yydbVersion, } from './binding.js';
|
|
5
|
+
/**
|
|
6
|
+
* Browser-facing YYDB handle backed by an in-process wasm session.
|
|
7
|
+
* Use `open` for OPFS-backed paths and `openInMemory` for ephemeral state.
|
|
8
|
+
*/
|
|
9
|
+
export class Database {
|
|
10
|
+
path;
|
|
11
|
+
session;
|
|
12
|
+
kind;
|
|
13
|
+
microRegistry;
|
|
14
|
+
constructor(kind, path, session) {
|
|
15
|
+
this.kind = kind;
|
|
16
|
+
this.path = path;
|
|
17
|
+
this.session = session;
|
|
18
|
+
this.microRegistry = new MicroSessionRegistry();
|
|
19
|
+
session.setMicroHostInvoker((payload) => this.microRegistry.invokeFromWire(payload));
|
|
20
|
+
}
|
|
21
|
+
/** Open an OPFS-backed database at `path` (for example `app.yydb`). */
|
|
22
|
+
static async open(path, options = {}) {
|
|
23
|
+
await initWasm(options);
|
|
24
|
+
const session = openPersistentSession(path);
|
|
25
|
+
return new Database('persistent', session.path ?? path, session);
|
|
26
|
+
}
|
|
27
|
+
/** Open a stateful in-memory database session. */
|
|
28
|
+
static async openInMemory(options = {}) {
|
|
29
|
+
await initWasm(options);
|
|
30
|
+
const session = createMemorySession();
|
|
31
|
+
return new Database('memory', ':memory:', session);
|
|
32
|
+
}
|
|
33
|
+
/** Library version from the wasm binding. */
|
|
34
|
+
version() {
|
|
35
|
+
return yydbVersion();
|
|
36
|
+
}
|
|
37
|
+
/** Engine version string (Node API parity). */
|
|
38
|
+
async serverVersion() {
|
|
39
|
+
return yydbVersion();
|
|
40
|
+
}
|
|
41
|
+
/** Database info text (`path=…\\n…`), matching the YY wire `Info` reply. */
|
|
42
|
+
async info() {
|
|
43
|
+
return this.requireSession('info').info();
|
|
44
|
+
}
|
|
45
|
+
/** Parse and validate a VOS schema document without opening a session. */
|
|
46
|
+
checkSchema(source) {
|
|
47
|
+
return checkSchema(source);
|
|
48
|
+
}
|
|
49
|
+
/** Persist schema document. `version` is accepted for Node API parity; wasm uses the document body. */
|
|
50
|
+
async ensureSchema(_version, document) {
|
|
51
|
+
parseWasmUnitResult(this.requireSession('schemaEnsure').ensureSchema(document), 'schemaEnsure');
|
|
52
|
+
}
|
|
53
|
+
async getSchema() {
|
|
54
|
+
return parseWasmSchemaResult(this.requireSession('schemaGet').getSchema(), 'schemaGet');
|
|
55
|
+
}
|
|
56
|
+
async get(key) {
|
|
57
|
+
return parseWasmKvGetResult(this.requireSession('kvGet').get(key), 'kvGet');
|
|
58
|
+
}
|
|
59
|
+
async put(key, value) {
|
|
60
|
+
const bytes = typeof value === 'string' ? new TextEncoder().encode(value) : value;
|
|
61
|
+
parseWasmUnitResult(this.requireSession('kvPut').put(key, bytes), 'kvPut');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build a typed session-local micro definition. Does not register it with
|
|
65
|
+
* the engine until `registerMicro` is called.
|
|
66
|
+
*/
|
|
67
|
+
defineMicro(definition) {
|
|
68
|
+
return buildMicro(definition);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Install a `defineMicro` definition into the current session registry and
|
|
72
|
+
* sync metadata to the embedded engine. Host micros are session-local.
|
|
73
|
+
*/
|
|
74
|
+
async registerMicro(definition) {
|
|
75
|
+
const handle = this.microRegistry.register(definition);
|
|
76
|
+
const body = encodeMicroRegister({
|
|
77
|
+
hostId: handle.hostId,
|
|
78
|
+
handleVersion: handle.implementationVersion,
|
|
79
|
+
udfVersion: definition.version,
|
|
80
|
+
name: definition.name,
|
|
81
|
+
functionId: handle.functionId,
|
|
82
|
+
args: definition.args.map(udfWireKind),
|
|
83
|
+
returns: udfWireKind(definition.returns),
|
|
84
|
+
fingerprint: microFingerprint(definition.name, definition.version),
|
|
85
|
+
});
|
|
86
|
+
parseWasmUnitResult(this.requireSession('microRegister').registerMicro(body), 'microRegister');
|
|
87
|
+
return handle;
|
|
88
|
+
}
|
|
89
|
+
/** Invoke a registered scalar UDF on the embedded engine. */
|
|
90
|
+
async callScalar(name, version, args) {
|
|
91
|
+
const body = encodeScalarCall(name, version, args);
|
|
92
|
+
return parseWasmScalarResult(this.requireSession('callScalar').callScalar(body), 'callScalar');
|
|
93
|
+
}
|
|
94
|
+
/** Whether this handle owns a persistent OPFS session. */
|
|
95
|
+
isPersistent() {
|
|
96
|
+
return this.kind === 'persistent';
|
|
97
|
+
}
|
|
98
|
+
/** Close the embedded session. Idempotent; further calls fail with `yydb.session.closed`. */
|
|
99
|
+
async close() {
|
|
100
|
+
const session = this.session;
|
|
101
|
+
this.session = null;
|
|
102
|
+
session?.close();
|
|
103
|
+
}
|
|
104
|
+
requireSession(operation) {
|
|
105
|
+
if (!this.session) {
|
|
106
|
+
throw new YydbError(YydbErrorCodes.sessionClosed, `${operation}: @yydb/yydb/wasm session is closed`, { operation });
|
|
107
|
+
}
|
|
108
|
+
return this.session;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Database, type WasmOpenOptions } from './database.js';
|
|
2
|
+
export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from '@yydb/yydb-client';
|
|
3
|
+
export type { YydbErrorCode, YydbErrorOptions } from '@yydb/yydb-client';
|
|
4
|
+
export { checkSchema, createMemorySession, initWasm, introspectSchema, openPersistentSession, resetWasmBindingForTests, yydbVersion, type CheckSchemaResult, type InitWasmOptions, type WasmInitInput, type WasmSession, } from './binding.js';
|
|
5
|
+
export { defineMicro, type DefinedMicro, type MicroHandle, type TsMicroDefinitionInput, MicroSessionRegistry } from '../shared/micro.js';
|
|
6
|
+
export { type InferUdfArgs, type InferUdfReturn, type MicroEffect, type MicroInvocationMode, type UdfScalarDescriptor, type UdfScalarKind, } from '../shared/udf-types.js';
|
|
7
|
+
export type { SchemaVersion } from '../shared/wasm-envelope.js';
|
|
8
|
+
export * from '../shared/vos.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Database } from './database.js';
|
|
2
|
+
export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from '@yydb/yydb-client';
|
|
3
|
+
export { checkSchema, createMemorySession, initWasm, introspectSchema, openPersistentSession, resetWasmBindingForTests, yydbVersion, } from './binding.js';
|
|
4
|
+
export { defineMicro, MicroSessionRegistry } from '../shared/micro.js';
|
|
5
|
+
export * from '../shared/vos.js';
|
package/package.json
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yydb/yydb",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "YYDB all-in-one
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "YYDB all-in-one: Node embedded engine and CLI, browser wasm core",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"yydb": "./dist/cli.js"
|
|
8
|
+
"yydb": "./dist/node/cli.js"
|
|
9
9
|
},
|
|
10
|
-
"main": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
10
|
+
"main": "./dist/node/index.js",
|
|
11
|
+
"types": "./dist/node/index.d.ts",
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"types": "./dist/index.d.ts",
|
|
15
|
-
"
|
|
14
|
+
"types": "./dist/node/index.d.ts",
|
|
15
|
+
"node": "./dist/node/index.js",
|
|
16
|
+
"default": "./dist/wasm/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./node": {
|
|
19
|
+
"types": "./dist/node/index.d.ts",
|
|
20
|
+
"import": "./dist/node/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./wasm": {
|
|
23
|
+
"types": "./dist/wasm/index.d.ts",
|
|
24
|
+
"import": "./dist/wasm/index.js"
|
|
16
25
|
},
|
|
17
26
|
"./cli": {
|
|
18
|
-
"types": "./dist/cli.d.ts",
|
|
19
|
-
"import": "./dist/cli.js"
|
|
27
|
+
"types": "./dist/node/cli.d.ts",
|
|
28
|
+
"import": "./dist/node/cli.js"
|
|
20
29
|
}
|
|
21
30
|
},
|
|
22
31
|
"files": [
|
|
@@ -24,8 +33,8 @@
|
|
|
24
33
|
"README.md"
|
|
25
34
|
],
|
|
26
35
|
"scripts": {
|
|
27
|
-
"build": "tsc -p tsconfig.json",
|
|
28
|
-
"test": "pnpm run build && node --experimental-strip-types --test src/**/*.test.ts"
|
|
36
|
+
"build": "tsc -p tsconfig.node.json && tsc -p tsconfig.wasm.json",
|
|
37
|
+
"test": "pnpm run build && node --experimental-strip-types --test src/node/**/*.test.ts src/shared/**/*.test.ts"
|
|
29
38
|
},
|
|
30
39
|
"repository": {
|
|
31
40
|
"type": "git",
|
|
@@ -48,7 +57,9 @@
|
|
|
48
57
|
},
|
|
49
58
|
"dependencies": {
|
|
50
59
|
"@vmz/commander": "^0.2.0",
|
|
51
|
-
"@
|
|
60
|
+
"@voml/vos": "^0.0.1",
|
|
61
|
+
"@yydb/yydb-client": "0.0.6",
|
|
62
|
+
"@yydb/yydb-unknown-wasm32": "0.0.6"
|
|
52
63
|
},
|
|
53
64
|
"devDependencies": {
|
|
54
65
|
"@types/node": "^20.10.0",
|
|
@@ -58,9 +69,9 @@
|
|
|
58
69
|
"node": ">=18"
|
|
59
70
|
},
|
|
60
71
|
"optionalDependencies": {
|
|
61
|
-
"@yydb/yydb-win32-x64": "0.0.
|
|
62
|
-
"@yydb/yydb-linux-x64": "0.0.
|
|
63
|
-
"@yydb/yydb-darwin-x64": "0.0.
|
|
64
|
-
"@yydb/yydb-darwin-arm64": "0.0.
|
|
72
|
+
"@yydb/yydb-win32-x64": "0.0.6",
|
|
73
|
+
"@yydb/yydb-linux-x64": "0.0.6",
|
|
74
|
+
"@yydb/yydb-darwin-x64": "0.0.6",
|
|
75
|
+
"@yydb/yydb-darwin-arm64": "0.0.6"
|
|
65
76
|
}
|
|
66
77
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { Database, type OpenOptions } from './database.js';
|
|
2
|
-
export { defineMicro, type DefinedMicro, type MicroHandle, type TsMicroDefinitionInput, MicroSessionRegistry } from './micro.js';
|
|
3
|
-
export { bool, i64, nullType, text, type InferUdfArgs, type InferUdfReturn, type MicroEffect, type MicroInvocationMode, type UdfScalarKind, type UdfTypeDescriptor, } from './udf-types.js';
|
|
4
|
-
export { nativeBindingName, platformKey, resolveYydbBinary, resolveYydbCli } from './resolve-bin.js';
|
package/dist/index.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { Database } from './database.js';
|
|
2
|
-
export { defineMicro, MicroSessionRegistry } from './micro.js';
|
|
3
|
-
export { bool, i64, nullType, text, } from './udf-types.js';
|
|
4
|
-
export { nativeBindingName, platformKey, resolveYydbBinary, resolveYydbCli } from './resolve-bin.js';
|
package/dist/udf-types.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
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';
|
package/dist/udf-types.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
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
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|