@objectstack/metadata 17.0.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,288 @@
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
+
109
+ ## 17.1.0
110
+
111
+ ### Patch Changes
112
+
113
+ - 7337f30: chore(deps): production-dependency patch bumps from the weekly Dependabot group (#9212)
114
+
115
+ Routine dependency-range refresh, no behavior change: `@oclif/core` 4.13.2→4.13.3,
116
+ `esbuild` 0.28.1→0.28.2 and `better-sqlite3` ^13.0.2→^13.0.3 (optional) on
117
+ `@objectstack/cli`; `mingo` 7.2.2→7.2.4 on `@objectstack/driver-memory`; `nanoid`
118
+ 6.0.0→6.0.1 on `@objectstack/driver-mongodb`, `@objectstack/driver-sql`,
119
+ `@objectstack/driver-sqlite-wasm` and `@objectstack/driver-turso`, plus
120
+ `better-sqlite3` ^13.0.2→^13.0.3 (optional on `@objectstack/driver-sql`, peer on
121
+ `@objectstack/driver-turso`); `js-yaml` 5.2.2→5.2.3 on `@objectstack/metadata`;
122
+ `@noble/hashes` 2.2.0→2.3.0 and `jose` 6.2.5→6.2.8 on `@objectstack/plugin-auth`;
123
+ `nodemailer` 9.0.3→9.0.5 on `@objectstack/plugin-email`; `@hono/node-server`
124
+ 2.0.12→2.1.1 and `hono` 4.12.34→4.13.2 on `@objectstack/plugin-hono-server`;
125
+ `pinyin-pro` 3.28.2→3.29.1 on `@objectstack/plugin-pinyin-search`; and
126
+ `@noble/ciphers` 2.2.0→2.3.0 on `@objectstack/service-settings`.
127
+
128
+ Every entry above changed a `dependencies`, `optionalDependencies` or
129
+ `peerDependencies` range in the published manifest — the only kind of change
130
+ that reaches a consumer's install. The same Dependabot group also bumped
131
+ `devDependencies` on `@objectstack/hono`, `@objectstack/client`,
132
+ `@objectstack/core`, `@objectstack/plugin-sharing` and `@objectstack/spec`
133
+ (none consumer-facing), and touched the private `apps/docs`,
134
+ `examples/app-todo` and workspace-root manifests (none published) — none of
135
+ those get an entry here.
136
+ - 2a9752c: fix(metadata): `MetadataPlugin`'s `watch` option defaults to `false`, as its own doc comment documents (#9770)
137
+
138
+ `MetadataPluginOptions.watch` documents its default as ``Default: `false` (post PR-10e —
139
+ was previously `true`)``, directly above the field. The constructor implemented the
140
+ opposite, and it did so in **two** places, so both entry shapes resolved `true`:
141
+
142
+ - the options literal `{ watch: true, ...options }` — covering a caller who **omits** the key;
143
+ - the fallback `this.options.watch ?? true` — covering a caller who passes an explicit
144
+ `undefined`.
145
+
146
+ Both non-test construction sites in this repo pass `watch: false` explicitly and are
147
+ unaffected either way, which is exactly why the drift was invisible to every test and
148
+ gate: no in-repo configuration exercised the default. `MetadataPlugin` is a public export
149
+ (`@objectstack/metadata`, `@objectstack/metadata/node`), so the consumers who did reach it
150
+ were **external** ones — and they reached it by doing the documented-safe thing and not
151
+ naming the key at all. What they got was the configuration both internal call sites go out
152
+ of their way to refuse, citing an **EMFILE** hazard at both: a recursive chokidar poll
153
+ (`usePolling: true, interval: 1000`) over the entire project root, with `node_modules`
154
+ excluded only by chokidar's default `ignored`.
155
+
156
+ The default now resolves `false`. The flag is normalized once in the constructor
157
+ (`watch: options.watch ?? false`) rather than spelled `{ watch: false, ...options }`,
158
+ because a spread preserves an explicitly-passed `undefined` verbatim and not every read of
159
+ the flag routes through a nullish fallback — the `start()`-time `FileSystemRepository`
160
+ `disableWatch` keys on `=== false`. Coercing once makes an omitted key and an explicit
161
+ `undefined` resolve identically at every downstream read, instead of trading one
162
+ two-spelling divergence for another.
163
+
164
+ This is a default flip, **not** a capability removal: an explicit `watch: true` still
165
+ attaches the scanner and its watcher, and the sealed-runtime carve-out
166
+ (`bootstrap: 'artifact-only'` forces watching off even against an explicit `watch: true`)
167
+ is untouched. Pins cover all four shapes, asserting on the **observable** — whether a
168
+ watcher object exists on the manager — rather than on the resolved options value alone.
169
+ - Updated dependencies [56656aa]
170
+ - Updated dependencies [c9f5950]
171
+ - Updated dependencies [d6e80b2]
172
+ - Updated dependencies [07e630e]
173
+ - Updated dependencies [66beee0]
174
+ - Updated dependencies [2f65b1b]
175
+ - Updated dependencies [720ee95]
176
+ - Updated dependencies [f287435]
177
+ - Updated dependencies [2782805]
178
+ - Updated dependencies [e43d63a]
179
+ - Updated dependencies [9aa8890]
180
+ - Updated dependencies [7c9c1dd]
181
+ - Updated dependencies [03520eb]
182
+ - Updated dependencies [75b7c24]
183
+ - Updated dependencies [d5552ca]
184
+ - Updated dependencies [d9813a9]
185
+ - Updated dependencies [8640fb2]
186
+ - Updated dependencies [2420641]
187
+ - Updated dependencies [2ad91c3]
188
+ - Updated dependencies [f57fb38]
189
+ - Updated dependencies [00777a0]
190
+ - Updated dependencies [d491625]
191
+ - Updated dependencies [2d0af57]
192
+ - Updated dependencies [420804d]
193
+ - Updated dependencies [716ac9b]
194
+ - Updated dependencies [a38408a]
195
+ - Updated dependencies [62b1427]
196
+ - Updated dependencies [7ea1372]
197
+ - Updated dependencies [23abe27]
198
+ - Updated dependencies [985a9cd]
199
+ - Updated dependencies [5f5e234]
200
+ - Updated dependencies [a8189ae]
201
+ - Updated dependencies [26e70fb]
202
+ - Updated dependencies [27a567d]
203
+ - Updated dependencies [42b05af]
204
+ - Updated dependencies [2b292ce]
205
+ - Updated dependencies [abcf853]
206
+ - Updated dependencies [8b9eba5]
207
+ - Updated dependencies [d575779]
208
+ - Updated dependencies [94f7ef8]
209
+ - Updated dependencies [c5ac5e4]
210
+ - Updated dependencies [a777944]
211
+ - Updated dependencies [dd88e1c]
212
+ - Updated dependencies [856527c]
213
+ - Updated dependencies [870f710]
214
+ - Updated dependencies [79c46da]
215
+ - Updated dependencies [7ff3975]
216
+ - Updated dependencies [29d055b]
217
+ - Updated dependencies [65589d6]
218
+ - Updated dependencies [2c86fe3]
219
+ - Updated dependencies [e196c6a]
220
+ - Updated dependencies [24173e9]
221
+ - Updated dependencies [4ab7523]
222
+ - Updated dependencies [19539b4]
223
+ - Updated dependencies [f8eb736]
224
+ - Updated dependencies [11b779e]
225
+ - Updated dependencies [739fe5b]
226
+ - Updated dependencies [4bfe1a5]
227
+ - Updated dependencies [2065e31]
228
+ - Updated dependencies [b69d0f5]
229
+ - Updated dependencies [bd2fc8b]
230
+ - Updated dependencies [4d47afe]
231
+ - Updated dependencies [e4e5c6e]
232
+ - Updated dependencies [9a56784]
233
+ - Updated dependencies [d00d2f6]
234
+ - Updated dependencies [df0c12d]
235
+ - Updated dependencies [d31785f]
236
+ - Updated dependencies [c308a4f]
237
+ - Updated dependencies [e2899f6]
238
+ - Updated dependencies [b6c7690]
239
+ - Updated dependencies [3851f87]
240
+ - Updated dependencies [845e164]
241
+ - Updated dependencies [2a29caa]
242
+ - Updated dependencies [09a6eee]
243
+ - Updated dependencies [1a7f907]
244
+ - Updated dependencies [cd455c8]
245
+ - Updated dependencies [e1bb0ca]
246
+ - Updated dependencies [30d3752]
247
+ - Updated dependencies [c80e7ae]
248
+ - Updated dependencies [09a9a8a]
249
+ - Updated dependencies [07026cf]
250
+ - Updated dependencies [5d4f3d5]
251
+ - Updated dependencies [4d80e8b]
252
+ - Updated dependencies [30b1c63]
253
+ - Updated dependencies [7fc01db]
254
+ - Updated dependencies [079b457]
255
+ - Updated dependencies [e43b211]
256
+ - Updated dependencies [890b38f]
257
+ - Updated dependencies [8bee54b]
258
+ - Updated dependencies [04f8fdb]
259
+ - Updated dependencies [7a537ce]
260
+ - Updated dependencies [593c4bf]
261
+ - Updated dependencies [6158146]
262
+ - Updated dependencies [84cb121]
263
+ - Updated dependencies [ca19ee8]
264
+ - Updated dependencies [a675b4d]
265
+ - Updated dependencies [b887013]
266
+ - Updated dependencies [ff08691]
267
+ - Updated dependencies [60e0f90]
268
+ - Updated dependencies [90c5285]
269
+ - Updated dependencies [402c125]
270
+ - Updated dependencies [7901b2d]
271
+ - Updated dependencies [56bca91]
272
+ - Updated dependencies [b3f9831]
273
+ - Updated dependencies [79394d7]
274
+ - Updated dependencies [730fd9a]
275
+ - Updated dependencies [44bc51d]
276
+ - Updated dependencies [bbbfcfc]
277
+ - Updated dependencies [73cfddf]
278
+ - Updated dependencies [d634e66]
279
+ - @objectstack/spec@17.1.0
280
+ - @objectstack/platform-objects@17.1.0
281
+ - @objectstack/types@17.1.0
282
+ - @objectstack/core@17.1.0
283
+ - @objectstack/metadata-fs@17.1.0
284
+ - @objectstack/metadata-core@17.1.0
285
+
3
286
  ## 17.0.0
4
287
 
5
288
  ### Major 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,13 +4811,25 @@ 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
- watch: true,
4797
- ...options
4827
+ ...options,
4828
+ watch: options.watch ?? false
4798
4829
  };
4799
4830
  const rootDir = this.options.rootDir || process.cwd();
4800
4831
  const bootstrapMode = this.options.config?.bootstrap ?? "eager";
4801
- const effectiveWatch = bootstrapMode === "artifact-only" ? false : this.options.watch ?? true;
4832
+ const effectiveWatch = bootstrapMode === "artifact-only" ? false : this.options.watch ?? false;
4802
4833
  this.manager = new NodeMetadataManager({
4803
4834
  rootDir,
4804
4835
  watch: effectiveWatch,