@objectstack/metadata 4.2.0 → 5.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/dist/index.d.cts CHANGED
@@ -7,6 +7,8 @@ import { MetadataTypeRegistryEntry, MetadataQuery, MetadataQueryResult, Metadata
7
7
  export { MetadataBulkResult, MetadataDependency, MetadataPluginConfig, MetadataPluginManifest, MetadataQuery, MetadataQueryResult, MetadataType, MetadataTypeRegistryEntry, MetadataValidationResult } from '@objectstack/spec/kernel';
8
8
  import { Logger, Plugin, PluginContext } from '@objectstack/core';
9
9
  import { z } from 'zod';
10
+ import { MetadataRepository } from '@objectstack/metadata-core';
11
+ export { HistoryOptions, MetaRef, MetadataEvent, MetadataItem, MetadataItemHeader, MetadataRepository, WatchFilter } from '@objectstack/metadata-core';
10
12
  export { SysMetadataHistoryObject, SysMetadataObject } from '@objectstack/platform-objects/metadata';
11
13
 
12
14
  /**
@@ -159,6 +161,9 @@ declare class MetadataManager implements IMetadataService {
159
161
  private listCache;
160
162
  private static readonly LIST_CACHE_TTL_MS;
161
163
  private realtimeService?;
164
+ protected repository?: MetadataRepository;
165
+ private repoWatchIter?;
166
+ private repoWatchClosed;
162
167
  constructor(config: MetadataManagerOptions);
163
168
  /**
164
169
  * Set the type registry for metadata type discovery.
@@ -400,6 +405,34 @@ declare class MetadataManager implements IMetadataService {
400
405
  * Stop all watching
401
406
  */
402
407
  stopWatching(): Promise<void>;
408
+ /**
409
+ * Attach a {@link MetadataRepository} as a supplementary event source.
410
+ *
411
+ * The manager subscribes to `repo.watch({})` and re-emits each event
412
+ * through {@link notifyWatchers} as a legacy `MetadataWatchEvent`.
413
+ * Each event also invalidates the in-memory registry entry and the
414
+ * `list()` cache for the affected type so subsequent reads see fresh
415
+ * data.
416
+ *
417
+ * No write-through. `register()` / `unregister()` / `save()` are
418
+ * untouched in this PR (deferred to ADR-0008 M0 PR-10).
419
+ *
420
+ * Call {@link dispose} (or {@link stopRepositoryWatch}) to detach.
421
+ */
422
+ setRepository(repo: MetadataRepository): void;
423
+ /** Return the attached repository, if any. */
424
+ getRepository(): MetadataRepository | undefined;
425
+ /** Stop the active repo.watch() loop (best-effort). */
426
+ stopRepositoryWatch(): Promise<void>;
427
+ /**
428
+ * Best-effort cleanup. Stops the FS watcher (if any), drains the
429
+ * repository watch loop, and clears registry caches. Safe to call
430
+ * multiple times.
431
+ */
432
+ dispose(): Promise<void>;
433
+ private startRepositoryWatch;
434
+ /** Translate a repo event to the legacy MetadataWatchEvent + invalidate caches. */
435
+ private applyRepoEvent;
403
436
  protected notifyWatchers(type: string, event: MetadataWatchEvent): void;
404
437
  /**
405
438
  * Get the database loader for history operations.
@@ -428,7 +461,30 @@ declare class MetadataManager implements IMetadataService {
428
461
 
429
462
  interface MetadataPluginOptions {
430
463
  rootDir?: string;
464
+ /**
465
+ * When `true`, NodeMetadataManager scans `rootDir` for source-file metadata
466
+ * (yaml/json/ts/js loaders) AND attaches a chokidar watcher to react to
467
+ * filesystem changes. In **artifact-mode** (this is the normal path when
468
+ * a `defineStack()` config is compiled into `dist/objectstack.json`) this
469
+ * filesystem scan is redundant and expensive — leave `watch: false`.
470
+ *
471
+ * The artifact-file HMR watcher is controlled separately by
472
+ * {@link artifactWatch} so that the cheap, single-file polling watcher
473
+ * can be enabled in dev without paying the cost of scanning the entire
474
+ * project root.
475
+ *
476
+ * Default: `false` (post PR-10e — was previously `true`).
477
+ */
431
478
  watch?: boolean;
479
+ /**
480
+ * When `true` AND `artifactSource.mode === 'local-file'`, attach a
481
+ * polling chokidar watcher to the artifact file so the server reloads
482
+ * metadata when the CLI recompiles `dist/objectstack.json` in dev mode.
483
+ * Independent of {@link watch} (which controls the source-file scanner).
484
+ *
485
+ * Default: `true` when `artifactSource` is set, otherwise `false`.
486
+ */
487
+ artifactWatch?: boolean;
432
488
  config?: Partial<MetadataPluginConfig>;
433
489
  /** Organization ID for metadata-scoped consumers; MetadataPlugin itself does not persist runtime metadata. */
434
490
  organizationId?: string;
@@ -467,9 +523,13 @@ declare class MetadataPlugin implements Plugin {
467
523
  version: string;
468
524
  private manager;
469
525
  private options;
526
+ private repository?;
527
+ /** Chokidar watcher on the artifact file (local-file mode) — ADR-0008 PR-8. */
528
+ private artifactWatcher?;
470
529
  constructor(options?: MetadataPluginOptions);
471
530
  init: (ctx: PluginContext) => Promise<void>;
472
531
  start: (ctx: PluginContext) => Promise<void>;
532
+ stop: (ctx: PluginContext) => Promise<void>;
473
533
  /**
474
534
  * Fetch JSON content from a URL with configurable timeout.
475
535
  */
@@ -626,7 +686,13 @@ interface DatabaseLoaderOptions {
626
686
  historyTableName?: string;
627
687
  /** Organization ID for multi-tenant isolation */
628
688
  organizationId?: string;
629
- /** Project ID — null = platform-global, set = project-scoped */
689
+ /**
690
+ * @deprecated since ADR-0008 §0 amendment (branch/project removal).
691
+ * The metadata layer is keyed by organization only. This option is
692
+ * accepted for back-compat but ignored — writes do not set
693
+ * `project_id` and filters do not constrain on it. Will be removed
694
+ * in the next major release.
695
+ */
630
696
  projectId?: string;
631
697
  /** Enable history tracking (default: true) */
632
698
  trackHistory?: boolean;
@@ -651,7 +717,6 @@ declare class DatabaseLoader implements MetadataLoader {
651
717
  private tableName;
652
718
  private historyTableName;
653
719
  private organizationId?;
654
- private projectId?;
655
720
  private trackHistory;
656
721
  private schemaReady;
657
722
  private historySchemaReady;
@@ -687,6 +752,13 @@ declare class DatabaseLoader implements MetadataLoader {
687
752
  private _create;
688
753
  private _update;
689
754
  private _delete;
755
+ /**
756
+ * Compute the next per-org `event_seq` for `sys_metadata_history`.
757
+ * Reads `MAX(event_seq) + 1` for the configured `organization_id`.
758
+ * Legacy path — not transactional, so concurrent writes can collide.
759
+ * The canonical (transactional) producer is `SysMetadataRepository`.
760
+ */
761
+ private nextEventSeq;
690
762
  /**
691
763
  * Ensure the metadata table exists.
692
764
  * Uses IDataDriver.syncSchema with the SysMetadataObject definition
@@ -700,14 +772,14 @@ declare class DatabaseLoader implements MetadataLoader {
700
772
  private ensureHistorySchema;
701
773
  /**
702
774
  * Build base filter conditions for queries.
703
- * Filters by organizationId when configured; project_id when projectId is set,
704
- * or null (platform-global) when not set.
775
+ * Filters by organizationId when configured. `projectId` is accepted
776
+ * for back-compat but no longer constrains the query — see
777
+ * ADR-0008 §0 (branch/project removal).
705
778
  */
706
779
  private baseFilter;
707
780
  /**
708
781
  * Create a history record for a metadata change.
709
782
  *
710
- * @param metadataId - The metadata record ID
711
783
  * @param type - Metadata type
712
784
  * @param name - Metadata name
713
785
  * @param version - Version number
package/dist/index.d.ts CHANGED
@@ -7,6 +7,8 @@ import { MetadataTypeRegistryEntry, MetadataQuery, MetadataQueryResult, Metadata
7
7
  export { MetadataBulkResult, MetadataDependency, MetadataPluginConfig, MetadataPluginManifest, MetadataQuery, MetadataQueryResult, MetadataType, MetadataTypeRegistryEntry, MetadataValidationResult } from '@objectstack/spec/kernel';
8
8
  import { Logger, Plugin, PluginContext } from '@objectstack/core';
9
9
  import { z } from 'zod';
10
+ import { MetadataRepository } from '@objectstack/metadata-core';
11
+ export { HistoryOptions, MetaRef, MetadataEvent, MetadataItem, MetadataItemHeader, MetadataRepository, WatchFilter } from '@objectstack/metadata-core';
10
12
  export { SysMetadataHistoryObject, SysMetadataObject } from '@objectstack/platform-objects/metadata';
11
13
 
12
14
  /**
@@ -159,6 +161,9 @@ declare class MetadataManager implements IMetadataService {
159
161
  private listCache;
160
162
  private static readonly LIST_CACHE_TTL_MS;
161
163
  private realtimeService?;
164
+ protected repository?: MetadataRepository;
165
+ private repoWatchIter?;
166
+ private repoWatchClosed;
162
167
  constructor(config: MetadataManagerOptions);
163
168
  /**
164
169
  * Set the type registry for metadata type discovery.
@@ -400,6 +405,34 @@ declare class MetadataManager implements IMetadataService {
400
405
  * Stop all watching
401
406
  */
402
407
  stopWatching(): Promise<void>;
408
+ /**
409
+ * Attach a {@link MetadataRepository} as a supplementary event source.
410
+ *
411
+ * The manager subscribes to `repo.watch({})` and re-emits each event
412
+ * through {@link notifyWatchers} as a legacy `MetadataWatchEvent`.
413
+ * Each event also invalidates the in-memory registry entry and the
414
+ * `list()` cache for the affected type so subsequent reads see fresh
415
+ * data.
416
+ *
417
+ * No write-through. `register()` / `unregister()` / `save()` are
418
+ * untouched in this PR (deferred to ADR-0008 M0 PR-10).
419
+ *
420
+ * Call {@link dispose} (or {@link stopRepositoryWatch}) to detach.
421
+ */
422
+ setRepository(repo: MetadataRepository): void;
423
+ /** Return the attached repository, if any. */
424
+ getRepository(): MetadataRepository | undefined;
425
+ /** Stop the active repo.watch() loop (best-effort). */
426
+ stopRepositoryWatch(): Promise<void>;
427
+ /**
428
+ * Best-effort cleanup. Stops the FS watcher (if any), drains the
429
+ * repository watch loop, and clears registry caches. Safe to call
430
+ * multiple times.
431
+ */
432
+ dispose(): Promise<void>;
433
+ private startRepositoryWatch;
434
+ /** Translate a repo event to the legacy MetadataWatchEvent + invalidate caches. */
435
+ private applyRepoEvent;
403
436
  protected notifyWatchers(type: string, event: MetadataWatchEvent): void;
404
437
  /**
405
438
  * Get the database loader for history operations.
@@ -428,7 +461,30 @@ declare class MetadataManager implements IMetadataService {
428
461
 
429
462
  interface MetadataPluginOptions {
430
463
  rootDir?: string;
464
+ /**
465
+ * When `true`, NodeMetadataManager scans `rootDir` for source-file metadata
466
+ * (yaml/json/ts/js loaders) AND attaches a chokidar watcher to react to
467
+ * filesystem changes. In **artifact-mode** (this is the normal path when
468
+ * a `defineStack()` config is compiled into `dist/objectstack.json`) this
469
+ * filesystem scan is redundant and expensive — leave `watch: false`.
470
+ *
471
+ * The artifact-file HMR watcher is controlled separately by
472
+ * {@link artifactWatch} so that the cheap, single-file polling watcher
473
+ * can be enabled in dev without paying the cost of scanning the entire
474
+ * project root.
475
+ *
476
+ * Default: `false` (post PR-10e — was previously `true`).
477
+ */
431
478
  watch?: boolean;
479
+ /**
480
+ * When `true` AND `artifactSource.mode === 'local-file'`, attach a
481
+ * polling chokidar watcher to the artifact file so the server reloads
482
+ * metadata when the CLI recompiles `dist/objectstack.json` in dev mode.
483
+ * Independent of {@link watch} (which controls the source-file scanner).
484
+ *
485
+ * Default: `true` when `artifactSource` is set, otherwise `false`.
486
+ */
487
+ artifactWatch?: boolean;
432
488
  config?: Partial<MetadataPluginConfig>;
433
489
  /** Organization ID for metadata-scoped consumers; MetadataPlugin itself does not persist runtime metadata. */
434
490
  organizationId?: string;
@@ -467,9 +523,13 @@ declare class MetadataPlugin implements Plugin {
467
523
  version: string;
468
524
  private manager;
469
525
  private options;
526
+ private repository?;
527
+ /** Chokidar watcher on the artifact file (local-file mode) — ADR-0008 PR-8. */
528
+ private artifactWatcher?;
470
529
  constructor(options?: MetadataPluginOptions);
471
530
  init: (ctx: PluginContext) => Promise<void>;
472
531
  start: (ctx: PluginContext) => Promise<void>;
532
+ stop: (ctx: PluginContext) => Promise<void>;
473
533
  /**
474
534
  * Fetch JSON content from a URL with configurable timeout.
475
535
  */
@@ -626,7 +686,13 @@ interface DatabaseLoaderOptions {
626
686
  historyTableName?: string;
627
687
  /** Organization ID for multi-tenant isolation */
628
688
  organizationId?: string;
629
- /** Project ID — null = platform-global, set = project-scoped */
689
+ /**
690
+ * @deprecated since ADR-0008 §0 amendment (branch/project removal).
691
+ * The metadata layer is keyed by organization only. This option is
692
+ * accepted for back-compat but ignored — writes do not set
693
+ * `project_id` and filters do not constrain on it. Will be removed
694
+ * in the next major release.
695
+ */
630
696
  projectId?: string;
631
697
  /** Enable history tracking (default: true) */
632
698
  trackHistory?: boolean;
@@ -651,7 +717,6 @@ declare class DatabaseLoader implements MetadataLoader {
651
717
  private tableName;
652
718
  private historyTableName;
653
719
  private organizationId?;
654
- private projectId?;
655
720
  private trackHistory;
656
721
  private schemaReady;
657
722
  private historySchemaReady;
@@ -687,6 +752,13 @@ declare class DatabaseLoader implements MetadataLoader {
687
752
  private _create;
688
753
  private _update;
689
754
  private _delete;
755
+ /**
756
+ * Compute the next per-org `event_seq` for `sys_metadata_history`.
757
+ * Reads `MAX(event_seq) + 1` for the configured `organization_id`.
758
+ * Legacy path — not transactional, so concurrent writes can collide.
759
+ * The canonical (transactional) producer is `SysMetadataRepository`.
760
+ */
761
+ private nextEventSeq;
690
762
  /**
691
763
  * Ensure the metadata table exists.
692
764
  * Uses IDataDriver.syncSchema with the SysMetadataObject definition
@@ -700,14 +772,14 @@ declare class DatabaseLoader implements MetadataLoader {
700
772
  private ensureHistorySchema;
701
773
  /**
702
774
  * Build base filter conditions for queries.
703
- * Filters by organizationId when configured; project_id when projectId is set,
704
- * or null (platform-global) when not set.
775
+ * Filters by organizationId when configured. `projectId` is accepted
776
+ * for back-compat but no longer constrains the query — see
777
+ * ADR-0008 §0 (branch/project removal).
705
778
  */
706
779
  private baseFilter;
707
780
  /**
708
781
  * Create a history record for a metadata change.
709
782
  *
710
- * @param metadataId - The metadata record ID
711
783
  * @param type - Metadata type
712
784
  * @param name - Metadata name
713
785
  * @param version - Version number