@_linked/server 2.17.0 → 2.19.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 +14 -0
- package/lib/esm/data/lincd-server.json +1 -1
- package/lib/esm/index.d.ts +2 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/ontologies/lincd-server.d.ts +12 -0
- package/lib/esm/ontologies/lincd-server.js +13 -1
- package/lib/esm/ontologies/lincd-server.js.map +1 -1
- package/lib/esm/shapes/LinkedServer.d.ts +32 -0
- package/lib/esm/shapes/LinkedServer.js +88 -4
- package/lib/esm/shapes/LinkedServer.js.map +1 -1
- package/lib/esm/utils/fatalError.d.ts +36 -0
- package/lib/esm/utils/fatalError.js +22 -0
- package/lib/esm/utils/fatalError.js.map +1 -0
- package/package.json +1 -1
- package/readme.md +20 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @\_linked/server
|
|
2
2
|
|
|
3
|
+
## 2.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#130](https://github.com/linked-fw/server/pull/130) [`e554786`](https://github.com/linked-fw/server/commit/e554786ed4b43738d820290c8ece89d0788c8fd8) Thanks [@flyon](https://github.com/flyon)! - A provider can refuse to let the server start. An error with an own `fatal: true` property thrown at boot — from a provider constructor, a backend module's top level, or a boot hook — is no longer isolated: it is logged as `[linked] <pkg> <hook>: fatal error, refusing to start: …`, `start()` / `initOnly()` reject with it, and the process exits with code 1. After boot (per-request hooks, lazy loads, HMR) it is logged as fatal and contained. Non-fatal errors are isolated as before. Adds `FatalStartupError` and `isFatalError` (`@_linked/server/utils/fatalError`, also exported from the package root).
|
|
8
|
+
|
|
9
|
+
## 2.18.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#128](https://github.com/linked-fw/server/pull/128) [`2b8e8ac`](https://github.com/linked-fw/server/commit/2b8e8acde912d91d8b706f09ca0a6e2663155c0c) Thanks [@flyon](https://github.com/flyon)! - The server ontology moves from `http://lincd.org/ont/lincd-server/` to `https://linked.cm/ont/server/`, the first-party scheme every public package uses (`https://linked.cm/ont/{publicSlug}/`, next to its shapes at `https://linked.cm/shape/server/`).
|
|
14
|
+
|
|
15
|
+
No data migration is needed. No stored data is typed with these terms (`LincdServer`, `LincdAPI`, `LincdWebApp`, `hasAPI`, …). The only store triples that carried them are the synced shape descriptions of `LinkedServer`, `LincdAPI` and `LincdWebApp` (`sh:targetClass`, `sh:path`); boot sync deletes and recreates each registered shape's description, so they move to the new IRIs the next time the server starts. With `syncShapesOnBoot: false` they keep the old IRIs until the next sync. The prefix key (`lincd-server`) and the `ontologies/lincd-server` module are unchanged; code that hard-codes `http://lincd.org/ont/lincd-server/` must be updated.
|
|
16
|
+
|
|
3
17
|
## 2.17.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"owl": "http://www.w3.org/2002/07/owl#",
|
|
5
5
|
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
6
6
|
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
|
|
7
|
-
"lincd-server": "
|
|
7
|
+
"lincd-server": "https://linked.cm/ont/server/"
|
|
8
8
|
},
|
|
9
9
|
"@graph": [
|
|
10
10
|
{
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -4,4 +4,6 @@ import './shapes/index.js';
|
|
|
4
4
|
import './shapes/quadstores/BackendAPIStore.js';
|
|
5
5
|
import './shapes/filestores/LocalFileStore.js';
|
|
6
6
|
import './utils/accessUrl.js';
|
|
7
|
+
export { FatalStartupError, isFatalError } from './utils/fatalError.js';
|
|
8
|
+
export type { FatalError } from './utils/fatalError.js';
|
|
7
9
|
export type { RouteConfig, RoutesConfig, RoutesModule, } from '@_linked/server-utils/types/RouteConfig';
|
package/lib/esm/index.js
CHANGED
|
@@ -7,4 +7,6 @@ import './shapes/quadstores/BackendAPIStore.js';
|
|
|
7
7
|
import './shapes/filestores/LocalFileStore.js';
|
|
8
8
|
//THEN COMPONENTS
|
|
9
9
|
import './utils/accessUrl.js';
|
|
10
|
+
// The fatal-error contract a provider uses to refuse to let the server start.
|
|
11
|
+
export { FatalStartupError, isFatalError } from './utils/fatalError.js';
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,CAAC;AACpB,OAAO,uCAAuC,CAAC;AAE/C,cAAc;AACd,OAAO,mBAAmB,CAAC;AAC3B,mFAAmF;AACnF,OAAO,wCAAwC,CAAC;AAChD,OAAO,uCAAuC,CAAC;AAE/C,iBAAiB;AACjB,OAAO,sBAAsB,CAAC","sourcesContent":["import './types.js';\nimport './ontologies/lincd-server.register.js';\n\n//SHAPES FIRST\nimport './shapes/index.js';\n// Not shapes (plain store classes); kept so the entry's module graph is unchanged.\nimport './shapes/quadstores/BackendAPIStore.js';\nimport './shapes/filestores/LocalFileStore.js';\n\n//THEN COMPONENTS\nimport './utils/accessUrl.js';\n\n//TYPES — re-exported from @_linked/server-utils (canonical location)\nexport type {\n RouteConfig,\n RoutesConfig,\n RoutesModule,\n} from '@_linked/server-utils/types/RouteConfig';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,CAAC;AACpB,OAAO,uCAAuC,CAAC;AAE/C,cAAc;AACd,OAAO,mBAAmB,CAAC;AAC3B,mFAAmF;AACnF,OAAO,wCAAwC,CAAC;AAChD,OAAO,uCAAuC,CAAC;AAE/C,iBAAiB;AACjB,OAAO,sBAAsB,CAAC;AAE9B,8EAA8E;AAC9E,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["import './types.js';\nimport './ontologies/lincd-server.register.js';\n\n//SHAPES FIRST\nimport './shapes/index.js';\n// Not shapes (plain store classes); kept so the entry's module graph is unchanged.\nimport './shapes/quadstores/BackendAPIStore.js';\nimport './shapes/filestores/LocalFileStore.js';\n\n//THEN COMPONENTS\nimport './utils/accessUrl.js';\n\n// The fatal-error contract a provider uses to refuse to let the server start.\nexport { FatalStartupError, isFatalError } from './utils/fatalError.js';\nexport type { FatalError } from './utils/fatalError.js';\n\n//TYPES — re-exported from @_linked/server-utils (canonical location)\nexport type {\n RouteConfig,\n RoutesConfig,\n RoutesModule,\n} from '@_linked/server-utils/types/RouteConfig';\n"]}
|
|
@@ -20,6 +20,18 @@ export declare var loadData: () => Promise<{
|
|
|
20
20
|
"rdfs:label": string;
|
|
21
21
|
}[];
|
|
22
22
|
}>;
|
|
23
|
+
/**
|
|
24
|
+
* The namespace of this ontology.
|
|
25
|
+
*
|
|
26
|
+
* First-party ontologies live on linked.cm: `https://linked.cm/ont/{ontologySlug}/`, and a
|
|
27
|
+
* package's own ontology takes the package's publicSlug (`@_linked/server` → `server`), the same
|
|
28
|
+
* slug its shapes use under `https://linked.cm/shape/server/`.
|
|
29
|
+
*
|
|
30
|
+
* Until this release it was `http://lincd.org/ont/lincd-server/`. No stored data is typed with
|
|
31
|
+
* these terms; the only store triples that carried them were the synced shape descriptions of
|
|
32
|
+
* `LinkedServer`, `LincdAPI` and `LincdWebApp` (`sh:targetClass`, `sh:path`), which boot sync
|
|
33
|
+
* rewrites (delete, then recreate) the next time the server starts.
|
|
34
|
+
*/
|
|
23
35
|
export declare var ns: (term: string) => import("@_linked/core/utils/NodeReference").NodeReferenceValue;
|
|
24
36
|
export declare var _self: import("@_linked/core/utils/NodeReference").NodeReferenceValue;
|
|
25
37
|
export declare const lincdServer: {
|
|
@@ -10,7 +10,19 @@ export var loadData = async () => {
|
|
|
10
10
|
});
|
|
11
11
|
return data.default || data;
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The namespace of this ontology.
|
|
15
|
+
*
|
|
16
|
+
* First-party ontologies live on linked.cm: `https://linked.cm/ont/{ontologySlug}/`, and a
|
|
17
|
+
* package's own ontology takes the package's publicSlug (`@_linked/server` → `server`), the same
|
|
18
|
+
* slug its shapes use under `https://linked.cm/shape/server/`.
|
|
19
|
+
*
|
|
20
|
+
* Until this release it was `http://lincd.org/ont/lincd-server/`. No stored data is typed with
|
|
21
|
+
* these terms; the only store triples that carried them were the synced shape descriptions of
|
|
22
|
+
* `LinkedServer`, `LincdAPI` and `LincdWebApp` (`sh:targetClass`, `sh:path`), which boot sync
|
|
23
|
+
* rewrites (delete, then recreate) the next time the server starts.
|
|
24
|
+
*/
|
|
25
|
+
export var ns = createNameSpace('https://linked.cm/ont/server/');
|
|
14
26
|
export var _self = ns('');
|
|
15
27
|
// Terms are properties of the namespace object below, not module-scope
|
|
16
28
|
// exports. Most of these names are also SHAPE CLASS names in this package
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lincd-server.js","sourceRoot":"","sources":["../../../src/ontologies/lincd-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,IAAI,QAAQ,GAAG,KAAK,IAAI,EAAE;IAC/B,YAAY;IACZ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,2BAA2B,EAAE;QACrD,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;KACvB,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,CAAC,IAAI,EAAE,GAAG,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"lincd-server.js","sourceRoot":"","sources":["../../../src/ontologies/lincd-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,IAAI,QAAQ,GAAG,KAAK,IAAI,EAAE;IAC/B,YAAY;IACZ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,2BAA2B,EAAE;QACrD,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;KACvB,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;AAC9B,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,IAAI,EAAE,GAAG,eAAe,CAAC,+BAA+B,CAAC,CAAC;AAEjE,MAAM,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAE1B,uEAAuE;AACvE,0EAA0E;AAC1E,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,2EAA2E;AAC3E,0EAA0E;AAC1E,MAAM,WAAW,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC;AACtC,MAAM,gBAAgB,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;AAChD,MAAM,aAAa,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;AAC1C,MAAM,YAAY,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;AACxC,MAAM,eAAe,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC;AACtC,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC;AACpC,MAAM,gBAAgB,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;AAChD,MAAM,WAAW,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC;AACtC,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;AAChC,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW;IACX,gBAAgB;IAChB,aAAa;IACb,YAAY;IACZ,WAAW;IACX,eAAe;IACf,WAAW;IACX,UAAU;IACV,gBAAgB;IAChB,QAAQ;IACR,MAAM;CACP,CAAC","sourcesContent":["import { createNameSpace } from '@_linked/core/utils/NameSpace';\n\n/**\n * Load the data of this ontology.\n * In @_linked/core, loadData returns the raw JSON import — no JSONLD.parse() needed.\n */\nexport var loadData = async () => {\n //@ts-ignore\n const data = await import('../data/lincd-server.json', {\n with: { type: 'json' },\n });\n return data.default || data;\n};\n\n/**\n * The namespace of this ontology.\n *\n * First-party ontologies live on linked.cm: `https://linked.cm/ont/{ontologySlug}/`, and a\n * package's own ontology takes the package's publicSlug (`@_linked/server` → `server`), the same\n * slug its shapes use under `https://linked.cm/shape/server/`.\n *\n * Until this release it was `http://lincd.org/ont/lincd-server/`. No stored data is typed with\n * these terms; the only store triples that carried them were the synced shape descriptions of\n * `LinkedServer`, `LincdAPI` and `LincdWebApp` (`sh:targetClass`, `sh:path`), which boot sync\n * rewrites (delete, then recreate) the next time the server starts.\n */\nexport var ns = createNameSpace('https://linked.cm/ont/server/');\n\nexport var _self = ns('');\n\n// Terms are properties of the namespace object below, not module-scope\n// exports. Most of these names are also SHAPE CLASS names in this package\n// (BackendAPIStore, LincdWebApp, LincdAPI, ...). Two bindings of the same name\n// in one bundle scope make the bundler rename one of them, and when the loser\n// is the class, `constructor.name` becomes `BackendAPIStore2` -- which is the\n// shape's IRI and the name `Server.call` routes on. The client then asks a\n// backend that has no such shape, and every store round-trip answers 501.\nconst LincdServer = ns('LincdServer');\nconst BackendFileStore = ns('BackendFileStore');\nconst NodeFileStore = ns('NodeFileStore');\nconst BackendStore = ns('BackendStore');\nconst BackendAPIStore = ns('BackendAPIStore');\nconst LincdWebApp = ns('LincdWebApp');\nconst ownPackage = ns('ownPackage');\nconst maintainsPackage = ns('maintainsPackage');\nconst N3FileStore = ns('N3FileStore');\nconst LincdAPI = ns('LincdAPI');\nconst hasAPI = ns('hasAPI');\n\nexport const lincdServer = {\n LincdServer,\n BackendFileStore,\n NodeFileStore,\n BackendStore,\n N3FileStore,\n BackendAPIStore,\n LincdWebApp,\n ownPackage,\n maintainsPackage,\n LincdAPI,\n hasAPI,\n};\n\n"]}
|
|
@@ -51,6 +51,12 @@ export declare class LinkedServer extends Shape {
|
|
|
51
51
|
private warnedDuplicateInstalls;
|
|
52
52
|
private resizePathsMap;
|
|
53
53
|
private api;
|
|
54
|
+
/**
|
|
55
|
+
* True while start() / initOnly() runs. A fatal provider error (see
|
|
56
|
+
* utils/fatalError) thrown while booting stops the boot; after it, the same
|
|
57
|
+
* error is logged and contained.
|
|
58
|
+
*/
|
|
59
|
+
protected booting: boolean;
|
|
54
60
|
/**
|
|
55
61
|
* yarn linked start sends the contents of linked.config.js as an object to this constructor
|
|
56
62
|
* @param n
|
|
@@ -61,6 +67,7 @@ export declare class LinkedServer extends Shape {
|
|
|
61
67
|
get app(): ExpressServer;
|
|
62
68
|
initPackage(): void;
|
|
63
69
|
initOnly(): Promise<this>;
|
|
70
|
+
private initOnlyBoot;
|
|
64
71
|
/**
|
|
65
72
|
* Materialize this server's registered shapes into the RDF store as SHACL
|
|
66
73
|
* (core `syncShapes` → pure `sh:NodeShape` + property shapes), so a running
|
|
@@ -79,7 +86,32 @@ export declare class LinkedServer extends Shape {
|
|
|
79
86
|
* config.
|
|
80
87
|
*/
|
|
81
88
|
private materializeShapesIntoStore;
|
|
89
|
+
/**
|
|
90
|
+
* Boot the server and listen. Rejects — and makes the process exit non-zero —
|
|
91
|
+
* when a provider throws a fatal error while booting (see utils/fatalError).
|
|
92
|
+
*/
|
|
82
93
|
start(): Promise<this>;
|
|
94
|
+
/**
|
|
95
|
+
* Run a boot with `booting` set. A fatal provider error rejects it and hands
|
|
96
|
+
* the error to exitAfterFatalStartupError; any other boot error rejects as it
|
|
97
|
+
* always did.
|
|
98
|
+
*/
|
|
99
|
+
private bootOrRefuse;
|
|
100
|
+
/**
|
|
101
|
+
* Make sure a server that refused to start does not stay up as a process.
|
|
102
|
+
*
|
|
103
|
+
* start() rejects either way, so the caller can report the error. But a
|
|
104
|
+
* rejected start() does not end the process on its own: the CLI's `linked
|
|
105
|
+
* start` turns an unhandled rejection into a log line, and the Vite dev
|
|
106
|
+
* server, a store connection or a provider's timer keeps the event loop
|
|
107
|
+
* alive. So the exit code is set now — a process with nothing left running
|
|
108
|
+
* exits 1 — and, as a backstop, the process is exited after a moment, on an
|
|
109
|
+
* unref'd timer that never itself keeps the process alive.
|
|
110
|
+
*
|
|
111
|
+
* Override to embed the server somewhere that must not exit (tests).
|
|
112
|
+
*/
|
|
113
|
+
protected exitAfterFatalStartupError(_err: unknown): void;
|
|
114
|
+
private startBoot;
|
|
83
115
|
initOntologies(): Promise<void>;
|
|
84
116
|
/**
|
|
85
117
|
*
|
|
@@ -37,6 +37,7 @@ import { autoLoadOntologyData } from '@_linked/core/utils/Package';
|
|
|
37
37
|
import { getShapeClass, getSuperShapesClasses, } from '@_linked/core/utils/ShapeClass';
|
|
38
38
|
import path from 'path';
|
|
39
39
|
import { pathToFileURL } from 'node:url';
|
|
40
|
+
import { isFatalError } from '../utils/fatalError.js';
|
|
40
41
|
import { discoverLinkedDependencies, isBundledBySsr, NODE_IMPORT_CONDITIONS, readInstalledPackage, resolveBackendEntry, ssrNoExternalOf, } from '../utils/linkedDependencies.js';
|
|
41
42
|
/**
|
|
42
43
|
* `instanceof ShapeProvider`, tolerating a second copy of server-utils.
|
|
@@ -63,16 +64,38 @@ function isShapeProvider(provider) {
|
|
|
63
64
|
* for hooks that run for every provider (boot lifecycle hooks and per-request
|
|
64
65
|
* hooks), where one provider's bug must not take down boot or every request
|
|
65
66
|
* without saying which provider it was.
|
|
67
|
+
*
|
|
68
|
+
* The exception is a fatal error (see utils/fatalError): with `atBoot` it is
|
|
69
|
+
* logged and re-thrown, so the server refuses to start. Without it — the
|
|
70
|
+
* server is already serving — it is logged as fatal and contained like any
|
|
71
|
+
* other error: one provider must not take a running server down.
|
|
66
72
|
*/
|
|
67
|
-
async function runProviderHook(pkg, hook, call) {
|
|
73
|
+
async function runProviderHook(pkg, hook, call, atBoot = false) {
|
|
68
74
|
var _a;
|
|
69
75
|
try {
|
|
70
76
|
await call();
|
|
71
77
|
}
|
|
72
78
|
catch (err) {
|
|
79
|
+
if (isFatalError(err)) {
|
|
80
|
+
logFatalError(pkg, hook, err, atBoot);
|
|
81
|
+
if (atBoot)
|
|
82
|
+
throw err;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
73
85
|
console.error(paint('red', `[linked] ${pkg} ${hook} failed: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`), (err === null || err === void 0 ? void 0 : err.stack) ? `\n${err.stack}` : '');
|
|
74
86
|
}
|
|
75
87
|
}
|
|
88
|
+
/** Log a fatal error once, at the point it was thrown (see runProviderHook). */
|
|
89
|
+
function logFatalError(pkg, hook, err, atBoot) {
|
|
90
|
+
var _a, _b;
|
|
91
|
+
if (loggedFatalErrors.has(err))
|
|
92
|
+
return;
|
|
93
|
+
loggedFatalErrors.add(err);
|
|
94
|
+
console.error(paint('red', atBoot
|
|
95
|
+
? `[linked] ${pkg} ${hook}: fatal error, refusing to start: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`
|
|
96
|
+
: `[linked] ${pkg} ${hook}: fatal error after start, server keeps running: ${(_b = err === null || err === void 0 ? void 0 : err.message) !== null && _b !== void 0 ? _b : err}`), (err === null || err === void 0 ? void 0 : err.stack) ? `\n${err.stack}` : '');
|
|
97
|
+
}
|
|
98
|
+
const loggedFatalErrors = new WeakSet();
|
|
76
99
|
import process from 'process';
|
|
77
100
|
import * as React from 'react';
|
|
78
101
|
import { renderToPipeableStream, renderToStaticMarkup } from 'react-dom/server';
|
|
@@ -178,6 +201,12 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
178
201
|
this.warnedDuplicateInstalls = new Set();
|
|
179
202
|
//from resizedFileName to full resized path (CDN or similar)
|
|
180
203
|
this.resizePathsMap = new Map();
|
|
204
|
+
/**
|
|
205
|
+
* True while start() / initOnly() runs. A fatal provider error (see
|
|
206
|
+
* utils/fatalError) thrown while booting stops the boot; after it, the same
|
|
207
|
+
* error is logged and contained.
|
|
208
|
+
*/
|
|
209
|
+
this.booting = false;
|
|
181
210
|
if (config && typeof config !== 'string' && !('id' in config)) {
|
|
182
211
|
// The absence of `id` is the runtime discriminator for a LinkedConfig;
|
|
183
212
|
// the widened `{id?: string}` member of the union keeps TS from narrowing
|
|
@@ -232,6 +261,9 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
232
261
|
this.package = JSON.parse(fsNative.readFileSync(path.resolve(process.cwd(), 'package.json'), 'utf-8'));
|
|
233
262
|
}
|
|
234
263
|
async initOnly() {
|
|
264
|
+
return this.bootOrRefuse(() => this.initOnlyBoot());
|
|
265
|
+
}
|
|
266
|
+
async initOnlyBoot() {
|
|
235
267
|
await this.initOntologies();
|
|
236
268
|
await this.initStores();
|
|
237
269
|
this.initPackage();
|
|
@@ -290,7 +322,50 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
290
322
|
// return nodeURI.includes(store.namedNode.uri)
|
|
291
323
|
// })
|
|
292
324
|
// }
|
|
325
|
+
/**
|
|
326
|
+
* Boot the server and listen. Rejects — and makes the process exit non-zero —
|
|
327
|
+
* when a provider throws a fatal error while booting (see utils/fatalError).
|
|
328
|
+
*/
|
|
293
329
|
async start() {
|
|
330
|
+
return this.bootOrRefuse(() => this.startBoot());
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Run a boot with `booting` set. A fatal provider error rejects it and hands
|
|
334
|
+
* the error to exitAfterFatalStartupError; any other boot error rejects as it
|
|
335
|
+
* always did.
|
|
336
|
+
*/
|
|
337
|
+
async bootOrRefuse(boot) {
|
|
338
|
+
this.booting = true;
|
|
339
|
+
try {
|
|
340
|
+
return await boot();
|
|
341
|
+
}
|
|
342
|
+
catch (err) {
|
|
343
|
+
if (isFatalError(err))
|
|
344
|
+
this.exitAfterFatalStartupError(err);
|
|
345
|
+
throw err;
|
|
346
|
+
}
|
|
347
|
+
finally {
|
|
348
|
+
this.booting = false;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Make sure a server that refused to start does not stay up as a process.
|
|
353
|
+
*
|
|
354
|
+
* start() rejects either way, so the caller can report the error. But a
|
|
355
|
+
* rejected start() does not end the process on its own: the CLI's `linked
|
|
356
|
+
* start` turns an unhandled rejection into a log line, and the Vite dev
|
|
357
|
+
* server, a store connection or a provider's timer keeps the event loop
|
|
358
|
+
* alive. So the exit code is set now — a process with nothing left running
|
|
359
|
+
* exits 1 — and, as a backstop, the process is exited after a moment, on an
|
|
360
|
+
* unref'd timer that never itself keeps the process alive.
|
|
361
|
+
*
|
|
362
|
+
* Override to embed the server somewhere that must not exit (tests).
|
|
363
|
+
*/
|
|
364
|
+
exitAfterFatalStartupError(_err) {
|
|
365
|
+
process.exitCode = 1;
|
|
366
|
+
setTimeout(() => process.exit(1), 1000).unref();
|
|
367
|
+
}
|
|
368
|
+
async startBoot() {
|
|
294
369
|
var _a, _b, _c, _d;
|
|
295
370
|
this.initPackage();
|
|
296
371
|
// Static assets should come from the static store URL (versioned path),
|
|
@@ -563,7 +638,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
563
638
|
if (!genericProvider || typeof genericProvider[method] !== 'function') {
|
|
564
639
|
continue;
|
|
565
640
|
}
|
|
566
|
-
await runProviderHook(pkg, method, () => genericProvider[method](...args));
|
|
641
|
+
await runProviderHook(pkg, method, () => genericProvider[method](...args), this.booting);
|
|
567
642
|
}
|
|
568
643
|
}
|
|
569
644
|
/**
|
|
@@ -627,6 +702,9 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
627
702
|
});
|
|
628
703
|
}
|
|
629
704
|
catch (err) {
|
|
705
|
+
// Already logged where it was thrown; it must reach start().
|
|
706
|
+
if (isFatalError(err))
|
|
707
|
+
throw err;
|
|
630
708
|
console.warn(err);
|
|
631
709
|
}
|
|
632
710
|
}
|
|
@@ -1053,6 +1131,12 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
1053
1131
|
// console.log(`✅ Successfully loaded: ${pkg}`);
|
|
1054
1132
|
}
|
|
1055
1133
|
catch (e) {
|
|
1134
|
+
if (isFatalError(e)) {
|
|
1135
|
+
logFatalError(pkg, 'module load', e, this.booting);
|
|
1136
|
+
if (this.booting)
|
|
1137
|
+
throw e;
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1056
1140
|
let providerNotFound = e.code === 'MODULE_NOT_FOUND' &&
|
|
1057
1141
|
e.message.indexOf(`Cannot find package '${pkg}'`) !== -1;
|
|
1058
1142
|
if (providerNotFound) {
|
|
@@ -1168,7 +1252,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
1168
1252
|
await runProviderHook(pkg, `backend ${entry}`, async () => {
|
|
1169
1253
|
backendProviderExports = await load();
|
|
1170
1254
|
loaded = true;
|
|
1171
|
-
});
|
|
1255
|
+
}, this.booting);
|
|
1172
1256
|
if (loaded) {
|
|
1173
1257
|
for (const key of Object.keys(backendProviderExports)) {
|
|
1174
1258
|
const providerClass = backendProviderExports[key];
|
|
@@ -1177,7 +1261,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
1177
1261
|
//TODO: do not create an instance, just save the class and instantiate it when needed
|
|
1178
1262
|
await runProviderHook(pkg, `${key} constructor`, () => {
|
|
1179
1263
|
provider = new providerClass(this.server, this);
|
|
1180
|
-
});
|
|
1264
|
+
}, this.booting);
|
|
1181
1265
|
if (!provider)
|
|
1182
1266
|
continue;
|
|
1183
1267
|
if (isShapeProvider(provider)) {
|