@objectstack/objectql 7.2.1 → 7.4.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/dist/index.d.mts +343 -9
- package/dist/index.d.ts +343 -9
- package/dist/index.js +606 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +599 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ import * as _objectstack_metadata_core from '@objectstack/metadata-core';
|
|
|
4
4
|
import { MetadataRepository, MetaRef, MetadataItem, PutOptions, PutResult, DeleteOptions, DeleteResult, MetadataWriteIntent, ListFilter, MetadataItemHeader, HistoryOptions, MetadataEvent, WatchFilter } from '@objectstack/metadata-core';
|
|
5
5
|
import { ObjectStackProtocol, MetadataCacheRequest, MetadataCacheResponse, BatchUpdateRequest, BatchUpdateResponse, UpdateManyDataRequest, DeleteManyDataRequest } from '@objectstack/spec/api';
|
|
6
6
|
import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext, ObjectKernel } from '@objectstack/core';
|
|
7
|
-
import { IFeedService, IRealtimeService } from '@objectstack/spec/contracts';
|
|
7
|
+
import { IFeedService, IRealtimeService, ICryptoProvider } from '@objectstack/spec/contracts';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Reserved namespaces that do not get FQN prefix applied.
|
|
@@ -138,6 +138,29 @@ declare class SchemaRegistry {
|
|
|
138
138
|
private namespaceRegistry;
|
|
139
139
|
/** Type → Name/ID → MetadataItem */
|
|
140
140
|
private metadata;
|
|
141
|
+
/**
|
|
142
|
+
* App name → navigation contributions (ADR-0029 D7).
|
|
143
|
+
*
|
|
144
|
+
* Lets packages inject nav items into apps they do not own (the UI analog
|
|
145
|
+
* of object extenders). Merged into the owning app's `navigation` tree on
|
|
146
|
+
* read in {@link getApp} / {@link getAllApps} by group id + priority.
|
|
147
|
+
*/
|
|
148
|
+
private appNavContributions;
|
|
149
|
+
/**
|
|
150
|
+
* Package ids that must be installed in a DISABLED state. Seeded once at
|
|
151
|
+
* boot (from persisted state) BEFORE any package registration so that every
|
|
152
|
+
* registration path — boot artifact, marketplace rehydrate, local import —
|
|
153
|
+
* honors persisted disable state uniformly without a fragile post-boot
|
|
154
|
+
* re-application hook. See {@link setInitialDisabledPackageIds} and
|
|
155
|
+
* {@link installPackage}.
|
|
156
|
+
*/
|
|
157
|
+
private initialDisabledPackageIds;
|
|
158
|
+
/**
|
|
159
|
+
* Seed the set of package ids that should be installed disabled. Call this
|
|
160
|
+
* before package registration begins; later `installPackage` calls for these
|
|
161
|
+
* ids land in the `disabled` state. Replaces any previously seeded set.
|
|
162
|
+
*/
|
|
163
|
+
setInitialDisabledPackageIds(ids: Iterable<string>): void;
|
|
141
164
|
/**
|
|
142
165
|
* Register a namespace for a package.
|
|
143
166
|
* Multiple packages can share the same namespace (e.g. 'sys').
|
|
@@ -200,6 +223,25 @@ declare class SchemaRegistry {
|
|
|
200
223
|
* Get the owner contributor for an object.
|
|
201
224
|
*/
|
|
202
225
|
getObjectOwner(fqn: string): ObjectContributor | undefined;
|
|
226
|
+
/**
|
|
227
|
+
* ADR-0029 K0 — assert every registered object resolves to exactly one
|
|
228
|
+
* owner.
|
|
229
|
+
*
|
|
230
|
+
* A second `own` from a different package is already rejected eagerly in
|
|
231
|
+
* {@link registerObject} (it throws). This is the install-time backstop
|
|
232
|
+
* called once all packages are registered (kernel bootstrap complete),
|
|
233
|
+
* and it additionally catches the case `registerObject` cannot: an object
|
|
234
|
+
* that has only `extend` contributions and **no owner** — which would
|
|
235
|
+
* otherwise resolve to nothing. Surfacing it here turns a silent
|
|
236
|
+
* "extend a non-existent object" into a clear bootstrap error.
|
|
237
|
+
*
|
|
238
|
+
* This is the invariant the kernel-decomposition (ADR-0029) relies on:
|
|
239
|
+
* the `sys` namespace is shared across many first-party plugins, but each
|
|
240
|
+
* object name has exactly one owner.
|
|
241
|
+
*
|
|
242
|
+
* @throws Error listing every object whose owner count is not exactly 1.
|
|
243
|
+
*/
|
|
244
|
+
assertSingleOwnerPerObject(): void;
|
|
203
245
|
/**
|
|
204
246
|
* Unregister all objects contributed by a package.
|
|
205
247
|
*
|
|
@@ -226,6 +268,11 @@ declare class SchemaRegistry {
|
|
|
226
268
|
* Universal List Method
|
|
227
269
|
*/
|
|
228
270
|
listItems<T>(type: string, packageId?: string): T[];
|
|
271
|
+
/**
|
|
272
|
+
* Whether a package has been explicitly disabled. Unknown packages and
|
|
273
|
+
* items with no owning package are treated as enabled.
|
|
274
|
+
*/
|
|
275
|
+
isPackageDisabled(packageId?: string): boolean;
|
|
229
276
|
/**
|
|
230
277
|
* Get all registered metadata types (Kinds)
|
|
231
278
|
*/
|
|
@@ -239,6 +286,41 @@ declare class SchemaRegistry {
|
|
|
239
286
|
registerApp(app: any, packageId?: string): void;
|
|
240
287
|
getApp(name: string): any;
|
|
241
288
|
getAllApps(): any[];
|
|
289
|
+
/**
|
|
290
|
+
* Register a navigation contribution — a package injecting nav items into
|
|
291
|
+
* an app it does not own (the UI-layer analog of object `extend`).
|
|
292
|
+
*
|
|
293
|
+
* Contributions are merged into the target app's `navigation` tree lazily
|
|
294
|
+
* on read ({@link getApp} / {@link getAllApps}) by group id + priority, so
|
|
295
|
+
* registration order does not matter and the owning app can be registered
|
|
296
|
+
* before or after its contributors.
|
|
297
|
+
*/
|
|
298
|
+
registerAppNavContribution(contribution: {
|
|
299
|
+
app: string;
|
|
300
|
+
group?: string;
|
|
301
|
+
priority?: number;
|
|
302
|
+
items?: any[];
|
|
303
|
+
}, packageId?: string): void;
|
|
304
|
+
/** Contributions registered for an app (empty array when none). */
|
|
305
|
+
getAppNavContributions(appName: string): Array<{
|
|
306
|
+
packageId?: string;
|
|
307
|
+
group?: string;
|
|
308
|
+
priority: number;
|
|
309
|
+
items: any[];
|
|
310
|
+
}>;
|
|
311
|
+
/**
|
|
312
|
+
* Return a copy of `app` with all registered navigation contributions
|
|
313
|
+
* merged into its `navigation` tree. The stored app is never mutated, so
|
|
314
|
+
* repeated reads stay idempotent.
|
|
315
|
+
*
|
|
316
|
+
* Public so the protocol serving path (`getMetaItems` / `getMetaItem` for
|
|
317
|
+
* `app`) can merge contributions the same way `getApp` / `getAllApps` do —
|
|
318
|
+
* the REST app endpoints read through the protocol, not these helpers, so
|
|
319
|
+
* the merge must be reachable from there too (ADR-0029 D7).
|
|
320
|
+
*/
|
|
321
|
+
applyNavContributions(app: any): any;
|
|
322
|
+
/** Depth-first search for a `type: 'group'` nav item by id. */
|
|
323
|
+
private findNavGroup;
|
|
242
324
|
registerPlugin(manifest: ObjectStackManifest): void;
|
|
243
325
|
getAllPlugins(): ObjectStackManifest[];
|
|
244
326
|
registerKind(kind: {
|
|
@@ -366,13 +448,100 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
366
448
|
getMetaTypes(): Promise<{
|
|
367
449
|
types: string[];
|
|
368
450
|
entries: {
|
|
451
|
+
actions?: {
|
|
452
|
+
name: string;
|
|
453
|
+
label: string;
|
|
454
|
+
type: "url" | "flow" | "script" | "api" | "form" | "modal";
|
|
455
|
+
refreshAfter: boolean;
|
|
456
|
+
objectName?: string | undefined;
|
|
457
|
+
icon?: string | undefined;
|
|
458
|
+
locations?: ("list_toolbar" | "list_item" | "record_header" | "record_more" | "record_related" | "record_section" | "global_nav")[] | undefined;
|
|
459
|
+
component?: "action:button" | "action:icon" | "action:menu" | "action:group" | undefined;
|
|
460
|
+
target?: string | undefined;
|
|
461
|
+
body?: {
|
|
462
|
+
language: "expression";
|
|
463
|
+
source: string;
|
|
464
|
+
} | {
|
|
465
|
+
language: "js";
|
|
466
|
+
source: string;
|
|
467
|
+
capabilities: ("log" | "api.read" | "api.write" | "crypto.uuid" | "crypto.hash")[];
|
|
468
|
+
timeoutMs?: number | undefined;
|
|
469
|
+
memoryMb?: number | undefined;
|
|
470
|
+
} | undefined;
|
|
471
|
+
execute?: string | undefined;
|
|
472
|
+
params?: {
|
|
473
|
+
required: boolean;
|
|
474
|
+
name?: string | undefined;
|
|
475
|
+
field?: string | undefined;
|
|
476
|
+
objectOverride?: string | undefined;
|
|
477
|
+
label?: string | undefined;
|
|
478
|
+
type?: "number" | "boolean" | "date" | "record" | "file" | "code" | "json" | "url" | "summary" | "datetime" | "color" | "time" | "text" | "textarea" | "email" | "phone" | "password" | "secret" | "markdown" | "html" | "richtext" | "currency" | "percent" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "lookup" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "autonumber" | "composite" | "repeater" | "location" | "address" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector" | undefined;
|
|
479
|
+
options?: {
|
|
480
|
+
label: string;
|
|
481
|
+
value: string;
|
|
482
|
+
}[] | undefined;
|
|
483
|
+
placeholder?: string | undefined;
|
|
484
|
+
helpText?: string | undefined;
|
|
485
|
+
defaultValue?: unknown;
|
|
486
|
+
defaultFromRow?: boolean | undefined;
|
|
487
|
+
}[] | undefined;
|
|
488
|
+
variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | undefined;
|
|
489
|
+
confirmText?: string | undefined;
|
|
490
|
+
successMessage?: string | undefined;
|
|
491
|
+
resultDialog?: {
|
|
492
|
+
title?: string | undefined;
|
|
493
|
+
description?: string | undefined;
|
|
494
|
+
acknowledge?: string | undefined;
|
|
495
|
+
format?: "json" | "text" | "secret" | "qrcode" | "code-list" | undefined;
|
|
496
|
+
fields?: {
|
|
497
|
+
path: string;
|
|
498
|
+
label?: string | undefined;
|
|
499
|
+
format?: "json" | "text" | "secret" | "qrcode" | "code-list" | undefined;
|
|
500
|
+
}[] | undefined;
|
|
501
|
+
} | undefined;
|
|
502
|
+
visible?: {
|
|
503
|
+
dialect: "cron" | "cel" | "js" | "template";
|
|
504
|
+
source?: string | undefined;
|
|
505
|
+
ast?: unknown;
|
|
506
|
+
meta?: {
|
|
507
|
+
rationale?: string | undefined;
|
|
508
|
+
generatedBy?: string | undefined;
|
|
509
|
+
} | undefined;
|
|
510
|
+
} | undefined;
|
|
511
|
+
disabled?: boolean | {
|
|
512
|
+
dialect: "cron" | "cel" | "js" | "template";
|
|
513
|
+
source?: string | undefined;
|
|
514
|
+
ast?: unknown;
|
|
515
|
+
meta?: {
|
|
516
|
+
rationale?: string | undefined;
|
|
517
|
+
generatedBy?: string | undefined;
|
|
518
|
+
} | undefined;
|
|
519
|
+
} | undefined;
|
|
520
|
+
shortcut?: string | undefined;
|
|
521
|
+
bulkEnabled?: boolean | undefined;
|
|
522
|
+
aiExposed?: boolean | undefined;
|
|
523
|
+
recordIdParam?: string | undefined;
|
|
524
|
+
recordIdField?: string | undefined;
|
|
525
|
+
bodyShape?: "flat" | {
|
|
526
|
+
wrap: string;
|
|
527
|
+
} | undefined;
|
|
528
|
+
method?: "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
529
|
+
bodyExtra?: Record<string, unknown> | undefined;
|
|
530
|
+
mode?: "custom" | "create" | "delete" | "edit" | undefined;
|
|
531
|
+
timeout?: number | undefined;
|
|
532
|
+
aria?: {
|
|
533
|
+
ariaLabel?: string | undefined;
|
|
534
|
+
ariaDescribedBy?: string | undefined;
|
|
535
|
+
role?: string | undefined;
|
|
536
|
+
} | undefined;
|
|
537
|
+
}[] | undefined;
|
|
369
538
|
type: string;
|
|
370
539
|
schemaId: string;
|
|
371
540
|
allowOrgOverride: boolean;
|
|
372
541
|
overrideSource: "env" | "registry";
|
|
373
542
|
schema: Record<string, unknown>;
|
|
374
543
|
form: {
|
|
375
|
-
type: "split" | "
|
|
544
|
+
type: "split" | "drawer" | "modal" | "simple" | "tabbed" | "wizard";
|
|
376
545
|
data?: {
|
|
377
546
|
provider: "object";
|
|
378
547
|
object: string;
|
|
@@ -403,7 +572,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
403
572
|
sections?: {
|
|
404
573
|
collapsible: boolean;
|
|
405
574
|
collapsed: boolean;
|
|
406
|
-
columns: 1 | 2 |
|
|
575
|
+
columns: 1 | 2 | 4 | 3;
|
|
407
576
|
fields: any[];
|
|
408
577
|
name?: string | undefined;
|
|
409
578
|
label?: string | undefined;
|
|
@@ -429,7 +598,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
429
598
|
groups?: {
|
|
430
599
|
collapsible: boolean;
|
|
431
600
|
collapsed: boolean;
|
|
432
|
-
columns: 1 | 2 |
|
|
601
|
+
columns: 1 | 2 | 4 | 3;
|
|
433
602
|
fields: any[];
|
|
434
603
|
name?: string | undefined;
|
|
435
604
|
label?: string | undefined;
|
|
@@ -685,7 +854,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
685
854
|
label: string | undefined;
|
|
686
855
|
required: boolean;
|
|
687
856
|
readonly: boolean;
|
|
688
|
-
type: "number" | "boolean" | "tags" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "
|
|
857
|
+
type: "number" | "boolean" | "tags" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "currency" | "percent" | "password" | "secret" | "email" | "time" | "text" | "textarea" | "phone" | "markdown" | "html" | "richtext" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "lookup" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
|
|
689
858
|
colSpan: number;
|
|
690
859
|
}[];
|
|
691
860
|
}[];
|
|
@@ -841,6 +1010,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
841
1010
|
type: string;
|
|
842
1011
|
name: string;
|
|
843
1012
|
cacheRequest?: MetadataCacheRequest;
|
|
1013
|
+
locale?: string;
|
|
844
1014
|
}): Promise<MetadataCacheResponse>;
|
|
845
1015
|
batchData(request: {
|
|
846
1016
|
object: string;
|
|
@@ -977,6 +1147,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
977
1147
|
actor?: string;
|
|
978
1148
|
force?: boolean;
|
|
979
1149
|
mode?: 'draft' | 'publish';
|
|
1150
|
+
packageId?: string | null;
|
|
980
1151
|
}): Promise<{
|
|
981
1152
|
success: boolean;
|
|
982
1153
|
version: string;
|
|
@@ -1432,12 +1603,14 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1432
1603
|
private logger;
|
|
1433
1604
|
private datasourceMapping;
|
|
1434
1605
|
private manifests;
|
|
1606
|
+
private datasourceDefs;
|
|
1435
1607
|
private hooks;
|
|
1436
1608
|
private middlewares;
|
|
1437
1609
|
private actions;
|
|
1438
1610
|
private functions;
|
|
1439
1611
|
private hostContext;
|
|
1440
1612
|
private realtimeService?;
|
|
1613
|
+
private cryptoProvider?;
|
|
1441
1614
|
private _registry;
|
|
1442
1615
|
constructor(hostContext?: Record<string, any>);
|
|
1443
1616
|
/**
|
|
@@ -1635,6 +1808,31 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1635
1808
|
* Register a new storage driver
|
|
1636
1809
|
*/
|
|
1637
1810
|
registerDriver(driver: DriverInterface, isDefault?: boolean): void;
|
|
1811
|
+
/**
|
|
1812
|
+
* Register a Datasource *definition* (ADR-0015).
|
|
1813
|
+
*
|
|
1814
|
+
* Distinct from {@link registerDriver}, which registers a live connection.
|
|
1815
|
+
* This captures the declarative `schemaMode` + `external.allowWrites` so the
|
|
1816
|
+
* write gate ({@link assertWriteAllowed}) can enforce external-datasource
|
|
1817
|
+
* ownership. Safe to call repeatedly; last write wins.
|
|
1818
|
+
*/
|
|
1819
|
+
registerDatasourceDef(def: {
|
|
1820
|
+
name: string;
|
|
1821
|
+
schemaMode?: string;
|
|
1822
|
+
external?: {
|
|
1823
|
+
allowWrites?: boolean;
|
|
1824
|
+
};
|
|
1825
|
+
}): void;
|
|
1826
|
+
/**
|
|
1827
|
+
* Write gate — Gate 3 of ADR-0015 §5.3.
|
|
1828
|
+
*
|
|
1829
|
+
* Blocks insert/update/delete against a federated datasource
|
|
1830
|
+
* (`schemaMode !== 'managed'`) unless BOTH the datasource opts in
|
|
1831
|
+
* (`external.allowWrites`) AND the object opts in (`external.writable`).
|
|
1832
|
+
* Managed datasources (the common case, including the absence of any
|
|
1833
|
+
* definition) are unaffected.
|
|
1834
|
+
*/
|
|
1835
|
+
private assertWriteAllowed;
|
|
1638
1836
|
/**
|
|
1639
1837
|
* Set the realtime service for publishing data change events.
|
|
1640
1838
|
* Should be called after kernel resolves the realtime service.
|
|
@@ -1642,6 +1840,54 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1642
1840
|
* @param service - An IRealtimeService instance for event publishing
|
|
1643
1841
|
*/
|
|
1644
1842
|
setRealtimeService(service: IRealtimeService): void;
|
|
1843
|
+
/**
|
|
1844
|
+
* Register the crypto provider that backs `secret`-typed fields.
|
|
1845
|
+
*
|
|
1846
|
+
* When set, the engine encrypts secret fields on write (storing ciphertext in
|
|
1847
|
+
* `sys_secret` and only an opaque ref on the business row) and masks them on
|
|
1848
|
+
* read. When NOT set, writing to an object that declares a secret field is
|
|
1849
|
+
* **fail-closed** — the write throws rather than persist cleartext.
|
|
1850
|
+
*
|
|
1851
|
+
* Mirrors the Settings subsystem's ICryptoProvider wiring; the host (e.g.
|
|
1852
|
+
* `serve`) injects `InMemoryCryptoProvider` in dev and a KMS/Vault-backed
|
|
1853
|
+
* provider in production.
|
|
1854
|
+
*/
|
|
1855
|
+
setCryptoProvider(provider: ICryptoProvider): void;
|
|
1856
|
+
/**
|
|
1857
|
+
* Encrypt any `secret`-typed fields on `row` in place before it reaches the
|
|
1858
|
+
* driver. Each plaintext is wrapped by the ICryptoProvider, persisted as a
|
|
1859
|
+
* `sys_secret` row, and replaced on `row` by an opaque ref. Cleartext never
|
|
1860
|
+
* reaches the business table.
|
|
1861
|
+
*
|
|
1862
|
+
* Rules:
|
|
1863
|
+
* - No secret fields on the object ⇒ no-op (fast path, no crypto cost).
|
|
1864
|
+
* - `null`/`undefined` value ⇒ left as-is (clears the secret).
|
|
1865
|
+
* - Value already a ref (re-save of an unchanged ref) ⇒ left as-is.
|
|
1866
|
+
* - Value equal to the read mask ⇒ dropped, so a form round-trip that
|
|
1867
|
+
* echoes the mask does not overwrite the stored secret.
|
|
1868
|
+
* - **Fail-closed:** any other value with no CryptoProvider registered, or
|
|
1869
|
+
* no reachable `sys_secret` store, THROWS — never persists cleartext.
|
|
1870
|
+
*/
|
|
1871
|
+
private encryptSecretFields;
|
|
1872
|
+
/**
|
|
1873
|
+
* Mask `secret`-typed fields on read so plaintext never leaves the engine
|
|
1874
|
+
* through the normal query path. A set secret becomes {@link SECRET_MASK};
|
|
1875
|
+
* an unset one stays `null`. Privileged callers that genuinely need the
|
|
1876
|
+
* plaintext use {@link resolveSecret} against the stored ref.
|
|
1877
|
+
*/
|
|
1878
|
+
private maskSecretFields;
|
|
1879
|
+
/**
|
|
1880
|
+
* Dereference a stored secret ref back to its plaintext. Intended for
|
|
1881
|
+
* privileged, server-side consumers (e.g. a datasource connection-pool
|
|
1882
|
+
* binder) — NOT exposed through the generic read path, which only ever
|
|
1883
|
+
* returns the mask.
|
|
1884
|
+
*
|
|
1885
|
+
* Fail-closed: throws when no CryptoProvider is registered or the
|
|
1886
|
+
* `sys_secret` row is missing. Returns `null` when `ref` is not a secret ref.
|
|
1887
|
+
*/
|
|
1888
|
+
resolveSecret(ref: unknown, opts?: {
|
|
1889
|
+
tenantId?: string;
|
|
1890
|
+
}): Promise<string | null>;
|
|
1645
1891
|
/**
|
|
1646
1892
|
* Helper to get object definition
|
|
1647
1893
|
*/
|
|
@@ -1777,6 +2023,17 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1777
2023
|
* this method directly looks up a driver by its registered name.
|
|
1778
2024
|
*/
|
|
1779
2025
|
getDriverByName(name: string): DriverInterface | undefined;
|
|
2026
|
+
/**
|
|
2027
|
+
* Introspect a datasource's live remote schema (ADR-0015).
|
|
2028
|
+
*
|
|
2029
|
+
* Resolves the driver registered under `datasource` and delegates to its
|
|
2030
|
+
* `introspectSchema()` capability. Used by the external-datasource service
|
|
2031
|
+
* (and CLI/REST) to list remote tables and validate federated objects.
|
|
2032
|
+
*
|
|
2033
|
+
* @throws if the datasource has no registered driver, or the driver does
|
|
2034
|
+
* not support introspection.
|
|
2035
|
+
*/
|
|
2036
|
+
introspectDatasource(datasource: string): Promise<unknown>;
|
|
1780
2037
|
/**
|
|
1781
2038
|
* Get the driver responsible for the given object.
|
|
1782
2039
|
*
|
|
@@ -2122,7 +2379,7 @@ declare function wrapDeclarativeHook(meta: Hook, handler: HookHandler, opts?: Wr
|
|
|
2122
2379
|
|
|
2123
2380
|
interface FieldValidationError {
|
|
2124
2381
|
field: string;
|
|
2125
|
-
code: 'required' | 'min_length' | 'max_length' | 'min_value' | 'max_value' | 'invalid_email' | 'invalid_url' | 'invalid_phone' | 'invalid_number' | 'invalid_boolean' | 'invalid_date' | 'invalid_option';
|
|
2382
|
+
code: 'required' | 'min_length' | 'max_length' | 'min_value' | 'max_value' | 'invalid_email' | 'invalid_url' | 'invalid_phone' | 'invalid_number' | 'invalid_boolean' | 'invalid_date' | 'invalid_option' | 'invalid_transition' | 'rule_violation';
|
|
2126
2383
|
message: string;
|
|
2127
2384
|
/** Allowed values for select/multiselect, when applicable. */
|
|
2128
2385
|
options?: string[];
|
|
@@ -2132,7 +2389,7 @@ declare class ValidationError extends Error {
|
|
|
2132
2389
|
readonly fields: FieldValidationError[];
|
|
2133
2390
|
constructor(fields: FieldValidationError[]);
|
|
2134
2391
|
}
|
|
2135
|
-
type Mode = 'insert' | 'update';
|
|
2392
|
+
type Mode$1 = 'insert' | 'update';
|
|
2136
2393
|
interface FieldDef {
|
|
2137
2394
|
name?: string;
|
|
2138
2395
|
type: string;
|
|
@@ -2158,7 +2415,45 @@ interface FieldDef {
|
|
|
2158
2415
|
*/
|
|
2159
2416
|
declare function validateRecord(objectSchema: {
|
|
2160
2417
|
fields?: Record<string, FieldDef>;
|
|
2161
|
-
} | undefined | null, data: Record<string, unknown> | undefined | null, mode: Mode): void;
|
|
2418
|
+
} | undefined | null, data: Record<string, unknown> | undefined | null, mode: Mode$1): void;
|
|
2419
|
+
|
|
2420
|
+
type Mode = 'insert' | 'update';
|
|
2421
|
+
interface EvaluateRulesOptions {
|
|
2422
|
+
/** Prior persisted record (update only). Absent on insert. */
|
|
2423
|
+
previous?: Record<string, unknown> | null;
|
|
2424
|
+
/** Optional logger for non-blocking diagnostics (broken rules, warnings). */
|
|
2425
|
+
logger?: {
|
|
2426
|
+
warn?: (msg: string, meta?: any) => void;
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2429
|
+
/**
|
|
2430
|
+
* Returns true when the object declares at least one validation rule whose
|
|
2431
|
+
* correct evaluation needs the prior record (so the engine knows whether the
|
|
2432
|
+
* extra fetch on the update path is worth it).
|
|
2433
|
+
*/
|
|
2434
|
+
declare function needsPriorRecord(objectSchema: {
|
|
2435
|
+
validations?: unknown[];
|
|
2436
|
+
} | undefined | null): boolean;
|
|
2437
|
+
/**
|
|
2438
|
+
* Evaluate an object's declared validation rules against an incoming write.
|
|
2439
|
+
*
|
|
2440
|
+
* Throws `ValidationError` (the same envelope `validateRecord` uses, so REST
|
|
2441
|
+
* surfaces a single `400 VALIDATION_FAILED`) when one or more `error`-severity
|
|
2442
|
+
* rules are violated. Returns void otherwise.
|
|
2443
|
+
*/
|
|
2444
|
+
declare function evaluateValidationRules(objectSchema: {
|
|
2445
|
+
validations?: unknown[];
|
|
2446
|
+
} | undefined | null, data: Record<string, unknown> | undefined | null, mode: Mode, opts?: EvaluateRulesOptions): void;
|
|
2447
|
+
/**
|
|
2448
|
+
* Introspection helper (ADR-0020 D3.3): given an object's schema, a state
|
|
2449
|
+
* field, and a current state, return the legal next states declared by the
|
|
2450
|
+
* matching `state_machine` rule. Returns `null` when no such rule exists (so
|
|
2451
|
+
* callers can distinguish "no FSM governs this field" from "a dead-end state
|
|
2452
|
+
* with zero outgoing transitions", which returns `[]`).
|
|
2453
|
+
*/
|
|
2454
|
+
declare function legalNextStates(objectSchema: {
|
|
2455
|
+
validations?: unknown[];
|
|
2456
|
+
} | undefined | null, field: string, currentState: string): string[] | null;
|
|
2162
2457
|
|
|
2163
2458
|
/**
|
|
2164
2459
|
* MetadataFacade
|
|
@@ -2389,6 +2684,45 @@ interface ObjectQLKernelOptions {
|
|
|
2389
2684
|
*/
|
|
2390
2685
|
declare function createObjectQLKernel(options?: ObjectQLKernelOptions): Promise<ObjectKernel>;
|
|
2391
2686
|
|
|
2687
|
+
/**
|
|
2688
|
+
* Secret-field channel — helpers for the `secret` FieldType.
|
|
2689
|
+
*
|
|
2690
|
+
* A `secret` field (DB password, API key, token) is **reversible**: the engine
|
|
2691
|
+
* encrypts it on write via the registered `ICryptoProvider`, persists the
|
|
2692
|
+
* ciphertext as a `sys_secret` row, and stores only an opaque *ref* on the
|
|
2693
|
+
* business row. On read the ref is masked, never the plaintext. This mirrors
|
|
2694
|
+
* the Settings subsystem (`sys_setting.value_enc → sys_secret.id`), generalized
|
|
2695
|
+
* to object fields.
|
|
2696
|
+
*
|
|
2697
|
+
* Contrast with `password` — a one-way hash owned by the auth subsystem, never
|
|
2698
|
+
* decrypted. The two never share a code path.
|
|
2699
|
+
*/
|
|
2700
|
+
|
|
2701
|
+
/**
|
|
2702
|
+
* Prefix marking a persisted field value as a `sys_secret` handle ref rather
|
|
2703
|
+
* than cleartext. Chosen to be unambiguous and human-greppable in a DB dump,
|
|
2704
|
+
* while making it obvious that the column holds no plaintext.
|
|
2705
|
+
*/
|
|
2706
|
+
declare const SECRET_REF_PREFIX = "secret:";
|
|
2707
|
+
/**
|
|
2708
|
+
* Value returned in place of a secret field on a normal read. Indicates
|
|
2709
|
+
* "a secret is set" without leaking the handle id or the plaintext. A field
|
|
2710
|
+
* with no stored secret resolves to `null` instead.
|
|
2711
|
+
*/
|
|
2712
|
+
declare const SECRET_MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
2713
|
+
/** Wrap a `sys_secret` handle id as the opaque ref persisted on the row. */
|
|
2714
|
+
declare function makeSecretRef(handleId: string): string;
|
|
2715
|
+
/** True when `value` is a secret ref previously produced by {@link makeSecretRef}. */
|
|
2716
|
+
declare function isSecretRef(value: unknown): value is string;
|
|
2717
|
+
/** Extract the `sys_secret` handle id from a ref, or `null` when not a ref. */
|
|
2718
|
+
declare function parseSecretRef(value: unknown): string | null;
|
|
2719
|
+
/**
|
|
2720
|
+
* Collect the names of `secret`-typed fields declared on an object schema.
|
|
2721
|
+
* Returns an empty array when the schema has no fields or no secret fields —
|
|
2722
|
+
* callers can fast-path on `length === 0` to skip all crypto work.
|
|
2723
|
+
*/
|
|
2724
|
+
declare function collectSecretFields(schema: ServiceObject | undefined | null): string[];
|
|
2725
|
+
|
|
2392
2726
|
/**
|
|
2393
2727
|
* Column metadata from database introspection.
|
|
2394
2728
|
*/
|
|
@@ -2476,4 +2810,4 @@ declare function convertIntrospectedSchemaToObjects(introspectedSchema: Introspe
|
|
|
2476
2810
|
skipSystemColumns?: boolean;
|
|
2477
2811
|
}): ServiceObject[];
|
|
2478
2812
|
|
|
2479
|
-
export { type BindHooksOptions, type BindHooksResult, DEFAULT_EXTENDER_PRIORITY, DEFAULT_OWNER_PRIORITY, type EngineMiddleware, type FieldValidationError, type HookEntry, type HookHandler, type HookMetricLabel, type HookMetricOutcome, type HookMetricsRecorder, type HookSkipReason, InMemoryHookMetricsRecorder, type IntrospectedColumn, type IntrospectedForeignKey, type IntrospectedSchema, type IntrospectedTable, MetadataFacade, type ObjectContributor, ObjectQL, type ObjectQLHostContext, type ObjectQLKernelOptions, ObjectQLPlugin, ObjectRepository, ObjectStackProtocolImplementation, type OperationContext, RESERVED_NAMESPACES, SchemaRegistry, type SchemaRegistryOptions, ScopedContext, type SysMetadataEngine, SysMetadataRepository, type SysMetadataRepositoryOptions, ValidationError, type WrapDeclarativeOptions, applyInMemoryAggregation, applySystemFields, bindHooksToEngine, bucketDateValue, computeFQN, convertIntrospectedSchemaToObjects, createObjectQLKernel, noopHookMetricsRecorder, parseFQN, toTitleCase, validateRecord, wrapDeclarativeHook };
|
|
2813
|
+
export { type BindHooksOptions, type BindHooksResult, DEFAULT_EXTENDER_PRIORITY, DEFAULT_OWNER_PRIORITY, type EngineMiddleware, type EvaluateRulesOptions, type FieldValidationError, type HookEntry, type HookHandler, type HookMetricLabel, type HookMetricOutcome, type HookMetricsRecorder, type HookSkipReason, InMemoryHookMetricsRecorder, type IntrospectedColumn, type IntrospectedForeignKey, type IntrospectedSchema, type IntrospectedTable, MetadataFacade, type ObjectContributor, ObjectQL, type ObjectQLHostContext, type ObjectQLKernelOptions, ObjectQLPlugin, ObjectRepository, ObjectStackProtocolImplementation, type OperationContext, RESERVED_NAMESPACES, SECRET_MASK, SECRET_REF_PREFIX, SchemaRegistry, type SchemaRegistryOptions, ScopedContext, type SysMetadataEngine, SysMetadataRepository, type SysMetadataRepositoryOptions, ValidationError, type WrapDeclarativeOptions, applyInMemoryAggregation, applySystemFields, bindHooksToEngine, bucketDateValue, collectSecretFields, computeFQN, convertIntrospectedSchemaToObjects, createObjectQLKernel, evaluateValidationRules, isSecretRef, legalNextStates, makeSecretRef, needsPriorRecord, noopHookMetricsRecorder, parseFQN, parseSecretRef, toTitleCase, validateRecord, wrapDeclarativeHook };
|