@yydb/yydb 0.0.15 → 0.0.17
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 +86 -86
- package/package.json +40 -40
- package/dist/database.d.ts +0 -50
- package/dist/database.js +0 -181
- package/dist/micro.d.ts +0 -63
- package/dist/micro.js +0 -160
- package/dist/native.d.ts +0 -9
- package/dist/native.js +0 -32
- package/dist/node/cli/cli.d.ts +0 -1
- package/dist/node/cli/cli.js +0 -25
- package/dist/node/cli/info-cmd.d.ts +0 -3
- package/dist/node/cli/info-cmd.js +0 -10
- package/dist/node/cli/init-cmd.d.ts +0 -3
- package/dist/node/cli/init-cmd.js +0 -18
- package/dist/node/cli/options.d.ts +0 -4
- package/dist/node/cli/options.js +0 -14
- package/dist/node/cli/serve-cmd.d.ts +0 -3
- package/dist/node/cli/serve-cmd.js +0 -14
- package/dist/node/cli/version-cmd.d.ts +0 -3
- package/dist/node/cli/version-cmd.js +0 -8
- package/dist/node/cli.d.ts +0 -2
- package/dist/node/cli.js +0 -6
- package/dist/node/database.d.ts +0 -50
- package/dist/node/database.js +0 -173
- package/dist/node/index.d.ts +0 -7
- package/dist/node/index.js +0 -5
- package/dist/node/native.d.ts +0 -9
- package/dist/node/native.js +0 -32
- package/dist/node/resolve-bin.d.ts +0 -15
- package/dist/node/resolve-bin.js +0 -62
- package/dist/resolve-bin.d.ts +0 -15
- package/dist/resolve-bin.js +0 -62
- package/dist/shared/wasm-envelope.d.ts +0 -41
- package/dist/shared/wasm-envelope.js +0 -56
- package/dist/udf-types.d.ts +0 -26
- package/dist/udf-types.js +0 -16
- package/dist/wasm/binding.d.ts +0 -1
- package/dist/wasm/binding.js +0 -1
- package/dist/wasm/database.d.ts +0 -54
- package/dist/wasm/database.js +0 -118
- package/dist/wasm/index.d.ts +0 -8
- package/dist/wasm/index.js +0 -5
package/dist/micro.js
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
let nextHostId = 1;
|
|
2
|
-
/**
|
|
3
|
-
* Process-local registry for JS functions behind opaque host handles.
|
|
4
|
-
* Rust keeps `host_id + function_id + version`, not the closure.
|
|
5
|
-
*/
|
|
6
|
-
export class MicroSessionRegistry {
|
|
7
|
-
hostId;
|
|
8
|
-
nextFunctionId = 1;
|
|
9
|
-
byKey = new Map();
|
|
10
|
-
byFunctionId = new Map();
|
|
11
|
-
constructor(hostId = nextHostId++) {
|
|
12
|
-
this.hostId = hostId;
|
|
13
|
-
}
|
|
14
|
-
/** Installs a defined micro into the current session registry. */
|
|
15
|
-
register(definition) {
|
|
16
|
-
const key = logicalKey(definition.name, definition.version);
|
|
17
|
-
if (this.byKey.has(key)) {
|
|
18
|
-
throw new Error(`micro already registered: ${definition.name}@${definition.version}`);
|
|
19
|
-
}
|
|
20
|
-
const functionId = String(this.nextFunctionId++);
|
|
21
|
-
const handle = {
|
|
22
|
-
name: definition.name,
|
|
23
|
-
version: definition.version,
|
|
24
|
-
functionId,
|
|
25
|
-
hostId: this.hostId,
|
|
26
|
-
implementationVersion: 1,
|
|
27
|
-
};
|
|
28
|
-
const entry = { handle, definition: definition };
|
|
29
|
-
this.byKey.set(key, entry);
|
|
30
|
-
this.byFunctionId.set(functionId, entry);
|
|
31
|
-
return handle;
|
|
32
|
-
}
|
|
33
|
-
/** Returns a registered micro by opaque host handle. */
|
|
34
|
-
resolve(handle) {
|
|
35
|
-
if (handle.hostId !== this.hostId) {
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
return this.byFunctionId.get(handle.functionId)?.definition;
|
|
39
|
-
}
|
|
40
|
-
/** Invokes a registered micro from a wire `MicroHostInvoke` payload. */
|
|
41
|
-
invokeFromWire(payload) {
|
|
42
|
-
const handle = {
|
|
43
|
-
hostId: payload.hostId,
|
|
44
|
-
functionId: payload.functionId,
|
|
45
|
-
implementationVersion: payload.handleVersion,
|
|
46
|
-
name: '',
|
|
47
|
-
version: 0,
|
|
48
|
-
};
|
|
49
|
-
return this.invokeScalar(handle, [...payload.args]);
|
|
50
|
-
}
|
|
51
|
-
/** Invokes a registered scalar micro (host adapter entry point). */
|
|
52
|
-
invokeScalar(handle, args) {
|
|
53
|
-
const definition = this.resolve(handle);
|
|
54
|
-
if (!definition) {
|
|
55
|
-
throw new Error(`micro not found: ${handle.functionId}`);
|
|
56
|
-
}
|
|
57
|
-
if (definition.mode !== 'scalar') {
|
|
58
|
-
throw new Error(`micro ${definition.name} is not scalar mode`);
|
|
59
|
-
}
|
|
60
|
-
if (args.length !== definition.args.length) {
|
|
61
|
-
throw new Error(`micro ${definition.name} arity mismatch: expected ${definition.args.length}, got ${args.length}`);
|
|
62
|
-
}
|
|
63
|
-
validateArgTypes(definition, args);
|
|
64
|
-
const result = definition.fn(...args);
|
|
65
|
-
validateReturnType(definition.returns, result);
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
/** Lists logical names currently registered in this session. */
|
|
69
|
-
list() {
|
|
70
|
-
return [...this.byKey.values()].map((entry) => entry.definition.name).sort();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/** Builds a session-local micro definition without registering it. */
|
|
74
|
-
export function defineMicro(input) {
|
|
75
|
-
if (!input.name.trim()) {
|
|
76
|
-
throw new Error('micro name must not be empty');
|
|
77
|
-
}
|
|
78
|
-
if (!Number.isInteger(input.version) || input.version <= 0) {
|
|
79
|
-
throw new Error('micro version must be a positive integer');
|
|
80
|
-
}
|
|
81
|
-
if (input.effect !== 'pure') {
|
|
82
|
-
throw new Error('TS micro effect must be pure in Phase 1');
|
|
83
|
-
}
|
|
84
|
-
if (!input.deterministic) {
|
|
85
|
-
throw new Error('TS micro must be deterministic in Phase 1');
|
|
86
|
-
}
|
|
87
|
-
if (typeof input.fn !== 'function') {
|
|
88
|
-
throw new Error('micro fn must be a function');
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
name: input.name,
|
|
92
|
-
version: input.version,
|
|
93
|
-
args: input.args,
|
|
94
|
-
returns: input.returns,
|
|
95
|
-
effect: input.effect,
|
|
96
|
-
deterministic: input.deterministic,
|
|
97
|
-
mode: input.mode ?? 'scalar',
|
|
98
|
-
placement: 'host',
|
|
99
|
-
fn: input.fn,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
function logicalKey(name, version) {
|
|
103
|
-
return `${name}@${version}`;
|
|
104
|
-
}
|
|
105
|
-
function validateArgTypes(definition, args) {
|
|
106
|
-
for (let index = 0; index < definition.args.length; index += 1) {
|
|
107
|
-
const kind = definition.args[index]?.kind;
|
|
108
|
-
const value = args[index];
|
|
109
|
-
switch (kind) {
|
|
110
|
-
case 'i64':
|
|
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
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
function validateReturnType(descriptor, value) {
|
|
136
|
-
switch (descriptor.kind) {
|
|
137
|
-
case 'i64':
|
|
138
|
-
if (typeof value !== 'number' || !Number.isInteger(value)) {
|
|
139
|
-
throw new Error('micro return expects i64');
|
|
140
|
-
}
|
|
141
|
-
break;
|
|
142
|
-
case 'bool':
|
|
143
|
-
if (typeof value !== 'boolean') {
|
|
144
|
-
throw new Error('micro return expects bool');
|
|
145
|
-
}
|
|
146
|
-
break;
|
|
147
|
-
case 'text':
|
|
148
|
-
if (typeof value !== 'string') {
|
|
149
|
-
throw new Error('micro return expects text');
|
|
150
|
-
}
|
|
151
|
-
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
|
-
}
|
|
160
|
-
}
|
package/dist/native.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
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;
|
package/dist/native.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
}
|
package/dist/node/cli/cli.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function runCli(argv: string[]): Promise<number>;
|
package/dist/node/cli/cli.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { dirname, join } from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
|
-
import { createCli } from '@vmz/commander';
|
|
4
|
-
import { registerInfoCommand } from './info-cmd.js';
|
|
5
|
-
import { registerInitCommand } from './init-cmd.js';
|
|
6
|
-
import { registerServeCommand } from './serve-cmd.js';
|
|
7
|
-
import { registerVersionCommand } from './version-cmd.js';
|
|
8
|
-
function buildYydbCli() {
|
|
9
|
-
const localesRoot = join(dirname(fileURLToPath(import.meta.url)), '../../../locales');
|
|
10
|
-
const cli = createCli('yydb').locales(localesRoot).intro('cli.intro');
|
|
11
|
-
registerVersionCommand(cli);
|
|
12
|
-
registerInitCommand(cli);
|
|
13
|
-
registerInfoCommand(cli);
|
|
14
|
-
registerServeCommand(cli);
|
|
15
|
-
return cli;
|
|
16
|
-
}
|
|
17
|
-
export async function runCli(argv) {
|
|
18
|
-
try {
|
|
19
|
-
return await buildYydbCli().parse(argv);
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
23
|
-
return 1;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { loadNative } from '../native.js';
|
|
2
|
-
import { requiredPositional } from './options.js';
|
|
3
|
-
export function registerInfoCommand(cli) {
|
|
4
|
-
cli.command('info', 'cli.cmd.info').action((options) => cmdInfo(options));
|
|
5
|
-
}
|
|
6
|
-
export function cmdInfo(options) {
|
|
7
|
-
const dbPath = requiredPositional(options, 'info');
|
|
8
|
-
console.log(loadNative().infoText(dbPath));
|
|
9
|
-
return 0;
|
|
10
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { loadNative } from '../native.js';
|
|
2
|
-
import { requiredPositional, str } from './options.js';
|
|
3
|
-
export function registerInitCommand(cli) {
|
|
4
|
-
cli.command('init', 'cli.cmd.init')
|
|
5
|
-
.option('--schema-version <n>', 'cli.opt.schema-version')
|
|
6
|
-
.option('--schema-file <path>', 'cli.opt.schema-file')
|
|
7
|
-
.action((options) => cmdInit(options));
|
|
8
|
-
}
|
|
9
|
-
export function cmdInit(options) {
|
|
10
|
-
const dbPath = requiredPositional(options, 'init');
|
|
11
|
-
const schemaVersion = Number.parseInt(str(options, 'schema-version') ?? '1', 10);
|
|
12
|
-
const schemaFile = str(options, 'schema-file');
|
|
13
|
-
const native = loadNative();
|
|
14
|
-
const schemaDocument = schemaFile ? native.readSchemaFile(schemaFile) : null;
|
|
15
|
-
native.initDb(dbPath, schemaVersion, schemaDocument);
|
|
16
|
-
console.log(`initialized ${dbPath}`);
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { ParsedOptions } from '@vmz/commander';
|
|
2
|
-
export declare function str(options: ParsedOptions, key: string): string | undefined;
|
|
3
|
-
export declare function flag(options: ParsedOptions, key: string): boolean;
|
|
4
|
-
export declare function requiredPositional(options: ParsedOptions, label: string): string;
|
package/dist/node/cli/options.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function str(options, key) {
|
|
2
|
-
const value = options[key];
|
|
3
|
-
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
4
|
-
}
|
|
5
|
-
export function flag(options, key) {
|
|
6
|
-
return options[key] === true;
|
|
7
|
-
}
|
|
8
|
-
export function requiredPositional(options, label) {
|
|
9
|
-
const value = options._[0];
|
|
10
|
-
if (!value) {
|
|
11
|
-
throw new Error(`${label} requires a path argument`);
|
|
12
|
-
}
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { loadNative } from '../native.js';
|
|
2
|
-
import { flag, requiredPositional, str } from './options.js';
|
|
3
|
-
export function registerServeCommand(cli) {
|
|
4
|
-
cli.command('serve', 'cli.cmd.serve')
|
|
5
|
-
.option('--bind <host:port>', 'cli.opt.bind')
|
|
6
|
-
.option('--insecure-bind', 'cli.opt.insecure-bind')
|
|
7
|
-
.action((options) => cmdServe(options));
|
|
8
|
-
}
|
|
9
|
-
export function cmdServe(options) {
|
|
10
|
-
const dbPath = requiredPositional(options, 'serve');
|
|
11
|
-
const bind = str(options, 'bind') ?? '127.0.0.1:7700';
|
|
12
|
-
loadNative().serve(dbPath, bind, flag(options, 'insecure-bind'));
|
|
13
|
-
return 0;
|
|
14
|
-
}
|
package/dist/node/cli.d.ts
DELETED
package/dist/node/cli.js
DELETED
package/dist/node/database.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { defineMicro as buildMicro, type DefinedMicro, type MicroHandle } from '../shared/micro.js';
|
|
2
|
-
import type { UdfScalarDescriptor } from '../shared/udf-types.js';
|
|
3
|
-
export type { SchemaVersion } from '@yydb/yydb-client';
|
|
4
|
-
export interface OpenOptions {
|
|
5
|
-
/** Override CLI script path (tests / special installs). */
|
|
6
|
-
cli?: string;
|
|
7
|
-
/** @deprecated Use `cli`. */
|
|
8
|
-
binary?: string;
|
|
9
|
-
/** Prefer a specific loopback port; default = ephemeral free port. */
|
|
10
|
-
port?: number;
|
|
11
|
-
/** Extra args after `serve <path> --bind …`. */
|
|
12
|
-
serveArgs?: string[];
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Node-facing YYDB handle. Looks like one library; owns a private loopback
|
|
16
|
-
* `yydb serve` child under the hood.
|
|
17
|
-
*/
|
|
18
|
-
export declare class Database {
|
|
19
|
-
readonly path: string;
|
|
20
|
-
readonly endpoint: string;
|
|
21
|
-
private client;
|
|
22
|
-
private child;
|
|
23
|
-
private readonly microRegistry;
|
|
24
|
-
private constructor();
|
|
25
|
-
/**
|
|
26
|
-
* Open (create) a `.yydb` file. Spawns the engine on `127.0.0.1` automatically.
|
|
27
|
-
*/
|
|
28
|
-
static open(dbPath: string, options?: OpenOptions): Promise<Database>;
|
|
29
|
-
serverVersion(): Promise<string>;
|
|
30
|
-
info(): Promise<string>;
|
|
31
|
-
getSchema(): Promise<import("@yydb/yydb-client").SchemaVersion | null>;
|
|
32
|
-
ensureSchema(version: number, document: string): Promise<void>;
|
|
33
|
-
get(key: string): Promise<Uint8Array | null>;
|
|
34
|
-
put(key: string, value: Uint8Array | string): Promise<void>;
|
|
35
|
-
/**
|
|
36
|
-
* Build a typed session-local micro definition. Does not register it with
|
|
37
|
-
* the engine until [`registerMicro`](./database.ts) is called.
|
|
38
|
-
*/
|
|
39
|
-
defineMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: Parameters<typeof buildMicro<TArgs, TReturn>>[0]): DefinedMicro<TArgs, TReturn>;
|
|
40
|
-
/**
|
|
41
|
-
* Install a [`defineMicro`](./database.ts) definition into the current
|
|
42
|
-
* session registry and sync metadata to the private engine. Host micros are
|
|
43
|
-
* session-local and never written to `.yydb`.
|
|
44
|
-
*/
|
|
45
|
-
registerMicro<TArgs extends readonly UdfScalarDescriptor[], TReturn extends UdfScalarDescriptor>(definition: DefinedMicro<TArgs, TReturn>): Promise<MicroHandle>;
|
|
46
|
-
/** Invoke a registered scalar UDF on the private engine. */
|
|
47
|
-
callScalar(name: string, version: number, args: readonly (string | number | boolean | null)[]): Promise<string | number | boolean | null>;
|
|
48
|
-
/** Stop the private engine process. */
|
|
49
|
-
close(): Promise<void>;
|
|
50
|
-
}
|
package/dist/node/database.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import net from 'node:net';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { connect } from '@yydb/yydb-client/node';
|
|
6
|
-
import { defineMicro as buildMicro, microFingerprint, udfWireKind, MicroSessionRegistry } from '../shared/micro.js';
|
|
7
|
-
import { resolveYydbCli } from './resolve-bin.js';
|
|
8
|
-
async function freeLoopbackPort() {
|
|
9
|
-
return await new Promise((resolve, reject) => {
|
|
10
|
-
const server = net.createServer();
|
|
11
|
-
server.listen(0, '127.0.0.1', () => {
|
|
12
|
-
const address = server.address();
|
|
13
|
-
if (!address || typeof address === 'string') {
|
|
14
|
-
server.close();
|
|
15
|
-
reject(new Error('could not allocate loopback port'));
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const { port } = address;
|
|
19
|
-
server.close((error) => {
|
|
20
|
-
if (error)
|
|
21
|
-
reject(error);
|
|
22
|
-
else
|
|
23
|
-
resolve(port);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
server.on('error', reject);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
async function waitForTcp(host, port, timeoutMs) {
|
|
30
|
-
const deadline = Date.now() + timeoutMs;
|
|
31
|
-
while (Date.now() < deadline) {
|
|
32
|
-
try {
|
|
33
|
-
await new Promise((resolve, reject) => {
|
|
34
|
-
const socket = net.connect({ host, port }, () => {
|
|
35
|
-
socket.end();
|
|
36
|
-
resolve();
|
|
37
|
-
});
|
|
38
|
-
socket.on('error', reject);
|
|
39
|
-
});
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
await new Promise((r) => setTimeout(r, 40));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
throw new Error(`yydb engine did not accept connections on ${host}:${port}`);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Node-facing YYDB handle. Looks like one library; owns a private loopback
|
|
50
|
-
* `yydb serve` child under the hood.
|
|
51
|
-
*/
|
|
52
|
-
export class Database {
|
|
53
|
-
path;
|
|
54
|
-
endpoint;
|
|
55
|
-
client;
|
|
56
|
-
child;
|
|
57
|
-
microRegistry;
|
|
58
|
-
constructor(dbPath, endpoint, client, child) {
|
|
59
|
-
this.path = dbPath;
|
|
60
|
-
this.endpoint = endpoint;
|
|
61
|
-
this.client = client;
|
|
62
|
-
this.child = child;
|
|
63
|
-
this.microRegistry = new MicroSessionRegistry();
|
|
64
|
-
this.client.setMicroHostHandler((payload) => this.microRegistry.invokeFromWire(payload));
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Open (create) a `.yydb` file. Spawns the engine on `127.0.0.1` automatically.
|
|
68
|
-
*/
|
|
69
|
-
static async open(dbPath, options = {}) {
|
|
70
|
-
const resolved = path.resolve(dbPath);
|
|
71
|
-
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
72
|
-
const cli = options.cli ?? options.binary ?? resolveYydbCli();
|
|
73
|
-
const port = options.port ?? (await freeLoopbackPort());
|
|
74
|
-
const bind = `127.0.0.1:${port}`;
|
|
75
|
-
const args = [cli, 'serve', resolved, '--bind', bind, ...(options.serveArgs ?? [])];
|
|
76
|
-
const child = spawn(process.execPath, args, {
|
|
77
|
-
stdio: 'pipe',
|
|
78
|
-
windowsHide: true,
|
|
79
|
-
});
|
|
80
|
-
let stderr = '';
|
|
81
|
-
child.stderr?.setEncoding('utf8');
|
|
82
|
-
child.stderr?.on('data', (chunk) => {
|
|
83
|
-
stderr += chunk;
|
|
84
|
-
});
|
|
85
|
-
const exitPromise = new Promise((_, reject) => {
|
|
86
|
-
child.once('exit', (code, signal) => {
|
|
87
|
-
reject(new Error(`yydb engine exited early (code=${code}, signal=${signal}): ${stderr.trim()}`));
|
|
88
|
-
});
|
|
89
|
-
child.once('error', reject);
|
|
90
|
-
});
|
|
91
|
-
try {
|
|
92
|
-
await Promise.race([waitForTcp('127.0.0.1', port, 8000), exitPromise]);
|
|
93
|
-
const client = await connect(bind);
|
|
94
|
-
child.removeAllListeners('exit');
|
|
95
|
-
child.removeAllListeners('error');
|
|
96
|
-
child.on('exit', () => {
|
|
97
|
-
/* closed via Database.close or crash */
|
|
98
|
-
});
|
|
99
|
-
return new Database(resolved, bind, client, child);
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
child.kill('SIGTERM');
|
|
103
|
-
throw error;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
async serverVersion() {
|
|
107
|
-
return this.client.serverVersion();
|
|
108
|
-
}
|
|
109
|
-
async info() {
|
|
110
|
-
return this.client.info();
|
|
111
|
-
}
|
|
112
|
-
async getSchema() {
|
|
113
|
-
return this.client.getSchema();
|
|
114
|
-
}
|
|
115
|
-
async ensureSchema(version, document) {
|
|
116
|
-
await this.client.ensureSchema(version, document);
|
|
117
|
-
}
|
|
118
|
-
async get(key) {
|
|
119
|
-
return this.client.get(key);
|
|
120
|
-
}
|
|
121
|
-
async put(key, value) {
|
|
122
|
-
await this.client.put(key, value);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Build a typed session-local micro definition. Does not register it with
|
|
126
|
-
* the engine until [`registerMicro`](./database.ts) is called.
|
|
127
|
-
*/
|
|
128
|
-
defineMicro(definition) {
|
|
129
|
-
return buildMicro(definition);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Install a [`defineMicro`](./database.ts) definition into the current
|
|
133
|
-
* session registry and sync metadata to the private engine. Host micros are
|
|
134
|
-
* session-local and never written to `.yydb`.
|
|
135
|
-
*/
|
|
136
|
-
async registerMicro(definition) {
|
|
137
|
-
const handle = this.microRegistry.register(definition);
|
|
138
|
-
await this.client.registerMicro({
|
|
139
|
-
hostId: handle.hostId,
|
|
140
|
-
handleVersion: handle.implementationVersion,
|
|
141
|
-
udfVersion: definition.version,
|
|
142
|
-
name: definition.name,
|
|
143
|
-
functionId: handle.functionId,
|
|
144
|
-
args: definition.args.map(udfWireKind),
|
|
145
|
-
returns: udfWireKind(definition.returns),
|
|
146
|
-
fingerprint: microFingerprint(definition.name, definition.version),
|
|
147
|
-
});
|
|
148
|
-
return handle;
|
|
149
|
-
}
|
|
150
|
-
/** Invoke a registered scalar UDF on the private engine. */
|
|
151
|
-
async callScalar(name, version, args) {
|
|
152
|
-
return this.client.callScalar(name, version, args);
|
|
153
|
-
}
|
|
154
|
-
/** Stop the private engine process. */
|
|
155
|
-
async close() {
|
|
156
|
-
this.client.close();
|
|
157
|
-
const child = this.child;
|
|
158
|
-
this.child = null;
|
|
159
|
-
if (!child || child.exitCode !== null || child.killed) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
await new Promise((resolve) => {
|
|
163
|
-
child.once('exit', () => resolve());
|
|
164
|
-
child.kill('SIGTERM');
|
|
165
|
-
setTimeout(() => {
|
|
166
|
-
if (child.exitCode === null && !child.killed) {
|
|
167
|
-
child.kill('SIGKILL');
|
|
168
|
-
}
|
|
169
|
-
resolve();
|
|
170
|
-
}, 2000);
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
package/dist/node/index.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
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';
|
package/dist/node/index.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
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';
|
package/dist/node/native.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
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;
|
package/dist/node/native.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
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;
|