turbine-orm 0.49.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -39
- package/dist/cjs/adapters/cockroachdb.d.ts +39 -0
- package/dist/cjs/adapters/index.d.ts +110 -0
- package/dist/cjs/adapters/yugabytedb.d.ts +51 -0
- package/dist/cjs/cli/config.d.ts +181 -0
- package/dist/cjs/cli/config.js +32 -6
- package/dist/cjs/cli/destructive.d.ts +38 -0
- package/dist/cjs/cli/index.d.ts +359 -0
- package/dist/cjs/cli/index.js +228 -56
- package/dist/cjs/cli/loader.d.ts +61 -0
- package/dist/cjs/cli/mcp.d.ts +42 -0
- package/dist/cjs/cli/migrate.d.ts +356 -0
- package/dist/cjs/cli/migrate.js +131 -40
- package/dist/cjs/cli/observe-ui.d.ts +1 -0
- package/dist/cjs/cli/observe-ui.js +14 -5
- package/dist/cjs/cli/observe.d.ts +25 -0
- package/dist/cjs/cli/observe.js +49 -12
- package/dist/cjs/cli/pii-tags.d.ts +53 -0
- package/dist/cjs/cli/prisma-report.d.ts +33 -0
- package/dist/cjs/cli/prisma-report.js +73 -0
- package/dist/cjs/cli/prisma-resolve.d.ts +106 -0
- package/dist/cjs/cli/prisma-resolve.js +1 -0
- package/dist/cjs/cli/prisma-schema.d.ts +176 -0
- package/dist/cjs/cli/prisma-schema.js +82 -4
- package/dist/cjs/cli/rate-limit.d.ts +32 -0
- package/dist/cjs/cli/rate-limit.js +45 -0
- package/dist/cjs/cli/studio-demo.d.ts +43 -0
- package/dist/cjs/cli/studio-ui.generated.d.ts +1 -0
- package/dist/cjs/cli/studio.d.ts +207 -0
- package/dist/cjs/cli/studio.js +136 -71
- package/dist/cjs/cli/ui.d.ts +73 -0
- package/dist/cjs/cli/ui.js +51 -9
- package/dist/cjs/client.d.ts +837 -0
- package/dist/cjs/client.js +3 -0
- package/dist/cjs/dialect.d.ts +516 -0
- package/dist/cjs/dialect.js +37 -12
- package/dist/cjs/errors.d.ts +370 -0
- package/dist/cjs/generate.d.ts +137 -0
- package/dist/cjs/generate.js +39 -6
- package/dist/cjs/index-advisor.d.ts +153 -0
- package/dist/cjs/index-stats.d.ts +384 -0
- package/dist/cjs/index.d.ts +55 -0
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/introspect.d.ts +269 -0
- package/dist/cjs/mssql.d.ts +232 -0
- package/dist/cjs/mssql.js +6 -0
- package/dist/cjs/mysql.d.ts +173 -0
- package/dist/cjs/mysql.js +16 -0
- package/dist/cjs/nested-write.d.ts +96 -0
- package/dist/cjs/nested-write.js +414 -24
- package/dist/cjs/observe.d.ts +115 -0
- package/dist/cjs/optional-peer-import.d.cts +72 -0
- package/dist/cjs/pipeline-submittable.d.ts +93 -0
- package/dist/cjs/pipeline.d.ts +71 -0
- package/dist/cjs/powdb-introspect.d.ts +84 -0
- package/dist/cjs/powdb.d.ts +931 -0
- package/dist/cjs/powdb.js +106 -21
- package/dist/cjs/powql.d.ts +592 -0
- package/dist/cjs/powql.js +42 -6
- package/dist/cjs/prisma-compat.d.ts +283 -0
- package/dist/cjs/prisma-compat.js +167 -9
- package/dist/cjs/query/aggregates.d.ts +92 -0
- package/dist/cjs/query/aggregates.js +7 -3
- package/dist/cjs/query/batched-loader.d.ts +193 -0
- package/dist/cjs/query/builder.d.ts +849 -0
- package/dist/cjs/query/builder.js +571 -65
- package/dist/cjs/query/compound-unique.d.ts +51 -0
- package/dist/cjs/query/deferred.d.ts +223 -0
- package/dist/cjs/query/filters.d.ts +201 -0
- package/dist/cjs/query/index.d.ts +14 -0
- package/dist/cjs/query/index.js +6 -1
- package/dist/cjs/query/relations.d.ts +609 -0
- package/dist/cjs/query/relations.js +693 -46
- package/dist/cjs/query/types.d.ts +1300 -0
- package/dist/cjs/query/utils.d.ts +209 -0
- package/dist/cjs/query/utils.js +208 -1
- package/dist/cjs/query/warn-registry.d.ts +68 -0
- package/dist/cjs/query/warn-registry.js +9 -0
- package/dist/cjs/query/where-compile.d.ts +139 -0
- package/dist/cjs/query/where.d.ts +548 -0
- package/dist/cjs/query/where.js +58 -22
- package/dist/cjs/query/writes.d.ts +172 -0
- package/dist/cjs/query/writes.js +105 -12
- package/dist/cjs/realtime.d.ts +70 -0
- package/dist/cjs/schema-builder.d.ts +354 -0
- package/dist/cjs/schema-metadata.d.ts +83 -0
- package/dist/cjs/schema-sql.d.ts +217 -0
- package/dist/cjs/schema-sql.js +23 -5
- package/dist/cjs/schema.d.ts +356 -0
- package/dist/cjs/schema.js +125 -0
- package/dist/cjs/seed.d.ts +15 -0
- package/dist/cjs/serverless.d.ts +142 -0
- package/dist/cjs/sqlite.d.ts +143 -0
- package/dist/cjs/sqlite.js +4 -0
- package/dist/cjs/typed-sql.d.ts +102 -0
- package/dist/cli/config.d.ts +18 -4
- package/dist/cli/config.js +31 -6
- package/dist/cli/index.d.ts +123 -0
- package/dist/cli/index.js +223 -58
- package/dist/cli/migrate.d.ts +59 -10
- package/dist/cli/migrate.js +128 -41
- package/dist/cli/observe-ui.d.ts +1 -1
- package/dist/cli/observe-ui.js +14 -5
- package/dist/cli/observe.d.ts +7 -1
- package/dist/cli/observe.js +48 -12
- package/dist/cli/prisma-report.d.ts +14 -0
- package/dist/cli/prisma-report.js +72 -0
- package/dist/cli/prisma-resolve.d.ts +6 -0
- package/dist/cli/prisma-resolve.js +1 -0
- package/dist/cli/prisma-schema.d.ts +62 -2
- package/dist/cli/prisma-schema.js +81 -4
- package/dist/cli/rate-limit.d.ts +32 -0
- package/dist/cli/rate-limit.js +40 -0
- package/dist/cli/studio.d.ts +5 -5
- package/dist/cli/studio.js +135 -70
- package/dist/cli/ui.d.ts +1 -1
- package/dist/cli/ui.js +51 -9
- package/dist/client.d.ts +40 -0
- package/dist/client.js +3 -0
- package/dist/dialect.d.ts +17 -1
- package/dist/dialect.js +37 -12
- package/dist/generate.js +40 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mssql.js +6 -0
- package/dist/mysql.js +16 -0
- package/dist/nested-write.d.ts +2 -0
- package/dist/nested-write.js +415 -25
- package/dist/powdb.d.ts +4 -2
- package/dist/powdb.js +106 -21
- package/dist/powql.d.ts +5 -0
- package/dist/powql.js +42 -6
- package/dist/prisma-compat.d.ts +2 -0
- package/dist/prisma-compat.js +166 -8
- package/dist/query/aggregates.js +7 -3
- package/dist/query/builder.d.ts +292 -21
- package/dist/query/builder.js +570 -64
- package/dist/query/deferred.d.ts +39 -0
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/relations.d.ts +173 -5
- package/dist/query/relations.js +688 -47
- package/dist/query/types.d.ts +123 -39
- package/dist/query/utils.d.ts +116 -0
- package/dist/query/utils.js +198 -0
- package/dist/query/warn-registry.d.ts +9 -0
- package/dist/query/warn-registry.js +9 -0
- package/dist/query/where.d.ts +38 -1
- package/dist/query/where.js +58 -23
- package/dist/query/writes.d.ts +42 -1
- package/dist/query/writes.js +104 -13
- package/dist/schema-sql.d.ts +14 -0
- package/dist/schema-sql.js +23 -5
- package/dist/schema.d.ts +38 -0
- package/dist/schema.js +123 -0
- package/dist/sqlite.js +4 -0
- package/package.json +77 -28
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True dynamic `import()` for the optional peer dependencies (`mysql2`,
|
|
3
|
+
* `mssql`, `@zvndev/powdb-client`, `@zvndev/powdb-embedded`) — safe in BOTH
|
|
4
|
+
* build outputs, including for peers that are ESM-only.
|
|
5
|
+
*
|
|
6
|
+
* THE PROBLEM THIS FILE SOLVES (the `@zvndev/powdb-client` ≥ 0.9 CJS break):
|
|
7
|
+
* the engine subpaths load their optional peers with dynamic `import()` so the
|
|
8
|
+
* peers stay out of the static graph. The ESM build (`tsconfig.json`, module
|
|
9
|
+
* NodeNext) emits that `import()` verbatim. The CJS build (`tsconfig.cjs.json`,
|
|
10
|
+
* module CommonJS) however TRANSPILES `import()` into
|
|
11
|
+
* `Promise.resolve().then(() => require(...))` — and `require()` of an
|
|
12
|
+
* ESM-only package (no `require` export condition, e.g. powdb-client ≥ 0.9)
|
|
13
|
+
* throws `ERR_PACKAGE_PATH_NOT_EXPORTED`, breaking every CJS consumer.
|
|
14
|
+
*
|
|
15
|
+
* TypeScript offers no way to preserve `import()` under `module: CommonJS`,
|
|
16
|
+
* and the CJS pass cannot switch to `module: NodeNext` (the root package.json
|
|
17
|
+
* says `"type": "module"`, so NodeNext would classify every `.ts` source as
|
|
18
|
+
* ESM and emit ESM into dist/cjs). A `.cts` file is the escape hatch: it is
|
|
19
|
+
* CommonJS-format by extension regardless of package `type`, so under the ESM
|
|
20
|
+
* pass (NodeNext) it compiles to `dist/optional-peer-import.cjs` — a CommonJS
|
|
21
|
+
* file whose `import()` SURVIVES transpilation (NodeNext preserves dynamic
|
|
22
|
+
* import in CJS files precisely because it is the only way CJS can load ESM).
|
|
23
|
+
*
|
|
24
|
+
* That gives the published package two copies of this module:
|
|
25
|
+
* - `dist/optional-peer-import.cjs` (ESM pass, NodeNext) — real `import()`
|
|
26
|
+
* - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS) — lowered to `require()`
|
|
27
|
+
*
|
|
28
|
+
* The lowered copy works fine for CJS-loadable peers (`mysql2`, `mssql`, older
|
|
29
|
+
* powdb peers). When it hits an ESM-only peer, the `require()` fails with a
|
|
30
|
+
* recognizable code and this function falls back to delegating the load to the
|
|
31
|
+
* sibling NodeNext copy one directory up (`../optional-peer-import.cjs`) —
|
|
32
|
+
* which is a plain CommonJS file (loadable by `require()` on every supported
|
|
33
|
+
* Node) whose real `import()` then loads the ESM peer. The ESM-pass copy has
|
|
34
|
+
* no such sibling; its lazy `require` throws and the original error surfaces,
|
|
35
|
+
* so the fallback can never recurse.
|
|
36
|
+
*
|
|
37
|
+
* Keep this module dependency-free and side-effect-free: it must be loadable
|
|
38
|
+
* from both module systems on every supported Node (≥ 20) without pulling in
|
|
39
|
+
* anything else.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Dynamically import an optional peer dependency. In the ESM build this is a
|
|
43
|
+
* plain `import()`. In the CJS build the first attempt is a transpiled
|
|
44
|
+
* `require()`; if the peer turns out to be ESM-only, the load is retried
|
|
45
|
+
* through the ESM-build sibling copy of this file, whose `import()` survived
|
|
46
|
+
* transpilation (see the module doc comment).
|
|
47
|
+
*
|
|
48
|
+
* @param specifier bare package specifier (e.g. `'@zvndev/powdb-client'`).
|
|
49
|
+
* @param allowEsmFallback internal recursion guard — the delegated call passes
|
|
50
|
+
* `false` so a failure in the sibling copy can never bounce back.
|
|
51
|
+
*/
|
|
52
|
+
declare function importOptionalPeer(specifier: string, allowEsmFallback?: boolean): Promise<unknown>;
|
|
53
|
+
/**
|
|
54
|
+
* Merged namespace so callers can reach {@link peerPackageVersion} off the same
|
|
55
|
+
* default import (`importOptionalPeer.peerPackageVersion(...)`). Lives in this
|
|
56
|
+
* `.cts` file for the same reason the dynamic import does: a `.cts` compiles to
|
|
57
|
+
* CommonJS in BOTH build passes, so `require` / `require.resolve` are natively
|
|
58
|
+
* available and `import.meta` is never emitted (which would break the CJS build
|
|
59
|
+
* and crash CJS consumers, see `resolveEmbeddedVersion` in powdb.ts).
|
|
60
|
+
*/
|
|
61
|
+
declare namespace importOptionalPeer {
|
|
62
|
+
/**
|
|
63
|
+
* Resolve an optional peer's declared `package.json` version WITHOUT loading
|
|
64
|
+
* the package itself (so an ESM-only peer never trips `require`). `require` is
|
|
65
|
+
* anchored on THIS module's location (inside the published `dist/`), so bare
|
|
66
|
+
* resolution walks up `node_modules` and finds the peer exactly where
|
|
67
|
+
* `import.meta.url` used to point, but it compiles under `module: CommonJS`
|
|
68
|
+
* too. Returns `null` when the peer / its package.json cannot be resolved.
|
|
69
|
+
*/
|
|
70
|
+
function peerPackageVersion(specifier: string): string | null;
|
|
71
|
+
}
|
|
72
|
+
export = importOptionalPeer;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm — Real Postgres pipeline protocol implementation
|
|
3
|
+
*
|
|
4
|
+
* Uses the pg extended-query protocol wire methods (parse/bind/describe/execute/sync)
|
|
5
|
+
* exposed on pg.Client's Connection object to send multiple queries in a single
|
|
6
|
+
* TCP flush. This achieves true 1-RTT pipeline execution instead of the sequential
|
|
7
|
+
* await-per-query approach.
|
|
8
|
+
*
|
|
9
|
+
* The approach (listener-swap):
|
|
10
|
+
* 1. Detach the pg.Client's event listeners from the Connection
|
|
11
|
+
* 2. Attach our own state-machine listeners
|
|
12
|
+
* 3. Cork the TCP stream, push all protocol messages, uncork (one TCP write)
|
|
13
|
+
* 4. Drive a state machine over backend response events
|
|
14
|
+
* 5. Restore original listeners and release the client
|
|
15
|
+
*
|
|
16
|
+
* This is the same pattern used by pg-cursor and pg-query-stream, but extended
|
|
17
|
+
* to handle N queries in a single pipeline.
|
|
18
|
+
*/
|
|
19
|
+
import type { EventEmitter } from 'node:events';
|
|
20
|
+
import type { DeferredQuery } from './query/index.js';
|
|
21
|
+
/** The pg Connection object — an EventEmitter with wire-protocol methods */
|
|
22
|
+
export interface PgConnection extends EventEmitter {
|
|
23
|
+
stream: {
|
|
24
|
+
cork?: () => void;
|
|
25
|
+
uncork?: () => void;
|
|
26
|
+
writable?: boolean;
|
|
27
|
+
destroy?: (err?: Error) => void;
|
|
28
|
+
write?: (...args: unknown[]) => boolean;
|
|
29
|
+
};
|
|
30
|
+
parse(query: {
|
|
31
|
+
text: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
types?: number[];
|
|
34
|
+
}): void;
|
|
35
|
+
bind(config: {
|
|
36
|
+
portal?: string;
|
|
37
|
+
statement?: string;
|
|
38
|
+
values?: unknown[];
|
|
39
|
+
binary?: boolean;
|
|
40
|
+
valueMapper?: (val: unknown, index: number) => unknown;
|
|
41
|
+
}): void;
|
|
42
|
+
describe(msg: {
|
|
43
|
+
type: 'S' | 'P';
|
|
44
|
+
name?: string;
|
|
45
|
+
}): void;
|
|
46
|
+
execute(config: {
|
|
47
|
+
portal?: string;
|
|
48
|
+
rows?: number;
|
|
49
|
+
}): void;
|
|
50
|
+
sync(): void;
|
|
51
|
+
}
|
|
52
|
+
/** A pg PoolClient with the internal fields we need */
|
|
53
|
+
export interface PgPoolClient {
|
|
54
|
+
connection: PgConnection;
|
|
55
|
+
/** pg.Client sets this to control query queue draining */
|
|
56
|
+
readyForQuery: boolean;
|
|
57
|
+
/** Type parser overrides (if the client has custom type parsers) */
|
|
58
|
+
_types?: unknown;
|
|
59
|
+
release(err?: Error | boolean): void;
|
|
60
|
+
}
|
|
61
|
+
export interface PipelineRunOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Whether to wrap the pipeline in BEGIN/COMMIT (default: true).
|
|
64
|
+
* When true, all queries execute atomically. On error, ROLLBACK is sent.
|
|
65
|
+
* When false, each query gets its own Sync message for error isolation.
|
|
66
|
+
*/
|
|
67
|
+
transactional?: boolean;
|
|
68
|
+
/** Timeout in milliseconds. If exceeded, the connection is destroyed. */
|
|
69
|
+
timeout?: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Execute multiple queries using the Postgres extended-query pipeline protocol.
|
|
73
|
+
*
|
|
74
|
+
* All protocol messages are buffered into a single TCP write via cork/uncork.
|
|
75
|
+
* The backend processes them in order and sends back results which our state
|
|
76
|
+
* machine collects.
|
|
77
|
+
*
|
|
78
|
+
* @param client - A pg PoolClient with an accessible Connection
|
|
79
|
+
* @param queries - Array of DeferredQuery descriptors
|
|
80
|
+
* @param options - Pipeline options (transactional, timeout)
|
|
81
|
+
* @returns Array of transformed results in the same order as queries
|
|
82
|
+
*/
|
|
83
|
+
export declare function runPipelined<T extends readonly DeferredQuery<unknown>[]>(client: PgPoolClient, queries: T, options?: PipelineRunOptions): Promise<unknown[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Check whether a pool client supports the extended-query pipeline protocol.
|
|
86
|
+
*
|
|
87
|
+
* Returns true if the client has a Connection object with the required wire
|
|
88
|
+
* protocol methods (parse, bind, describe, execute, sync) and is an EventEmitter.
|
|
89
|
+
*
|
|
90
|
+
* Returns false for HTTP-based drivers (Neon HTTP, Vercel Postgres), mock pools,
|
|
91
|
+
* and any pool that doesn't expose pg internals.
|
|
92
|
+
*/
|
|
93
|
+
export declare function supportsExtendedPipeline(poolClient: unknown): poolClient is PgPoolClient;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm — Pipeline execution
|
|
3
|
+
*
|
|
4
|
+
* Pipelines batch multiple independent queries into a single database round-trip.
|
|
5
|
+
* Instead of N sequential awaits (N round-trips), you get 1 round-trip for all N queries.
|
|
6
|
+
*
|
|
7
|
+
* How it works:
|
|
8
|
+
* 1. Each query method (findUnique, count, etc.) can produce a DeferredQuery descriptor
|
|
9
|
+
* containing the SQL, params, and a transform function.
|
|
10
|
+
* 2. pipeline() collects these descriptors, checks whether the underlying pool client
|
|
11
|
+
* supports the extended-query pipeline protocol, and either:
|
|
12
|
+
* (a) executes them via real Postgres pipeline protocol (one TCP flush), or
|
|
13
|
+
* (b) falls back to sequential execution on a single connection.
|
|
14
|
+
*
|
|
15
|
+
* Real pipeline mode uses `src/pipeline-submittable.ts` which drives the pg Connection's
|
|
16
|
+
* wire-protocol methods (parse/bind/describe/execute/sync) directly with listener-swap.
|
|
17
|
+
*
|
|
18
|
+
* Sequential fallback covers HTTP-based drivers (Neon HTTP, Vercel Postgres, Cloudflare
|
|
19
|
+
* Hyperdrive), mock pools in tests, and any pool that doesn't expose pg internals.
|
|
20
|
+
*/
|
|
21
|
+
import type pg from 'pg';
|
|
22
|
+
import type { DeferredQuery } from './query/index.js';
|
|
23
|
+
export interface PipelineOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Whether to wrap the pipeline in a transaction (default: true).
|
|
26
|
+
*
|
|
27
|
+
* - `true` (default): All queries execute atomically within BEGIN/COMMIT.
|
|
28
|
+
* If any query fails, the entire batch is rolled back.
|
|
29
|
+
*
|
|
30
|
+
* - `false`: Each query is independent. A failure in one query does NOT
|
|
31
|
+
* affect others. On partial failure, a `PipelineError` is thrown with
|
|
32
|
+
* per-query results in `.results`.
|
|
33
|
+
*/
|
|
34
|
+
transactional?: boolean;
|
|
35
|
+
/** Timeout in milliseconds. If exceeded, the connection is destroyed. */
|
|
36
|
+
timeout?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Execute multiple deferred queries in a single batch.
|
|
40
|
+
*
|
|
41
|
+
* On pg.Pool-backed connections with the standard TCP driver, this uses the
|
|
42
|
+
* real Postgres extended-query pipeline protocol for true 1-RTT execution.
|
|
43
|
+
* On HTTP-based drivers (Neon HTTP, Vercel Postgres, etc.) or mock pools,
|
|
44
|
+
* it falls back to sequential execution on a single connection.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const [user, count, posts] = await executePipeline(pool, [
|
|
49
|
+
* db.users.buildFindUnique({ where: { id: 1 } }),
|
|
50
|
+
* db.posts.buildCount({ where: { orgId: 1 } }),
|
|
51
|
+
* db.posts.buildFindMany({ where: { userId: 1 }, limit: 10 }),
|
|
52
|
+
* ]);
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function executePipeline<T extends readonly DeferredQuery<unknown>[]>(pool: pg.Pool, queries: T, options?: PipelineOptions): Promise<PipelineResults<T>>;
|
|
56
|
+
/**
|
|
57
|
+
* Check whether a pool supports the real pipeline protocol.
|
|
58
|
+
* Call this to determine at runtime whether pipelines will use the fast path
|
|
59
|
+
* or fall back to sequential execution.
|
|
60
|
+
*
|
|
61
|
+
* Note: This acquires and immediately releases a connection to inspect it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function pipelineSupported(pool: pg.Pool): Promise<boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* Extract the result types from a tuple of DeferredQuery objects.
|
|
66
|
+
* If you pass [DeferredQuery<User>, DeferredQuery<number>, DeferredQuery<Post[]>],
|
|
67
|
+
* you get back [User, number, Post[]].
|
|
68
|
+
*/
|
|
69
|
+
export type PipelineResults<T extends readonly DeferredQuery<unknown>[]> = {
|
|
70
|
+
[K in keyof T]: T[K] extends DeferredQuery<infer R> ? R : never;
|
|
71
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm/powdb — `describe`-based introspection.
|
|
3
|
+
*
|
|
4
|
+
* PowDB exposes its catalog through two ordinary rows-returning statements
|
|
5
|
+
* (keywords since engine 0.10):
|
|
6
|
+
* - `schema` → one row per type: `{ name, columns }` (columns = a count).
|
|
7
|
+
* - `describe <T>` / `schema <T>` → one row per column:
|
|
8
|
+
* `{ column, type, nullable, index }` where `type` is a PowQL type name
|
|
9
|
+
* (`str`/`int`/`float`/`bool`/`json`/`datetime`/`uuid`/`bytes`), `nullable`
|
|
10
|
+
* is `"true"`/`"false"`, and `index` is `"unique"` / `"index"` / `""`.
|
|
11
|
+
*
|
|
12
|
+
* {@link introspectPowdbDatabase} turns those into the same {@link SchemaMetadata}
|
|
13
|
+
* shape the SQL introspectors produce, so a code-first PowDB database can be
|
|
14
|
+
* introspected for bootstrap/verification. It is transport-agnostic: the caller
|
|
15
|
+
* supplies an `exec(powql)` that returns row objects **keyed by column name**.
|
|
16
|
+
* - Embedded / owned pool: `exec = async (q) => ({ rows: await db.raw([q]) })`
|
|
17
|
+
* using a live `turbinePowDB` client's `raw` tagged template.
|
|
18
|
+
* - Networked: the raw `@zvndev/powdb-client` returns POSITIONAL rows
|
|
19
|
+
* (`{ columns: string[], rows: string[][] }`), so zip them into records.
|
|
20
|
+
* A bare `(await client.query(q)).rows` would hand this function `string[][]`
|
|
21
|
+
* whose `.name` cell is `undefined` and every table would silently drop out:
|
|
22
|
+
* ```ts
|
|
23
|
+
* const exec = async (q) => {
|
|
24
|
+
* const r = await client.query(q);
|
|
25
|
+
* return { rows: r.rows.map((row) => Object.fromEntries(r.columns.map((c, i) => [c, row[i]]))) };
|
|
26
|
+
* };
|
|
27
|
+
* ```
|
|
28
|
+
* (A mis-shaped exec is now caught: if `schema` returns rows but none carry
|
|
29
|
+
* a `name`, {@link introspectPowdbDatabase} throws instead of returning an
|
|
30
|
+
* empty schema.)
|
|
31
|
+
*
|
|
32
|
+
* IMPORTANT LIMITATIONS (all documented, none silent):
|
|
33
|
+
* - Relations are ALWAYS `{}`: PowDB has no declared foreign keys, so
|
|
34
|
+
* `describe` cannot report them. The recommended flow for relation-aware
|
|
35
|
+
* metadata is code-first `defineSchema` + `schemaDefToMetadata`; use
|
|
36
|
+
* introspection to bootstrap or verify column shape.
|
|
37
|
+
* - Primary key is a HEURISTIC (`describe` has no PK concept): PowDB marks a
|
|
38
|
+
* PK column as `required unique`, so the first non-nullable `unique` column
|
|
39
|
+
* is chosen (a column named `id` wins ties). A table with no such column
|
|
40
|
+
* yields `primaryKey: []` and a warning; single-row ops on it fail loudly.
|
|
41
|
+
* - `isGenerated` is always `false`: `describe` does not expose PowDB's `auto`
|
|
42
|
+
* modifier, so an introspected int PK is treated as client-supplied unless
|
|
43
|
+
* the caller hand-edits the metadata.
|
|
44
|
+
* - Doc-field expression indexes are INVISIBLE to `describe`, so they never
|
|
45
|
+
* round-trip; only plain `unique`/`index` columns appear in `indexes`.
|
|
46
|
+
* - `datetime` / `uuid` / `bytes` columns map to read-oriented TS types
|
|
47
|
+
* (`Date` / `string` / `Uint8Array`). Turbine never emits those PowQL types
|
|
48
|
+
* on write, so writing to such a column may not round-trip.
|
|
49
|
+
*
|
|
50
|
+
* v1 is a PROGRAMMATIC API (exported from `turbine-orm/powdb`); the CLI's
|
|
51
|
+
* `turbine generate` still defaults to Postgres. Routing a `powdb://` URL
|
|
52
|
+
* through the CLI would additionally need: a `powdbDialect.introspector`
|
|
53
|
+
* wired to a networked `exec`, and `cli/config.ts` teaching the generate
|
|
54
|
+
* funnel to construct a PowDB client instead of a `pg` client for `powdb://`.
|
|
55
|
+
*/
|
|
56
|
+
import { type PowdbCapabilities } from './powdb.js';
|
|
57
|
+
import type { SchemaMetadata } from './schema.js';
|
|
58
|
+
/** A minimal rows-returning executor over a PowDB connection (embedded or networked). */
|
|
59
|
+
export type PowdbExec = (powql: string) => Promise<{
|
|
60
|
+
rows: Record<string, unknown>[];
|
|
61
|
+
}>;
|
|
62
|
+
/** Options controlling which tables {@link introspectPowdbDatabase} reads. */
|
|
63
|
+
export interface PowdbIntrospectOptions {
|
|
64
|
+
/** Only introspect these table names (snake_case, as PowDB reports them). */
|
|
65
|
+
include?: string[];
|
|
66
|
+
/** Skip these table names. */
|
|
67
|
+
exclude?: string[];
|
|
68
|
+
/**
|
|
69
|
+
* Bound connection capabilities. When supplied AND `introspection` (engine
|
|
70
|
+
* >= 0.10) is false, this throws a version-hinting {@link UnsupportedFeatureError}
|
|
71
|
+
* (E017) up front instead of letting a pre-0.10 engine reject the `schema` /
|
|
72
|
+
* `describe` keywords with an opaque parse error. Omit it (the bare-exec path)
|
|
73
|
+
* to run ungated; the pool paths that know the version pass it through.
|
|
74
|
+
*/
|
|
75
|
+
capabilities?: PowdbCapabilities;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read a live PowDB database into {@link SchemaMetadata} via `schema` +
|
|
79
|
+
* `describe <T>` statements run through the supplied {@link PowdbExec}.
|
|
80
|
+
*
|
|
81
|
+
* @param exec Rows-returning executor (embedded `db.raw` or networked `client.query`).
|
|
82
|
+
* @param options `include`/`exclude` table filters.
|
|
83
|
+
*/
|
|
84
|
+
export declare function introspectPowdbDatabase(exec: PowdbExec, options?: PowdbIntrospectOptions): Promise<SchemaMetadata>;
|