@objectstack/metadata 3.0.6 → 3.0.7

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.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { MetadataFormat, MetadataLoaderContract, MetadataLoadOptions, MetadataLoadResult, MetadataStats, MetadataSaveOptions, MetadataSaveResult, MetadataWatchEvent, MetadataManagerConfig } from '@objectstack/spec/system';
2
2
  export { MetadataCollectionInfo, MetadataExportOptions, MetadataFormat, MetadataImportOptions, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataSaveOptions, MetadataSaveResult, MetadataStats, MetadataWatchEvent } from '@objectstack/spec/system';
3
- import { IMetadataService, MetadataWatchCallback, MetadataWatchHandle, MetadataExportOptions, MetadataImportOptions, MetadataImportResult, MetadataTypeInfo, ISchemaDriver } from '@objectstack/spec/contracts';
3
+ import { IMetadataService, IDataDriver, MetadataWatchCallback, MetadataWatchHandle, MetadataExportOptions, MetadataImportOptions, MetadataImportResult, MetadataTypeInfo, ISchemaDriver } from '@objectstack/spec/contracts';
4
4
  export { IMetadataService, MetadataImportResult, MetadataTypeInfo, MetadataWatchCallback, MetadataWatchHandle } from '@objectstack/spec/contracts';
5
5
  import { MetadataTypeRegistryEntry, MetadataQuery, MetadataQueryResult, MetadataBulkResult, MetadataOverlay, MetadataValidationResult, MetadataDependency, MetadataPluginConfig } from '@objectstack/spec/kernel';
6
6
  export { MetadataBulkResult, MetadataDependency, MetadataPluginConfig, MetadataPluginManifest, MetadataQuery, MetadataQueryResult, MetadataType, MetadataTypeRegistryEntry, MetadataValidationResult } from '@objectstack/spec/kernel';
7
7
  import { Logger, Plugin, PluginContext } from '@objectstack/core';
8
8
  import { z } from 'zod';
9
+ import * as _objectstack_spec_data from '@objectstack/spec/data';
9
10
  import { System } from '@objectstack/spec';
10
11
 
11
12
  /**
@@ -138,6 +139,8 @@ interface MetadataLoader {
138
139
  type WatchCallback = (event: MetadataWatchEvent) => void | Promise<void>;
139
140
  interface MetadataManagerOptions extends MetadataManagerConfig {
140
141
  loaders?: MetadataLoader[];
142
+ /** Optional IDataDriver instance. When provided alongside config.datasource, auto-configures DatabaseLoader. */
143
+ driver?: IDataDriver;
141
144
  }
142
145
  /**
143
146
  * Main metadata manager class.
@@ -158,6 +161,13 @@ declare class MetadataManager implements IMetadataService {
158
161
  * Set the type registry for metadata type discovery.
159
162
  */
160
163
  setTypeRegistry(entries: MetadataTypeRegistryEntry[]): void;
164
+ /**
165
+ * Configure and register a DatabaseLoader for database-backed metadata persistence.
166
+ * Can be called at any time to enable database storage (e.g. after kernel resolves the driver).
167
+ *
168
+ * @param driver - An IDataDriver instance for database operations
169
+ */
170
+ setDatabaseDriver(driver: IDataDriver): void;
161
171
  /**
162
172
  * Register a new metadata loader (data source)
163
173
  */
@@ -384,6 +394,392 @@ declare class RemoteLoader implements MetadataLoader {
384
394
  save(type: string, name: string, data: any, _options?: MetadataSaveOptions): Promise<MetadataSaveResult>;
385
395
  }
386
396
 
397
+ /**
398
+ * Database Metadata Loader
399
+ *
400
+ * Loads and persists metadata via an IDataDriver instance, enabling
401
+ * database-backed storage for platform and user scoped metadata.
402
+ * Uses the `sys_metadata` table (configurable) following the
403
+ * MetadataRecordSchema envelope defined in @objectstack/spec.
404
+ */
405
+
406
+ /**
407
+ * Configuration for the DatabaseLoader.
408
+ */
409
+ interface DatabaseLoaderOptions {
410
+ /** The IDataDriver instance to use for database operations */
411
+ driver: IDataDriver;
412
+ /** The table name to store metadata records (default: 'sys_metadata') */
413
+ tableName?: string;
414
+ /** Tenant ID for multi-tenant isolation */
415
+ tenantId?: string;
416
+ }
417
+ /**
418
+ * DatabaseLoader — Datasource-backed metadata persistence.
419
+ *
420
+ * Implements the MetadataLoader interface to provide database read/write
421
+ * for metadata records. Uses the MetadataRecordSchema envelope to persist
422
+ * metadata with scope, versioning, and audit fields.
423
+ */
424
+ declare class DatabaseLoader implements MetadataLoader {
425
+ readonly contract: MetadataLoaderContract;
426
+ private driver;
427
+ private tableName;
428
+ private tenantId?;
429
+ private schemaReady;
430
+ constructor(options: DatabaseLoaderOptions);
431
+ /**
432
+ * Ensure the metadata table exists.
433
+ * Uses IDataDriver.syncSchema with the SysMetadataObject definition
434
+ * to idempotently create/update the table.
435
+ */
436
+ private ensureSchema;
437
+ /**
438
+ * Build base filter conditions for queries.
439
+ * Always includes tenantId when configured.
440
+ */
441
+ private baseFilter;
442
+ /**
443
+ * Convert a database row to a metadata payload.
444
+ * Parses the JSON `metadata` column back into an object.
445
+ */
446
+ private rowToData;
447
+ /**
448
+ * Convert a database row to a MetadataRecord-like object.
449
+ */
450
+ private rowToRecord;
451
+ load(type: string, name: string, _options?: MetadataLoadOptions): Promise<MetadataLoadResult>;
452
+ loadMany<T = any>(type: string, _options?: MetadataLoadOptions): Promise<T[]>;
453
+ exists(type: string, name: string): Promise<boolean>;
454
+ stat(type: string, name: string): Promise<MetadataStats | null>;
455
+ list(type: string): Promise<string[]>;
456
+ save(type: string, name: string, data: any, _options?: MetadataSaveOptions): Promise<MetadataSaveResult>;
457
+ }
458
+
459
+ /**
460
+ * XState-inspired State Machine Protocol
461
+ * Used to define strict business logic constraints and lifecycle management.
462
+ * Prevent AI "hallucinations" by enforcing valid valid transitions.
463
+ */
464
+ /**
465
+ * References a named action (side effect)
466
+ * Can be a script, a webhook, or a field update.
467
+ */
468
+ declare const ActionRefSchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
469
+ type: z.ZodString;
470
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
471
+ }, z.core.$strip>]>;
472
+ /**
473
+ * State Transition Definition
474
+ * "When EVENT happens, if GUARD is true, go to TARGET and run ACTIONS"
475
+ */
476
+ declare const TransitionSchema: z.ZodObject<{
477
+ target: z.ZodOptional<z.ZodString>;
478
+ cond: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
479
+ type: z.ZodString;
480
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
481
+ }, z.core.$strip>]>>;
482
+ actions: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
483
+ type: z.ZodString;
484
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
485
+ }, z.core.$strip>]>>>;
486
+ description: z.ZodOptional<z.ZodString>;
487
+ }, z.core.$strip>;
488
+ type ActionRef = z.infer<typeof ActionRefSchema>;
489
+ type Transition = z.infer<typeof TransitionSchema>;
490
+ type StateNodeConfig = {
491
+ type?: 'atomic' | 'compound' | 'parallel' | 'final' | 'history';
492
+ entry?: ActionRef[];
493
+ exit?: ActionRef[];
494
+ on?: Record<string, string | Transition | Transition[]>;
495
+ always?: Transition[];
496
+ initial?: string;
497
+ states?: Record<string, StateNodeConfig>;
498
+ meta?: {
499
+ label?: string;
500
+ description?: string;
501
+ color?: string;
502
+ aiInstructions?: string;
503
+ };
504
+ };
505
+
506
+ /**
507
+ * sys_metadata — System Metadata Object
508
+ *
509
+ * Canonical ObjectStack object definition for the metadata persistence table.
510
+ * Stores all platform-scope and user-scope metadata records (Objects, Views,
511
+ * Flows, etc.) using the MetadataRecordSchema envelope.
512
+ *
513
+ * This is a system object (isSystem: true) — protected from deletion and
514
+ * automatically provisioned by the DatabaseLoader on first use.
515
+ *
516
+ * @see MetadataRecordSchema in metadata-persistence.zod.ts
517
+ */
518
+ declare const SysMetadataObject: {
519
+ name: string;
520
+ active: boolean;
521
+ isSystem: boolean;
522
+ abstract: boolean;
523
+ datasource: string;
524
+ fields: Record<string, {
525
+ type: "number" | "boolean" | "json" | "tags" | "date" | "lookup" | "file" | "text" | "textarea" | "email" | "url" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
526
+ required: boolean;
527
+ searchable: boolean;
528
+ multiple: boolean;
529
+ unique: boolean;
530
+ deleteBehavior: "set_null" | "cascade" | "restrict";
531
+ auditTrail: boolean;
532
+ hidden: boolean;
533
+ readonly: boolean;
534
+ sortable: boolean;
535
+ index: boolean;
536
+ externalId: boolean;
537
+ name?: string | undefined;
538
+ label?: string | undefined;
539
+ description?: string | undefined;
540
+ format?: string | undefined;
541
+ defaultValue?: unknown;
542
+ maxLength?: number | undefined;
543
+ minLength?: number | undefined;
544
+ precision?: number | undefined;
545
+ scale?: number | undefined;
546
+ min?: number | undefined;
547
+ max?: number | undefined;
548
+ options?: {
549
+ label: string;
550
+ value: string;
551
+ color?: string | undefined;
552
+ default?: boolean | undefined;
553
+ }[] | undefined;
554
+ reference?: string | undefined;
555
+ referenceFilters?: string[] | undefined;
556
+ writeRequiresMasterRead?: boolean | undefined;
557
+ expression?: string | undefined;
558
+ summaryOperations?: {
559
+ object: string;
560
+ field: string;
561
+ function: "min" | "max" | "count" | "sum" | "avg";
562
+ } | undefined;
563
+ language?: string | undefined;
564
+ theme?: string | undefined;
565
+ lineNumbers?: boolean | undefined;
566
+ maxRating?: number | undefined;
567
+ allowHalf?: boolean | undefined;
568
+ displayMap?: boolean | undefined;
569
+ allowGeocoding?: boolean | undefined;
570
+ addressFormat?: "us" | "uk" | "international" | undefined;
571
+ colorFormat?: "hex" | "rgb" | "rgba" | "hsl" | undefined;
572
+ allowAlpha?: boolean | undefined;
573
+ presetColors?: string[] | undefined;
574
+ step?: number | undefined;
575
+ showValue?: boolean | undefined;
576
+ marks?: Record<string, string> | undefined;
577
+ barcodeFormat?: "qr" | "ean13" | "ean8" | "code128" | "code39" | "upca" | "upce" | undefined;
578
+ qrErrorCorrection?: "L" | "M" | "Q" | "H" | undefined;
579
+ displayValue?: boolean | undefined;
580
+ allowScanning?: boolean | undefined;
581
+ currencyConfig?: {
582
+ precision: number;
583
+ currencyMode: "dynamic" | "fixed";
584
+ defaultCurrency: string;
585
+ } | undefined;
586
+ vectorConfig?: {
587
+ dimensions: number;
588
+ distanceMetric: "cosine" | "euclidean" | "dotProduct" | "manhattan";
589
+ normalized: boolean;
590
+ indexed: boolean;
591
+ indexType?: "hnsw" | "ivfflat" | "flat" | undefined;
592
+ } | undefined;
593
+ fileAttachmentConfig?: {
594
+ virusScan: boolean;
595
+ virusScanOnUpload: boolean;
596
+ quarantineOnThreat: boolean;
597
+ allowMultiple: boolean;
598
+ allowReplace: boolean;
599
+ allowDelete: boolean;
600
+ requireUpload: boolean;
601
+ extractMetadata: boolean;
602
+ extractText: boolean;
603
+ versioningEnabled: boolean;
604
+ publicRead: boolean;
605
+ presignedUrlExpiry: number;
606
+ minSize?: number | undefined;
607
+ maxSize?: number | undefined;
608
+ allowedTypes?: string[] | undefined;
609
+ blockedTypes?: string[] | undefined;
610
+ allowedMimeTypes?: string[] | undefined;
611
+ blockedMimeTypes?: string[] | undefined;
612
+ virusScanProvider?: "custom" | "clamav" | "virustotal" | "metadefender" | undefined;
613
+ storageProvider?: string | undefined;
614
+ storageBucket?: string | undefined;
615
+ storagePrefix?: string | undefined;
616
+ imageValidation?: {
617
+ generateThumbnails: boolean;
618
+ preserveMetadata: boolean;
619
+ autoRotate: boolean;
620
+ minWidth?: number | undefined;
621
+ maxWidth?: number | undefined;
622
+ minHeight?: number | undefined;
623
+ maxHeight?: number | undefined;
624
+ aspectRatio?: string | undefined;
625
+ thumbnailSizes?: {
626
+ name: string;
627
+ width: number;
628
+ height: number;
629
+ crop: boolean;
630
+ }[] | undefined;
631
+ } | undefined;
632
+ maxVersions?: number | undefined;
633
+ } | undefined;
634
+ encryptionConfig?: {
635
+ enabled: boolean;
636
+ algorithm: "aes-256-gcm" | "aes-256-cbc" | "chacha20-poly1305";
637
+ keyManagement: {
638
+ provider: "local" | "aws-kms" | "azure-key-vault" | "gcp-kms" | "hashicorp-vault";
639
+ keyId?: string | undefined;
640
+ rotationPolicy?: {
641
+ enabled: boolean;
642
+ frequencyDays: number;
643
+ retainOldVersions: number;
644
+ autoRotate: boolean;
645
+ } | undefined;
646
+ };
647
+ scope: "field" | "table" | "record" | "database";
648
+ deterministicEncryption: boolean;
649
+ searchableEncryption: boolean;
650
+ } | undefined;
651
+ maskingRule?: {
652
+ field: string;
653
+ strategy: "hash" | "redact" | "partial" | "tokenize" | "randomize" | "nullify" | "substitute";
654
+ preserveFormat: boolean;
655
+ preserveLength: boolean;
656
+ pattern?: string | undefined;
657
+ roles?: string[] | undefined;
658
+ exemptRoles?: string[] | undefined;
659
+ } | undefined;
660
+ dependencies?: string[] | undefined;
661
+ cached?: {
662
+ enabled: boolean;
663
+ ttl: number;
664
+ invalidateOn: string[];
665
+ } | undefined;
666
+ dataQuality?: {
667
+ uniqueness: boolean;
668
+ completeness: number;
669
+ accuracy?: {
670
+ source: string;
671
+ threshold: number;
672
+ } | undefined;
673
+ } | undefined;
674
+ group?: string | undefined;
675
+ conditionalRequired?: string | undefined;
676
+ inlineHelpText?: string | undefined;
677
+ trackFeedHistory?: boolean | undefined;
678
+ caseSensitive?: boolean | undefined;
679
+ autonumberFormat?: string | undefined;
680
+ }>;
681
+ label?: string | undefined;
682
+ pluralLabel?: string | undefined;
683
+ description?: string | undefined;
684
+ icon?: string | undefined;
685
+ tags?: string[] | undefined;
686
+ tableName?: string | undefined;
687
+ indexes?: {
688
+ fields: string[];
689
+ type: "hash" | "btree" | "gin" | "gist" | "fulltext";
690
+ unique: boolean;
691
+ name?: string | undefined;
692
+ partial?: string | undefined;
693
+ }[] | undefined;
694
+ tenancy?: {
695
+ enabled: boolean;
696
+ strategy: "shared" | "isolated" | "hybrid";
697
+ tenantField: string;
698
+ crossTenantAccess: boolean;
699
+ } | undefined;
700
+ softDelete?: {
701
+ enabled: boolean;
702
+ field: string;
703
+ cascadeDelete: boolean;
704
+ } | undefined;
705
+ versioning?: {
706
+ enabled: boolean;
707
+ strategy: "snapshot" | "delta" | "event-sourcing";
708
+ versionField: string;
709
+ retentionDays?: number | undefined;
710
+ } | undefined;
711
+ partitioning?: {
712
+ enabled: boolean;
713
+ strategy: "hash" | "range" | "list";
714
+ key: string;
715
+ interval?: string | undefined;
716
+ } | undefined;
717
+ cdc?: {
718
+ enabled: boolean;
719
+ events: ("update" | "delete" | "insert")[];
720
+ destination: string;
721
+ } | undefined;
722
+ validations?: _objectstack_spec_data.BaseValidationRuleShape[] | undefined;
723
+ stateMachines?: Record<string, {
724
+ id: string;
725
+ initial: string;
726
+ states: Record<string, StateNodeConfig>;
727
+ description?: string | undefined;
728
+ contextSchema?: Record<string, unknown> | undefined;
729
+ on?: Record<string, string | {
730
+ target?: string | undefined;
731
+ cond?: string | {
732
+ type: string;
733
+ params?: Record<string, unknown> | undefined;
734
+ } | undefined;
735
+ actions?: (string | {
736
+ type: string;
737
+ params?: Record<string, unknown> | undefined;
738
+ })[] | undefined;
739
+ description?: string | undefined;
740
+ } | {
741
+ target?: string | undefined;
742
+ cond?: string | {
743
+ type: string;
744
+ params?: Record<string, unknown> | undefined;
745
+ } | undefined;
746
+ actions?: (string | {
747
+ type: string;
748
+ params?: Record<string, unknown> | undefined;
749
+ })[] | undefined;
750
+ description?: string | undefined;
751
+ }[]> | undefined;
752
+ }> | undefined;
753
+ displayNameField?: string | undefined;
754
+ recordName?: {
755
+ type: "text" | "autonumber";
756
+ displayFormat?: string | undefined;
757
+ startNumber?: number | undefined;
758
+ } | undefined;
759
+ titleFormat?: string | undefined;
760
+ compactLayout?: string[] | undefined;
761
+ search?: {
762
+ fields: string[];
763
+ displayFields?: string[] | undefined;
764
+ filters?: string[] | undefined;
765
+ } | undefined;
766
+ enable?: {
767
+ trackHistory: boolean;
768
+ searchable: boolean;
769
+ apiEnabled: boolean;
770
+ files: boolean;
771
+ feeds: boolean;
772
+ activities: boolean;
773
+ trash: boolean;
774
+ mru: boolean;
775
+ clone: boolean;
776
+ apiMethods?: ("create" | "search" | "list" | "update" | "delete" | "upsert" | "history" | "get" | "bulk" | "aggregate" | "restore" | "purge" | "import" | "export")[] | undefined;
777
+ } | undefined;
778
+ recordTypes?: string[] | undefined;
779
+ sharingModel?: "full" | "private" | "read" | "read_write" | undefined;
780
+ keyPrefix?: string | undefined;
781
+ };
782
+
387
783
  /**
388
784
  * JSON Metadata Serializer
389
785
  *
@@ -439,4 +835,4 @@ declare class TypeScriptSerializer implements MetadataSerializer {
439
835
  getFormat(): MetadataFormat;
440
836
  }
441
837
 
442
- export { JSONSerializer, MemoryLoader, type MetadataLoader, MetadataManager, type MetadataManagerOptions, MetadataPlugin, type MetadataSerializer, index as Migration, RemoteLoader, type SerializeOptions, TypeScriptSerializer, type WatchCallback, YAMLSerializer };
838
+ export { DatabaseLoader, type DatabaseLoaderOptions, JSONSerializer, MemoryLoader, type MetadataLoader, MetadataManager, type MetadataManagerOptions, MetadataPlugin, type MetadataSerializer, index as Migration, RemoteLoader, type SerializeOptions, SysMetadataObject, TypeScriptSerializer, type WatchCallback, YAMLSerializer };