@objectstack/metadata 17.1.0 → 17.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,111 @@
1
1
  # @objectstack/metadata
2
2
 
3
+ ## 17.2.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 047ac86: Five `Plugin` implementations now release their resources from `destroy()`, the
8
+ only teardown hook the kernel calls (#10772).
9
+
10
+ `Plugin` (`@objectstack/core`'s `types.ts`) declares `init()`, `start?(ctx)` and
11
+ `destroy?()`. `ObjectKernel.performShutdown()` and `LiteKernel.destroy()` walk
12
+ the plugins in reverse calling `plugin.destroy()` — and nothing anywhere calls
13
+ `stop()`, `dispose()`, `close()` or `shutdown()` on a plugin. Each of these five
14
+ spelled its teardown with one of those names instead, so what it released was
15
+ still held after `await kernel.shutdown()` had **resolved**:
16
+
17
+ | package | class | was spelled | what outlived shutdown |
18
+ |:--|:--|:--|:--|
19
+ | `@objectstack/metadata` | `MetadataPlugin` | `stop` (arrow property) | artifact watcher, `manager.dispose()`, repository handle |
20
+ | `@objectstack/runtime` | `AppPlugin` | `stop` (arrow property) | the `app:unregistered` catalog event, never emitted |
21
+ | `@objectstack/runtime` | `ExternalValidationPlugin` | `stop` (arrow property) | every armed drift-check `setInterval` |
22
+ | `@objectstack/plugin-email` | `EmailServicePlugin` | `dispose` | two metadata subscriptions, the SMTP transport, an engine binding |
23
+ | `@objectstack/plugin-webhooks` | `WebhookOutboxPlugin` | `dispose` | the auto-enqueuer (2 realtime subscriptions + a refresh interval) and two engine hooks |
24
+
25
+ `ExternalValidationPlugin` is the one with teeth: it is one of only two `Plugin`
26
+ implementations in the tree that own `setInterval` directly, it is mounted on
27
+ the real `os serve` path, and its `stop()`'s only caller anywhere was the class
28
+ itself re-arming. Measured against a real kernel, its drift checker performed
29
+ five further reads in the five intervals after a resolved shutdown — the #9371
30
+ mechanism verbatim. `WebhookOutboxPlugin.dispose()` had **zero** callers in the
31
+ entire repo, so its teardown had never run in any process at all.
32
+
33
+ **Nothing is removed and no signature narrows.** Each old name is retained as a
34
+ delegating alias, because it is public API of an exported class and an embedder
35
+ may have learned to call it directly precisely BECAUSE the kernel never did.
36
+ `stop` stays an arrow property where it was one (so a detached
37
+ `const { stop } = plugin` keeps working) and stays synchronous on
38
+ `ExternalValidationPlugin` (so a non-awaiting call site is unaffected). The two
39
+ `stop(ctx)` aliases widen their parameter to optional.
40
+
41
+ One behavioural note for direct callers, since `destroy()` takes no context:
42
+ `MetadataPlugin.stop(ctx)` and `AppPlugin.stop(ctx)` now use the context
43
+ captured in `init()` and ignore the argument. In a real composition these are
44
+ the same object. The visible difference is confined to a plugin whose `init()`
45
+ never ran — for `MetadataPlugin` a dropped `warn` line, for `AppPlugin` a
46
+ catalog event that is no longer emitted for an app that was never registered.
47
+ - Updated dependencies [8f04d9a]
48
+ - Updated dependencies [6936d07]
49
+ - Updated dependencies [59eb04d]
50
+ - Updated dependencies [9f05b7d]
51
+ - Updated dependencies [3b2af5e]
52
+ - Updated dependencies [7d2d112]
53
+ - Updated dependencies [5fa0d72]
54
+ - Updated dependencies [8cc8401]
55
+ - Updated dependencies [02b3b07]
56
+ - Updated dependencies [46644e2]
57
+ - Updated dependencies [46d34ab]
58
+ - Updated dependencies [914c413]
59
+ - Updated dependencies [55809a0]
60
+ - Updated dependencies [ee2ff45]
61
+ - Updated dependencies [47cd3ec]
62
+ - Updated dependencies [52db1d1]
63
+ - Updated dependencies [5649efb]
64
+ - Updated dependencies [9d7d2de]
65
+ - Updated dependencies [c815c50]
66
+ - Updated dependencies [795ea05]
67
+ - Updated dependencies [2306a76]
68
+ - Updated dependencies [e5ea701]
69
+ - Updated dependencies [26f3588]
70
+ - Updated dependencies [a40dcc1]
71
+ - Updated dependencies [def0d3e]
72
+ - Updated dependencies [8d0bb79]
73
+ - Updated dependencies [5acb58d]
74
+ - Updated dependencies [2e3cf95]
75
+ - Updated dependencies [4c93387]
76
+ - Updated dependencies [504c8d5]
77
+ - Updated dependencies [a037f7c]
78
+ - Updated dependencies [3ee8ddf]
79
+ - Updated dependencies [16cef97]
80
+ - Updated dependencies [a79bd35]
81
+ - Updated dependencies [6ceaa4b]
82
+ - Updated dependencies [15ea214]
83
+ - Updated dependencies [de19489]
84
+ - Updated dependencies [c684d00]
85
+ - Updated dependencies [923c424]
86
+ - Updated dependencies [0ab81d1]
87
+ - Updated dependencies [1ec36b7]
88
+ - Updated dependencies [5f2e54c]
89
+ - Updated dependencies [189373b]
90
+ - Updated dependencies [35ad101]
91
+ - Updated dependencies [ceb33a9]
92
+ - Updated dependencies [dccbcec]
93
+ - Updated dependencies [05bc692]
94
+ - Updated dependencies [73d9795]
95
+ - Updated dependencies [8012960]
96
+ - Updated dependencies [266654d]
97
+ - Updated dependencies [f34f56b]
98
+ - Updated dependencies [f399618]
99
+ - Updated dependencies [75e9301]
100
+ - Updated dependencies [f334d66]
101
+ - Updated dependencies [2810695]
102
+ - @objectstack/platform-objects@17.2.0
103
+ - @objectstack/spec@17.2.0
104
+ - @objectstack/core@17.2.0
105
+ - @objectstack/metadata-core@17.2.0
106
+ - @objectstack/metadata-fs@17.2.0
107
+ - @objectstack/types@17.2.0
108
+
3
109
  ## 17.1.0
4
110
 
5
111
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -4536,7 +4536,10 @@ var ARTIFACT_FIELD_TO_TYPE = {
4536
4536
  dashboards: "dashboard",
4537
4537
  reports: "report",
4538
4538
  actions: "action",
4539
- themes: "theme",
4539
+ // `themes: 'theme'` removed at #10485 (ADR-0049): the carrier key is
4540
+ // retired, so a parsed artifact can no longer carry the field — and the
4541
+ // ingest half of the dead pipeline (items stored, read by nothing) goes
4542
+ // with the authoring half rather than surviving it as drift.
4540
4543
  workflows: "workflow",
4541
4544
  flows: "flow",
4542
4545
  // ADR-0090 D3: stacks declare `positions` (stack.zod.ts); the retired
@@ -4589,6 +4592,7 @@ var MetadataPlugin = class {
4589
4592
  */
4590
4593
  this.optionalDependencies = ["com.objectstack.engine.objectql"];
4591
4594
  this.init = async (ctx) => {
4595
+ this.initCtx = ctx;
4592
4596
  ctx.logger.info("Initializing Metadata Manager", {
4593
4597
  root: this.options.rootDir || process.cwd(),
4594
4598
  watch: this.options.watch,
@@ -4770,7 +4774,22 @@ var MetadataPlugin = class {
4770
4774
  console.warn("[MetadataPlugin] Failed to register HMR endpoint", e?.message);
4771
4775
  }
4772
4776
  };
4773
- this.stop = async (ctx) => {
4777
+ /**
4778
+ * Teardown — the kernel's ONLY teardown hook.
4779
+ *
4780
+ * [#10772] This body used to be spelled `stop(ctx)`. `Plugin`
4781
+ * (`@objectstack/core`'s `types.ts`) declares `init()`, `start?(ctx)` and
4782
+ * `destroy?()` and no `stop()`, and `ObjectKernel.performShutdown()` /
4783
+ * `LiteKernel.destroy()` walk the plugins in reverse calling
4784
+ * `plugin.destroy()` — so the artifact watcher, the manager and the
4785
+ * repository were all still held after `await kernel.shutdown()` had
4786
+ * RESOLVED. The `start`/`stop` pair read symmetric to a reviewer because
4787
+ * `start()` really is on the interface; only one half was ever called.
4788
+ *
4789
+ * Idempotent: every handle is cleared as it is released, so a second
4790
+ * teardown is a no-op rather than a second close.
4791
+ */
4792
+ this.destroy = async () => {
4774
4793
  if (this.artifactWatcher) {
4775
4794
  try {
4776
4795
  await this.artifactWatcher.close();
@@ -4781,7 +4800,7 @@ var MetadataPlugin = class {
4781
4800
  try {
4782
4801
  await this.manager.dispose();
4783
4802
  } catch (e) {
4784
- ctx.logger.warn("[MetadataPlugin] manager.dispose() failed", { error: e?.message });
4803
+ this.initCtx?.logger?.warn?.("[MetadataPlugin] manager.dispose() failed", { error: e?.message });
4785
4804
  }
4786
4805
  const repo = this.repository;
4787
4806
  if (repo && typeof repo.close === "function") {
@@ -4792,6 +4811,18 @@ var MetadataPlugin = class {
4792
4811
  }
4793
4812
  this.repository = void 0;
4794
4813
  };
4814
+ /**
4815
+ * Retained alias for {@link destroy}. Kept because it is public API of an
4816
+ * exported class: an embedder may have learned to call it directly
4817
+ * precisely BECAUSE the kernel never did, and deleting it would break them.
4818
+ * Still an arrow property, so a detached `const { stop } = plugin` call
4819
+ * keeps working too. The parameter is now optional and ignored —
4820
+ * `destroy()` takes no context, so teardown logs through the context
4821
+ * captured in `init()`.
4822
+ */
4823
+ this.stop = async (_ctx) => {
4824
+ await this.destroy();
4825
+ };
4795
4826
  this.options = {
4796
4827
  ...options,
4797
4828
  watch: options.watch ?? false