@_linked/server 3.6.0 → 3.7.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 +33 -0
- package/lib/esm/data/server.ttl +75 -0
- package/lib/esm/ontologies/server.d.ts +4 -22
- package/lib/esm/ontologies/server.js +5 -11
- package/lib/esm/ontologies/server.js.map +1 -1
- package/lib/esm/ontologies/server.register.js +3 -3
- package/lib/esm/ontologies/server.register.js.map +1 -1
- package/lib/esm/package.d.ts +1 -1
- package/lib/esm/shapes/LinkedServer.d.ts +39 -9
- package/lib/esm/shapes/LinkedServer.js +104 -25
- package/lib/esm/shapes/LinkedServer.js.map +1 -1
- package/lib/esm/utils/adminChannel.d.ts +28 -0
- package/lib/esm/utils/adminChannel.js +35 -4
- package/lib/esm/utils/adminChannel.js.map +1 -1
- package/lib/esm/utils/linkedDependencies.d.ts +7 -0
- package/lib/esm/utils/linkedDependencies.js +29 -0
- package/lib/esm/utils/linkedDependencies.js.map +1 -1
- package/lib/esm/utils/ontologySync.d.ts +126 -0
- package/lib/esm/utils/ontologySync.js +124 -0
- package/lib/esm/utils/ontologySync.js.map +1 -0
- package/lib/esm/utils/withTimeout.d.ts +7 -0
- package/lib/esm/utils/withTimeout.js +17 -0
- package/lib/esm/utils/withTimeout.js.map +1 -0
- package/package.json +4 -4
- package/readme.md +29 -0
- package/lib/esm/data/server.json +0 -47
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @\_linked/server
|
|
2
2
|
|
|
3
|
+
## 3.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#202](https://github.com/linked-fw/server/pull/202) [`9e9cf47`](https://github.com/linked-fw/server/commit/9e9cf479c42c82a287a640c6f02c300186653176) Thanks [@flyon](https://github.com/flyon)! - Ontology data: labels, descriptions and types for every term.
|
|
8
|
+
|
|
9
|
+
- `src/data/server.ttl` gains the ontology node (`dcterms:title`, `dcterms:description`,
|
|
10
|
+
`owl:versionInfo`) and the seven terms it lacked (`LincdWebApp`, `LincdAPI`, `hasAPI`,
|
|
11
|
+
`N3FileStore`, `BackendAPIStore`, `ownPackage`, `maintainsPackage`), and is written in the
|
|
12
|
+
deterministic Turtle form. All 11 terms are typed (`owl:Class`, was `rdfs:Class`, or
|
|
13
|
+
`owl:ObjectProperty`) with an English label and comment; the labels say "Linked", not "LINCD".
|
|
14
|
+
- Two axioms: `server:BackendFileStore` and `server:BackendAPIStore` are `rdfs:subClassOf`
|
|
15
|
+
`server:BackendStore`. No shape targets these classes.
|
|
16
|
+
|
|
17
|
+
- [#202](https://github.com/linked-fw/server/pull/202) [`4e992f4`](https://github.com/linked-fw/server/commit/4e992f458ab3366bbd673a74d12105217c289190) Thanks [@flyon](https://github.com/flyon)! - The server syncs the class hierarchy of every registered ontology into its app data and runs core's shape check before its shape sync, at boot and on `POST /admin/sync-shapes`, whose answer gains `ontologies: {written, skipped}` and `shapeCheck: {errors, warnings}`. The boot's ontology sync follows the shape sync's switches; `LINKED_SYNC_ONTOLOGIES_ON_BOOT=false` turns off only it. The server's own ontology data is Turtle (`data/server.ttl`), and the server no longer calls `autoLoadOntologyData`.
|
|
18
|
+
|
|
19
|
+
- [#202](https://github.com/linked-fw/server/pull/202) [`4fcafde`](https://github.com/linked-fw/server/commit/4fcafde29dca73f34d45ce5054f24dba79f0d89b) Thanks [@flyon](https://github.com/flyon)! - At boot and on `POST /admin/sync-shapes`, every linked package the server discovered in the app's
|
|
20
|
+
dependency tree registers its ontologies (core `registerInstalledOntologies`) before the ontology
|
|
21
|
+
sync and the shape check, so a package the app only deep-imports shape files from
|
|
22
|
+
(`@_linked/schema/shapes/Person`) is synced and checked too.
|
|
23
|
+
|
|
24
|
+
- [#202](https://github.com/linked-fw/server/pull/202) [`49a02be`](https://github.com/linked-fw/server/commit/49a02bea25b9526bf732a01db20cd1a33b9560e0) Thanks [@flyon](https://github.com/flyon)! - The ontology registration before the sync and the shape check also covers the app's own workspace
|
|
25
|
+
packages (`linkedPackage: true` under its `workspaces`), which the dependency walk misses when no
|
|
26
|
+
package imports them (a Create Now clone's `packages/<slug>-ont`). In dev, a package without a
|
|
27
|
+
built `lib/` registers from `src/ontologies/*.register.ts` through Vite's `ssrLoadModule` (core
|
|
28
|
+
`registerInstalledOntologies`' `importModule`); a built app skips it.
|
|
29
|
+
|
|
30
|
+
## 3.6.1
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- [#200](https://github.com/linked-fw/server/pull/200) [`935d0ca`](https://github.com/linked-fw/server/commit/935d0caf014cae8c71ae3b40963305ac8d43792c) Thanks [@flyon](https://github.com/flyon)! - `POST /admin/sync-shapes` now answers which packages it reloaded (`reloaded`) and the node shapes registered afterwards (`shapes`), refuses (400) package names that are not valid npm names, `@_linked/*` packages, or neither the app nor one of its direct dependencies, and times out a hung sync (`LINKED_SHAPE_SYNC_TIMEOUT_MS`, default 120 s) or source reload (`LINKED_SOURCE_RELOAD_TIMEOUT_MS`, default 60 s) so the queue is released. The README documents the control channel and the side effects of a reload and a restart.
|
|
35
|
+
|
|
3
36
|
## 3.6.0
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
@prefix server: <https://linked.cm/ont/server/> .
|
|
2
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
3
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
4
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
5
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
6
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
|
7
|
+
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
|
|
8
|
+
@prefix schema: <http://schema.org/> .
|
|
9
|
+
|
|
10
|
+
server:
|
|
11
|
+
a owl:Ontology ;
|
|
12
|
+
dcterms:description "Terms of the Linked Node.js server: the server, the web app it serves and its data API."@en ;
|
|
13
|
+
dcterms:title "Linked server"@en ;
|
|
14
|
+
owl:versionInfo "3.7.0" .
|
|
15
|
+
|
|
16
|
+
server:BackendAPIStore
|
|
17
|
+
a owl:Class ;
|
|
18
|
+
rdfs:comment "A frontend store that sends every query to the Linked server's data API instead of holding quads locally."@en ;
|
|
19
|
+
rdfs:label "backend API store"@en ;
|
|
20
|
+
rdfs:subClassOf server:BackendStore .
|
|
21
|
+
|
|
22
|
+
server:BackendFileStore
|
|
23
|
+
a owl:Class ;
|
|
24
|
+
rdfs:comment "A frontend quad store that loads and updates its quads through API calls to the Linked server's backend."@en ;
|
|
25
|
+
rdfs:isDefinedBy server: ;
|
|
26
|
+
rdfs:label "backend file store"@en ;
|
|
27
|
+
rdfs:subClassOf server:BackendStore .
|
|
28
|
+
|
|
29
|
+
server:BackendStore
|
|
30
|
+
a owl:Class ;
|
|
31
|
+
rdfs:comment "The base class of frontend quad stores that are loaded and updated through the Linked server's backend API."@en ;
|
|
32
|
+
rdfs:isDefinedBy server: ;
|
|
33
|
+
rdfs:label "backend store"@en .
|
|
34
|
+
|
|
35
|
+
server:LincdAPI
|
|
36
|
+
a owl:Class ;
|
|
37
|
+
rdfs:comment "The server's data API endpoint, which answers select, update, create, delete and raw SPARQL calls from the client (LincdAPI.process)."@en ;
|
|
38
|
+
rdfs:label "Linked data API"@en .
|
|
39
|
+
|
|
40
|
+
server:LincdServer
|
|
41
|
+
a owl:Class ;
|
|
42
|
+
rdfs:comment "The Node.js HTTP server that serves a Linked app, its assets and its /call and data API routes (LinkedServer)."@en ;
|
|
43
|
+
rdfs:isDefinedBy server: ;
|
|
44
|
+
rdfs:label "Linked server"@en .
|
|
45
|
+
|
|
46
|
+
server:LincdWebApp
|
|
47
|
+
a owl:Class ;
|
|
48
|
+
rdfs:comment "A Linked web app as the server knows it: the site at SITE_ROOT, with the data API it exposes."@en ;
|
|
49
|
+
rdfs:label "Linked web app"@en .
|
|
50
|
+
|
|
51
|
+
server:N3FileStore
|
|
52
|
+
a owl:Class ;
|
|
53
|
+
rdfs:comment "A quad store that keeps its quads in an N3/Turtle file on a Node.js server."@en ;
|
|
54
|
+
rdfs:label "N3 file store"@en .
|
|
55
|
+
|
|
56
|
+
server:NodeFileStore
|
|
57
|
+
a owl:Class ;
|
|
58
|
+
rdfs:comment "A quad store that keeps its quads in a JSON-LD file on a Node.js server."@en ;
|
|
59
|
+
rdfs:isDefinedBy server: ;
|
|
60
|
+
rdfs:label "Node file store"@en .
|
|
61
|
+
|
|
62
|
+
server:hasAPI
|
|
63
|
+
a owl:ObjectProperty ;
|
|
64
|
+
rdfs:comment "Links a web app to the client of its data API."@en ;
|
|
65
|
+
rdfs:label "has API"@en .
|
|
66
|
+
|
|
67
|
+
server:maintainsPackage
|
|
68
|
+
a owl:ObjectProperty ;
|
|
69
|
+
rdfs:comment "Links a web app to a package it maintains."@en ;
|
|
70
|
+
rdfs:label "maintains package"@en .
|
|
71
|
+
|
|
72
|
+
server:ownPackage
|
|
73
|
+
a owl:ObjectProperty ;
|
|
74
|
+
rdfs:comment "Links a web app to the npm package that is its own code."@en ;
|
|
75
|
+
rdfs:label "own package"@en .
|
|
@@ -1,25 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare var loadData: () => Promise<{
|
|
6
|
-
"@context": {
|
|
7
|
-
dc: string;
|
|
8
|
-
owl: string;
|
|
9
|
-
rdf: string;
|
|
10
|
-
rdfs: string;
|
|
11
|
-
server: string;
|
|
12
|
-
};
|
|
13
|
-
"@graph": {
|
|
14
|
-
"@id": string;
|
|
15
|
-
"@type": string;
|
|
16
|
-
"rdfs:comment": string;
|
|
17
|
-
"rdfs:isDefinedBy": {
|
|
18
|
-
"@id": string;
|
|
19
|
-
};
|
|
20
|
-
"rdfs:label": string;
|
|
21
|
-
}[];
|
|
22
|
-
}>;
|
|
1
|
+
/** This ontology's data files, relative to this module (`linked build` copies them to `lib/esm/data/`). */
|
|
2
|
+
export declare const dataFiles: string[];
|
|
3
|
+
/** Read this ontology's Turtle data (server only). */
|
|
4
|
+
export declare const loadData: () => Promise<string[]>;
|
|
23
5
|
/**
|
|
24
6
|
* The namespace of this ontology.
|
|
25
7
|
*
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { createNameSpace } from '@_linked/core/utils/NameSpace';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*/
|
|
6
|
-
export
|
|
7
|
-
//@ts-ignore
|
|
8
|
-
const data = await import('../data/server.json', {
|
|
9
|
-
with: { type: 'json' },
|
|
10
|
-
});
|
|
11
|
-
return data.default || data;
|
|
12
|
-
};
|
|
2
|
+
import { loadOntologyFiles } from '@_linked/core/ontology/loadOntologyFiles';
|
|
3
|
+
/** This ontology's data files, relative to this module (`linked build` copies them to `lib/esm/data/`). */
|
|
4
|
+
export const dataFiles = ['../data/server.ttl'];
|
|
5
|
+
/** Read this ontology's Turtle data (server only). */
|
|
6
|
+
export const loadData = () => loadOntologyFiles(import.meta.url, dataFiles);
|
|
13
7
|
/**
|
|
14
8
|
* The namespace of this ontology.
|
|
15
9
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/ontologies/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/ontologies/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAE7E,2GAA2G;AAC3G,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAEhD,sDAAsD;AACtD,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAE5E;;;;;;;;;;;;;;GAcG;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,MAAM,GAAG;IACpB,WAAW;IACX,gBAAgB;IAChB,aAAa;IACb,YAAY;IACZ,WAAW;IACX,eAAe;IACf,WAAW;IACX,UAAU;IACV,gBAAgB;IAChB,QAAQ;IACR,MAAM;CACP,CAAC;AAEF,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC","sourcesContent":["import { createNameSpace } from '@_linked/core/utils/NameSpace';\nimport { loadOntologyFiles } from '@_linked/core/ontology/loadOntologyFiles';\n\n/** This ontology's data files, relative to this module (`linked build` copies them to `lib/esm/data/`). */\nexport const dataFiles = ['../data/server.ttl'];\n\n/** Read this ontology's Turtle data (server only). */\nexport const loadData = () => loadOntologyFiles(import.meta.url, dataFiles);\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 * Its prefix label is the same slug, `server` (`server:LincdAPI`). It used to be `lincd-server`,\n * which is still registered as a deprecated alias so `lincd-server:` names keep expanding.\n *\n * Until an earlier release the namespace was `http://lincd.org/ont/lincd-server/`. No stored\n * data is typed with 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 server = {\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/** @deprecated use `server` — same object, kept under its old name. */\nexport const lincdServer = server;\n"]}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* From a sibling module the same import is ordinary and survives.
|
|
12
12
|
*/
|
|
13
13
|
import * as terms from './server.js';
|
|
14
|
-
import { loadData, ns } from './server.js';
|
|
14
|
+
import { dataFiles, loadData, ns } from './server.js';
|
|
15
15
|
import { linkedOntology } from '../package.js';
|
|
16
16
|
import { Prefix } from '@_linked/core/utils/Prefix';
|
|
17
17
|
// Deprecated prefix label, kept so `lincd-server:X` names still expand. It is added
|
|
@@ -19,6 +19,6 @@ import { Prefix } from '@_linked/core/utils/Prefix';
|
|
|
19
19
|
// last add wins: registering `server` second makes compaction emit `server:X`.
|
|
20
20
|
Prefix.add('lincd-server', ns('').id);
|
|
21
21
|
// The prefix is also the key this ontology is registered under in the package tree,
|
|
22
|
-
// and the name of its data file: `server` → `../data/server.
|
|
23
|
-
linkedOntology(terms, ns, 'server', loadData,
|
|
22
|
+
// and the name of its data file: `server` → `../data/server.ttl`.
|
|
23
|
+
linkedOntology(terms, ns, 'server', loadData, dataFiles);
|
|
24
24
|
//# sourceMappingURL=server.register.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.register.js","sourceRoot":"","sources":["../../../src/ontologies/server.register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AACrC,OAAO,EAAC,QAAQ,EAAE,EAAE,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"server.register.js","sourceRoot":"","sources":["../../../src/ontologies/server.register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AACrC,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAC,MAAM,aAAa,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAC;AAElD,oFAAoF;AACpF,sFAAsF;AACtF,+EAA+E;AAC/E,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAEtC,oFAAoF;AACpF,kEAAkE;AAClE,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC","sourcesContent":["/**\n * Registers this ontology.\n *\n * Kept out of `server.ts` because registration needs that module's whole export\n * namespace, and a module cannot import itself once a bundler is involved: Rollup\n * treats a static self-reference as a circular import and elides it, so the binding is\n * undefined at runtime and the consuming app dies at boot with `_this is not\n * defined`. `tsc` preserves it, which is why the pattern survived for as long as\n * packages were built with `tsc` alone.\n *\n * From a sibling module the same import is ordinary and survives.\n */\nimport * as terms from './server.js';\nimport {dataFiles, loadData, ns} from './server.js';\nimport {linkedOntology} from '../package.js';\nimport {Prefix} from '@_linked/core/utils/Prefix';\n\n// Deprecated prefix label, kept so `lincd-server:X` names still expand. It is added\n// BEFORE the registration below because Prefix keeps one prefix per namespace and the\n// last add wins: registering `server` second makes compaction emit `server:X`.\nPrefix.add('lincd-server', ns('').id);\n\n// The prefix is also the key this ontology is registered under in the package tree,\n// and the name of its data file: `server` → `../data/server.ttl`.\nlinkedOntology(terms, ns, 'server', loadData, dataFiles);\n"]}
|
package/lib/esm/package.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const linkedShape: {
|
|
2
2
|
<T extends typeof import("@_linked/core").Shape>(constructor: T): void;
|
|
3
3
|
<T extends typeof import("@_linked/core").Shape>(config?: import("@_linked/core/utils/Package").ShapeConfig): (constructor: T) => void;
|
|
4
|
-
}, linkedUtil: (constructor: any) => any, linkedOntology: (allFileExports: any, nameSpace: (term: string) => import("@_linked/core/utils/NodeReference.js").NodeReferenceValue, suggestedPrefixAndFileName: string, loadDataFunction?: () => Promise<
|
|
4
|
+
}, linkedUtil: (constructor: any) => any, linkedOntology: (allFileExports: any, nameSpace: (term: string) => import("@_linked/core/utils/NodeReference.js").NodeReferenceValue, suggestedPrefixAndFileName: string, loadDataFunction?: () => Promise<unknown>, dataSource?: string | string[]) => void, packageExports: any, packageName: string;
|
|
@@ -82,6 +82,8 @@ export declare class LinkedServer extends Shape {
|
|
|
82
82
|
* could not be loaded at all.
|
|
83
83
|
*/
|
|
84
84
|
private linkedPackageDirs;
|
|
85
|
+
/** The app's own workspace packages (`linkedPackage: true`), by real path. */
|
|
86
|
+
private workspacePackageDirs;
|
|
85
87
|
private warnedDuplicateInstalls;
|
|
86
88
|
private resizePathsMap;
|
|
87
89
|
private api;
|
|
@@ -127,24 +129,51 @@ export declare class LinkedServer extends Shape {
|
|
|
127
129
|
private materializeShapesIntoStore;
|
|
128
130
|
/** One shape sync into the default dataset; throws when it fails. */
|
|
129
131
|
private syncRegisteredShapes;
|
|
132
|
+
/**
|
|
133
|
+
* Boot: sync the registered ontologies' class hierarchy into app data and run the shape
|
|
134
|
+
* check, before the shape sync (see utils/ontologySync). The sync follows the shape sync's
|
|
135
|
+
* switch (`syncShapesOnBoot`, `LINKED_SYNC_SHAPES_ON_BOOT`), plus the opt-out
|
|
136
|
+
* `LINKED_SYNC_ONTOLOGIES_ON_BOOT=false`; the in-memory class hierarchy is loaded either way.
|
|
137
|
+
* Never stops the boot: failures and findings are logged.
|
|
138
|
+
*/
|
|
139
|
+
private syncOntologiesOnBoot;
|
|
140
|
+
/**
|
|
141
|
+
* Every discovered linked package and every workspace package of the app registers its
|
|
142
|
+
* ontologies (in dev, an unbuilt one through Vite), then the ontology sync (when
|
|
143
|
+
* `sync` is set) into the default dataset, then the shape check.
|
|
144
|
+
* Orphaned sync nodes are pruned under the shape sync's orphan policy
|
|
145
|
+
* (`LINKED_SYNC_SHAPES_PRUNE_ORPHANS`).
|
|
146
|
+
*/
|
|
147
|
+
private runOntologyPhase;
|
|
130
148
|
/** Tail of the {@link resyncShapes} queue: one re-sync at a time. */
|
|
131
149
|
private shapeSyncQueue;
|
|
132
150
|
/**
|
|
133
|
-
* Re-sync the registered shapes into app data, as the boot does,
|
|
134
|
-
* what was written
|
|
151
|
+
* Re-sync the registered ontologies and shapes into app data, as the boot does,
|
|
152
|
+
* and report what was written: the ontology sync (every registered package,
|
|
153
|
+
* hash-skipped), the shape check's counts, then the shape sync. A failed ontology
|
|
154
|
+
* sync does not stop the shape sync; the run then fails with the ontology error. The host calls it (`POST /admin/sync-shapes`) after it
|
|
135
155
|
* changed the app's shape code, so the app — the only process that loads that
|
|
136
156
|
* code — writes its own shapes and their hashes.
|
|
137
157
|
*
|
|
138
|
-
* `packages` names the packages whose source changed
|
|
139
|
-
*
|
|
140
|
-
* (
|
|
141
|
-
*
|
|
142
|
-
*
|
|
158
|
+
* `packages` names the packages whose source changed: the app itself or its
|
|
159
|
+
* direct dependencies, never `@_linked/*` ({@link assertReloadablePackages}). In
|
|
160
|
+
* dev (Vite) their modules are invalidated and their backends reloaded first
|
|
161
|
+
* ({@link onSourceChange}), so a shape added since the boot is registered before
|
|
162
|
+
* the sync; without Vite (a built app) nothing is reloaded. The answer names the
|
|
163
|
+
* packages reloaded and the node shapes registered after it, so the host can check
|
|
164
|
+
* that the shape it wrote is there. Runs as the system, never as the caller of a
|
|
165
|
+
* request, one at a time; a run that takes longer than
|
|
166
|
+
* `LINKED_SHAPE_SYNC_TIMEOUT_MS` (default 120 s) fails and releases the queue.
|
|
143
167
|
*/
|
|
144
168
|
resyncShapes({ packages }?: {
|
|
145
169
|
packages?: string[];
|
|
146
170
|
}): Promise<ShapeSyncResult>;
|
|
147
|
-
/**
|
|
171
|
+
/** The packages a host may ask to reload: the app itself and its direct dependencies. */
|
|
172
|
+
private reloadablePackages;
|
|
173
|
+
/**
|
|
174
|
+
* Re-read one package's source from disk (dev only); see {@link resyncShapes}.
|
|
175
|
+
* Resolves whether it reloaded anything.
|
|
176
|
+
*/
|
|
148
177
|
private reloadPackageFromDisk;
|
|
149
178
|
/**
|
|
150
179
|
* Boot the server and listen. Rejects — and makes the process exit non-zero —
|
|
@@ -257,7 +286,8 @@ export declare class LinkedServer extends Shape {
|
|
|
257
286
|
* don't accumulate), drops them from the registry, and re-runs
|
|
258
287
|
* indexPackageBackendProviders to pick up the freshly-imported module.
|
|
259
288
|
* Reloads run one at a time: each re-registers routes on the shared express
|
|
260
|
-
* stack.
|
|
289
|
+
* stack. One that takes longer than `LINKED_SOURCE_RELOAD_TIMEOUT_MS` (default
|
|
290
|
+
* 60 s) rejects and releases the queue.
|
|
261
291
|
*
|
|
262
292
|
* Dispose calls have a 5 s soft timeout. A hanging dispose logs a
|
|
263
293
|
* warning and is abandoned so HMR doesn't stall the whole dev loop.
|
|
@@ -36,12 +36,11 @@ import { paint } from '../utils/paint.js';
|
|
|
36
36
|
import { nativeImport } from '../utils/nativeImport.js';
|
|
37
37
|
import { createJsonBodyParser } from '../utils/jsonBodyParser.js';
|
|
38
38
|
import { LinkedStorage } from '@_linked/core/utils/LinkedStorage';
|
|
39
|
-
import {
|
|
40
|
-
import { getShapeClass, getSuperShapesClasses, } from '@_linked/core/utils/ShapeClass';
|
|
39
|
+
import { getAllShapeClasses, getShapeClass, getSuperShapesClasses, } from '@_linked/core/utils/ShapeClass';
|
|
41
40
|
import path from 'path';
|
|
42
41
|
import { pathToFileURL } from 'node:url';
|
|
43
42
|
import { isFatalError } from '../utils/fatalError.js';
|
|
44
|
-
import { discoverLinkedDependencies, hasModuleEntry, isBundledBySsr, NODE_IMPORT_CONDITIONS, readInstalledPackage, resolveBackendEntry, resolveDevBackendEntry, ssrNoExternalOf, } from '../utils/linkedDependencies.js';
|
|
43
|
+
import { discoverLinkedDependencies, hasModuleEntry, isBundledBySsr, NODE_IMPORT_CONDITIONS, readDependencyLists, readInstalledPackage, resolveBackendEntry, resolveDevBackendEntry, ssrNoExternalOf, } from '../utils/linkedDependencies.js';
|
|
45
44
|
/**
|
|
46
45
|
* `instanceof ShapeProvider`, tolerating a second copy of server-utils.
|
|
47
46
|
*
|
|
@@ -138,8 +137,10 @@ import { resolveStaticAccessURL, staticAssetURL, } from '../utils/releaseManifes
|
|
|
138
137
|
import { resolveBootstrapEntry, resolveViteMainEntry, resolveViteServingMode, } from '../utils/bootstrapEntry.js';
|
|
139
138
|
import { resolveRouteAssets } from '../utils/routeAssets.js';
|
|
140
139
|
import { resolveRouteComponent, ssrCssInlineUrls, ssrCssScope, } from '../utils/ssrCss.js';
|
|
141
|
-
import { materializeShapes } from '../utils/syncShapes.js';
|
|
142
|
-
import {
|
|
140
|
+
import { bootOrphanScope, materializeShapes } from '../utils/syncShapes.js';
|
|
141
|
+
import { bootSyncsOntologies, loadOntologyCore, runOntologyPhase, ontologyPackageDirs, sourceModuleImporter, shapeSyncOn, syncOntologiesThenShapes, } from '../utils/ontologySync.js';
|
|
142
|
+
import { AdminRequestError, assertReloadablePackages, registerAdminRoutes, } from '../utils/adminChannel.js';
|
|
143
|
+
import { envMs, withTimeout } from '../utils/withTimeout.js';
|
|
143
144
|
import { invalidateSourceUnder } from '../utils/reloadSource.js';
|
|
144
145
|
import { installSpaFallback, repinSpaFallback, } from '../utils/spaFallback.js';
|
|
145
146
|
import { LincdAPI } from './LincdAPI.js';
|
|
@@ -191,7 +192,6 @@ function installProcessSetup() {
|
|
|
191
192
|
//
|
|
192
193
|
// global['document'] = document;
|
|
193
194
|
global['reactStaticRenderer'] = renderToStaticMarkup;
|
|
194
|
-
autoLoadOntologyData(true);
|
|
195
195
|
/**
|
|
196
196
|
* How RPC arguments treat a `{__sc}` (live Shape class) marker. No call takes a
|
|
197
197
|
* Shape class from the client: logged in 'warn', refused (400) in 'enforce'.
|
|
@@ -284,6 +284,8 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
284
284
|
* could not be loaded at all.
|
|
285
285
|
*/
|
|
286
286
|
this.linkedPackageDirs = new Map();
|
|
287
|
+
/** The app's own workspace packages (`linkedPackage: true`), by real path. */
|
|
288
|
+
this.workspacePackageDirs = [];
|
|
287
289
|
this.warnedDuplicateInstalls = new Set();
|
|
288
290
|
//from resizedFileName to full resized path (CDN or similar)
|
|
289
291
|
this.resizePathsMap = new Map();
|
|
@@ -359,6 +361,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
359
361
|
this.initPackage();
|
|
360
362
|
this.server = express();
|
|
361
363
|
await this.initBackendProviders();
|
|
364
|
+
await this.syncOntologiesOnBoot();
|
|
362
365
|
await this.materializeShapesIntoStore();
|
|
363
366
|
return this;
|
|
364
367
|
}
|
|
@@ -395,9 +398,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
395
398
|
/** One shape sync into the default dataset; throws when it fails. */
|
|
396
399
|
async syncRegisteredShapes() {
|
|
397
400
|
var _a;
|
|
398
|
-
|
|
399
|
-
const envFlag = process.env.LINKED_SYNC_SHAPES_ON_BOOT;
|
|
400
|
-
if (configFlag === false || envFlag === 'false') {
|
|
401
|
+
if (!shapeSyncOn(process.env, (_a = this.config) === null || _a === void 0 ? void 0 : _a.syncShapesOnBoot)) {
|
|
401
402
|
return { written: 0, skipped: 'disabled' };
|
|
402
403
|
}
|
|
403
404
|
const appData = LinkedStorage.getDefaultDataset();
|
|
@@ -410,27 +411,93 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
410
411
|
return { written: count, orphanScope };
|
|
411
412
|
}
|
|
412
413
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
414
|
+
* Boot: sync the registered ontologies' class hierarchy into app data and run the shape
|
|
415
|
+
* check, before the shape sync (see utils/ontologySync). The sync follows the shape sync's
|
|
416
|
+
* switch (`syncShapesOnBoot`, `LINKED_SYNC_SHAPES_ON_BOOT`), plus the opt-out
|
|
417
|
+
* `LINKED_SYNC_ONTOLOGIES_ON_BOOT=false`; the in-memory class hierarchy is loaded either way.
|
|
418
|
+
* Never stops the boot: failures and findings are logged.
|
|
419
|
+
*/
|
|
420
|
+
async syncOntologiesOnBoot() {
|
|
421
|
+
try {
|
|
422
|
+
await runAsSystem(() => { var _a; return this.runOntologyPhase(bootSyncsOntologies(process.env, (_a = this.config) === null || _a === void 0 ? void 0 : _a.syncShapesOnBoot)); }, 'ontology sync at boot');
|
|
423
|
+
}
|
|
424
|
+
catch (err) {
|
|
425
|
+
console.warn('[LinkedServer] ontology sync failed (non-fatal):', err);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Every discovered linked package and every workspace package of the app registers its
|
|
430
|
+
* ontologies (in dev, an unbuilt one through Vite), then the ontology sync (when
|
|
431
|
+
* `sync` is set) into the default dataset, then the shape check.
|
|
432
|
+
* Orphaned sync nodes are pruned under the shape sync's orphan policy
|
|
433
|
+
* (`LINKED_SYNC_SHAPES_PRUNE_ORPHANS`).
|
|
434
|
+
*/
|
|
435
|
+
async runOntologyPhase(sync) {
|
|
436
|
+
var _a, _b, _c, _d;
|
|
437
|
+
return runOntologyPhase(LinkedStorage.getDefaultDataset(), {
|
|
438
|
+
core: await loadOntologyCore(),
|
|
439
|
+
sync,
|
|
440
|
+
orphanScope: bootOrphanScope(),
|
|
441
|
+
dependencies: readDependencyLists((_a = this.linkedPackageDirs) !== null && _a !== void 0 ? _a : new Map(), this.package),
|
|
442
|
+
packageDirs: ontologyPackageDirs(((_b = this.linkedPackageDirs) !== null && _b !== void 0 ? _b : new Map()).values(), (_c = this.workspacePackageDirs) !== null && _c !== void 0 ? _c : []),
|
|
443
|
+
importModule: sourceModuleImporter((_d = this.config.server) === null || _d === void 0 ? void 0 : _d.vite),
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Re-sync the registered ontologies and shapes into app data, as the boot does,
|
|
448
|
+
* and report what was written: the ontology sync (every registered package,
|
|
449
|
+
* hash-skipped), the shape check's counts, then the shape sync. A failed ontology
|
|
450
|
+
* sync does not stop the shape sync; the run then fails with the ontology error. The host calls it (`POST /admin/sync-shapes`) after it
|
|
415
451
|
* changed the app's shape code, so the app — the only process that loads that
|
|
416
452
|
* code — writes its own shapes and their hashes.
|
|
417
453
|
*
|
|
418
|
-
* `packages` names the packages whose source changed
|
|
419
|
-
*
|
|
420
|
-
* (
|
|
421
|
-
*
|
|
422
|
-
*
|
|
454
|
+
* `packages` names the packages whose source changed: the app itself or its
|
|
455
|
+
* direct dependencies, never `@_linked/*` ({@link assertReloadablePackages}). In
|
|
456
|
+
* dev (Vite) their modules are invalidated and their backends reloaded first
|
|
457
|
+
* ({@link onSourceChange}), so a shape added since the boot is registered before
|
|
458
|
+
* the sync; without Vite (a built app) nothing is reloaded. The answer names the
|
|
459
|
+
* packages reloaded and the node shapes registered after it, so the host can check
|
|
460
|
+
* that the shape it wrote is there. Runs as the system, never as the caller of a
|
|
461
|
+
* request, one at a time; a run that takes longer than
|
|
462
|
+
* `LINKED_SHAPE_SYNC_TIMEOUT_MS` (default 120 s) fails and releases the queue.
|
|
423
463
|
*/
|
|
424
464
|
async resyncShapes({ packages = [] } = {}) {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
465
|
+
assertReloadablePackages(packages, this.reloadablePackages());
|
|
466
|
+
const timeoutMs = envMs('LINKED_SHAPE_SYNC_TIMEOUT_MS', 120000);
|
|
467
|
+
const run = this.shapeSyncQueue.then(() => withTimeout(runAsSystem(async () => {
|
|
468
|
+
const reloaded = [];
|
|
469
|
+
for (const pkg of packages) {
|
|
470
|
+
if (await this.reloadPackageFromDisk(pkg))
|
|
471
|
+
reloaded.push(pkg);
|
|
472
|
+
}
|
|
473
|
+
const result = await syncOntologiesThenShapes(() => { var _a; return this.runOntologyPhase(shapeSyncOn(process.env, (_a = this.config) === null || _a === void 0 ? void 0 : _a.syncShapesOnBoot)); }, () => this.syncRegisteredShapes());
|
|
474
|
+
return { ...result, reloaded, shapes: [...getAllShapeClasses().keys()].sort() };
|
|
475
|
+
}, 'shape sync requested by the host'), timeoutMs, `the shape sync did not finish within ${timeoutMs} ms`));
|
|
430
476
|
this.shapeSyncQueue = run.catch(() => undefined);
|
|
431
477
|
return run;
|
|
432
478
|
}
|
|
433
|
-
/**
|
|
479
|
+
/** The packages a host may ask to reload: the app itself and its direct dependencies. */
|
|
480
|
+
reloadablePackages() {
|
|
481
|
+
var _a, _b;
|
|
482
|
+
const names = new Set();
|
|
483
|
+
if ((_a = this.package) === null || _a === void 0 ? void 0 : _a.name)
|
|
484
|
+
names.add(this.package.name);
|
|
485
|
+
try {
|
|
486
|
+
const json = JSON.parse(fsNative.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'));
|
|
487
|
+
if (json.name)
|
|
488
|
+
names.add(json.name);
|
|
489
|
+
for (const field of ['dependencies', 'devDependencies']) {
|
|
490
|
+
for (const name of Object.keys((_b = json[field]) !== null && _b !== void 0 ? _b : {}))
|
|
491
|
+
names.add(name);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
catch (_c) { }
|
|
495
|
+
return names;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Re-read one package's source from disk (dev only); see {@link resyncShapes}.
|
|
499
|
+
* Resolves whether it reloaded anything.
|
|
500
|
+
*/
|
|
434
501
|
async reloadPackageFromDisk(pkg) {
|
|
435
502
|
var _a, _b, _c;
|
|
436
503
|
const root = pkg === ((_a = this.package) === null || _a === void 0 ? void 0 : _a.name) ? process.cwd() : this.packageDirFor(pkg);
|
|
@@ -438,7 +505,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
438
505
|
throw new AdminRequestError(`unknown package: ${pkg}`);
|
|
439
506
|
const graph = (_c = (_b = this.config.server) === null || _b === void 0 ? void 0 : _b.vite) === null || _c === void 0 ? void 0 : _c.moduleGraph;
|
|
440
507
|
if (!graph)
|
|
441
|
-
return; // a built app: there is no source to reload
|
|
508
|
+
return false; // a built app: there is no source to reload
|
|
442
509
|
const roots = [root];
|
|
443
510
|
try {
|
|
444
511
|
roots.push(fsNative.realpathSync(root));
|
|
@@ -446,6 +513,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
446
513
|
catch (_d) { }
|
|
447
514
|
invalidateSourceUnder(graph, roots);
|
|
448
515
|
await this.onSourceChange(pkg);
|
|
516
|
+
return true;
|
|
449
517
|
}
|
|
450
518
|
// async serveData(req,res) {
|
|
451
519
|
// let nodeURI = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
|
|
@@ -589,6 +657,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
589
657
|
// });
|
|
590
658
|
// before controllers
|
|
591
659
|
await this.initBackendProviders();
|
|
660
|
+
await this.syncOntologiesOnBoot();
|
|
592
661
|
await this.materializeShapesIntoStore();
|
|
593
662
|
//START OF EXPRESS ROUTES AND MIDDLEWARE
|
|
594
663
|
//use cors
|
|
@@ -760,6 +829,14 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
760
829
|
// Local workspace packages in this app's dependency tree. These are also
|
|
761
830
|
// imported whole at boot (indexLincdPackage), not only their /backend.
|
|
762
831
|
const allLocalPackages = getLincdPackages();
|
|
832
|
+
this.workspacePackageDirs = allLocalPackages.map((pkg) => {
|
|
833
|
+
try {
|
|
834
|
+
return fsNative.realpathSync(pkg.path);
|
|
835
|
+
}
|
|
836
|
+
catch (_a) {
|
|
837
|
+
return pkg.path;
|
|
838
|
+
}
|
|
839
|
+
});
|
|
763
840
|
const localPackageMap = new Map(allLocalPackages.map((pkg) => [pkg.packageName, pkg]));
|
|
764
841
|
const relevantPackages = this.filterPackagesByDependencyTree(localPackageMap, this.package);
|
|
765
842
|
// Every linked package in the dependency tree, installed or local, each
|
|
@@ -1416,13 +1493,15 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
1416
1493
|
* don't accumulate), drops them from the registry, and re-runs
|
|
1417
1494
|
* indexPackageBackendProviders to pick up the freshly-imported module.
|
|
1418
1495
|
* Reloads run one at a time: each re-registers routes on the shared express
|
|
1419
|
-
* stack.
|
|
1496
|
+
* stack. One that takes longer than `LINKED_SOURCE_RELOAD_TIMEOUT_MS` (default
|
|
1497
|
+
* 60 s) rejects and releases the queue.
|
|
1420
1498
|
*
|
|
1421
1499
|
* Dispose calls have a 5 s soft timeout. A hanging dispose logs a
|
|
1422
1500
|
* warning and is abandoned so HMR doesn't stall the whole dev loop.
|
|
1423
1501
|
*/
|
|
1424
1502
|
async onSourceChange(pkg) {
|
|
1425
|
-
const
|
|
1503
|
+
const timeoutMs = envMs('LINKED_SOURCE_RELOAD_TIMEOUT_MS', 60000);
|
|
1504
|
+
const run = this.sourceReloadQueue.then(() => withTimeout(this.reloadPackageSource(pkg), timeoutMs, `the reload of ${pkg} did not finish within ${timeoutMs} ms`));
|
|
1426
1505
|
this.sourceReloadQueue = run.catch(() => undefined);
|
|
1427
1506
|
return run;
|
|
1428
1507
|
}
|