@objectstack/metadata 4.0.5 → 4.1.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/README.md +69 -2
- package/dist/index.cjs +374 -357
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -85
- package/dist/index.d.ts +120 -85
- package/dist/index.js +379 -364
- package/dist/index.js.map +1 -1
- package/dist/migrations/{migrate-env-id-to-project-id.cjs → index.cjs} +83 -11
- package/dist/migrations/index.cjs.map +1 -0
- package/dist/migrations/index.d.cts +103 -0
- package/dist/migrations/index.d.ts +103 -0
- package/dist/migrations/index.js +127 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/node.cjs +374 -357
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +379 -364
- package/dist/node.js.map +1 -1
- package/package.json +10 -10
- package/dist/migrations/migrate-env-id-to-project-id.cjs.map +0 -1
- package/dist/migrations/migrate-env-id-to-project-id.d.cts +0 -37
- package/dist/migrations/migrate-env-id-to-project-id.d.ts +0 -37
- package/dist/migrations/migrate-env-id-to-project-id.js +0 -59
- package/dist/migrations/migrate-env-id-to-project-id.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -156,6 +156,8 @@ declare class MetadataManager implements IMetadataService {
|
|
|
156
156
|
private overlays;
|
|
157
157
|
private typeRegistry;
|
|
158
158
|
private dependencies;
|
|
159
|
+
private listCache;
|
|
160
|
+
private static readonly LIST_CACHE_TTL_MS;
|
|
159
161
|
private realtimeService?;
|
|
160
162
|
constructor(config: MetadataManagerOptions);
|
|
161
163
|
/**
|
|
@@ -209,6 +211,9 @@ declare class MetadataManager implements IMetadataService {
|
|
|
209
211
|
* List all metadata items of a given type
|
|
210
212
|
*/
|
|
211
213
|
list(type: string): Promise<unknown[]>;
|
|
214
|
+
private cacheListResult;
|
|
215
|
+
/** Internal helper: drop the cached `list()` result for a type. */
|
|
216
|
+
private invalidateListCache;
|
|
212
217
|
/**
|
|
213
218
|
* Unregister/remove a metadata item by type and name.
|
|
214
219
|
* Deletes from database-backed loaders only (same rationale as register()).
|
|
@@ -425,14 +430,17 @@ interface MetadataPluginOptions {
|
|
|
425
430
|
artifactSource?: {
|
|
426
431
|
mode: 'local-file';
|
|
427
432
|
path: string;
|
|
433
|
+
fetchTimeoutMs?: number;
|
|
428
434
|
} | {
|
|
429
435
|
mode: 'artifact-api';
|
|
430
436
|
url: string;
|
|
437
|
+
token?: string;
|
|
438
|
+
commitId?: string;
|
|
439
|
+
fetchTimeoutMs?: number;
|
|
431
440
|
};
|
|
432
441
|
/**
|
|
433
|
-
* Register the
|
|
434
|
-
*
|
|
435
|
-
* kernel. Default `true` for backward compatibility.
|
|
442
|
+
* Register the `sys_metadata` + `sys_metadata_history` storage objects
|
|
443
|
+
* on this kernel. Default `true` for backward compatibility.
|
|
436
444
|
*
|
|
437
445
|
* Set to `false` for **per-project** kernels: in cloud / project mode the
|
|
438
446
|
* control plane is the sole owner of metadata storage tables — exposing
|
|
@@ -450,89 +458,21 @@ declare class MetadataPlugin implements Plugin {
|
|
|
450
458
|
constructor(options?: MetadataPluginOptions);
|
|
451
459
|
init: (ctx: PluginContext) => Promise<void>;
|
|
452
460
|
start: (ctx: PluginContext) => Promise<void>;
|
|
453
|
-
private _loadFromLocalFile;
|
|
454
|
-
private _loadFromFileSystem;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Metadata Projection Service
|
|
459
|
-
*
|
|
460
|
-
* Implements the dual-table architecture pattern:
|
|
461
|
-
* - sys_metadata: Source of truth for package management, versioning
|
|
462
|
-
* - Type-specific tables (sys_object, sys_view, etc.): Queryable projections
|
|
463
|
-
*
|
|
464
|
-
* When metadata is saved to sys_metadata, this service projects it into
|
|
465
|
-
* the appropriate type-specific table so Studio can query it via Object Protocol.
|
|
466
|
-
*/
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Configuration for the MetadataProjector
|
|
470
|
-
*/
|
|
471
|
-
interface MetadataProjectorOptions {
|
|
472
|
-
/** The IDataDriver instance to use for database operations */
|
|
473
|
-
driver?: IDataDriver;
|
|
474
|
-
/** The IDataEngine (ObjectQL) instance — preferred over raw driver */
|
|
475
|
-
engine?: IDataEngine;
|
|
476
|
-
/** Organization ID for multi-tenant isolation */
|
|
477
|
-
organizationId?: string;
|
|
478
|
-
/** Project ID — null = platform-global, set = project-scoped */
|
|
479
|
-
projectId?: string;
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* MetadataProjector
|
|
483
|
-
*
|
|
484
|
-
* Handles projection from sys_metadata to type-specific tables.
|
|
485
|
-
*/
|
|
486
|
-
declare class MetadataProjector {
|
|
487
|
-
private driver?;
|
|
488
|
-
private engine?;
|
|
489
|
-
/** Reserved for future multi-tenant projection scoping */
|
|
490
|
-
readonly scope: {
|
|
491
|
-
organizationId?: string;
|
|
492
|
-
projectId?: string;
|
|
493
|
-
};
|
|
494
|
-
private readonly typeTableMap;
|
|
495
|
-
constructor(options: MetadataProjectorOptions);
|
|
496
|
-
/**
|
|
497
|
-
* Project metadata to type-specific table
|
|
498
|
-
*/
|
|
499
|
-
project(type: string, name: string, data: any): Promise<void>;
|
|
500
|
-
/**
|
|
501
|
-
* Delete projection from type-specific table
|
|
502
|
-
*/
|
|
503
|
-
deleteProjection(type: string, name: string): Promise<void>;
|
|
504
461
|
/**
|
|
505
|
-
*
|
|
462
|
+
* Fetch JSON content from a URL with configurable timeout.
|
|
506
463
|
*/
|
|
507
|
-
private
|
|
464
|
+
private _fetchJson;
|
|
508
465
|
/**
|
|
509
|
-
*
|
|
466
|
+
* Parse raw artifact JSON (envelope or bare definition) and register all
|
|
467
|
+
* metadata items into the MetadataManager.
|
|
510
468
|
*/
|
|
511
|
-
private
|
|
512
|
-
|
|
513
|
-
* Project view metadata to sys_view
|
|
514
|
-
*/
|
|
515
|
-
private projectView;
|
|
516
|
-
/**
|
|
517
|
-
* Project agent metadata to sys_agent
|
|
518
|
-
*/
|
|
519
|
-
private projectAgent;
|
|
520
|
-
/**
|
|
521
|
-
* Project tool metadata to sys_tool
|
|
522
|
-
*/
|
|
523
|
-
private projectTool;
|
|
524
|
-
/**
|
|
525
|
-
* Project flow metadata to sys_flow
|
|
526
|
-
*/
|
|
527
|
-
private projectFlow;
|
|
528
|
-
private _findOne;
|
|
529
|
-
private _create;
|
|
530
|
-
private _update;
|
|
531
|
-
private _delete;
|
|
469
|
+
private _parseAndRegisterArtifact;
|
|
470
|
+
private _loadFromLocalFile;
|
|
532
471
|
/**
|
|
533
|
-
*
|
|
472
|
+
* P2: Load metadata from the cloud artifact API endpoint.
|
|
534
473
|
*/
|
|
535
|
-
private
|
|
474
|
+
private _loadFromArtifactApi;
|
|
475
|
+
private _loadFromFileSystem;
|
|
536
476
|
}
|
|
537
477
|
|
|
538
478
|
/**
|
|
@@ -578,6 +518,52 @@ declare class RemoteLoader implements MetadataLoader {
|
|
|
578
518
|
save(type: string, name: string, data: any, _options?: MetadataSaveOptions): Promise<MetadataSaveResult>;
|
|
579
519
|
}
|
|
580
520
|
|
|
521
|
+
/**
|
|
522
|
+
* Generic LRU (Least Recently Used) cache with optional TTL.
|
|
523
|
+
*
|
|
524
|
+
* Implementation notes:
|
|
525
|
+
* - Backed by a `Map`, which preserves insertion order. We promote entries on
|
|
526
|
+
* read by deleting and re-inserting, so the oldest entry is always
|
|
527
|
+
* `map.keys().next()`.
|
|
528
|
+
* - TTL is checked lazily on `get` / `has`. Expired entries are evicted on
|
|
529
|
+
* access; we do not run a background sweeper to keep the implementation
|
|
530
|
+
* side-effect free in serverless / edge runtimes.
|
|
531
|
+
* - Set `maxSize <= 0` to disable the size cap; set `ttl <= 0` (or omit) to
|
|
532
|
+
* disable expiration.
|
|
533
|
+
*
|
|
534
|
+
* Designed for `DatabaseLoader` read-path caching — see
|
|
535
|
+
* `packages/metadata/src/loaders/database-loader.ts`.
|
|
536
|
+
*/
|
|
537
|
+
interface LRUCacheOptions {
|
|
538
|
+
/** Maximum number of entries; when exceeded, the LRU entry is evicted. */
|
|
539
|
+
maxSize?: number;
|
|
540
|
+
/** Time-to-live in milliseconds. Zero or undefined disables TTL. */
|
|
541
|
+
ttl?: number;
|
|
542
|
+
}
|
|
543
|
+
declare class LRUCache<K, V> {
|
|
544
|
+
private readonly map;
|
|
545
|
+
private readonly maxSize;
|
|
546
|
+
private readonly ttl;
|
|
547
|
+
private hits;
|
|
548
|
+
private misses;
|
|
549
|
+
constructor(options?: LRUCacheOptions);
|
|
550
|
+
get(key: K): V | undefined;
|
|
551
|
+
set(key: K, value: V): void;
|
|
552
|
+
has(key: K): boolean;
|
|
553
|
+
delete(key: K): boolean;
|
|
554
|
+
clear(): void;
|
|
555
|
+
get size(): number;
|
|
556
|
+
/** Diagnostic counters — useful for `metrics` endpoints. */
|
|
557
|
+
stats(): {
|
|
558
|
+
size: number;
|
|
559
|
+
hits: number;
|
|
560
|
+
misses: number;
|
|
561
|
+
hitRate: number;
|
|
562
|
+
};
|
|
563
|
+
/** Resets hit/miss counters without dropping cached entries. */
|
|
564
|
+
resetStats(): void;
|
|
565
|
+
}
|
|
566
|
+
|
|
581
567
|
/**
|
|
582
568
|
* Database Metadata Loader
|
|
583
569
|
*
|
|
@@ -587,6 +573,28 @@ declare class RemoteLoader implements MetadataLoader {
|
|
|
587
573
|
* MetadataRecordSchema envelope defined in @objectstack/spec.
|
|
588
574
|
*/
|
|
589
575
|
|
|
576
|
+
/**
|
|
577
|
+
* Cache configuration for `DatabaseLoader`.
|
|
578
|
+
*
|
|
579
|
+
* The cache sits in front of `load()`, `loadMany()`, `exists()`, `stat()`,
|
|
580
|
+
* and `list()` so that hot read paths (REST `/meta/*`, ObjectQL plan
|
|
581
|
+
* resolution, runtime overlay merges) do not hit the database on every
|
|
582
|
+
* request. All write paths (`save`, `delete`, `registerRollback`) invalidate
|
|
583
|
+
* the relevant entries.
|
|
584
|
+
*
|
|
585
|
+
* Defaults are conservative: 500 entries, 60s TTL — chosen so that single-
|
|
586
|
+
* tenant Studio usage does not burn memory and so that an external write
|
|
587
|
+
* (out-of-band SQL update) becomes visible within a minute even without
|
|
588
|
+
* realtime invalidation.
|
|
589
|
+
*/
|
|
590
|
+
interface DatabaseLoaderCacheOptions {
|
|
591
|
+
/** Whether the cache is active. Default: `true`. */
|
|
592
|
+
enabled?: boolean;
|
|
593
|
+
/** Max number of cached `(type, name)` entries. Default: `500`. */
|
|
594
|
+
maxSize?: number;
|
|
595
|
+
/** TTL in milliseconds. Set to `0` to disable expiry. Default: `60_000`. */
|
|
596
|
+
ttl?: number;
|
|
597
|
+
}
|
|
590
598
|
/**
|
|
591
599
|
* Configuration for the DatabaseLoader.
|
|
592
600
|
*
|
|
@@ -610,8 +618,12 @@ interface DatabaseLoaderOptions {
|
|
|
610
618
|
projectId?: string;
|
|
611
619
|
/** Enable history tracking (default: true) */
|
|
612
620
|
trackHistory?: boolean;
|
|
613
|
-
/**
|
|
614
|
-
|
|
621
|
+
/**
|
|
622
|
+
* Read-through cache configuration. Pass `{ enabled: false }` to disable
|
|
623
|
+
* caching outright (useful in tests or when the caller wants the loader to
|
|
624
|
+
* always read fresh from the database).
|
|
625
|
+
*/
|
|
626
|
+
cache?: DatabaseLoaderCacheOptions;
|
|
615
627
|
}
|
|
616
628
|
/**
|
|
617
629
|
* DatabaseLoader — Datasource-backed metadata persistence.
|
|
@@ -631,9 +643,32 @@ declare class DatabaseLoader implements MetadataLoader {
|
|
|
631
643
|
private trackHistory;
|
|
632
644
|
private schemaReady;
|
|
633
645
|
private historySchemaReady;
|
|
634
|
-
|
|
635
|
-
private
|
|
646
|
+
/** (type, name) → metadata payload — primes `load()` */
|
|
647
|
+
private readonly loadCache?;
|
|
648
|
+
/** type → array of payloads — primes `loadMany()` */
|
|
649
|
+
private readonly loadManyCache?;
|
|
650
|
+
/** type → list of names — primes `list()` */
|
|
651
|
+
private readonly listCache?;
|
|
652
|
+
/** (type, name) → MetadataStats — primes `stat()` */
|
|
653
|
+
private readonly statCache?;
|
|
636
654
|
constructor(options: DatabaseLoaderOptions);
|
|
655
|
+
private cacheKey;
|
|
656
|
+
/**
|
|
657
|
+
* Invalidate all cached entries for a specific (type, name) pair plus
|
|
658
|
+
* the type-level aggregates (`loadMany`, `list`). Called from every write
|
|
659
|
+
* path (`save`, `delete`, `registerRollback`).
|
|
660
|
+
*/
|
|
661
|
+
private invalidate;
|
|
662
|
+
/** Drop the entire cache — useful after bulk imports or schema changes. */
|
|
663
|
+
invalidateAll(): void;
|
|
664
|
+
/** Diagnostic: aggregated cache statistics for `metrics` endpoints. */
|
|
665
|
+
getCacheStats(): {
|
|
666
|
+
enabled: boolean;
|
|
667
|
+
load: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
668
|
+
loadMany: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
669
|
+
list: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
670
|
+
stat: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
671
|
+
};
|
|
637
672
|
private _find;
|
|
638
673
|
private _findOne;
|
|
639
674
|
private _count;
|
|
@@ -887,4 +922,4 @@ declare class TypeScriptSerializer implements MetadataSerializer {
|
|
|
887
922
|
getFormat(): MetadataFormat;
|
|
888
923
|
}
|
|
889
924
|
|
|
890
|
-
export { DatabaseLoader, type DatabaseLoaderOptions, HistoryCleanupManager, JSONSerializer, MemoryLoader, type MetadataLoader, MetadataManager, type MetadataManagerOptions, MetadataPlugin,
|
|
925
|
+
export { DatabaseLoader, type DatabaseLoaderOptions, HistoryCleanupManager, JSONSerializer, MemoryLoader, type MetadataLoader, MetadataManager, type MetadataManagerOptions, MetadataPlugin, type MetadataSerializer, index as Migration, RemoteLoader, type SerializeOptions, TypeScriptSerializer, type WatchCallback, YAMLSerializer, calculateChecksum, generateDiffSummary, generateSimpleDiff, registerMetadataHistoryRoutes };
|
package/dist/index.d.ts
CHANGED
|
@@ -156,6 +156,8 @@ declare class MetadataManager implements IMetadataService {
|
|
|
156
156
|
private overlays;
|
|
157
157
|
private typeRegistry;
|
|
158
158
|
private dependencies;
|
|
159
|
+
private listCache;
|
|
160
|
+
private static readonly LIST_CACHE_TTL_MS;
|
|
159
161
|
private realtimeService?;
|
|
160
162
|
constructor(config: MetadataManagerOptions);
|
|
161
163
|
/**
|
|
@@ -209,6 +211,9 @@ declare class MetadataManager implements IMetadataService {
|
|
|
209
211
|
* List all metadata items of a given type
|
|
210
212
|
*/
|
|
211
213
|
list(type: string): Promise<unknown[]>;
|
|
214
|
+
private cacheListResult;
|
|
215
|
+
/** Internal helper: drop the cached `list()` result for a type. */
|
|
216
|
+
private invalidateListCache;
|
|
212
217
|
/**
|
|
213
218
|
* Unregister/remove a metadata item by type and name.
|
|
214
219
|
* Deletes from database-backed loaders only (same rationale as register()).
|
|
@@ -425,14 +430,17 @@ interface MetadataPluginOptions {
|
|
|
425
430
|
artifactSource?: {
|
|
426
431
|
mode: 'local-file';
|
|
427
432
|
path: string;
|
|
433
|
+
fetchTimeoutMs?: number;
|
|
428
434
|
} | {
|
|
429
435
|
mode: 'artifact-api';
|
|
430
436
|
url: string;
|
|
437
|
+
token?: string;
|
|
438
|
+
commitId?: string;
|
|
439
|
+
fetchTimeoutMs?: number;
|
|
431
440
|
};
|
|
432
441
|
/**
|
|
433
|
-
* Register the
|
|
434
|
-
*
|
|
435
|
-
* kernel. Default `true` for backward compatibility.
|
|
442
|
+
* Register the `sys_metadata` + `sys_metadata_history` storage objects
|
|
443
|
+
* on this kernel. Default `true` for backward compatibility.
|
|
436
444
|
*
|
|
437
445
|
* Set to `false` for **per-project** kernels: in cloud / project mode the
|
|
438
446
|
* control plane is the sole owner of metadata storage tables — exposing
|
|
@@ -450,89 +458,21 @@ declare class MetadataPlugin implements Plugin {
|
|
|
450
458
|
constructor(options?: MetadataPluginOptions);
|
|
451
459
|
init: (ctx: PluginContext) => Promise<void>;
|
|
452
460
|
start: (ctx: PluginContext) => Promise<void>;
|
|
453
|
-
private _loadFromLocalFile;
|
|
454
|
-
private _loadFromFileSystem;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Metadata Projection Service
|
|
459
|
-
*
|
|
460
|
-
* Implements the dual-table architecture pattern:
|
|
461
|
-
* - sys_metadata: Source of truth for package management, versioning
|
|
462
|
-
* - Type-specific tables (sys_object, sys_view, etc.): Queryable projections
|
|
463
|
-
*
|
|
464
|
-
* When metadata is saved to sys_metadata, this service projects it into
|
|
465
|
-
* the appropriate type-specific table so Studio can query it via Object Protocol.
|
|
466
|
-
*/
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Configuration for the MetadataProjector
|
|
470
|
-
*/
|
|
471
|
-
interface MetadataProjectorOptions {
|
|
472
|
-
/** The IDataDriver instance to use for database operations */
|
|
473
|
-
driver?: IDataDriver;
|
|
474
|
-
/** The IDataEngine (ObjectQL) instance — preferred over raw driver */
|
|
475
|
-
engine?: IDataEngine;
|
|
476
|
-
/** Organization ID for multi-tenant isolation */
|
|
477
|
-
organizationId?: string;
|
|
478
|
-
/** Project ID — null = platform-global, set = project-scoped */
|
|
479
|
-
projectId?: string;
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* MetadataProjector
|
|
483
|
-
*
|
|
484
|
-
* Handles projection from sys_metadata to type-specific tables.
|
|
485
|
-
*/
|
|
486
|
-
declare class MetadataProjector {
|
|
487
|
-
private driver?;
|
|
488
|
-
private engine?;
|
|
489
|
-
/** Reserved for future multi-tenant projection scoping */
|
|
490
|
-
readonly scope: {
|
|
491
|
-
organizationId?: string;
|
|
492
|
-
projectId?: string;
|
|
493
|
-
};
|
|
494
|
-
private readonly typeTableMap;
|
|
495
|
-
constructor(options: MetadataProjectorOptions);
|
|
496
|
-
/**
|
|
497
|
-
* Project metadata to type-specific table
|
|
498
|
-
*/
|
|
499
|
-
project(type: string, name: string, data: any): Promise<void>;
|
|
500
|
-
/**
|
|
501
|
-
* Delete projection from type-specific table
|
|
502
|
-
*/
|
|
503
|
-
deleteProjection(type: string, name: string): Promise<void>;
|
|
504
461
|
/**
|
|
505
|
-
*
|
|
462
|
+
* Fetch JSON content from a URL with configurable timeout.
|
|
506
463
|
*/
|
|
507
|
-
private
|
|
464
|
+
private _fetchJson;
|
|
508
465
|
/**
|
|
509
|
-
*
|
|
466
|
+
* Parse raw artifact JSON (envelope or bare definition) and register all
|
|
467
|
+
* metadata items into the MetadataManager.
|
|
510
468
|
*/
|
|
511
|
-
private
|
|
512
|
-
|
|
513
|
-
* Project view metadata to sys_view
|
|
514
|
-
*/
|
|
515
|
-
private projectView;
|
|
516
|
-
/**
|
|
517
|
-
* Project agent metadata to sys_agent
|
|
518
|
-
*/
|
|
519
|
-
private projectAgent;
|
|
520
|
-
/**
|
|
521
|
-
* Project tool metadata to sys_tool
|
|
522
|
-
*/
|
|
523
|
-
private projectTool;
|
|
524
|
-
/**
|
|
525
|
-
* Project flow metadata to sys_flow
|
|
526
|
-
*/
|
|
527
|
-
private projectFlow;
|
|
528
|
-
private _findOne;
|
|
529
|
-
private _create;
|
|
530
|
-
private _update;
|
|
531
|
-
private _delete;
|
|
469
|
+
private _parseAndRegisterArtifact;
|
|
470
|
+
private _loadFromLocalFile;
|
|
532
471
|
/**
|
|
533
|
-
*
|
|
472
|
+
* P2: Load metadata from the cloud artifact API endpoint.
|
|
534
473
|
*/
|
|
535
|
-
private
|
|
474
|
+
private _loadFromArtifactApi;
|
|
475
|
+
private _loadFromFileSystem;
|
|
536
476
|
}
|
|
537
477
|
|
|
538
478
|
/**
|
|
@@ -578,6 +518,52 @@ declare class RemoteLoader implements MetadataLoader {
|
|
|
578
518
|
save(type: string, name: string, data: any, _options?: MetadataSaveOptions): Promise<MetadataSaveResult>;
|
|
579
519
|
}
|
|
580
520
|
|
|
521
|
+
/**
|
|
522
|
+
* Generic LRU (Least Recently Used) cache with optional TTL.
|
|
523
|
+
*
|
|
524
|
+
* Implementation notes:
|
|
525
|
+
* - Backed by a `Map`, which preserves insertion order. We promote entries on
|
|
526
|
+
* read by deleting and re-inserting, so the oldest entry is always
|
|
527
|
+
* `map.keys().next()`.
|
|
528
|
+
* - TTL is checked lazily on `get` / `has`. Expired entries are evicted on
|
|
529
|
+
* access; we do not run a background sweeper to keep the implementation
|
|
530
|
+
* side-effect free in serverless / edge runtimes.
|
|
531
|
+
* - Set `maxSize <= 0` to disable the size cap; set `ttl <= 0` (or omit) to
|
|
532
|
+
* disable expiration.
|
|
533
|
+
*
|
|
534
|
+
* Designed for `DatabaseLoader` read-path caching — see
|
|
535
|
+
* `packages/metadata/src/loaders/database-loader.ts`.
|
|
536
|
+
*/
|
|
537
|
+
interface LRUCacheOptions {
|
|
538
|
+
/** Maximum number of entries; when exceeded, the LRU entry is evicted. */
|
|
539
|
+
maxSize?: number;
|
|
540
|
+
/** Time-to-live in milliseconds. Zero or undefined disables TTL. */
|
|
541
|
+
ttl?: number;
|
|
542
|
+
}
|
|
543
|
+
declare class LRUCache<K, V> {
|
|
544
|
+
private readonly map;
|
|
545
|
+
private readonly maxSize;
|
|
546
|
+
private readonly ttl;
|
|
547
|
+
private hits;
|
|
548
|
+
private misses;
|
|
549
|
+
constructor(options?: LRUCacheOptions);
|
|
550
|
+
get(key: K): V | undefined;
|
|
551
|
+
set(key: K, value: V): void;
|
|
552
|
+
has(key: K): boolean;
|
|
553
|
+
delete(key: K): boolean;
|
|
554
|
+
clear(): void;
|
|
555
|
+
get size(): number;
|
|
556
|
+
/** Diagnostic counters — useful for `metrics` endpoints. */
|
|
557
|
+
stats(): {
|
|
558
|
+
size: number;
|
|
559
|
+
hits: number;
|
|
560
|
+
misses: number;
|
|
561
|
+
hitRate: number;
|
|
562
|
+
};
|
|
563
|
+
/** Resets hit/miss counters without dropping cached entries. */
|
|
564
|
+
resetStats(): void;
|
|
565
|
+
}
|
|
566
|
+
|
|
581
567
|
/**
|
|
582
568
|
* Database Metadata Loader
|
|
583
569
|
*
|
|
@@ -587,6 +573,28 @@ declare class RemoteLoader implements MetadataLoader {
|
|
|
587
573
|
* MetadataRecordSchema envelope defined in @objectstack/spec.
|
|
588
574
|
*/
|
|
589
575
|
|
|
576
|
+
/**
|
|
577
|
+
* Cache configuration for `DatabaseLoader`.
|
|
578
|
+
*
|
|
579
|
+
* The cache sits in front of `load()`, `loadMany()`, `exists()`, `stat()`,
|
|
580
|
+
* and `list()` so that hot read paths (REST `/meta/*`, ObjectQL plan
|
|
581
|
+
* resolution, runtime overlay merges) do not hit the database on every
|
|
582
|
+
* request. All write paths (`save`, `delete`, `registerRollback`) invalidate
|
|
583
|
+
* the relevant entries.
|
|
584
|
+
*
|
|
585
|
+
* Defaults are conservative: 500 entries, 60s TTL — chosen so that single-
|
|
586
|
+
* tenant Studio usage does not burn memory and so that an external write
|
|
587
|
+
* (out-of-band SQL update) becomes visible within a minute even without
|
|
588
|
+
* realtime invalidation.
|
|
589
|
+
*/
|
|
590
|
+
interface DatabaseLoaderCacheOptions {
|
|
591
|
+
/** Whether the cache is active. Default: `true`. */
|
|
592
|
+
enabled?: boolean;
|
|
593
|
+
/** Max number of cached `(type, name)` entries. Default: `500`. */
|
|
594
|
+
maxSize?: number;
|
|
595
|
+
/** TTL in milliseconds. Set to `0` to disable expiry. Default: `60_000`. */
|
|
596
|
+
ttl?: number;
|
|
597
|
+
}
|
|
590
598
|
/**
|
|
591
599
|
* Configuration for the DatabaseLoader.
|
|
592
600
|
*
|
|
@@ -610,8 +618,12 @@ interface DatabaseLoaderOptions {
|
|
|
610
618
|
projectId?: string;
|
|
611
619
|
/** Enable history tracking (default: true) */
|
|
612
620
|
trackHistory?: boolean;
|
|
613
|
-
/**
|
|
614
|
-
|
|
621
|
+
/**
|
|
622
|
+
* Read-through cache configuration. Pass `{ enabled: false }` to disable
|
|
623
|
+
* caching outright (useful in tests or when the caller wants the loader to
|
|
624
|
+
* always read fresh from the database).
|
|
625
|
+
*/
|
|
626
|
+
cache?: DatabaseLoaderCacheOptions;
|
|
615
627
|
}
|
|
616
628
|
/**
|
|
617
629
|
* DatabaseLoader — Datasource-backed metadata persistence.
|
|
@@ -631,9 +643,32 @@ declare class DatabaseLoader implements MetadataLoader {
|
|
|
631
643
|
private trackHistory;
|
|
632
644
|
private schemaReady;
|
|
633
645
|
private historySchemaReady;
|
|
634
|
-
|
|
635
|
-
private
|
|
646
|
+
/** (type, name) → metadata payload — primes `load()` */
|
|
647
|
+
private readonly loadCache?;
|
|
648
|
+
/** type → array of payloads — primes `loadMany()` */
|
|
649
|
+
private readonly loadManyCache?;
|
|
650
|
+
/** type → list of names — primes `list()` */
|
|
651
|
+
private readonly listCache?;
|
|
652
|
+
/** (type, name) → MetadataStats — primes `stat()` */
|
|
653
|
+
private readonly statCache?;
|
|
636
654
|
constructor(options: DatabaseLoaderOptions);
|
|
655
|
+
private cacheKey;
|
|
656
|
+
/**
|
|
657
|
+
* Invalidate all cached entries for a specific (type, name) pair plus
|
|
658
|
+
* the type-level aggregates (`loadMany`, `list`). Called from every write
|
|
659
|
+
* path (`save`, `delete`, `registerRollback`).
|
|
660
|
+
*/
|
|
661
|
+
private invalidate;
|
|
662
|
+
/** Drop the entire cache — useful after bulk imports or schema changes. */
|
|
663
|
+
invalidateAll(): void;
|
|
664
|
+
/** Diagnostic: aggregated cache statistics for `metrics` endpoints. */
|
|
665
|
+
getCacheStats(): {
|
|
666
|
+
enabled: boolean;
|
|
667
|
+
load: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
668
|
+
loadMany: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
669
|
+
list: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
670
|
+
stat: ReturnType<LRUCache<string, unknown>['stats']> | null;
|
|
671
|
+
};
|
|
637
672
|
private _find;
|
|
638
673
|
private _findOne;
|
|
639
674
|
private _count;
|
|
@@ -887,4 +922,4 @@ declare class TypeScriptSerializer implements MetadataSerializer {
|
|
|
887
922
|
getFormat(): MetadataFormat;
|
|
888
923
|
}
|
|
889
924
|
|
|
890
|
-
export { DatabaseLoader, type DatabaseLoaderOptions, HistoryCleanupManager, JSONSerializer, MemoryLoader, type MetadataLoader, MetadataManager, type MetadataManagerOptions, MetadataPlugin,
|
|
925
|
+
export { DatabaseLoader, type DatabaseLoaderOptions, HistoryCleanupManager, JSONSerializer, MemoryLoader, type MetadataLoader, MetadataManager, type MetadataManagerOptions, MetadataPlugin, type MetadataSerializer, index as Migration, RemoteLoader, type SerializeOptions, TypeScriptSerializer, type WatchCallback, YAMLSerializer, calculateChecksum, generateDiffSummary, generateSimpleDiff, registerMetadataHistoryRoutes };
|