@vibeorm/runtime 1.3.0 → 2.0.0-alpha.10
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 +50 -107
- package/dist/adapter.d.ts +250 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/bulk-upsert.d.ts +282 -0
- package/dist/bulk-upsert.d.ts.map +1 -0
- package/dist/client.d.ts +200 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/codecs.d.ts +170 -0
- package/dist/codecs.d.ts.map +1 -0
- package/dist/computed.d.ts +43 -0
- package/dist/computed.d.ts.map +1 -0
- package/dist/db-now.d.ts +41 -0
- package/dist/db-now.d.ts.map +1 -0
- package/dist/diagnostics/index.d.ts +12 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/insight.d.ts +63 -0
- package/dist/diagnostics/insight.d.ts.map +1 -0
- package/dist/diagnostics/plan.d.ts +88 -0
- package/dist/diagnostics/plan.d.ts.map +1 -0
- package/dist/diagnostics/preview.d.ts +43 -0
- package/dist/diagnostics/preview.d.ts.map +1 -0
- package/dist/diagnostics/types.d.ts +223 -0
- package/dist/diagnostics/types.d.ts.map +1 -0
- package/dist/diagnostics/workload.d.ts +32 -0
- package/dist/diagnostics/workload.d.ts.map +1 -0
- package/dist/extensions.d.ts +102 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13070 -0
- package/dist/index.js.map +43 -0
- package/dist/keyset-iterator.d.ts +73 -0
- package/dist/keyset-iterator.d.ts.map +1 -0
- package/dist/keyset.d.ts +121 -0
- package/dist/keyset.d.ts.map +1 -0
- package/dist/model-meta.d.ts +200 -0
- package/dist/model-meta.d.ts.map +1 -0
- package/dist/nested-writes.d.ts +67 -0
- package/dist/nested-writes.d.ts.map +1 -0
- package/dist/policy-operation.d.ts +14 -0
- package/dist/policy-operation.d.ts.map +1 -0
- package/dist/policy.d.ts +17 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/query-builder.d.ts +271 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/relation-key.d.ts +23 -0
- package/dist/relation-key.d.ts.map +1 -0
- package/dist/relation-loader.d.ts +46 -0
- package/dist/relation-loader.d.ts.map +1 -0
- package/dist/relation-plan.d.ts +141 -0
- package/dist/relation-plan.d.ts.map +1 -0
- package/dist/render-cache.d.ts +48 -0
- package/dist/render-cache.d.ts.map +1 -0
- package/dist/rls-context.d.ts +14 -0
- package/dist/rls-context.d.ts.map +1 -0
- package/dist/rls-readiness.d.ts +114 -0
- package/dist/rls-readiness.d.ts.map +1 -0
- package/dist/scoped.d.ts +104 -0
- package/dist/scoped.d.ts.map +1 -0
- package/dist/strict-args.d.ts +47 -0
- package/dist/strict-args.d.ts.map +1 -0
- package/dist/telemetry/collector.d.ts +53 -0
- package/dist/telemetry/collector.d.ts.map +1 -0
- package/dist/telemetry/config.d.ts +53 -0
- package/dist/telemetry/config.d.ts.map +1 -0
- package/dist/telemetry/fingerprint.d.ts +38 -0
- package/dist/telemetry/fingerprint.d.ts.map +1 -0
- package/dist/telemetry/index.d.ts +18 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/recorder.d.ts +93 -0
- package/dist/telemetry/recorder.d.ts.map +1 -0
- package/dist/telemetry/statement.d.ts +53 -0
- package/dist/telemetry/statement.d.ts.map +1 -0
- package/dist/telemetry/types.d.ts +265 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/validators.d.ts +61 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/views.d.ts +97 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/write-scope.d.ts +14 -0
- package/dist/write-scope.d.ts.map +1 -0
- package/package.json +33 -26
- package/src/adapter.ts +0 -146
- package/src/client.ts +0 -2172
- package/src/coerce.ts +0 -184
- package/src/count-loader.ts +0 -152
- package/src/errors.ts +0 -492
- package/src/id-generators.ts +0 -151
- package/src/index.ts +0 -55
- package/src/lateral-join-builder.ts +0 -1053
- package/src/query-builder.ts +0 -1832
- package/src/relation-loader.ts +0 -534
- package/src/retry.ts +0 -183
- package/src/types.ts +0 -317
- package/src/view.ts +0 -629
- package/src/where-builder.ts +0 -772
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded-memory export: a sequential async iterator over keyset pages.
|
|
3
|
+
*
|
|
4
|
+
* One page is held at a time and the next one is fetched only when the
|
|
5
|
+
* consumer asks for a row the buffer cannot serve. There is no prefetch, no
|
|
6
|
+
* look-ahead and no unbounded accumulation — `pagesFetched()` is the receipt.
|
|
7
|
+
*
|
|
8
|
+
* What this deliberately is NOT:
|
|
9
|
+
* - **not a snapshot.** No transaction is opened, so the traversal is a LIVE
|
|
10
|
+
* view: concurrent inserts, deletes and sort-key updates change what a
|
|
11
|
+
* later page sees. A row that moves behind the position is missed; one
|
|
12
|
+
* that moves ahead of it is seen twice. A consistent export means running
|
|
13
|
+
* the whole iteration inside `$transaction` at an explicit isolation
|
|
14
|
+
* level, paying its connection and deadline cost — never a secretly
|
|
15
|
+
* long-lived transaction.
|
|
16
|
+
* - **not exactly-once.** `checkpoint()` records the last row the consumer
|
|
17
|
+
* came BACK for, so a `break` or an exception leaves the in-flight row
|
|
18
|
+
* uncheckpointed and resuming re-delivers it. At-least-once. The consumer
|
|
19
|
+
* owns acknowledgement and de-duplication; this is not a durable job
|
|
20
|
+
* engine.
|
|
21
|
+
* - **not statement cancellation.** Aborting the signal stops FUTURE page
|
|
22
|
+
* fetches. A page query already in flight keeps running: per EPIC 6 only
|
|
23
|
+
* `adapter-pg` / `adapter-bun` can cancel a running statement, and only
|
|
24
|
+
* inside a transaction carrying a deadline — which this iterator does not
|
|
25
|
+
* open.
|
|
26
|
+
*/
|
|
27
|
+
import type { SqlDialect } from "@vibeorm/sql";
|
|
28
|
+
import type { KeysetTimestampPrecision } from "./keyset.ts";
|
|
29
|
+
import type { RuntimeMeta } from "./model-meta.ts";
|
|
30
|
+
/** The one method this iterator needs — a model delegate satisfies it. */
|
|
31
|
+
export type KeysetPageSource = {
|
|
32
|
+
readonly findMany: (args: Record<string, unknown>) => Promise<Record<string, unknown>[]>;
|
|
33
|
+
};
|
|
34
|
+
export type KeysetIterateOptions = {
|
|
35
|
+
readonly source: KeysetPageSource;
|
|
36
|
+
readonly meta: RuntimeMeta;
|
|
37
|
+
readonly dialect: SqlDialect;
|
|
38
|
+
readonly model: string;
|
|
39
|
+
readonly orderBy: unknown;
|
|
40
|
+
/** Bounded and required, 1…{@link KEYSET_MAX_PAGE_SIZE}. There is no unbounded default. */
|
|
41
|
+
readonly pageSize: number;
|
|
42
|
+
readonly where?: Record<string, unknown>;
|
|
43
|
+
readonly select?: Record<string, unknown>;
|
|
44
|
+
readonly omit?: Record<string, unknown>;
|
|
45
|
+
readonly include?: Record<string, unknown>;
|
|
46
|
+
/** Resume from a checkpoint minted by a previous run over the SAME ordering. */
|
|
47
|
+
readonly after?: string;
|
|
48
|
+
/** Consumer cancellation: stops future page fetches; ends iteration cleanly. */
|
|
49
|
+
readonly signal?: AbortSignal;
|
|
50
|
+
readonly timestampPrecision?: KeysetTimestampPrecision;
|
|
51
|
+
};
|
|
52
|
+
export type KeysetIterator = AsyncIterableIterator<Record<string, unknown>> & {
|
|
53
|
+
/** Always present: `break` and an exception both have to be able to release the traversal. */
|
|
54
|
+
readonly return: (value?: unknown) => Promise<IteratorResult<Record<string, unknown>>>;
|
|
55
|
+
readonly throw: (error?: unknown) => Promise<IteratorResult<Record<string, unknown>>>;
|
|
56
|
+
/** Token for the last SUCCESSFULLY CONSUMED row; `null` before the first one settles. */
|
|
57
|
+
readonly checkpoint: () => string | null;
|
|
58
|
+
/** Pages fetched so far — the bounded-fetch receipt. */
|
|
59
|
+
readonly pagesFetched: () => number;
|
|
60
|
+
/** True when the signal aborted the traversal. */
|
|
61
|
+
readonly cancelled: () => boolean;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Iterate a model in keyset order, one bounded page at a time.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const rows = iterateKeyset({ source: db.$models.product, meta, dialect,
|
|
68
|
+
* model: "Product", orderBy: [{ price: "asc" }, { id: "asc" }], pageSize: 500 });
|
|
69
|
+
* for await (const row of rows) { … }
|
|
70
|
+
* const resumeFrom = rows.checkpoint();
|
|
71
|
+
*/
|
|
72
|
+
export declare function iterateKeyset(options: KeysetIterateOptions): KeysetIterator;
|
|
73
|
+
//# sourceMappingURL=keyset-iterator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyset-iterator.d.ts","sourceRoot":"","sources":["../src/keyset-iterator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAS/C,OAAO,KAAK,EAAmB,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,0EAA0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;CAC1F,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG;IAC5E,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvF,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACtF,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACzC,wDAAwD;IACxD,QAAQ,CAAC,YAAY,EAAE,MAAM,MAAM,CAAC;IACpC,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC;CACnC,CAAC;AAuCF;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,cAAc,CA2I3E"}
|
package/dist/keyset.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort-aware keyset pagination — the order plan and the opaque position token.
|
|
3
|
+
*
|
|
4
|
+
* A keyset position describes ORDERING VALUES plus a unique tie-breaker, not
|
|
5
|
+
* the identity of one row: the row a token was minted from may since have been
|
|
6
|
+
* deleted or had its sort key changed, and traversal still continues from the
|
|
7
|
+
* right place. That is the whole difference from the legacy `cursor`, which
|
|
8
|
+
* addresses a row by a unique key and is left untouched by this module.
|
|
9
|
+
*
|
|
10
|
+
* Two rules this module exists to enforce:
|
|
11
|
+
* - a position is only meaningful against ONE effective ordering, so the
|
|
12
|
+
* token carries that ordering's signature and a mismatch is refused loudly
|
|
13
|
+
* rather than silently paginating the wrong sequence;
|
|
14
|
+
* - a position's values are encoded LOSSLESSLY per scalar type — never
|
|
15
|
+
* through a float64 detour and never from a rounded display value.
|
|
16
|
+
*
|
|
17
|
+
* The token is ENCODED, not encrypted: anyone holding it can read the ordering
|
|
18
|
+
* values inside. It is also NOT an authorization credential — it selects a
|
|
19
|
+
* position, never a row; every query consuming one still compiles the caller's
|
|
20
|
+
* own `where` and keeps its `$scoped` / `$withPolicy` / RLS filters.
|
|
21
|
+
*/
|
|
22
|
+
import type { SqlDialect } from "@vibeorm/sql";
|
|
23
|
+
import type { FieldMeta, ModelMeta } from "./model-meta.ts";
|
|
24
|
+
export type KeysetDirection = "asc" | "desc";
|
|
25
|
+
export type KeysetNulls = "first" | "last";
|
|
26
|
+
/**
|
|
27
|
+
* The caller's assertion that every `DateTime` ordering column holds
|
|
28
|
+
* millisecond-exact values. See {@link compileKeysetOrderPlan}.
|
|
29
|
+
*/
|
|
30
|
+
export type KeysetTimestampPrecision = "milliseconds";
|
|
31
|
+
/** One order term, already resolved by the query builder. */
|
|
32
|
+
export type KeysetOrderInput = {
|
|
33
|
+
readonly field: FieldMeta;
|
|
34
|
+
readonly direction: KeysetDirection;
|
|
35
|
+
/** Resolved NULL placement: the explicit request, else the dialect's native one. */
|
|
36
|
+
readonly nulls: KeysetNulls;
|
|
37
|
+
};
|
|
38
|
+
/** One key of the effective keyset order. */
|
|
39
|
+
export type KeysetOrderKey = {
|
|
40
|
+
readonly field: FieldMeta;
|
|
41
|
+
readonly direction: KeysetDirection;
|
|
42
|
+
readonly nulls: KeysetNulls;
|
|
43
|
+
readonly tag: KeysetValueTag;
|
|
44
|
+
};
|
|
45
|
+
/** The effective order a token is bound to. */
|
|
46
|
+
export type KeysetOrderPlan = {
|
|
47
|
+
readonly model: string;
|
|
48
|
+
readonly keys: readonly KeysetOrderKey[];
|
|
49
|
+
/** Plain-text order signature carried inside the token. */
|
|
50
|
+
readonly signature: string;
|
|
51
|
+
};
|
|
52
|
+
/** Per-scalar lossless encoding tag stored in the token. */
|
|
53
|
+
export type KeysetValueTag = "s" | "i" | "b" | "f" | "c" | "t" | "o" | "y";
|
|
54
|
+
/** Token version. A token from another version is refused, never guessed at. */
|
|
55
|
+
export declare const KEYSET_TOKEN_VERSION: number;
|
|
56
|
+
/** Token prefix — `vk` for "vibe keyset", then the version. */
|
|
57
|
+
export declare const KEYSET_TOKEN_PREFIX: string;
|
|
58
|
+
/** Upper bound on an iterator page — memory is bounded by construction, not by hope. */
|
|
59
|
+
export declare const KEYSET_MAX_PAGE_SIZE: number;
|
|
60
|
+
/**
|
|
61
|
+
* Compile and VALIDATE the effective keyset order.
|
|
62
|
+
*
|
|
63
|
+
* Refuses, at build time and before any statement runs: list/Json/Bytes order
|
|
64
|
+
* keys, an order with no unique tie-breaker, and a `DateTime` key on a dialect
|
|
65
|
+
* that may store sub-millisecond values unless the caller passes
|
|
66
|
+
* `timestampPrecision: "milliseconds"` — the caller's explicit assertion that
|
|
67
|
+
* the column is millisecond-exact. That assertion is NOT safe for a
|
|
68
|
+
* `@default(now())` column on postgres, which is microsecond-precise: a
|
|
69
|
+
* truncated cursor value re-admits rows already delivered in that same
|
|
70
|
+
* millisecond, i.e. duplicates.
|
|
71
|
+
*/
|
|
72
|
+
export declare function compileKeysetOrderPlan(params: {
|
|
73
|
+
model: ModelMeta;
|
|
74
|
+
dialect: SqlDialect;
|
|
75
|
+
terms: readonly KeysetOrderInput[];
|
|
76
|
+
timestampPrecision?: KeysetTimestampPrecision;
|
|
77
|
+
}): KeysetOrderPlan;
|
|
78
|
+
/**
|
|
79
|
+
* Is `row` strictly after `position` in this ordering? `null` means the
|
|
80
|
+
* comparison is inconclusive in JavaScript (a collated string key), never
|
|
81
|
+
* "yes".
|
|
82
|
+
*
|
|
83
|
+
* Used as a LIVENESS guard, not as a filter: the SQL bound does the real work,
|
|
84
|
+
* and this only catches a traversal that fails to advance — which happens when
|
|
85
|
+
* an ordering is not actually total, or when a cursor value was lossy (a
|
|
86
|
+
* truncated sub-millisecond timestamp being the case this codebase can
|
|
87
|
+
* demonstrate). Without it that situation is an infinite page loop.
|
|
88
|
+
*/
|
|
89
|
+
export declare function keysetRowIsAfter(params: {
|
|
90
|
+
keys: readonly KeysetOrderKey[];
|
|
91
|
+
row: readonly unknown[];
|
|
92
|
+
position: readonly unknown[];
|
|
93
|
+
}): boolean | null;
|
|
94
|
+
/** Read a row's ordering values in plan order. */
|
|
95
|
+
export declare function keysetRowValues(params: {
|
|
96
|
+
plan: KeysetOrderPlan;
|
|
97
|
+
row: Readonly<Record<string, unknown>>;
|
|
98
|
+
}): readonly unknown[];
|
|
99
|
+
/**
|
|
100
|
+
* Mint a continuation token from a row that carries every ordering value.
|
|
101
|
+
*
|
|
102
|
+
* The row must contain each ordering field — a missing one is refused rather
|
|
103
|
+
* than encoded as a null, because a silently null position paginates the wrong
|
|
104
|
+
* sequence. Callers that project a subset (`select`) fetch the ordering
|
|
105
|
+
* columns HIDDEN and strip them from the payload; see `keyset-iterator.ts`.
|
|
106
|
+
*/
|
|
107
|
+
export declare function encodeKeysetToken(params: {
|
|
108
|
+
plan: KeysetOrderPlan;
|
|
109
|
+
row: Readonly<Record<string, unknown>>;
|
|
110
|
+
}): string;
|
|
111
|
+
/**
|
|
112
|
+
* Read a token back into ordering values, validating version, model and the
|
|
113
|
+
* effective order. A token minted under a different ordering (or for another
|
|
114
|
+
* model, or by a future version) is refused with a precise, non-guessing
|
|
115
|
+
* error — never used to paginate a sequence it does not describe.
|
|
116
|
+
*/
|
|
117
|
+
export declare function decodeKeysetToken(params: {
|
|
118
|
+
plan: KeysetOrderPlan;
|
|
119
|
+
token: string;
|
|
120
|
+
}): readonly unknown[];
|
|
121
|
+
//# sourceMappingURL=keyset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyset.d.ts","sourceRoot":"","sources":["../src/keyset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5D,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,CAAC;AAC7C,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAEtD,6DAA6D;AAC7D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;CAC9B,CAAC;AAEF,+CAA+C;AAC/C,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IACzC,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,4DAA4D;AAC5D,MAAM,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAI3E,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,EAAE,MAAU,CAAC;AAE9C,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,EAAE,MAAe,CAAC;AAElD,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,EAAE,MAAe,CAAC;AAuHnD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CAC/C,GAAG,eAAe,CA+ClB;AA0ID;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IAChC,GAAG,EAAE,SAAS,OAAO,EAAE,CAAC;IACxB,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;CAC9B,GAAG,OAAO,GAAG,IAAI,CAmBjB;AAED,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,IAAI,EAAE,eAAe,CAAC;IACtB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACxC,GAAG,SAAS,OAAO,EAAE,CAGrB;AAID;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,IAAI,EAAE,eAAe,CAAC;IACtB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACxC,GAAG,MAAM,CAcT;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,OAAO,EAAE,CA8EtG"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime model metadata: the pre-resolved view of the Schema IR the query
|
|
3
|
+
* builder and client run on.
|
|
4
|
+
*
|
|
5
|
+
* Built once per client (`buildRuntimeMeta`), then read-only. Everything the
|
|
6
|
+
* hot path needs is precomputed here — column names, field lookup maps, primary
|
|
7
|
+
* keys — so no query ever walks the IR. Relations are carried verbatim: the P2
|
|
8
|
+
* core slice does not load them, P3 does.
|
|
9
|
+
*
|
|
10
|
+
* Also the home of app-side default generation (uuid/cuid/nanoid/ulid/now),
|
|
11
|
+
* which is dialect-free by design: the id exists before the INSERT, which is
|
|
12
|
+
* what lets dialects without RETURNING re-select the row they just wrote.
|
|
13
|
+
*/
|
|
14
|
+
import type { ComputedConfig, DefaultValueIR, EnumStorage, FieldType, RelationIR, ScalarType, SchemaIR } from "@vibeorm/schema";
|
|
15
|
+
import type { ScalarCodec, SqlExpr } from "@vibeorm/sql";
|
|
16
|
+
/** Where a field's default value is produced. */
|
|
17
|
+
export type DefaultOrigin = "app" | "database" | "none";
|
|
18
|
+
/** A scalar or enum column, resolved for the runtime. */
|
|
19
|
+
export type FieldMeta = {
|
|
20
|
+
/** Client-facing field name. */
|
|
21
|
+
readonly name: string;
|
|
22
|
+
/** Database column name (`dbName ?? name`). */
|
|
23
|
+
readonly columnName: string;
|
|
24
|
+
/** Explicit column collation (@collation, board #36) — mysql insensitive-filter rendering reads it. */
|
|
25
|
+
readonly collation?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The declared `@db.*` native column type, verbatim as Prisma writes it
|
|
28
|
+
* (`Uuid`, `VarChar(191)`, `Char(10)`, `Decimal(10, 2)`), or `undefined`
|
|
29
|
+
* when the field takes the dialect's canonical mapping.
|
|
30
|
+
*
|
|
31
|
+
* Carried because the physical type decides value equality on its own,
|
|
32
|
+
* before any collation: `char(n)` pads, `uuid` folds case, `timestamp(0)`
|
|
33
|
+
* truncates, `real` narrows a Float. `upsertMany`'s duplicate rule reads it
|
|
34
|
+
* (`conflictKeyComparisonOf` in bulk-upsert.ts). It is a schema claim, not a
|
|
35
|
+
* reading of the live column.
|
|
36
|
+
*/
|
|
37
|
+
readonly nativeType?: string;
|
|
38
|
+
readonly type: FieldType;
|
|
39
|
+
/** The scalar type, or `null` when the field is an enum reference. */
|
|
40
|
+
readonly scalarType: ScalarType | null;
|
|
41
|
+
/** The enum name, or `null` when the field is a scalar. */
|
|
42
|
+
readonly enumName: string | null;
|
|
43
|
+
/** Physical enum storage, or `null` for ordinary scalar fields. */
|
|
44
|
+
readonly enumStorage: EnumStorage | null;
|
|
45
|
+
/** Precomputed membership codec for string-backed enums only. */
|
|
46
|
+
readonly enumCodec: ScalarCodec | null;
|
|
47
|
+
readonly isList: boolean;
|
|
48
|
+
readonly isOptional: boolean;
|
|
49
|
+
readonly isId: boolean;
|
|
50
|
+
readonly isUnique: boolean;
|
|
51
|
+
readonly isUpdatedAt: boolean;
|
|
52
|
+
readonly default: DefaultValueIR | null;
|
|
53
|
+
/**
|
|
54
|
+
* `"app"` — the runtime generates the value and sends it (uuid/cuid/nanoid/
|
|
55
|
+
* ulid/now). `"database"` — the column's DEFAULT clause applies and the field
|
|
56
|
+
* is omitted from INSERTs (autoincrement, dbgenerated, literal, enum value).
|
|
57
|
+
*/
|
|
58
|
+
readonly defaultOrigin: DefaultOrigin;
|
|
59
|
+
};
|
|
60
|
+
/** One computed field, resolved for the runtime (config-declared, see @vibeorm/schema computed.ts). */
|
|
61
|
+
export type ComputedFieldMeta = {
|
|
62
|
+
readonly name: string;
|
|
63
|
+
/** The declared TypeScript type (informational at runtime; the generator wrote it into the .d.ts). */
|
|
64
|
+
readonly type: string;
|
|
65
|
+
/** Scalar fields the compute reads — fetched with the computed field, stripped unless selected. */
|
|
66
|
+
readonly needs: readonly string[];
|
|
67
|
+
readonly compute: (row: Record<string, unknown>) => unknown;
|
|
68
|
+
};
|
|
69
|
+
/** A model, resolved for the runtime. */
|
|
70
|
+
export type ModelMeta = {
|
|
71
|
+
/** IR model name, e.g. `"User"`. */
|
|
72
|
+
readonly name: string;
|
|
73
|
+
/** Delegate key on the client, e.g. `"user"`. */
|
|
74
|
+
readonly clientName: string;
|
|
75
|
+
/** Table name (`dbName ?? name`). */
|
|
76
|
+
readonly tableName: string;
|
|
77
|
+
readonly fields: readonly FieldMeta[];
|
|
78
|
+
readonly fieldByName: ReadonlyMap<string, FieldMeta>;
|
|
79
|
+
/** Reverse map for row materialization (driver rows are keyed by column). */
|
|
80
|
+
readonly fieldByColumn: ReadonlyMap<string, FieldMeta>;
|
|
81
|
+
/** Primary-key fields: the single `@id` field, or the `@@id` fields in order. */
|
|
82
|
+
readonly primaryKey: readonly FieldMeta[];
|
|
83
|
+
/** Fields that identify a row on their own (`@id` or `@unique`). */
|
|
84
|
+
readonly uniqueFields: readonly FieldMeta[];
|
|
85
|
+
/**
|
|
86
|
+
* COMPOSITE ways to address one row, keyed exactly like the generated
|
|
87
|
+
* `…WhereUniqueInput` property — the declared client selector name
|
|
88
|
+
* (`@@unique`/`@@id` `name:`) when present, else member field names joined
|
|
89
|
+
* with `_` (`projectId_userId`). The composite `@@id` comes first, then
|
|
90
|
+
* every multi-field `@@unique`, in schema order. Empty for models without
|
|
91
|
+
* one.
|
|
92
|
+
*/
|
|
93
|
+
readonly compoundUniques: ReadonlyMap<string, UniqueGroupMeta>;
|
|
94
|
+
/**
|
|
95
|
+
* Single-field unique INDEXES that are addressable but not folded into
|
|
96
|
+
* `field.isUnique` (today: NULLS NOT DISTINCT singles) — mirrors the
|
|
97
|
+
* generator's WhereUniqueInput surface.
|
|
98
|
+
*/
|
|
99
|
+
readonly singleIndexUniques: readonly UniqueGroupMeta[];
|
|
100
|
+
/** Carried verbatim from the IR — consumed by relation loading in P3. */
|
|
101
|
+
readonly relations: readonly RelationIR[];
|
|
102
|
+
readonly relationByName: ReadonlyMap<string, RelationIR>;
|
|
103
|
+
readonly isView: boolean;
|
|
104
|
+
/** Row-scoping policy (@@policy) — the client fails closed on it ($withPolicy). */
|
|
105
|
+
readonly policy?: {
|
|
106
|
+
readonly field: string;
|
|
107
|
+
readonly context: string;
|
|
108
|
+
};
|
|
109
|
+
/** Computed fields configured for this model, or `null` (the common case). */
|
|
110
|
+
readonly computed: ReadonlyMap<string, ComputedFieldMeta> | null;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* A pre-bound extension where-operator: compiles one use (`{ similarTo: … }`)
|
|
114
|
+
* into a SqlExpr fragment. Built by `buildExtensionOperatorMap` in
|
|
115
|
+
* extensions.ts with dialect/provider/options already curried in.
|
|
116
|
+
*/
|
|
117
|
+
export type ExtensionOperatorFn = (params: {
|
|
118
|
+
/** Identifier path of the column (qualified when inside a subquery). */
|
|
119
|
+
readonly column: readonly string[];
|
|
120
|
+
readonly operand: unknown;
|
|
121
|
+
readonly model: string;
|
|
122
|
+
readonly field: string;
|
|
123
|
+
}) => SqlExpr;
|
|
124
|
+
/**
|
|
125
|
+
* One addressable unique group beyond the flat `@id`/`@unique` fields: a
|
|
126
|
+
* composite `@@id`/`@@unique`, or a single-field unique INDEX that does not
|
|
127
|
+
* fold into `field.isUnique` (today: `nullsNotDistinct` uniques). Under
|
|
128
|
+
* NULLS NOT DISTINCT the database keeps at most one row per key INCLUDING
|
|
129
|
+
* null dimensions, so a `null` member addresses exactly one row — those
|
|
130
|
+
* groups accept `null` where members; default (nulls-distinct) groups never
|
|
131
|
+
* do.
|
|
132
|
+
*/
|
|
133
|
+
export type UniqueGroupMeta = {
|
|
134
|
+
readonly fields: readonly FieldMeta[];
|
|
135
|
+
readonly nullsNotDistinct: boolean;
|
|
136
|
+
};
|
|
137
|
+
/** All runtime metadata for one schema. */
|
|
138
|
+
export type RuntimeMeta = {
|
|
139
|
+
readonly models: readonly ModelMeta[];
|
|
140
|
+
/** Keyed by BOTH camelCase client name (`user`) and model name (`User`). */
|
|
141
|
+
readonly modelByName: ReadonlyMap<string, ModelMeta>;
|
|
142
|
+
/** Enum name → its values, for validation and codec decisions. */
|
|
143
|
+
readonly enums: ReadonlyMap<string, readonly string[]>;
|
|
144
|
+
/**
|
|
145
|
+
* Extension where-operators (extension sql plane), keyed by operator name.
|
|
146
|
+
* Rides on the meta so the WHERE compiler reaches it at every site without
|
|
147
|
+
* threading a parameter through the hot path.
|
|
148
|
+
*/
|
|
149
|
+
readonly extensionOperators?: ReadonlyMap<string, ExtensionOperatorFn>;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Delegate key for a model name: the first character lowercased, nothing else
|
|
153
|
+
* (the Prisma convention — `User` → `user`, `URLMap` → `uRLMap`). Keeping the
|
|
154
|
+
* rest untouched makes the mapping unambiguous and reversible.
|
|
155
|
+
*/
|
|
156
|
+
export declare function toClientName(params: {
|
|
157
|
+
name: string;
|
|
158
|
+
}): string;
|
|
159
|
+
/** RFC 4122 v4 UUID. */
|
|
160
|
+
export declare function generateUuid(): string;
|
|
161
|
+
/**
|
|
162
|
+
* Collision-resistant, sortable-ish id in the CUID spirit: `"c"` + a base-36
|
|
163
|
+
* millisecond timestamp + 16 random base-36 characters. Starts with a letter so
|
|
164
|
+
* it is safe as an HTML id and in every database identifier context.
|
|
165
|
+
*/
|
|
166
|
+
export declare function generateCuid(): string;
|
|
167
|
+
/** 21-character NanoID over the standard URL-safe alphabet (64 chars, unbiased 6-bit mask). */
|
|
168
|
+
export declare function generateNanoid(): string;
|
|
169
|
+
/**
|
|
170
|
+
* ULID: 10 characters of millisecond timestamp + 16 of randomness, Crockford
|
|
171
|
+
* base32, lexicographically sortable by creation time. 256 % 32 === 0, so the
|
|
172
|
+
* byte-to-symbol fold is unbiased.
|
|
173
|
+
*/
|
|
174
|
+
export declare function generateUlid(): string;
|
|
175
|
+
/**
|
|
176
|
+
* The value the runtime sends for an app-side default, or `undefined` when the
|
|
177
|
+
* database owns it (autoincrement, dbgenerated, literal, enum value — those
|
|
178
|
+
* ride the column's DEFAULT clause so the database stays the single source of
|
|
179
|
+
* truth for them).
|
|
180
|
+
*/
|
|
181
|
+
export declare function generateDefaultValue(params: {
|
|
182
|
+
spec: DefaultValueIR;
|
|
183
|
+
}): unknown;
|
|
184
|
+
/** Resolve a whole schema into the runtime's read-only metadata. */
|
|
185
|
+
export declare function buildRuntimeMeta(params: {
|
|
186
|
+
schema: SchemaIR;
|
|
187
|
+
computed?: ComputedConfig;
|
|
188
|
+
}): RuntimeMeta;
|
|
189
|
+
/** Look a model up by client name or model name; unknown names are a caller error. */
|
|
190
|
+
export declare function getModelMeta(params: {
|
|
191
|
+
meta: RuntimeMeta;
|
|
192
|
+
model: string;
|
|
193
|
+
}): ModelMeta;
|
|
194
|
+
/** Look a field up on a model; unknown names are a caller error naming the field. */
|
|
195
|
+
export declare function getFieldMeta(params: {
|
|
196
|
+
model: ModelMeta;
|
|
197
|
+
field: string;
|
|
198
|
+
context: string;
|
|
199
|
+
}): FieldMeta;
|
|
200
|
+
//# sourceMappingURL=model-meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-meta.d.ts","sourceRoot":"","sources":["../src/model-meta.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { SqlDialect, SqlStatement } from "@vibeorm/sql";
|
|
2
|
+
import type { ModelMeta, RuntimeMeta } from "./model-meta.ts";
|
|
3
|
+
import type { QueryMethod } from "./query-builder.ts";
|
|
4
|
+
export type ClientRowLike = Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* Executes ORM statements against ONE adapter (plain or transactional).
|
|
7
|
+
* `single` runs a single-row mutation with the client's full RETURNING /
|
|
8
|
+
* re-select machinery (mysql-safe); `statement` runs a raw AST statement
|
|
9
|
+
* (join-table work has no model).
|
|
10
|
+
*/
|
|
11
|
+
export type StatementRunner = {
|
|
12
|
+
readonly single: (params: {
|
|
13
|
+
model: string;
|
|
14
|
+
method: QueryMethod;
|
|
15
|
+
args: Record<string, unknown>;
|
|
16
|
+
}) => Promise<ClientRowLike>;
|
|
17
|
+
readonly rows: (params: {
|
|
18
|
+
model: string;
|
|
19
|
+
method: QueryMethod;
|
|
20
|
+
args: Record<string, unknown>;
|
|
21
|
+
}) => Promise<ClientRowLike[]>;
|
|
22
|
+
readonly affected: (params: {
|
|
23
|
+
model: string;
|
|
24
|
+
method: QueryMethod;
|
|
25
|
+
args: Record<string, unknown>;
|
|
26
|
+
}) => Promise<number>;
|
|
27
|
+
readonly statement: (params: {
|
|
28
|
+
statement: SqlStatement;
|
|
29
|
+
model: string;
|
|
30
|
+
method: string;
|
|
31
|
+
}) => Promise<ClientRowLike[]>;
|
|
32
|
+
};
|
|
33
|
+
/** What the client hands the nested-write orchestrator. */
|
|
34
|
+
export type WriteContext = {
|
|
35
|
+
readonly meta: RuntimeMeta;
|
|
36
|
+
readonly dialect: SqlDialect;
|
|
37
|
+
/** Runner on the client's current adapter (may already be transactional). */
|
|
38
|
+
readonly run: StatementRunner;
|
|
39
|
+
/** Runs `fn` with a runner bound to a (nested) transaction. */
|
|
40
|
+
readonly transactional: <T>(fn: (run: StatementRunner) => Promise<T>) => Promise<T>;
|
|
41
|
+
};
|
|
42
|
+
/** Does this `data` object carry nested relation operations? */
|
|
43
|
+
export declare function hasNestedWrites(params: {
|
|
44
|
+
model: ModelMeta;
|
|
45
|
+
data: unknown;
|
|
46
|
+
}): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* `create` with nested relation operations. Returns the parent row as the
|
|
49
|
+
* INSERT produced it (relation loading/projection are the client's follow-up).
|
|
50
|
+
*/
|
|
51
|
+
export declare function createWithNested(params: {
|
|
52
|
+
ctx: WriteContext;
|
|
53
|
+
model: ModelMeta;
|
|
54
|
+
data: Record<string, unknown>;
|
|
55
|
+
}): Promise<ClientRowLike>;
|
|
56
|
+
/**
|
|
57
|
+
* `update` with nested relation operations. Always transactional (the flow is
|
|
58
|
+
* multi-statement by construction). Returns the parent row after its UPDATE
|
|
59
|
+
* (or the pre-read row when only children changed).
|
|
60
|
+
*/
|
|
61
|
+
export declare function updateWithNested(params: {
|
|
62
|
+
ctx: WriteContext;
|
|
63
|
+
model: ModelMeta;
|
|
64
|
+
where: Record<string, unknown>;
|
|
65
|
+
data: Record<string, unknown>;
|
|
66
|
+
}): Promise<ClientRowLike>;
|
|
67
|
+
//# sourceMappingURL=nested-writes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-writes.d.ts","sourceRoot":"","sources":["../src/nested-writes.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAgFtD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,WAAW,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,WAAW,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE;QAC1B,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,WAAW,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE;QAC3B,SAAS,EAAE,YAAY,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAChC,CAAC;AAEF,2DAA2D;AAC3D,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACrF,CAAC;AAmCF,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAQpF;AA4eD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,GAAG,OAAO,CAAC,aAAa,CAAC,CAOzB;AA0hBD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,GAAG,OAAO,CAAC,aAAa,CAAC,CAqCzB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DynamicClient } from "./client.ts";
|
|
2
|
+
type PolicyOperationFactory = <T>(run: (client: DynamicClient) => Promise<T>) => Promise<T>;
|
|
3
|
+
/** Register the engine-owned deferred-operation factory without exposing it on clients. */
|
|
4
|
+
export declare function registerPolicyOperations(params: {
|
|
5
|
+
client: DynamicClient;
|
|
6
|
+
factory: PolicyOperationFactory;
|
|
7
|
+
}): void;
|
|
8
|
+
/** Defer the whole policy flow; its client is selected by the ordinary array-transaction runner. */
|
|
9
|
+
export declare function deferPolicyOperation<T>(params: {
|
|
10
|
+
client: DynamicClient;
|
|
11
|
+
run: (client: DynamicClient) => Promise<T>;
|
|
12
|
+
}): Promise<T>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=policy-operation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-operation.d.ts","sourceRoot":"","sources":["../src/policy-operation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,KAAK,sBAAsB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAG5F,2FAA2F;AAC3F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,GAAG,IAAI,CAEjH;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAIjI"}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RuntimeMeta } from "./model-meta.ts";
|
|
2
|
+
import type { DynamicClient, ModelDelegate } from "./client.ts";
|
|
3
|
+
/** Values a policy context may bind — the scoping column's scalar shape. */
|
|
4
|
+
export type PolicyContextValue = string | number | bigint;
|
|
5
|
+
/**
|
|
6
|
+
* Attach `$withPolicy`/`$bypassPolicy` and fail-close the base delegates of
|
|
7
|
+
* policied models. No-op on schemas without @@policy.
|
|
8
|
+
*/
|
|
9
|
+
export declare function attachPolicy(params: {
|
|
10
|
+
client: DynamicClient;
|
|
11
|
+
meta: RuntimeMeta;
|
|
12
|
+
wrapDelegate?: (params: {
|
|
13
|
+
model: string;
|
|
14
|
+
delegate: ModelDelegate;
|
|
15
|
+
}) => ModelDelegate;
|
|
16
|
+
}): void;
|
|
17
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAA0B,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGxF,4EAA4E;AAC5E,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAkrB1D;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,aAAa,CAAA;KAAE,KAAK,aAAa,CAAC;CAAE,GAAG,IAAI,CAmK9K"}
|