stonyx 0.2.3-alpha.57 → 0.2.3-alpha.58

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.
Files changed (2) hide show
  1. package/dist/modules.js +52 -7
  2. package/package.json +1 -1
package/dist/modules.js CHANGED
@@ -18,8 +18,24 @@ function configureLog(chronicle, module, config) {
18
18
  function initializeModule(moduleName, moduleClass, modules, initPromises) {
19
19
  const moduleInstance = new moduleClass();
20
20
  modules.push(moduleInstance);
21
- if (!moduleInstance.init)
21
+ // A module class with no `init()` has nothing to initialise, so it is ready
22
+ // the moment it is instantiated. Without this its registered promise dangles
23
+ // — the only resolve on this path lives inside the `init()` wrapper below,
24
+ // which is never created. Third of the three never-resolved paths named in
25
+ // #120, and the one that scoping registration to `discovered` does NOT close,
26
+ // because such a module IS discovered — measured, not reasoned: with only
27
+ // the registration fix applied the suite read 180/1 with T24 the sole
28
+ // failure. Resolving here is truthful, because the module really did load,
29
+ // and that is what separates it from resolving on a discovery `continue`,
30
+ // where there is no module to be ready.
31
+ //
32
+ // `?.` for the reason the resolve below carries it: `initializeModule` is
33
+ // also reached from the standalone path as `initializeModule(projectName, …)`,
34
+ // and `projectName` is never a key in `modulePromises`.
35
+ if (!moduleInstance.init) {
36
+ modulePromises[moduleName]?.resolve();
22
37
  return;
38
+ }
23
39
  initPromises.push((async () => {
24
40
  await moduleInstance.init();
25
41
  modulePromises[moduleName]?.resolve();
@@ -107,12 +123,6 @@ export default async function loadModules(config, rootPath, chronicle) {
107
123
  // unresolved. T3 owns that kill. What is a module is decided below, by the
108
124
  // `stonyx-module` keyword; this is only a name test that bounds the scan.
109
125
  const moduleDependencies = Object.keys(declaredDependencies).filter((moduleName) => moduleName.startsWith('@stonyx/'));
110
- // Setup module promises prior to initialization
111
- for (const moduleName of moduleDependencies) {
112
- const promise = {};
113
- modulePromises[moduleName] = promise;
114
- promise.ready = new Promise(resolve => promise.resolve = resolve);
115
- }
116
126
  // DISCOVERY, hoisted above the pre-flight.
117
127
  //
118
128
  // The pre-flight must check exactly what the loader loads, and no more.
@@ -143,6 +153,41 @@ export default async function loadModules(config, rootPath, chronicle) {
143
153
  keywords,
144
154
  });
145
155
  }
156
+ // Setup module promises prior to initialization — over `discovered`, NOT
157
+ // over `moduleDependencies`.
158
+ //
159
+ // This loop used to run above discovery and consume the declared list. That
160
+ // was already the shape at base, but rule 3 widened what the declared list
161
+ // contains, and the widening turned a fast named throw into an unbounded
162
+ // boot hang. A name registered here but never resolved leaves
163
+ // `waitForModule` pending forever; discovery `continue`s past two kinds of
164
+ // name without reaching either of this file's two resolve sites — a manifest
165
+ // that is not there, and a package without the `stonyx-module` keyword.
166
+ // `@stonyx/logs` ships without that keyword and is an ordinary `dependencies`
167
+ // entry, so this is a shape the fleet actually has.
168
+ //
169
+ // name in `dependencies`, not installed, another module awaits it
170
+ // base 5693744 throws "…was not registered in project dependencies", 3 ms
171
+ // a57045e one console.warn, then loadModules never settles
172
+ //
173
+ // Registering only what discovery admitted restores the fail-fast for both,
174
+ // and for `devDependencies`-declared names too — that half is INHERITED, not
175
+ // introduced here, and it is a real behaviour change: hang becomes throw.
176
+ // T13 pins it, and the PR body names it.
177
+ //
178
+ // The alternative — resolving in each `continue` branch — also removes the
179
+ // hang and is worse: `waitForModule` would report success for a module that
180
+ // was never loaded, silently. T23 asserts the named rejection precisely so
181
+ // that remedy cannot pass.
182
+ //
183
+ // Ordering is safe: nothing between here and the old site touches
184
+ // `modulePromises`, discovery only reads manifests, and registration still
185
+ // completes before the first `init()` can run.
186
+ for (const { name: moduleName } of discovered) {
187
+ const promise = {};
188
+ modulePromises[moduleName] = promise;
189
+ promise.ready = new Promise(resolve => promise.resolve = resolve);
190
+ }
146
191
  // Pre-flight: invariant I1, "one core". Before ANY module entry point is
147
192
  // imported, because the point of the check is the module that would NOT
148
193
  // throw — it would load, initialise, and register its hooks on a second
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stonyx",
3
- "version": "0.2.3-alpha.57",
3
+ "version": "0.2.3-alpha.58",
4
4
  "description": "Base stonyx framework module",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",