@objectstack/objectql 7.3.0 → 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 +322 -9
- package/dist/index.d.ts +322 -9
- package/dist/index.js +538 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +531 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
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,14 @@ 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;
|
|
141
149
|
/**
|
|
142
150
|
* Package ids that must be installed in a DISABLED state. Seeded once at
|
|
143
151
|
* boot (from persisted state) BEFORE any package registration so that every
|
|
@@ -215,6 +223,25 @@ declare class SchemaRegistry {
|
|
|
215
223
|
* Get the owner contributor for an object.
|
|
216
224
|
*/
|
|
217
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;
|
|
218
245
|
/**
|
|
219
246
|
* Unregister all objects contributed by a package.
|
|
220
247
|
*
|
|
@@ -259,6 +286,41 @@ declare class SchemaRegistry {
|
|
|
259
286
|
registerApp(app: any, packageId?: string): void;
|
|
260
287
|
getApp(name: string): any;
|
|
261
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;
|
|
262
324
|
registerPlugin(manifest: ObjectStackManifest): void;
|
|
263
325
|
getAllPlugins(): ObjectStackManifest[];
|
|
264
326
|
registerKind(kind: {
|
|
@@ -386,13 +448,100 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
386
448
|
getMetaTypes(): Promise<{
|
|
387
449
|
types: string[];
|
|
388
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;
|
|
389
538
|
type: string;
|
|
390
539
|
schemaId: string;
|
|
391
540
|
allowOrgOverride: boolean;
|
|
392
541
|
overrideSource: "env" | "registry";
|
|
393
542
|
schema: Record<string, unknown>;
|
|
394
543
|
form: {
|
|
395
|
-
type: "split" | "
|
|
544
|
+
type: "split" | "drawer" | "modal" | "simple" | "tabbed" | "wizard";
|
|
396
545
|
data?: {
|
|
397
546
|
provider: "object";
|
|
398
547
|
object: string;
|
|
@@ -423,7 +572,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
423
572
|
sections?: {
|
|
424
573
|
collapsible: boolean;
|
|
425
574
|
collapsed: boolean;
|
|
426
|
-
columns: 1 | 2 |
|
|
575
|
+
columns: 1 | 2 | 4 | 3;
|
|
427
576
|
fields: any[];
|
|
428
577
|
name?: string | undefined;
|
|
429
578
|
label?: string | undefined;
|
|
@@ -449,7 +598,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
449
598
|
groups?: {
|
|
450
599
|
collapsible: boolean;
|
|
451
600
|
collapsed: boolean;
|
|
452
|
-
columns: 1 | 2 |
|
|
601
|
+
columns: 1 | 2 | 4 | 3;
|
|
453
602
|
fields: any[];
|
|
454
603
|
name?: string | undefined;
|
|
455
604
|
label?: string | undefined;
|
|
@@ -705,7 +854,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
705
854
|
label: string | undefined;
|
|
706
855
|
required: boolean;
|
|
707
856
|
readonly: boolean;
|
|
708
|
-
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";
|
|
709
858
|
colSpan: number;
|
|
710
859
|
}[];
|
|
711
860
|
}[];
|
|
@@ -861,6 +1010,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
861
1010
|
type: string;
|
|
862
1011
|
name: string;
|
|
863
1012
|
cacheRequest?: MetadataCacheRequest;
|
|
1013
|
+
locale?: string;
|
|
864
1014
|
}): Promise<MetadataCacheResponse>;
|
|
865
1015
|
batchData(request: {
|
|
866
1016
|
object: string;
|
|
@@ -1453,12 +1603,14 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1453
1603
|
private logger;
|
|
1454
1604
|
private datasourceMapping;
|
|
1455
1605
|
private manifests;
|
|
1606
|
+
private datasourceDefs;
|
|
1456
1607
|
private hooks;
|
|
1457
1608
|
private middlewares;
|
|
1458
1609
|
private actions;
|
|
1459
1610
|
private functions;
|
|
1460
1611
|
private hostContext;
|
|
1461
1612
|
private realtimeService?;
|
|
1613
|
+
private cryptoProvider?;
|
|
1462
1614
|
private _registry;
|
|
1463
1615
|
constructor(hostContext?: Record<string, any>);
|
|
1464
1616
|
/**
|
|
@@ -1656,6 +1808,31 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1656
1808
|
* Register a new storage driver
|
|
1657
1809
|
*/
|
|
1658
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;
|
|
1659
1836
|
/**
|
|
1660
1837
|
* Set the realtime service for publishing data change events.
|
|
1661
1838
|
* Should be called after kernel resolves the realtime service.
|
|
@@ -1663,6 +1840,54 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1663
1840
|
* @param service - An IRealtimeService instance for event publishing
|
|
1664
1841
|
*/
|
|
1665
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>;
|
|
1666
1891
|
/**
|
|
1667
1892
|
* Helper to get object definition
|
|
1668
1893
|
*/
|
|
@@ -1798,6 +2023,17 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1798
2023
|
* this method directly looks up a driver by its registered name.
|
|
1799
2024
|
*/
|
|
1800
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>;
|
|
1801
2037
|
/**
|
|
1802
2038
|
* Get the driver responsible for the given object.
|
|
1803
2039
|
*
|
|
@@ -2143,7 +2379,7 @@ declare function wrapDeclarativeHook(meta: Hook, handler: HookHandler, opts?: Wr
|
|
|
2143
2379
|
|
|
2144
2380
|
interface FieldValidationError {
|
|
2145
2381
|
field: string;
|
|
2146
|
-
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';
|
|
2147
2383
|
message: string;
|
|
2148
2384
|
/** Allowed values for select/multiselect, when applicable. */
|
|
2149
2385
|
options?: string[];
|
|
@@ -2153,7 +2389,7 @@ declare class ValidationError extends Error {
|
|
|
2153
2389
|
readonly fields: FieldValidationError[];
|
|
2154
2390
|
constructor(fields: FieldValidationError[]);
|
|
2155
2391
|
}
|
|
2156
|
-
type Mode = 'insert' | 'update';
|
|
2392
|
+
type Mode$1 = 'insert' | 'update';
|
|
2157
2393
|
interface FieldDef {
|
|
2158
2394
|
name?: string;
|
|
2159
2395
|
type: string;
|
|
@@ -2179,7 +2415,45 @@ interface FieldDef {
|
|
|
2179
2415
|
*/
|
|
2180
2416
|
declare function validateRecord(objectSchema: {
|
|
2181
2417
|
fields?: Record<string, FieldDef>;
|
|
2182
|
-
} | 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;
|
|
2183
2457
|
|
|
2184
2458
|
/**
|
|
2185
2459
|
* MetadataFacade
|
|
@@ -2410,6 +2684,45 @@ interface ObjectQLKernelOptions {
|
|
|
2410
2684
|
*/
|
|
2411
2685
|
declare function createObjectQLKernel(options?: ObjectQLKernelOptions): Promise<ObjectKernel>;
|
|
2412
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
|
+
|
|
2413
2726
|
/**
|
|
2414
2727
|
* Column metadata from database introspection.
|
|
2415
2728
|
*/
|
|
@@ -2497,4 +2810,4 @@ declare function convertIntrospectedSchemaToObjects(introspectedSchema: Introspe
|
|
|
2497
2810
|
skipSystemColumns?: boolean;
|
|
2498
2811
|
}): ServiceObject[];
|
|
2499
2812
|
|
|
2500
|
-
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 };
|