@jarenjs/linq 0.73.0 → 0.83.2
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/ARCHITECTURE.md +8 -10
- package/README.md +15 -1
- package/docs/AI-PEN.md +1 -1
- package/docs/APP-PEN.md +3 -3
- package/docs/CHARTS-PEN.md +1 -1
- package/docs/CONTRACT-PEN.md +4 -4
- package/docs/DB-CLIENT.md +200 -8
- package/docs/FLOW-PEN.md +3 -3
- package/docs/FORMS-PEN.md +2 -2
- package/docs/FORMULA-PEN.md +41 -0
- package/docs/JSLT-PEN.md +4 -4
- package/docs/JTLT-PEN.md +1 -1
- package/docs/LINQ-FORMAT.md +60 -43
- package/docs/MESSAGES-PEN.md +1 -1
- package/docs/MIGRATION-PEN.md +3 -3
- package/docs/MODEL-PEN.md +27 -3
- package/docs/PROJECT-PEN.md +10 -4
- package/docs/QUERY-PEN.md +78 -51
- package/docs/SCHEMA-PEN.md +2 -2
- package/package.json +10 -6
- package/src/db/effects.js +148 -0
- package/src/db/handle.js +2 -0
- package/src/db/index.js +6 -0
- package/src/db/ingest.js +153 -0
- package/src/db/open.js +3 -0
- package/src/db/range.js +261 -0
- package/src/db/receipts.js +151 -0
- package/src/db/records.js +61 -0
- package/src/db/runs.js +164 -0
- package/src/db/search.js +86 -0
- package/src/errors.js +3 -1
- package/src/expression.js +5 -2
- package/src/federate.js +157 -139
- package/src/formula/index.js +15 -0
- package/src/messages/vocabulary.js +2 -1
- package/src/model/define.js +2 -0
- package/src/model/entity.js +15 -0
- package/src/project/index.js +6 -5
- package/types/db.d.ts +101 -0
- package/types/formula.d.ts +9 -0
- package/types/index.d.ts +14 -2
- package/types/message-vocabulary.d.ts +2 -1
- package/types/model.d.ts +18 -0
- package/types/project.d.ts +9 -3
package/types/db.d.ts
CHANGED
|
@@ -145,6 +145,7 @@ export type Continuation<S, M extends EntityMeta> = LoadContinuation & {
|
|
|
145
145
|
/** A page's options over this graph (the store's `PageOptions`, the
|
|
146
146
|
* continuation typed by the declared ordering). */
|
|
147
147
|
export interface GraphPageOptions<S, M extends EntityMeta> extends EntityCursorOptions {
|
|
148
|
+
lookahead?: boolean;
|
|
148
149
|
limit?: number;
|
|
149
150
|
after?: Continuation<S, M>;
|
|
150
151
|
maxBytes?: number;
|
|
@@ -205,6 +206,7 @@ export interface Graph<E extends MetaMap<E>, M extends EntityMeta, S> {
|
|
|
205
206
|
* exactly the many-to-many members. */
|
|
206
207
|
export type EntityHandle<E extends MetaMap<E>, M extends EntityMeta> =
|
|
207
208
|
TypedEntitySet<E, M> & ChainStart<M['doc']> & {
|
|
209
|
+
range(spec: import('@jarenjs/db').LoadSpec, options: DbRangeOptions): Promise<DbRangeProvider<M['doc']>>;
|
|
208
210
|
/** Open a graph: include one relation member with an optional spec. */
|
|
209
211
|
include<K extends keyof M['relations'] & string, const I extends IncludeSpec<E, TargetMeta<E, M, K>> = true>(
|
|
210
212
|
pick: (u: RelationPicker<M>) => Picked<K>, spec?: I | NoInfer<IncludeSpec<E, TargetMeta<E, M, K>>>,
|
|
@@ -217,6 +219,40 @@ export type EntityHandle<E extends MetaMap<E>, M extends EntityMeta> =
|
|
|
217
219
|
live<T = M['doc']>(source?: AsyncSequence<T, any> | object, options?: LiveOptions): Promise<TypedLiveQuery<T>>;
|
|
218
220
|
};
|
|
219
221
|
|
|
222
|
+
export interface DbRangeOptions {
|
|
223
|
+
keys: readonly string[];
|
|
224
|
+
resident?: boolean; seekIndex?: boolean; exactTotal?: boolean;
|
|
225
|
+
source?: string; query?: string; schemaVersion?: string;
|
|
226
|
+
profile?: 'safe' | import('@jarenjs/db').ProfileSpec;
|
|
227
|
+
maxRows?: number; maxBytes?: number; maxPages?: number; maxInFlight?: number; maxSubscriptions?: number;
|
|
228
|
+
runtime?: Partial<Runtime>;
|
|
229
|
+
}
|
|
230
|
+
export interface DbRangeRequest {
|
|
231
|
+
generation: number; requestId: string; query: string; snapshot: string;
|
|
232
|
+
range?: { start: number; end: number }; continuation?: string;
|
|
233
|
+
credits: { pages: number; rows: number; bytes: number; work: number };
|
|
234
|
+
}
|
|
235
|
+
export interface DbRangeResponse<T = unknown> {
|
|
236
|
+
generation: number; requestId: string; query: string; snapshot: string;
|
|
237
|
+
state: 'ready' | 'loading' | 'error' | 'invalidated' | 'budget-exhausted'; reason?: string;
|
|
238
|
+
rows?: readonly T[]; keys?: readonly string[]; continuation?: string | null;
|
|
239
|
+
total?: { kind: 'known'; value: number } | { kind: 'unknown' };
|
|
240
|
+
used: { pages: number; rows: number; bytes: number; work: number };
|
|
241
|
+
}
|
|
242
|
+
export interface DbRangeProvider<T = unknown> {
|
|
243
|
+
readonly query: string; readonly snapshot: string;
|
|
244
|
+
readonly capabilities: Readonly<{ seekIndex: boolean; seekKey: false; continuation: true;
|
|
245
|
+
live: true; exactTotal: boolean; completeExport: false }>;
|
|
246
|
+
request(request: DbRangeRequest, signal?: AbortSignal): Promise<DbRangeResponse<T>>;
|
|
247
|
+
subscribe(observer: (event: { type: 'reset'; reason: string; query: string; snapshot: string; revision: number; capture: string }) => void): () => boolean;
|
|
248
|
+
stats(): { sourceReads: number; sourceRows: number; sourceBytes: number; pending: number;
|
|
249
|
+
pages: number; rows: number; bytes: number; subscriptions: number; disposed: boolean };
|
|
250
|
+
dispose(): Promise<void>;
|
|
251
|
+
}
|
|
252
|
+
/** Source capture is required; keyset mode is sequential unless resident is explicit. */
|
|
253
|
+
export declare function createDbRangeProvider<T = unknown>(store: import('@jarenjs/db').Store | TypedStore<any>,
|
|
254
|
+
entity: string, spec: import('@jarenjs/db').LoadSpec, options: DbRangeOptions): Promise<DbRangeProvider<T>>;
|
|
255
|
+
|
|
220
256
|
/** Present exactly when the model declares entities, as on the store. */
|
|
221
257
|
export interface EntityClientMembers {
|
|
222
258
|
/** The store's unit of work, flushed. */
|
|
@@ -331,6 +367,9 @@ export type TransactionClientOf<E extends MetaMap<E>, C = Record<string, unknown
|
|
|
331
367
|
/** The scope-bound store — the escape hatch, still inside. It carries
|
|
332
368
|
* no `close`: a transaction never owns the connection's lifetime. */
|
|
333
369
|
readonly store: TransactionStore;
|
|
370
|
+
readonly sql: TransactionStore['sql'];
|
|
371
|
+
readonly jobs: TransactionStore['jobs'];
|
|
372
|
+
readonly sync: TransactionStore['sync'];
|
|
334
373
|
readonly capabilities: StoreCapabilities;
|
|
335
374
|
readonly entities: { readonly [K in keyof E & string]: EntityHandle<E, E[K]> };
|
|
336
375
|
readonly collections: { readonly [K in keyof C & string]: CollectionHandle<C[K]> };
|
|
@@ -364,3 +403,65 @@ export function defineReplication(header: Omit<import('@jarenjs/db').Replication
|
|
|
364
403
|
toDocument(): import('@jarenjs/db').ReplicationEnvelope;
|
|
365
404
|
toJSON(): import('@jarenjs/db').ReplicationEnvelope;
|
|
366
405
|
};
|
|
406
|
+
|
|
407
|
+
/** A complete lexical membership composed with the common structural range provider. */
|
|
408
|
+
export declare function createLexicalRangeProvider(source: import('@jarenjs/db/search').DbSearch,
|
|
409
|
+
text: string, request?: Record<string, unknown>, options?: {maxMatches?:number; maxSourceBytes?:number;
|
|
410
|
+
maxRows?:number; maxBytes?:number; maxPages?:number; maxInFlight?:number; query?:string;
|
|
411
|
+
source?:string; exactTotal?:boolean; seekIndex?:boolean; disposeSource?:boolean}): Promise<any>;
|
|
412
|
+
|
|
413
|
+
/** Atomic staging and publication over application-declared collections. */
|
|
414
|
+
export function createDbIngestionStore(client: Client<any> | TransactionClientOf<any>, options: {
|
|
415
|
+
staging: string; checkpoints: string; publications: string; facts?: string;
|
|
416
|
+
reconcile?: (existing: any, incoming: any, evidence: any) => any;
|
|
417
|
+
}): {
|
|
418
|
+
begin(plan: any): Promise<any>;
|
|
419
|
+
stage(plan: any, partition: string, page: any): Promise<any>;
|
|
420
|
+
invalidate(plan: any, reason: string): Promise<void>;
|
|
421
|
+
publish(plan: any, evidence: any, context?: { signal?: AbortSignal }): Promise<any>;
|
|
422
|
+
current(source: string): Promise<any>;
|
|
423
|
+
inspect(plan: any): Promise<any>;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
/** Lossless canonical-record mapping onto an application-declared collection. */
|
|
427
|
+
export type DurableRecordMapping = string | (({ collection: string; entity?: never } | { entity: string; collection?: never }) & { key?: (id: string) => any; read: (stored: any) => any; write: (record: any) => any });
|
|
428
|
+
export interface CommandIdentity {
|
|
429
|
+
tenant: string; environment: string; aggregate: string; op: string; key: string; hashVersion: string; hash: string;
|
|
430
|
+
}
|
|
431
|
+
/** Permanent business outcomes and independently expiring execution authority. */
|
|
432
|
+
export function createDbReceipts(client: Client<any> | TransactionClientOf<any>, options: {
|
|
433
|
+
receipts: DurableRecordMapping; leases?: DurableRecordMapping; runtime?: Partial<import('@jarenjs/core/runtime').Runtime>;
|
|
434
|
+
}): {
|
|
435
|
+
lookup(identity: CommandIdentity): Promise<any>;
|
|
436
|
+
execute(identity: CommandIdentity, work: (tx: TransactionClientOf<any>) => Promise<{ outcome: any; references?: any[] }>, context?: { lease?: any }): Promise<any>;
|
|
437
|
+
claim(identity: CommandIdentity, options: { leaseMs: number }): Promise<any>;
|
|
438
|
+
release(identity: CommandIdentity, lease: any): Promise<any>;
|
|
439
|
+
sweep(identities: CommandIdentity[]): Promise<{ changes: number; writes: number; revisions: number }>;
|
|
440
|
+
migrate(records: any[]): Promise<{ changes: number; writes: number; revisions: number }>;
|
|
441
|
+
compact(identity: CommandIdentity, policy: { retainReplay: true; retainReferences: true; actor: string; reason: string }): Promise<any>;
|
|
442
|
+
};
|
|
443
|
+
/** Durable preparation, job-fenced sending and explicit reconciliation. */
|
|
444
|
+
export function createDbEffectStore(client: Client<any> | TransactionClientOf<any>, options: {
|
|
445
|
+
operations: DurableRecordMapping; maxLegs?: number; maxBytes?: number;
|
|
446
|
+
}): {
|
|
447
|
+
prepare(plan: any, prepare?: (tx: TransactionClientOf<any>) => any): Promise<any>;
|
|
448
|
+
get(id: string): Promise<any>;
|
|
449
|
+
begin(id: string, legId: string, revision: number, lease: import('@jarenjs/db').JobLease): Promise<any>;
|
|
450
|
+
settle(id: string, legId: string, revision: number, lease: import('@jarenjs/db').JobLease, outcome: any): Promise<any>;
|
|
451
|
+
recover(id: string, revision: number, lease: import('@jarenjs/db').JobLease): Promise<any>;
|
|
452
|
+
reconcile(id: string, legId: string, revision: number, lease: import('@jarenjs/db').JobLease, decision: any): Promise<any>;
|
|
453
|
+
};
|
|
454
|
+
/** Application run/checkpoint records and bounded public revision pages. */
|
|
455
|
+
export function createDbRunStore(client: Client<any> | TransactionClientOf<any>, options: {
|
|
456
|
+
runs: DurableRecordMapping; events: DurableRecordMapping; statuses?: Record<string, string>;
|
|
457
|
+
summary?: (snapshot: any) => any; canReset?: (tx: TransactionClientOf<any>, record: any) => any; maxPage?: number; maxBytes?: number;
|
|
458
|
+
}): {
|
|
459
|
+
attach(identity: { id: string; jobId: string; workflow: string; schemaVersion: string }, lease: import('@jarenjs/db').JobLease): Promise<any>;
|
|
460
|
+
load(id: string, identity: any, lease: import('@jarenjs/db').JobLease): Promise<any>;
|
|
461
|
+
save(id: string, snapshot: any, expectedGeneration: number, lease: import('@jarenjs/db').JobLease): Promise<boolean>;
|
|
462
|
+
get(id: string): Promise<any>;
|
|
463
|
+
page(id: string, options?: { after?: number; limit?: number }): Promise<any>;
|
|
464
|
+
requestCancel(id: string, revision: number, evidence: { actor: string; reason: string }): Promise<any>;
|
|
465
|
+
finish(id: string, state: 'cancelled' | 'failed', lease: import('@jarenjs/db').JobLease): Promise<any>;
|
|
466
|
+
reset(id: string, revision: number, evidence: any, lease: import('@jarenjs/db').JobLease): Promise<any>;
|
|
467
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Author a saved JSON Query formula without executing it. */
|
|
2
|
+
export declare function defineFormula(id: string, expression: unknown, options?: {
|
|
3
|
+
revision?: string;
|
|
4
|
+
bindings?: Record<string, unknown>;
|
|
5
|
+
inputSchema?: { id: string; version: string };
|
|
6
|
+
resultSchema?: { id: string; version: string };
|
|
7
|
+
helpers?: { name: string; version: string }[];
|
|
8
|
+
resultMode?: 'value' | 'outcome';
|
|
9
|
+
}): any;
|
package/types/index.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export interface StringExpr extends ExprBase<string>, EqExpr<string>, SpatialMet
|
|
|
77
77
|
contains(value: string | StringExpr): BoolExpr;
|
|
78
78
|
/** I-Regexp (RFC 9485) full match. */
|
|
79
79
|
matches(pattern: string): BoolExpr;
|
|
80
|
+
/** Explicit lexical provider request; preserves ranked-result completeness. */
|
|
81
|
+
lexical(provider: string, request?: Record<string, unknown>): UnknownExpr;
|
|
80
82
|
upper(): StringExpr;
|
|
81
83
|
lower(): StringExpr;
|
|
82
84
|
length(): NumberExpr;
|
|
@@ -363,6 +365,8 @@ export interface UnknownExpr
|
|
|
363
365
|
endsWith(value: unknown): BoolExpr;
|
|
364
366
|
contains(value: unknown): BoolExpr;
|
|
365
367
|
matches(pattern: string): BoolExpr;
|
|
368
|
+
/** Explicit lexical provider request; preserves ranked-result completeness. */
|
|
369
|
+
lexical(provider: string, request?: Record<string, unknown>): UnknownExpr;
|
|
366
370
|
upper(): UnknownExpr;
|
|
367
371
|
lower(): UnknownExpr;
|
|
368
372
|
length(): NumberExpr;
|
|
@@ -795,15 +799,18 @@ export interface FederatedSide {
|
|
|
795
799
|
readonly document: unknown;
|
|
796
800
|
/** Whether this side is pulled row by row, or answered whole. */
|
|
797
801
|
readonly streaming: 'row' | 'buffered';
|
|
802
|
+
readonly children?: readonly FederatedSide[];
|
|
798
803
|
}
|
|
799
804
|
|
|
800
805
|
/** What a federated document will do, without doing any of it (§12.1). */
|
|
801
806
|
export interface FederationPlan {
|
|
802
807
|
readonly strategy: 'hash';
|
|
803
808
|
readonly budget: { readonly maxRows: number; readonly maxBytes: number };
|
|
809
|
+
readonly combinedBudget: { readonly maxTotalRows: number; readonly maxTotalBytes: number };
|
|
810
|
+
readonly order: readonly FederatedSide[];
|
|
804
811
|
readonly build: FederatedSide;
|
|
805
812
|
readonly probe: FederatedSide;
|
|
806
|
-
/** The
|
|
813
|
+
/** The engine evaluates the original binding order over the reduced sets. */
|
|
807
814
|
readonly resident: { readonly document: unknown };
|
|
808
815
|
}
|
|
809
816
|
|
|
@@ -822,13 +829,18 @@ export interface FederatedSource<T = unknown> extends AsyncProvider<T> {
|
|
|
822
829
|
* out of that, by naming the sources and the bounds together: each
|
|
823
830
|
* side's own filters and projection run at its source, the smaller side
|
|
824
831
|
* fills a bounded hash table, the other is probed against it, and the
|
|
825
|
-
* caller's own document decides over the
|
|
832
|
+
* caller's own document decides over the reduced sets. Connected N-way
|
|
833
|
+
* graphs and nested fluent joins share cumulative admission credits. A side that
|
|
826
834
|
* reaches `maxRows` or `maxBytes` raises `JL2008` at the row that would
|
|
827
835
|
* have broken the bound. */
|
|
828
836
|
export function federate(spec: {
|
|
829
837
|
sources: Record<string, AsyncProvider | { provider: AsyncProvider; estimatedRows?: number }>;
|
|
830
838
|
maxRows: number;
|
|
831
839
|
maxBytes: number;
|
|
840
|
+
/** Shared admission credits across source reads and intermediate sets; defaults to 2 * maxRows. */
|
|
841
|
+
maxTotalRows?: number;
|
|
842
|
+
/** Defaults to 2 * maxBytes. Buffered providers/intermediates are checked after production. */
|
|
843
|
+
maxTotalBytes?: number;
|
|
832
844
|
strategy?: 'hash';
|
|
833
845
|
}): {
|
|
834
846
|
source<T = unknown>(name: string): FederatedSource<T>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Derived from the English catalogs by scripts/generate-message-pen.js.
|
|
2
2
|
export interface CatalogIds {
|
|
3
3
|
validate: "type" | "required" | "minimum" | "maximum" | "exclusiveMinimum" | "exclusiveMaximum" | "multipleOf" | "minLength" | "maxLength" | "pattern" | "additionalProperties" | "minProperties" | "maxProperties" | "minItems" | "maxItems" | "uniqueItems" | "contains" | "items" | "allOf" | "anyOf" | "oneOf" | "not" | "format" | "if" | "then" | "else" | "false schema" | "$query" | "JQ2001" | "JQ2003";
|
|
4
|
-
forms: "form/required" | "form/type" | "form/const" | "form/enum" | "form/minLength" | "form/maxLength" | "form/pattern" | "form/format" | "form/minimum" | "form/maximum" | "form/exclusiveMinimum" | "form/exclusiveMaximum" | "form/multipleOf" | "form/minItems" | "form/maxItems" | "form/uniqueItems" | "form/minProperties" | "form/maxProperties" | "x-form/assert" | "form/addItem" | "form/removeItem";
|
|
4
|
+
forms: "form/required" | "form/type" | "form/const" | "form/enum" | "form/minLength" | "form/maxLength" | "form/pattern" | "form/format" | "form/minimum" | "form/maximum" | "form/exclusiveMinimum" | "form/exclusiveMaximum" | "form/multipleOf" | "form/minItems" | "form/maxItems" | "form/uniqueItems" | "form/minProperties" | "form/maxProperties" | "x-form/assert" | "form/addItem" | "form/removeItem" | "form/jsonPlaceholder";
|
|
5
5
|
contract: "contract/not-found" | "contract/method-not-allowed" | "contract/body-too-large" | "contract/unsupported-media" | "contract/malformed-json" | "contract/invalid-input" | "contract/idempotency-key-required" | "contract/handler-failed" | "contract/idempotency-conflict" | "contract/invalid-output" | "contract/malformed-path" | "contract/malformed-query" | "contract/not-implemented" | "contract/precondition-failed" | "contract/invalid-header" | "contract/handler-error" | "contract/client-invalid-input" | "contract/network" | "contract/cancelled" | "contract/invalid-response" | "contract/key-storage-failed" | "contract/undeclared-response" | "contract/not-a-contract" | "contract/incompatible" | "contract/host-failed" | "contract/local-handler-failed" | "contract/unknown-operation" | "contract/port-timeout" | "contract/malformed-frame" | "contract/channel-closed" | "contract/not-a-stream" | "contract/invalid-snapshot" | "contract/seq-regression" | "contract/stream-error" | "contract/heartbeat-missed" | "contract/slow-consumer" | "contract/reconnect-exhausted";
|
|
6
6
|
}
|
|
7
7
|
export interface MessageParameters {
|
|
@@ -56,6 +56,7 @@ export interface MessageParameters {
|
|
|
56
56
|
"x-form/assert": never;
|
|
57
57
|
"form/addItem": never;
|
|
58
58
|
"form/removeItem": never;
|
|
59
|
+
"form/jsonPlaceholder": never;
|
|
59
60
|
"contract/not-found": never;
|
|
60
61
|
"contract/method-not-allowed": "allow";
|
|
61
62
|
"contract/body-too-large": "limit" | "op";
|
package/types/model.d.ts
CHANGED
|
@@ -61,6 +61,20 @@ export interface EntityBlock {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/** Explicit column-only layout for an existing SQLite object. */
|
|
65
|
+
export interface PhysicalLayout {
|
|
66
|
+
readonly table: string;
|
|
67
|
+
readonly kind?: 'table' | 'view';
|
|
68
|
+
readonly keys?: readonly string[];
|
|
69
|
+
readonly columns: Readonly<Record<string, {
|
|
70
|
+
readonly name: string;
|
|
71
|
+
readonly codec: 'text' | 'integer' | 'number' | 'boolean' | 'json' | 'date' | 'datetime' | 'epoch-ms' | 'bigint' | 'decimal' | 'blob-hex';
|
|
72
|
+
readonly null: 'null' | 'absent' | 'reject';
|
|
73
|
+
readonly default?: 'database';
|
|
74
|
+
readonly generated?: boolean;
|
|
75
|
+
}>>;
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
// ————— the entity-aware builders —————
|
|
65
79
|
|
|
66
80
|
/** The base every untyped kind is built from, plus the vocabulary. */
|
|
@@ -203,6 +217,10 @@ export class EntityObjectBuilder<
|
|
|
203
217
|
P extends Props, Open extends boolean = false, PV = never, PVIn = PV,
|
|
204
218
|
N extends boolean = false, F extends Flag = never,
|
|
205
219
|
> extends ObjectBuilder<P, Open, PV, PVIn, N, F> {
|
|
220
|
+
physical(layout: PhysicalLayout): this;
|
|
221
|
+
invariants(rules: readonly { name: string; on: readonly ('insert' | 'update' | 'delete')[];
|
|
222
|
+
enforcement: 'database' | 'store'; assert: unknown;
|
|
223
|
+
audit?: { entity: string; values: Readonly<Record<string, unknown>> } }[]): this;
|
|
206
224
|
optional(): EntityObjectBuilder<P, Open, PV, PVIn, N, F | 'optional'>;
|
|
207
225
|
nullable(): EntityObjectBuilder<P, Open, PV, PVIn, true, F>;
|
|
208
226
|
open(): EntityObjectBuilder<P, true, PV, PVIn, N, F>;
|
package/types/project.d.ts
CHANGED
|
@@ -7,7 +7,13 @@ export type JsonInput<T> = unknown extends T ? unknown
|
|
|
7
7
|
: T extends object ? { readonly [K in keyof T]: JsonInput<T[K]> } : never;
|
|
8
8
|
|
|
9
9
|
export type FileKind = 'app' | 'jslt' | 'query' | 'state' | 'data' | 'schema' | 'fsm' | 'dag' | 'model' | 'contract';
|
|
10
|
-
export interface
|
|
10
|
+
export interface ProjectFileOptions {
|
|
11
|
+
readonly imports?: Readonly<Record<string, string>>;
|
|
12
|
+
readonly input?: string;
|
|
13
|
+
readonly model?: string;
|
|
14
|
+
readonly collection?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ProjectFile<Name extends string = string, Kind extends FileKind = FileKind> extends ProjectFileOptions {
|
|
11
17
|
readonly name: Name;
|
|
12
18
|
readonly kind: Kind;
|
|
13
19
|
readonly text: string;
|
|
@@ -24,8 +30,8 @@ export interface ProjectDocument {
|
|
|
24
30
|
readonly layout?: ProjectLayout;
|
|
25
31
|
}
|
|
26
32
|
export const FILE_KINDS: readonly FileKind[];
|
|
27
|
-
export function file<const N extends string, K extends FileKind>(name: N, kind: K, text: string): ProjectFile<N, K>;
|
|
28
|
-
export function jsonFile<const N extends string, K extends FileKind, const D>(name: N, kind: K, document: D & JsonInput<D
|
|
33
|
+
export function file<const N extends string, K extends FileKind>(name: N, kind: K, text: string, options?: ProjectFileOptions): ProjectFile<N, K>;
|
|
34
|
+
export function jsonFile<const N extends string, K extends FileKind, const D>(name: N, kind: K, document: D & JsonInput<D>, options?: ProjectFileOptions): ProjectFile<N, K>;
|
|
29
35
|
/** Names are a phantom; the public document has no extra registry. */
|
|
30
36
|
export class ProjectBuilder<Names extends string = never> {
|
|
31
37
|
protected constructor();
|