@wildo-ai/platform-core-shared 1.1.10 → 1.1.12
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/esm/core/resources/resources-operations.custom.shared.definitions.js.map +1 -1
- package/dist/esm/core/resources/resources-relationships.custom.shared.definitions.js.map +1 -1
- package/dist/esm/core/resources/resources-types.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/core/resources/resources-types.custom.shared.schemas.js.map +1 -1
- package/dist/esm/dev-runtime/dependency-install-record.d.ts +111 -0
- package/dist/esm/dev-runtime/dependency-install-record.d.ts.map +1 -0
- package/dist/esm/dev-runtime/dependency-install-record.js +185 -0
- package/dist/esm/dev-runtime/dependency-install-record.js.map +1 -0
- package/dist/esm/dev-runtime/dev-runtime-command.d.ts +50 -0
- package/dist/esm/dev-runtime/dev-runtime-command.d.ts.map +1 -0
- package/dist/esm/dev-runtime/dev-runtime-command.js +147 -0
- package/dist/esm/dev-runtime/dev-runtime-command.js.map +1 -0
- package/dist/esm/dev-runtime/dev-runtime-processes.d.ts +47 -0
- package/dist/esm/dev-runtime/dev-runtime-processes.d.ts.map +1 -0
- package/dist/esm/dev-runtime/dev-runtime-processes.js +163 -0
- package/dist/esm/dev-runtime/dev-runtime-processes.js.map +1 -0
- package/dist/esm/dev-runtime/dev-runtime-signals.d.ts +54 -0
- package/dist/esm/dev-runtime/dev-runtime-signals.d.ts.map +1 -0
- package/dist/esm/dev-runtime/dev-runtime-signals.js +113 -0
- package/dist/esm/dev-runtime/dev-runtime-signals.js.map +1 -0
- package/dist/esm/dev-runtime/emitted-relative-specifiers.d.ts +14 -0
- package/dist/esm/dev-runtime/emitted-relative-specifiers.d.ts.map +1 -0
- package/dist/esm/dev-runtime/emitted-relative-specifiers.js +71 -0
- package/dist/esm/dev-runtime/emitted-relative-specifiers.js.map +1 -0
- package/dist/esm/dev-runtime/frontend-dev-runtime.d.ts +43 -0
- package/dist/esm/dev-runtime/frontend-dev-runtime.d.ts.map +1 -0
- package/dist/esm/dev-runtime/frontend-dev-runtime.js +42 -0
- package/dist/esm/dev-runtime/frontend-dev-runtime.js.map +1 -0
- package/dist/esm/dev-runtime/node-runtime-dev-supervisor.d.ts +233 -0
- package/dist/esm/dev-runtime/node-runtime-dev-supervisor.d.ts.map +1 -0
- package/dist/esm/dev-runtime/node-runtime-dev-supervisor.js +578 -0
- package/dist/esm/dev-runtime/node-runtime-dev-supervisor.js.map +1 -0
- package/dist/esm/dev-runtime/package-compile-loop.d.ts +125 -0
- package/dist/esm/dev-runtime/package-compile-loop.d.ts.map +1 -0
- package/dist/esm/dev-runtime/package-compile-loop.js +386 -0
- package/dist/esm/dev-runtime/package-compile-loop.js.map +1 -0
- package/dist/esm/dev-runtime.exports.d.ts +19 -0
- package/dist/esm/dev-runtime.exports.d.ts.map +1 -0
- package/dist/esm/dev-runtime.exports.js +19 -0
- package/dist/esm/dev-runtime.exports.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/runtime/application-backend-env.contracts.d.ts +16 -2
- package/dist/esm/runtime/application-backend-env.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/application-backend-env.contracts.js +20 -1
- package/dist/esm/runtime/application-backend-env.contracts.js.map +1 -1
- package/dist/esm/runtime/application-worker-env.contracts.d.ts +14 -4
- package/dist/esm/runtime/application-worker-env.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/application-worker-env.contracts.js +12 -0
- package/dist/esm/runtime/application-worker-env.contracts.js.map +1 -1
- package/dist/esm/runtime/backend-start-outcome.contracts.d.ts +27 -0
- package/dist/esm/runtime/backend-start-outcome.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/backend-start-outcome.contracts.js +34 -0
- package/dist/esm/runtime/backend-start-outcome.contracts.js.map +1 -1
- package/dist/esm/runtime/frontend-settings-hub-wiring.contracts.d.ts +28 -0
- package/dist/esm/runtime/frontend-settings-hub-wiring.contracts.d.ts.map +1 -0
- package/dist/esm/runtime/frontend-settings-hub-wiring.contracts.js +35 -0
- package/dist/esm/runtime/frontend-settings-hub-wiring.contracts.js.map +1 -0
- package/dist/esm/runtime/http-server-env.contracts.d.ts +14 -1
- package/dist/esm/runtime/http-server-env.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/http-server-env.contracts.js +13 -0
- package/dist/esm/runtime/http-server-env.contracts.js.map +1 -1
- package/dist/esm/runtime/local-dev-runtime-signals.contracts.d.ts +239 -0
- package/dist/esm/runtime/local-dev-runtime-signals.contracts.d.ts.map +1 -0
- package/dist/esm/runtime/local-dev-runtime-signals.contracts.js +256 -0
- package/dist/esm/runtime/local-dev-runtime-signals.contracts.js.map +1 -0
- package/dist/esm/runtime/runtime-topology.contracts.js.map +1 -1
- package/dist/esm/security/authorizations/roles.custom.shared.definitions.js.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.d.ts +362 -36
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.js +4 -3
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.d.ts +400 -37
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.js +107 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.d.ts +26 -26
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.js +4 -3
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.d.ts +33 -27
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.js +26 -2
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.d.ts +3 -3
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.js +30 -42
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.d.ts +9 -9
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.schemas.d.ts +7 -7
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/creation-drive.custom.shared.schemas.d.ts +52 -0
- package/dist/esm/workbench/creation-drive.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/creation-drive.custom.shared.schemas.js +49 -0
- package/dist/esm/workbench/creation-drive.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/creation-journey-timeline.custom.shared.schemas.d.ts +183 -0
- package/dist/esm/workbench/creation-journey-timeline.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/creation-journey-timeline.custom.shared.schemas.js +188 -0
- package/dist/esm/workbench/creation-journey-timeline.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.js +76 -0
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.d.ts +170 -7
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.js +177 -7
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.d.ts +21 -3
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.js +7 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.d.ts +611 -405
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.js +98 -17
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.d.ts +821 -240
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.js +795 -41
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-domain-model.custom.shared.schemas.d.ts +34 -0
- package/dist/esm/workbench/workbench-domain-model.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-domain-model.custom.shared.schemas.js +31 -0
- package/dist/esm/workbench/workbench-domain-model.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.d.ts +14 -2
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.js +25 -3
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.d.ts +353 -250
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.js +1 -0
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.d.ts +34 -29
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.js +9 -5
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +13 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitted-relative-specifiers.d.ts","sourceRoot":"","sources":["../../../src/dev-runtime/emitted-relative-specifiers.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,4BAA4B;IAC3C,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,wEAAwE;AACxE,wBAAgB,kCAAkC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/E;AAED;;;;GAIG;AACH,wBAAgB,wCAAwC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAI,EAAE,KAAK,SAAK,GAAG,4BAA4B,EAAE,CA8BlI"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Find the relative module specifiers Node cannot resolve in an emitted ESM tree: `./x` or `../x` with no file
|
|
5
|
+
* extension, which is what `tsc` writes and what the post-emit alias pass (`tsc-alias --resolve-full-paths`) exists to
|
|
6
|
+
* rewrite. A tree that still holds one is NOT publishable: Node's ESM loader resolves no extension, so a backend that
|
|
7
|
+
* starts on it dies with `ERR_MODULE_NOT_FOUND` — the failure #3216 recorded on `app-creation-test-007` after nearly
|
|
8
|
+
* every relationship task of a wave.
|
|
9
|
+
*
|
|
10
|
+
* The verification is what lets the compiler say `READY` and mean it: the alias pass exiting 0 is the pass's word,
|
|
11
|
+
* this scan is the tree's.
|
|
12
|
+
*/
|
|
13
|
+
/** `from '…'`, `import '…'` and `import('…')`, with either quote. Comments are not stripped: an emitted file has few. */
|
|
14
|
+
const SPECIFIER_PATTERN = /(?:\bfrom\s*|\bimport\s*\(\s*|\bimport\s+)(['"])(\.{1,2}\/[^'"\n]*)\1/gu;
|
|
15
|
+
/** Extensions Node's ESM loader resolves as written. A specifier ending in any of them is fully specified. */
|
|
16
|
+
const RESOLVABLE_EXTENSION_PATTERN = /\.(?:m?js|cjs|json|node)$/u;
|
|
17
|
+
/** Emitted JavaScript only: declaration files carry extensionless specifiers legitimately and Node never loads them. */
|
|
18
|
+
const EMITTED_JAVASCRIPT_PATTERN = /\.(?:m?js|cjs)$/u;
|
|
19
|
+
/** Every extensionless relative specifier in one file's source text. */
|
|
20
|
+
export function findUnresolvableRelativeSpecifiers(sourceText) {
|
|
21
|
+
const found = [];
|
|
22
|
+
for (const match of sourceText.matchAll(SPECIFIER_PATTERN)) {
|
|
23
|
+
const specifier = match[2];
|
|
24
|
+
if (!RESOLVABLE_EXTENSION_PATTERN.test(specifier))
|
|
25
|
+
found.push(specifier);
|
|
26
|
+
}
|
|
27
|
+
return found;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Scan the emitted JavaScript under `distRoot` that was written at or after `sinceMs` (an incremental build rewrites
|
|
31
|
+
* only what changed, and every older file was verified when it was written). `sinceMs` of 0 scans the whole tree.
|
|
32
|
+
* Returns at most `limit` findings: one is enough to refuse, a few are enough to name the cause.
|
|
33
|
+
*/
|
|
34
|
+
export function scanEmittedTreeForUnresolvableSpecifiers(distRoot, sinceMs = 0, limit = 10) {
|
|
35
|
+
const findings = [];
|
|
36
|
+
const walk = (directory) => {
|
|
37
|
+
let entries;
|
|
38
|
+
try {
|
|
39
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
for (const entry of entries) {
|
|
45
|
+
if (findings.length >= limit)
|
|
46
|
+
return;
|
|
47
|
+
const path = join(directory, entry.name);
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
walk(path);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!entry.isFile() || !EMITTED_JAVASCRIPT_PATTERN.test(entry.name))
|
|
53
|
+
continue;
|
|
54
|
+
try {
|
|
55
|
+
if (sinceMs > 0 && statSync(path).mtimeMs < sinceMs)
|
|
56
|
+
continue;
|
|
57
|
+
for (const specifier of findUnresolvableRelativeSpecifiers(readFileSync(path, 'utf8'))) {
|
|
58
|
+
findings.push({ file: relative(distRoot, path), specifier });
|
|
59
|
+
if (findings.length >= limit)
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// A file removed mid-scan was rewritten by a newer compilation, which is verified on its own.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
walk(distRoot);
|
|
69
|
+
return findings;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=emitted-relative-specifiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitted-relative-specifiers.js","sourceRoot":"","sources":["../../../src/dev-runtime/emitted-relative-specifiers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE3C;;;;;;;;;GASG;AAEH,yHAAyH;AACzH,MAAM,iBAAiB,GAAG,yEAAyE,CAAC;AAEpG,8GAA8G;AAC9G,MAAM,4BAA4B,GAAG,4BAA4B,CAAC;AAElE,wHAAwH;AACxH,MAAM,0BAA0B,GAAG,kBAAkB,CAAC;AAQtD,wEAAwE;AACxE,MAAM,UAAU,kCAAkC,CAAC,UAAkB;IACnE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC3D,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5B,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wCAAwC,CAAC,QAAgB,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE;IAChG,MAAM,QAAQ,GAAmC,EAAE,CAAC;IACpD,MAAM,IAAI,GAAG,CAAC,SAAiB,EAAQ,EAAE;QACvC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK;gBAAE,OAAO;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,CAAC;gBACX,SAAS;YACX,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC9E,IAAI,CAAC;gBACH,IAAI,OAAO,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,OAAO;oBAAE,SAAS;gBAC9D,KAAK,MAAM,SAAS,IAAI,kCAAkC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;oBACvF,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;oBAC7D,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK;wBAAE,OAAO;gBACvC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,8FAA8F;YAChG,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,CAAC;IACf,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["import { readdirSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n/**\n * Find the relative module specifiers Node cannot resolve in an emitted ESM tree: `./x` or `../x` with no file\n * extension, which is what `tsc` writes and what the post-emit alias pass (`tsc-alias --resolve-full-paths`) exists to\n * rewrite. A tree that still holds one is NOT publishable: Node's ESM loader resolves no extension, so a backend that\n * starts on it dies with `ERR_MODULE_NOT_FOUND` — the failure #3216 recorded on `app-creation-test-007` after nearly\n * every relationship task of a wave.\n *\n * The verification is what lets the compiler say `READY` and mean it: the alias pass exiting 0 is the pass's word,\n * this scan is the tree's.\n */\n\n/** `from '…'`, `import '…'` and `import('…')`, with either quote. Comments are not stripped: an emitted file has few. */\nconst SPECIFIER_PATTERN = /(?:\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bimport\\s+)(['\"])(\\.{1,2}\\/[^'\"\\n]*)\\1/gu;\n\n/** Extensions Node's ESM loader resolves as written. A specifier ending in any of them is fully specified. */\nconst RESOLVABLE_EXTENSION_PATTERN = /\\.(?:m?js|cjs|json|node)$/u;\n\n/** Emitted JavaScript only: declaration files carry extensionless specifiers legitimately and Node never loads them. */\nconst EMITTED_JAVASCRIPT_PATTERN = /\\.(?:m?js|cjs)$/u;\n\nexport interface UnresolvableEmittedSpecifier {\n /** Path relative to the scanned tree. */\n readonly file: string;\n readonly specifier: string;\n}\n\n/** Every extensionless relative specifier in one file's source text. */\nexport function findUnresolvableRelativeSpecifiers(sourceText: string): string[] {\n const found: string[] = [];\n for (const match of sourceText.matchAll(SPECIFIER_PATTERN)) {\n const specifier = match[2]!;\n if (!RESOLVABLE_EXTENSION_PATTERN.test(specifier)) found.push(specifier);\n }\n return found;\n}\n\n/**\n * Scan the emitted JavaScript under `distRoot` that was written at or after `sinceMs` (an incremental build rewrites\n * only what changed, and every older file was verified when it was written). `sinceMs` of 0 scans the whole tree.\n * Returns at most `limit` findings: one is enough to refuse, a few are enough to name the cause.\n */\nexport function scanEmittedTreeForUnresolvableSpecifiers(distRoot: string, sinceMs = 0, limit = 10): UnresolvableEmittedSpecifier[] {\n const findings: UnresolvableEmittedSpecifier[] = [];\n const walk = (directory: string): void => {\n let entries;\n try {\n entries = readdirSync(directory, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (findings.length >= limit) return;\n const path = join(directory, entry.name);\n if (entry.isDirectory()) {\n walk(path);\n continue;\n }\n if (!entry.isFile() || !EMITTED_JAVASCRIPT_PATTERN.test(entry.name)) continue;\n try {\n if (sinceMs > 0 && statSync(path).mtimeMs < sinceMs) continue;\n for (const specifier of findUnresolvableRelativeSpecifiers(readFileSync(path, 'utf8'))) {\n findings.push({ file: relative(distRoot, path), specifier });\n if (findings.length >= limit) return;\n }\n } catch {\n // A file removed mid-scan was rewritten by a newer compilation, which is verified on its own.\n }\n }\n };\n walk(distRoot);\n return findings;\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
import type { PackageCompileLoop } from './package-compile-loop';
|
|
3
|
+
/**
|
|
4
|
+
* An app-creator FRONTEND's dev process (#3226): its dev server, and the compiler that keeps its config library current.
|
|
5
|
+
*
|
|
6
|
+
* ## Why a frontend has a compiled library at all, and why nothing kept it current
|
|
7
|
+
*
|
|
8
|
+
* The frontend package exports its configuration (`./companion`, `./resource-ui-behaviors`) from `dist/library`, built by
|
|
9
|
+
* `tsc -p tsconfig.library.json` + the alias pass. The dev companion's introspection imports THAT build to answer what
|
|
10
|
+
* the shell composes (`app-shell-placement-content`), the settings rail, and every placement task's landing. Vite serves
|
|
11
|
+
* the source and never builds the library, and a coding worker is told not to run builds, so in an application created
|
|
12
|
+
* from the published framework the library was produced by `pnpm build` only. On app-creation-test-007 it was dated
|
|
13
|
+
* 2026-10-21 while `app-shell.config.ts` was edited on 2026-10-29: the sidebar read as carrying nothing, and three
|
|
14
|
+
* placement tasks read `completed_unlanded` until something rebuilt it. A framework developer's application never saw it,
|
|
15
|
+
* because its `dev:watch` script runs the library compiler.
|
|
16
|
+
*
|
|
17
|
+
* So the frontend's `dev` runs both: the {@link PackageCompileLoop} over `tsconfig.library.json` (the same loop the shared
|
|
18
|
+
* library and the backend use, publishing the same compile record, so a reader can tell a current library from a stale
|
|
19
|
+
* one), and the dev server as a child. They live and die together: the dev server exiting stops the compiler, and a
|
|
20
|
+
* signal stops both.
|
|
21
|
+
*/
|
|
22
|
+
export interface FrontendDevRuntimeOptions {
|
|
23
|
+
readonly packageRoot: string;
|
|
24
|
+
readonly compileLoop: Pick<PackageCompileLoop, 'start' | 'stop' | 'killChildrenNow'>;
|
|
25
|
+
/** The dev server's command line (`vite`), run through the shell with the package's binaries on the path. */
|
|
26
|
+
readonly command: string;
|
|
27
|
+
/** Called once with the dev server's exit code when it ends on its own, not when this runtime stopped it. */
|
|
28
|
+
readonly onCommandExit: (code: number) => void;
|
|
29
|
+
/** Injectable for tests. */
|
|
30
|
+
readonly spawnCommand?: (command: string, packageRoot: string) => ChildProcess;
|
|
31
|
+
}
|
|
32
|
+
export declare class FrontendDevRuntime {
|
|
33
|
+
private readonly options;
|
|
34
|
+
private child;
|
|
35
|
+
private stopping;
|
|
36
|
+
constructor(options: FrontendDevRuntimeOptions);
|
|
37
|
+
/** Start the library compiler first (it refuses when another process compiles this package), then the dev server. */
|
|
38
|
+
start(): Promise<void>;
|
|
39
|
+
stop(): Promise<void>;
|
|
40
|
+
/** Kill both synchronously: for a process that is exiting and cannot await {@link stop}. */
|
|
41
|
+
killChildrenNow(): void;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=frontend-dev-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontend-dev-runtime.d.ts","sourceRoot":"","sources":["../../../src/dev-runtime/frontend-dev-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,MAAM,GAAG,iBAAiB,CAAC,CAAC;IACrF,6GAA6G;IAC7G,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6GAA6G;IAC7G,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,4BAA4B;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,YAAY,CAAC;CAChF;AAOD,qBAAa,kBAAkB;IAIV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAH3C,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,QAAQ,CAAS;gBAEW,OAAO,EAAE,yBAAyB;IAEtE,qHAAqH;IACxG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUlC,4FAA4F;IACrF,eAAe,IAAI,IAAI;CAI/B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { killProcessGroupNow, terminateProcessGroup, usesProcessGroups } from './dev-runtime-processes.js';
|
|
3
|
+
/** Spawn the dev server as the leader of its own process group, so stopping it stops everything it started. */
|
|
4
|
+
function spawnDevServer(command, packageRoot) {
|
|
5
|
+
return spawn(command, { cwd: packageRoot, shell: true, detached: usesProcessGroups(), stdio: ['inherit', 'inherit', 'inherit'] });
|
|
6
|
+
}
|
|
7
|
+
export class FrontendDevRuntime {
|
|
8
|
+
options;
|
|
9
|
+
child = null;
|
|
10
|
+
stopping = false;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
}
|
|
14
|
+
/** Start the library compiler first (it refuses when another process compiles this package), then the dev server. */
|
|
15
|
+
async start() {
|
|
16
|
+
await this.options.compileLoop.start();
|
|
17
|
+
const child = (this.options.spawnCommand ?? spawnDevServer)(this.options.command, this.options.packageRoot);
|
|
18
|
+
this.child = child;
|
|
19
|
+
child.once('exit', (code, signal) => {
|
|
20
|
+
if (this.child === child)
|
|
21
|
+
this.child = null;
|
|
22
|
+
if (this.stopping)
|
|
23
|
+
return;
|
|
24
|
+
this.options.onCommandExit(code ?? (signal === null ? 0 : 1));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async stop() {
|
|
28
|
+
this.stopping = true;
|
|
29
|
+
const child = this.child;
|
|
30
|
+
this.child = null;
|
|
31
|
+
await Promise.all([
|
|
32
|
+
child?.pid !== undefined ? terminateProcessGroup(child.pid, 5_000) : Promise.resolve(),
|
|
33
|
+
this.options.compileLoop.stop(),
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
/** Kill both synchronously: for a process that is exiting and cannot await {@link stop}. */
|
|
37
|
+
killChildrenNow() {
|
|
38
|
+
killProcessGroupNow(this.child?.pid);
|
|
39
|
+
this.options.compileLoop.killChildrenNow();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=frontend-dev-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontend-dev-runtime.js","sourceRoot":"","sources":["../../../src/dev-runtime/frontend-dev-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAiCxG,+GAA+G;AAC/G,SAAS,cAAc,CAAC,OAAe,EAAE,WAAmB;IAC1D,OAAO,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;AACpI,CAAC;AAED,MAAM,OAAO,kBAAkB;IAIO;IAH5B,KAAK,GAAwB,IAAI,CAAC;IAClC,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAAoC,OAAkC;QAAlC,YAAO,GAAP,OAAO,CAA2B;IAAG,CAAC;IAE1E,qHAAqH;IAC9G,KAAK,CAAC,KAAK;QAChB,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC5G,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAClC,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAC5C,IAAI,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAC1B,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,KAAK,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE;YACtF,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE;SAChC,CAAC,CAAC;IACL,CAAC;IAED,4FAA4F;IACrF,eAAe;QACpB,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;IAC7C,CAAC;CACF","sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\n\nimport { killProcessGroupNow, terminateProcessGroup, usesProcessGroups } from './dev-runtime-processes';\nimport type { PackageCompileLoop } from './package-compile-loop';\n\n/**\n * An app-creator FRONTEND's dev process (#3226): its dev server, and the compiler that keeps its config library current.\n *\n * ## Why a frontend has a compiled library at all, and why nothing kept it current\n *\n * The frontend package exports its configuration (`./companion`, `./resource-ui-behaviors`) from `dist/library`, built by\n * `tsc -p tsconfig.library.json` + the alias pass. The dev companion's introspection imports THAT build to answer what\n * the shell composes (`app-shell-placement-content`), the settings rail, and every placement task's landing. Vite serves\n * the source and never builds the library, and a coding worker is told not to run builds, so in an application created\n * from the published framework the library was produced by `pnpm build` only. On app-creation-test-007 it was dated\n * 2026-10-21 while `app-shell.config.ts` was edited on 2026-10-29: the sidebar read as carrying nothing, and three\n * placement tasks read `completed_unlanded` until something rebuilt it. A framework developer's application never saw it,\n * because its `dev:watch` script runs the library compiler.\n *\n * So the frontend's `dev` runs both: the {@link PackageCompileLoop} over `tsconfig.library.json` (the same loop the shared\n * library and the backend use, publishing the same compile record, so a reader can tell a current library from a stale\n * one), and the dev server as a child. They live and die together: the dev server exiting stops the compiler, and a\n * signal stops both.\n */\nexport interface FrontendDevRuntimeOptions {\n readonly packageRoot: string;\n readonly compileLoop: Pick<PackageCompileLoop, 'start' | 'stop' | 'killChildrenNow'>;\n /** The dev server's command line (`vite`), run through the shell with the package's binaries on the path. */\n readonly command: string;\n /** Called once with the dev server's exit code when it ends on its own, not when this runtime stopped it. */\n readonly onCommandExit: (code: number) => void;\n /** Injectable for tests. */\n readonly spawnCommand?: (command: string, packageRoot: string) => ChildProcess;\n}\n\n/** Spawn the dev server as the leader of its own process group, so stopping it stops everything it started. */\nfunction spawnDevServer(command: string, packageRoot: string): ChildProcess {\n return spawn(command, { cwd: packageRoot, shell: true, detached: usesProcessGroups(), stdio: ['inherit', 'inherit', 'inherit'] });\n}\n\nexport class FrontendDevRuntime {\n private child: ChildProcess | null = null;\n private stopping = false;\n\n public constructor(private readonly options: FrontendDevRuntimeOptions) {}\n\n /** Start the library compiler first (it refuses when another process compiles this package), then the dev server. */\n public async start(): Promise<void> {\n await this.options.compileLoop.start();\n const child = (this.options.spawnCommand ?? spawnDevServer)(this.options.command, this.options.packageRoot);\n this.child = child;\n child.once('exit', (code, signal) => {\n if (this.child === child) this.child = null;\n if (this.stopping) return;\n this.options.onCommandExit(code ?? (signal === null ? 0 : 1));\n });\n }\n\n public async stop(): Promise<void> {\n this.stopping = true;\n const child = this.child;\n this.child = null;\n await Promise.all([\n child?.pid !== undefined ? terminateProcessGroup(child.pid, 5_000) : Promise.resolve(),\n this.options.compileLoop.stop(),\n ]);\n }\n\n /** Kill both synchronously: for a process that is exiting and cannot await {@link stop}. */\n public killChildrenNow(): void {\n killProcessGroupNow(this.child?.pid);\n this.options.compileLoop.killChildrenNow();\n }\n}\n"]}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { BackendStartFailureCause, BackendStartOutcome, type BackendStartOutcomeRecord } from '../runtime/backend-start-outcome.contracts';
|
|
2
|
+
import { type LocalDevCompileObservation, type LocalDevPortHolder, type LocalDevSupervisorObservation } from '../runtime/local-dev-runtime-signals.contracts';
|
|
3
|
+
import type { PackageCompileLoop } from './package-compile-loop';
|
|
4
|
+
/**
|
|
5
|
+
* The dev supervisor of one NODE RUNTIME of an app-creator install — the backend, a minion, a node worker (#3214, #3215,
|
|
6
|
+
* #3216, #3257).
|
|
7
|
+
*
|
|
8
|
+
* It owns the runtime's process the way the monorepo's `runtime-supervisor.mjs` does for a framework developer, and keeps
|
|
9
|
+
* the promises the old `tsc-watch --onSuccess "node dist/index.js"` could not. They are written about the backend, where
|
|
10
|
+
* every one of them was measured; each holds for any runtime it supervises, see below:
|
|
11
|
+
*
|
|
12
|
+
* 1. **It starts the backend only on PUBLISHED builds.** The backend's own package and every workspace package it
|
|
13
|
+
* depends on must report `READY` (emitted, rewritten, verified — see `PackageCompileLoop`). A backend therefore never
|
|
14
|
+
* starts between `tsc` and its alias pass, which is how `ERR_MODULE_NOT_FOUND` reached it (#3216).
|
|
15
|
+
* 2. **It restarts the backend when ANY package it loads publishes a newer build**, the shared library included. Before
|
|
16
|
+
* this, only a change to the backend's own sources restarted it, and a fix landed in the shared library left the
|
|
17
|
+
* backend down on a tree that already booted (#3215).
|
|
18
|
+
* 3. **It owns the backend's process group**: the child leads its own group, and a restart or a stop signals the whole
|
|
19
|
+
* group. A second supervisor for the same package refuses to start, and a backend an earlier generation left behind
|
|
20
|
+
* (its supervisor killed outright) is stopped before a new one starts (#3214).
|
|
21
|
+
* 4. **A port another process holds is named, not retried into the ground.** When a start fails binding its port, the
|
|
22
|
+
* supervisor asks the operating system who listens there. The orphan of an earlier generation — `node <entry>` in this
|
|
23
|
+
* package — is stopped and the backend restarted; anything else pauses the supervisor with
|
|
24
|
+
* `PORT_HELD_BY_FOREIGN_PROCESS`, the holder's pid, parent, start time and working directory in its record and its
|
|
25
|
+
* log, and the backend starts the moment the port is free.
|
|
26
|
+
* 5. **A crash recovers by itself on the next build, and a dependency outage by itself (#3365).** A failed start is
|
|
27
|
+
* respawned with a bounded backoff. A spent budget pauses the supervisor only when the start record says the
|
|
28
|
+
* backend's own startup refused; the next published build of any package it loads starts it again. Any other cause
|
|
29
|
+
* (a dependency that did not answer, or no record) crash-loops: the delay keeps doubling up to
|
|
30
|
+
* {@link CRASH_LOOP_MAX_DELAY_MS} and never stops, so a database that comes back brings the backend back. A child
|
|
31
|
+
* resets the budget only once its own start record says it STARTED — or, for a runtime that writes no start record
|
|
32
|
+
* at all, once it stayed up {@link DEFAULT_HEALTHY_UPTIME_WITHOUT_START_RECORD_MS}.
|
|
33
|
+
* 6. **Nothing outlives it.** A stop terminates the backend and the compiler in parallel; an exit without one (an
|
|
34
|
+
* uncaught error, a forced stop) kills both groups synchronously on the way out.
|
|
35
|
+
*
|
|
36
|
+
* Its state is published at `<app>/.wildo-saas/runtime-signals/supervisors/<label>.json`, the record the dev companion's
|
|
37
|
+
* boot guard already reads, so a paused backend is visible to the build lane in this mode too.
|
|
38
|
+
*
|
|
39
|
+
* 7. **A restart can be ASKED for (#2134).** The supervisor creates `<app>/.wildo-saas/runtime-signals/<label>.signal`,
|
|
40
|
+
* names it in its record (`signalFilePath`), and restarts the runtime when the file's modification time changes, on
|
|
41
|
+
* the build it is already running, with a fresh crash budget. That is the door `wildo secrets set` uses: it regenerates
|
|
42
|
+
* the runtime's `.env` and touches the signal of every runtime that reads the key and whose supervisor is live, so the
|
|
43
|
+
* restarted process reads the new value. Before this the backend of a created application kept its boot-time value
|
|
44
|
+
* until `wildo local dev` was restarted, because this supervisor honoured no request and the CLI found no signal.
|
|
45
|
+
* A request arriving while a package it loads is not publishable waits for it, like any start (promise 1); one
|
|
46
|
+
* arriving while paused or backing off starts the runtime now; one arriving while a foreign process holds the port
|
|
47
|
+
* re-checks the port now. The same file the monorepo's `runtime-supervisor.mjs` honours under the same name, so the
|
|
48
|
+
* CLI needs no branch per mode.
|
|
49
|
+
*
|
|
50
|
+
* Rejected: a route per runtime that reloads its environment in place, as the companion has
|
|
51
|
+
* (`POST /api/companion/runtime/env/apply`). The backend's configuration is read once into services built at boot
|
|
52
|
+
* (provider clients, the mailer), so reloading `process.env` would change nothing they hold, and every runtime would
|
|
53
|
+
* need its own. A restart is the one remedy that is right for every runtime.
|
|
54
|
+
*
|
|
55
|
+
* ## Why one supervisor for every node runtime (#3257)
|
|
56
|
+
*
|
|
57
|
+
* Promises 1, 2, 3, 5 and 6 say nothing about HTTP, so a minion and a node worker get them by construction rather than
|
|
58
|
+
* through a copy that would drift: they start only on published builds of every workspace package they load (the
|
|
59
|
+
* shared library, and the backend whose companion exports a minion imports), restart when one of them publishes, and
|
|
60
|
+
* own their process group, so `wildo local dev` stopping leaves none of them re-parented to init.
|
|
61
|
+
*
|
|
62
|
+
* Promise 4 is the one backend-shaped decision, and it is taken from the START RECORD the engine's
|
|
63
|
+
* `StartApplicationBackendService.initialize` writes for the process (`failureCause: port-in-use`, with the port),
|
|
64
|
+
* looked up by the child's pid. A runtime whose start writes no such record never enters the branch; nothing has to be
|
|
65
|
+
* switched off. A minion binds no port and so never writes that cause. A node worker listens on its declared port and
|
|
66
|
+
* records its start through the same writer since #3288 (`StartWorkerApplicationBackendService.initialize`, filed as
|
|
67
|
+
* `workers.<name>`), so a port another process holds is named for it exactly as for the backend. The orphan of a
|
|
68
|
+
* supervisor killed outright is also stopped at {@link NodeRuntimeDevSupervisor.start}, through the supervisor record.
|
|
69
|
+
*
|
|
70
|
+
* The crash budget's reset (promise 5) also keys on the start record. The backend, a minion and a node worker all write
|
|
71
|
+
* one, but none does when its environment carries no runtime-signals home (a `.env` generated before #3288, an
|
|
72
|
+
* environment that is not LOCAL), and a child that dies before its bootstrap reaches the writer leaves none. Such a
|
|
73
|
+
* runtime would otherwise never reset the budget: five crashes spread over a day would spend it.
|
|
74
|
+
* For a process that left NO record at all, staying up {@link DEFAULT_HEALTHY_UPTIME_WITHOUT_START_RECORD_MS}
|
|
75
|
+
* counts as having started. Uptime stays out of the decision whenever a record exists, which is the case the uptime
|
|
76
|
+
* rule was wrong for (a start refused after twenty seconds of registry initialization).
|
|
77
|
+
*/
|
|
78
|
+
export declare const CRASH_RESPAWN_MAX_ATTEMPTS = 5;
|
|
79
|
+
/**
|
|
80
|
+
* How long a child that wrote NO start record must stay up before its exit counts as a fresh failure with a fresh
|
|
81
|
+
* budget. Only consulted when the process left no record at all; see the class JSDoc.
|
|
82
|
+
*/
|
|
83
|
+
export declare const DEFAULT_HEALTHY_UPTIME_WITHOUT_START_RECORD_MS = 60000;
|
|
84
|
+
/**
|
|
85
|
+
* The crash-loop cap (#3365): past the budget, a crash whose cause is a dependency (or cannot be told) keeps being
|
|
86
|
+
* restarted with the delay doubling up to five minutes, Kubernetes' CrashLoopBackOff ceiling, and never stops.
|
|
87
|
+
*/
|
|
88
|
+
export declare const CRASH_LOOP_MAX_DELAY_MS = 300000;
|
|
89
|
+
/**
|
|
90
|
+
* Whether a spent crash budget may PAUSE the runtime (#3365): only when its own start record says its startup refused,
|
|
91
|
+
* which a new build is what fixes. A dependency that did not answer or was not ready yet (`dependency-unreachable`,
|
|
92
|
+
* #3377), and a crash that left
|
|
93
|
+
* no record or one from an engine that names no cause, crash-loop instead: a database that comes back must bring its
|
|
94
|
+
* runtime back by itself. A port held by another process is decided before the budget is read (promise 4).
|
|
95
|
+
*/
|
|
96
|
+
export declare function spentCrashBudgetPauses(started: {
|
|
97
|
+
readonly outcome: BackendStartOutcome;
|
|
98
|
+
readonly failureCause?: BackendStartFailureCause;
|
|
99
|
+
} | undefined): boolean;
|
|
100
|
+
export interface NodeRuntimeDevSupervisorOptions {
|
|
101
|
+
readonly appRoot: string;
|
|
102
|
+
readonly packageRoot: string;
|
|
103
|
+
readonly packageName: string;
|
|
104
|
+
/**
|
|
105
|
+
* The runtime's name in the dev loop and the supervisor record's file name: `backend-api` for the backend, the
|
|
106
|
+
* minion's or worker's directory name otherwise. Two runtimes of one application must never share it — the record
|
|
107
|
+
* is how a second supervisor of the same runtime is refused.
|
|
108
|
+
*/
|
|
109
|
+
readonly label: string;
|
|
110
|
+
/** The entry module, absolute or relative to the package root (`dist/index.js`). */
|
|
111
|
+
readonly entry: string;
|
|
112
|
+
/** Arguments for `node` before the entry (`--import`, `--enable-source-maps`). */
|
|
113
|
+
readonly nodeArguments?: readonly string[];
|
|
114
|
+
/** The runtime package's own compiler, run in this process. */
|
|
115
|
+
readonly compileLoop: Pick<PackageCompileLoop, 'observation' | 'start' | 'stop' | 'killChildrenNow'>;
|
|
116
|
+
/** The workspace packages the runtime imports, whose compilers run in their own dev processes. */
|
|
117
|
+
readonly dependencyPackageNames: readonly string[];
|
|
118
|
+
/** How long to wait for a dependency's compile record before starting on the `dist` already on disk. */
|
|
119
|
+
readonly absentDependencyGraceMs?: number;
|
|
120
|
+
readonly pollIntervalMs?: number;
|
|
121
|
+
/** How long a new build must be settled before the runtime restarts on it (a burst of compilations restarts it once). */
|
|
122
|
+
readonly restartDebounceMs?: number;
|
|
123
|
+
/** See {@link DEFAULT_HEALTHY_UPTIME_WITHOUT_START_RECORD_MS}. */
|
|
124
|
+
readonly healthyUptimeWithoutStartRecordMs?: number;
|
|
125
|
+
readonly portRecheckIntervalMs?: number;
|
|
126
|
+
readonly log?: (line: string) => void;
|
|
127
|
+
}
|
|
128
|
+
/** Whether the packages a runtime loads are publishable, and the newest build among them. Pure. */
|
|
129
|
+
export declare function assessRuntimeBuilds(input: {
|
|
130
|
+
readonly own: LocalDevCompileObservation;
|
|
131
|
+
readonly dependencies: ReadonlyArray<{
|
|
132
|
+
readonly packageName: string;
|
|
133
|
+
readonly observation: LocalDevCompileObservation | undefined;
|
|
134
|
+
}>;
|
|
135
|
+
readonly dependencyGraceElapsed: boolean;
|
|
136
|
+
}): {
|
|
137
|
+
readonly ready: boolean;
|
|
138
|
+
readonly waitingFor: string | null;
|
|
139
|
+
readonly newestBuildAtMs: number;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Is the process on the port an orphaned runtime of THIS package — `node … <entry>` whose working directory is the
|
|
143
|
+
* package root — rather than something the supervisor must not touch? Pure.
|
|
144
|
+
*/
|
|
145
|
+
export declare function isOrphanedRuntimeOfPackage(holder: Pick<LocalDevPortHolder, 'cwd' | 'command'>, input: {
|
|
146
|
+
readonly packageRoot: string;
|
|
147
|
+
readonly entry: string;
|
|
148
|
+
}): boolean;
|
|
149
|
+
/** The start record this runtime process wrote, if any (the supervisor reads it to learn why a start failed). */
|
|
150
|
+
export declare function readBackendStartRecordOfProcess(appRoot: string, pid: number): BackendStartOutcomeRecord | undefined;
|
|
151
|
+
export declare class NodeRuntimeDevSupervisor {
|
|
152
|
+
private readonly options;
|
|
153
|
+
private readonly recordPath;
|
|
154
|
+
private readonly entryPath;
|
|
155
|
+
private readonly log;
|
|
156
|
+
private readonly startedAtMs;
|
|
157
|
+
private record;
|
|
158
|
+
private child;
|
|
159
|
+
private childStartedAtMs;
|
|
160
|
+
private expectedExit;
|
|
161
|
+
private stopping;
|
|
162
|
+
/**
|
|
163
|
+
* Held while ONE decision runs — a poll, or the handling of a child's exit. Both start children, so they must never
|
|
164
|
+
* interleave: a poll that spawned while an exit handler was stopping an orphan would put a second runtime on the port,
|
|
165
|
+
* and that one's failure would then name the first as the orphan.
|
|
166
|
+
*/
|
|
167
|
+
private busy;
|
|
168
|
+
private pollTimer;
|
|
169
|
+
private heartbeatTimer;
|
|
170
|
+
private backoffTimer;
|
|
171
|
+
private crashCount;
|
|
172
|
+
/** The newest build the supervisor was paused against; a build newer than it lifts a crash pause. */
|
|
173
|
+
private pausedAgainstBuildAtMs;
|
|
174
|
+
private heldPort;
|
|
175
|
+
private lastPortCheckAtMs;
|
|
176
|
+
private lastWaitingFor;
|
|
177
|
+
private loggedAbsentDependencies;
|
|
178
|
+
/** The restart-request file (promise 7) and its modification time when last read; `null` while it cannot be read. */
|
|
179
|
+
private readonly signalPath;
|
|
180
|
+
private lastSignalStamp;
|
|
181
|
+
/** A restart was asked for and is not served yet: the next start serves it. */
|
|
182
|
+
private restartRequested;
|
|
183
|
+
/**
|
|
184
|
+
* The dependency install (#3552) this supervisor already acted on, by its key. Seeded at {@link start} with an install
|
|
185
|
+
* that had already ended, so a supervisor started after an install never relaunches onto it.
|
|
186
|
+
*/
|
|
187
|
+
private handledInstallKey;
|
|
188
|
+
/** Whether the current install hold has been logged, so a 16 s install logs once rather than every poll. */
|
|
189
|
+
private loggedInstallHold;
|
|
190
|
+
constructor(options: NodeRuntimeDevSupervisorOptions);
|
|
191
|
+
get observation(): LocalDevSupervisorObservation;
|
|
192
|
+
/**
|
|
193
|
+
* Start supervising. REFUSES when another live supervisor already owns this runtime: two runtimes of one package is
|
|
194
|
+
* the defect this exists to prevent. A runtime left by a dead supervisor is stopped first.
|
|
195
|
+
*/
|
|
196
|
+
start(): Promise<void>;
|
|
197
|
+
/** Stop the runtime and the compiler, IN PARALLEL so a caller's stop deadline covers both. */
|
|
198
|
+
stop(): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* Kill the runtime and the compiler synchronously: the last act of a supervisor that is exiting without a clean stop
|
|
201
|
+
* (an uncaught error, a forced stop), so neither outlives it re-parented to init (#3214).
|
|
202
|
+
*/
|
|
203
|
+
killChildrenNow(): void;
|
|
204
|
+
private publish;
|
|
205
|
+
/** Run one decision at a time (see {@link busy}); a decision asked for while one runs is dropped, the next poll asks again. */
|
|
206
|
+
private serialized;
|
|
207
|
+
/**
|
|
208
|
+
* Create the restart-request file when absent, and take its current modification time as the baseline, so only a
|
|
209
|
+
* change made AFTER this supervisor started is a request. A file the supervisor cannot create leaves the runtime
|
|
210
|
+
* supervised as before, with the reason logged: a missing door must never stop the runtime.
|
|
211
|
+
*/
|
|
212
|
+
private prepareRestartSignal;
|
|
213
|
+
private readSignalStamp;
|
|
214
|
+
/** Whether the restart-request file changed since it was last read (promise 7). A file that vanished asks nothing. */
|
|
215
|
+
private takeRestartRequest;
|
|
216
|
+
/** The workspace dependencies' compile records, a record nobody live stands behind read as absent. */
|
|
217
|
+
private readDependencyObservations;
|
|
218
|
+
private decide;
|
|
219
|
+
/**
|
|
220
|
+
* A dependency install is a stack event (#3552). While one re-creates `node_modules`, nothing is started or restarted:
|
|
221
|
+
* a start would read a half-installed tree, and a running runtime keeps serving what it loaded. When it ends, the
|
|
222
|
+
* runtime is relaunched with a fresh crash budget — it loaded modules from the tree the install replaced, and a crash
|
|
223
|
+
* the install caused must not leave it paused. The relaunch waits, like every start, until every package it loads is
|
|
224
|
+
* publishable again (the compile loops recompile after an install too).
|
|
225
|
+
*/
|
|
226
|
+
private applyDependencyInstall;
|
|
227
|
+
private spawnChild;
|
|
228
|
+
private stopChild;
|
|
229
|
+
/** An exit is a decision too: it waits for a running poll to finish rather than interleave with it (see {@link busy}). */
|
|
230
|
+
private handleChildExitWhenFree;
|
|
231
|
+
private handleChildExit;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=node-runtime-dev-supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-runtime-dev-supervisor.d.ts","sourceRoot":"","sources":["../../../src/dev-runtime/node-runtime-dev-supervisor.ts"],"names":[],"mappings":"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"}
|