@_linked/server 3.6.1 → 3.8.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 +72 -0
- package/lib/esm/backend.d.ts +9 -0
- package/lib/esm/backend.js +28 -1
- package/lib/esm/backend.js.map +1 -1
- 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 +23 -3
- package/lib/esm/shapes/LinkedServer.js +60 -13
- package/lib/esm/shapes/LinkedServer.js.map +1 -1
- package/lib/esm/shapes/quadstores/RemoteDataset.d.ts +41 -1
- package/lib/esm/shapes/quadstores/RemoteDataset.js +152 -4
- package/lib/esm/shapes/quadstores/RemoteDataset.js.map +1 -1
- package/lib/esm/utils/adminChannel.d.ts +35 -0
- package/lib/esm/utils/adminChannel.js +47 -3
- 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 +144 -0
- package/lib/esm/utils/ontologySync.js +145 -0
- package/lib/esm/utils/ontologySync.js.map +1 -0
- package/lib/esm/utils/queryPlane.d.ts +21 -0
- package/lib/esm/utils/queryPlane.js +54 -0
- package/lib/esm/utils/queryPlane.js.map +1 -1
- package/package.json +4 -4
- package/readme.md +13 -3
- package/lib/esm/data/server.json +0 -47
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# @\_linked/server
|
|
2
2
|
|
|
3
|
+
## 3.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#204](https://github.com/linked-fw/server/pull/204) [`f1dc1a6`](https://github.com/linked-fw/server/commit/f1dc1a6fec0abae90c711daec51e929a9587b582) Thanks [@flyon](https://github.com/flyon)! - Graph queries through the server (named graphs and the graph registry, `@_linked/core`'s
|
|
8
|
+
`graphQuery`):
|
|
9
|
+
|
|
10
|
+
- `RemoteDataset.graphQuery`: graph queries (`graph_create`, `graph_replace`, `graph_patch`,
|
|
11
|
+
`graph_drop`) go out on the query wire like every other query, with the same token and
|
|
12
|
+
end-user header. A refusal comes back as core's `GraphQueryError` with its code; a server or
|
|
13
|
+
gateway without the method (404, 501) reads as `unsupported-query-kind`, so the ontology sync
|
|
14
|
+
falls back to the default graph there.
|
|
15
|
+
- In the url form, `RemoteDataset` expands `graphs.allOntologies` and `graphs.allShapes` in a
|
|
16
|
+
read's `.from()` set from its own graph-registry cache (per dataset, keyed by the url and the
|
|
17
|
+
dataset the server names in its `ping`, updated by its own graph queries, re-read after 30
|
|
18
|
+
seconds); `invalidateGraphRegistry(dataset?)` drops it. When the registry cannot be read, the
|
|
19
|
+
names are sent unexpanded.
|
|
20
|
+
- The generic plane answers `/call/@_linked/server/graphQuery`: the body is checked with core's
|
|
21
|
+
`parseGraphQuery`, the `graph` rule of the store its record class routes to decides
|
|
22
|
+
(`withAccess({graph})`; no rule refuses with 403), and `LinkedStorage.graphQuery` runs it. A
|
|
23
|
+
store's refusal answers with a status and its code: `{error, code}` (409 `graph-exists`, 409
|
|
24
|
+
`graph-not-registered`, 400 `graph-name-read-only`, 501 `unsupported-query-kind`). Any
|
|
25
|
+
`ServerCallError` carrying a string `code` now sends it in the error body.
|
|
26
|
+
- Control channel: `POST /admin/graph-registry-changed {dataset}` (with `CN_APP_ADMIN_SECRET`)
|
|
27
|
+
drops the process's cached graph registry, so the next expanding read re-reads it.
|
|
28
|
+
- The ontology phase (boot and `POST /admin/sync-shapes`) reports and logs the graphs the sync
|
|
29
|
+
wrote and dropped (`ontologies.graphs`, `ontologies.droppedGraphs`), and says when a store
|
|
30
|
+
without graph queries got the default-graph sync.
|
|
31
|
+
|
|
32
|
+
Breaking changes:
|
|
33
|
+
|
|
34
|
+
- Requires the `@_linked/core` with graph queries (`IDataset.graphQuery`, `NamedGraph`, the graph
|
|
35
|
+
registry cache), which in turn requires `ghcr.io/linked-fw/fuseki:6.2.0-2` or a store that
|
|
36
|
+
builds its hierarchy from the registry; and the `@_linked/server-utils` whose `QueryAccess` has
|
|
37
|
+
the `graph` operation (with an older one every graph query is refused). Both ranges are raised
|
|
38
|
+
at release.
|
|
39
|
+
- Graph queries on the generic plane are refused unless the store declares a `graph` rule with
|
|
40
|
+
`withAccess`.
|
|
41
|
+
- `.from(graphs.allOntologies)` and `.from(graphs.allShapes)` reads through a url-form
|
|
42
|
+
`RemoteDataset` now also select the `OntologyGraph` and `ShapesGraph` records on the data
|
|
43
|
+
server; its read rule decides whether they are answered (when refused, the names go
|
|
44
|
+
unexpanded).
|
|
45
|
+
- A `ServerCallError` that carries a string `code` now sends it in the error body
|
|
46
|
+
(`{error, code}`).
|
|
47
|
+
|
|
48
|
+
## 3.7.0
|
|
49
|
+
|
|
50
|
+
### Minor Changes
|
|
51
|
+
|
|
52
|
+
- [#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.
|
|
53
|
+
|
|
54
|
+
- `src/data/server.ttl` gains the ontology node (`dcterms:title`, `dcterms:description`,
|
|
55
|
+
`owl:versionInfo`) and the seven terms it lacked (`LincdWebApp`, `LincdAPI`, `hasAPI`,
|
|
56
|
+
`N3FileStore`, `BackendAPIStore`, `ownPackage`, `maintainsPackage`), and is written in the
|
|
57
|
+
deterministic Turtle form. All 11 terms are typed (`owl:Class`, was `rdfs:Class`, or
|
|
58
|
+
`owl:ObjectProperty`) with an English label and comment; the labels say "Linked", not "LINCD".
|
|
59
|
+
- Two axioms: `server:BackendFileStore` and `server:BackendAPIStore` are `rdfs:subClassOf`
|
|
60
|
+
`server:BackendStore`. No shape targets these classes.
|
|
61
|
+
|
|
62
|
+
- [#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`.
|
|
63
|
+
|
|
64
|
+
- [#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
|
|
65
|
+
dependency tree registers its ontologies (core `registerInstalledOntologies`) before the ontology
|
|
66
|
+
sync and the shape check, so a package the app only deep-imports shape files from
|
|
67
|
+
(`@_linked/schema/shapes/Person`) is synced and checked too.
|
|
68
|
+
|
|
69
|
+
- [#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
|
|
70
|
+
packages (`linkedPackage: true` under its `workspaces`), which the dependency walk misses when no
|
|
71
|
+
package imports them (a Create Now clone's `packages/<slug>-ont`). In dev, a package without a
|
|
72
|
+
built `lib/` registers from `src/ontologies/*.register.ts` through Vite's `ssrLoadModule` (core
|
|
73
|
+
`registerInstalledOntologies`' `importModule`); a built app skips it.
|
|
74
|
+
|
|
3
75
|
## 3.6.1
|
|
4
76
|
|
|
5
77
|
### Patch Changes
|
package/lib/esm/backend.d.ts
CHANGED
|
@@ -14,4 +14,13 @@ export default class LincdServerBackendProvider extends BackendProvider {
|
|
|
14
14
|
updateQuery(json: any): Promise<unknown>;
|
|
15
15
|
createQuery(json: any): Promise<unknown>;
|
|
16
16
|
deleteQuery(json: any): Promise<import("@_linked/core/queries/DeleteQuery.js").DeleteResponse>;
|
|
17
|
+
/**
|
|
18
|
+
* A whole-graph operation (`graph_create`, `graph_replace`, `graph_patch`, `graph_drop`), as
|
|
19
|
+
* `RemoteDataset.graphQuery` sends it. The query is plain data: core's `parseGraphQuery` checks
|
|
20
|
+
* it, the `graph` rule of the store its record class routes to decides (no rule refuses), and
|
|
21
|
+
* `LinkedStorage.graphQuery` runs it outside any shape catalog; no catalog is resolved for it,
|
|
22
|
+
* so the check resolves the same store. A store's refusal answers with its code (see
|
|
23
|
+
* `graphQueryCallError`).
|
|
24
|
+
*/
|
|
25
|
+
graphQuery(json: any): Promise<import("@_linked/core").GraphResult>;
|
|
17
26
|
}
|
package/lib/esm/backend.js
CHANGED
|
@@ -12,7 +12,8 @@ import { callable } from '@_linked/server-utils/utils/callable';
|
|
|
12
12
|
import { LinkedFileStorage } from '@_linked/core/utils/LinkedFileStorage';
|
|
13
13
|
import { LinkedStorage } from '@_linked/core/utils/LinkedStorage';
|
|
14
14
|
import { LocalFileStore } from './shapes/filestores/LocalFileStore.js';
|
|
15
|
-
import { authorizeGenericQuery, resolveQueryCatalog, toQueryBuilder, } from './utils/queryPlane.js';
|
|
15
|
+
import { authorizeGenericQuery, authorizeGraphQuery, graphQueryCallError, resolveQueryCatalog, toGraphQuery, toQueryBuilder, } from './utils/queryPlane.js';
|
|
16
|
+
import { ServerCallError } from '@_linked/server-utils/utils/ServerCallError';
|
|
16
17
|
import path from 'path';
|
|
17
18
|
import fs from 'fs/promises';
|
|
18
19
|
export default class LincdServerBackendProvider extends BackendProvider {
|
|
@@ -82,6 +83,26 @@ export default class LincdServerBackendProvider extends BackendProvider {
|
|
|
82
83
|
await authorizeGenericQuery('delete', json, query, 'deleteQuery');
|
|
83
84
|
return LinkedStorage.deleteQuery(query);
|
|
84
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* A whole-graph operation (`graph_create`, `graph_replace`, `graph_patch`, `graph_drop`), as
|
|
88
|
+
* `RemoteDataset.graphQuery` sends it. The query is plain data: core's `parseGraphQuery` checks
|
|
89
|
+
* it, the `graph` rule of the store its record class routes to decides (no rule refuses), and
|
|
90
|
+
* `LinkedStorage.graphQuery` runs it outside any shape catalog; no catalog is resolved for it,
|
|
91
|
+
* so the check resolves the same store. A store's refusal answers with its code (see
|
|
92
|
+
* `graphQueryCallError`).
|
|
93
|
+
*/
|
|
94
|
+
async graphQuery(json) {
|
|
95
|
+
const query = toGraphQuery(json);
|
|
96
|
+
await authorizeGraphQuery(json, query, 'graphQuery');
|
|
97
|
+
if (!query)
|
|
98
|
+
throw new ServerCallError(400, 'Invalid graph query');
|
|
99
|
+
try {
|
|
100
|
+
return await LinkedStorage.graphQuery(query);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
throw graphQueryCallError(err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
85
106
|
}
|
|
86
107
|
__decorate([
|
|
87
108
|
callable('public'),
|
|
@@ -119,4 +140,10 @@ __decorate([
|
|
|
119
140
|
__metadata("design:paramtypes", [Object]),
|
|
120
141
|
__metadata("design:returntype", Promise)
|
|
121
142
|
], LincdServerBackendProvider.prototype, "deleteQuery", null);
|
|
143
|
+
__decorate([
|
|
144
|
+
callable('public'),
|
|
145
|
+
__metadata("design:type", Function),
|
|
146
|
+
__metadata("design:paramtypes", [Object]),
|
|
147
|
+
__metadata("design:returntype", Promise)
|
|
148
|
+
], LincdServerBackendProvider.prototype, "graphQuery", null);
|
|
122
149
|
//# sourceMappingURL=backend.js.map
|
package/lib/esm/backend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/backend.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/backend.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,aAAa,CAAC;AAE7B,MAAM,CAAC,OAAO,OAAO,0BAA2B,SAAQ,eAAe;IACrE,KAAK,CAAC,sBAAsB;QAC1B,IAAI,CAAC,iBAAiB,CAAC,eAAe,EAAE,EAAE,CAAC;YACzC,iBAAiB,CAAC,eAAe,CAC/B,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC,CACxD,CAAC;QACJ,CAAC;QACD,IAAI,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3D,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,YAAY,CAAC,EAAE;gBAC5D,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IAEG,AAAN,KAAK,CAAC,IAAI;QACR,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAED,4EAA4E;IAC5E,EAAE;IACF,wDAAwD;IACxD,0FAA0F;IAC1F,wFAAwF;IACxF,qFAAqF;IACrF,EAAE;IACF,sFAAsF;IACtF,sFAAsF;IACtF,oFAAoF;IACpF,wFAAwF;IACxF,2EAA2E;IAC3E,EAAE;IACF,yEAAyE;IACzE,4EAA4E;IAC5E,0EAA0E;IAC1E,4EAA4E;IAC5E,4EAA4E;IAC5E,eAAe;IAGT,AAAN,KAAK,CAAC,WAAW,CAAC,IAAS;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,MAAM,qBAAqB,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QAClE,OAAO,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ,CAAC,IAAS;QACtB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,MAAM,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC5D,OAAO,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAGK,AAAN,KAAK,CAAC,WAAW,CAAC,IAAS;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,MAAM,qBAAqB,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QAClE,OAAO,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAGK,AAAN,KAAK,CAAC,WAAW,CAAC,IAAS;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,MAAM,qBAAqB,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QAClE,OAAO,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAGK,AAAN,KAAK,CAAC,WAAW,CAAC,IAAS;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,MAAM,qBAAqB,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QAClE,OAAO,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;OAOG;IAEG,AAAN,KAAK,CAAC,UAAU,CAAC,IAAS;QACxB,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,eAAe,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,OAAO,MAAM,aAAa,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF;AA9EO;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;sDAGlB;AAuBK;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;6DAKlB;AAGK;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;0DAKlB;AAGK;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;6DAKlB;AAGK;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;6DAKlB;AAGK;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;6DAKlB;AAWK;IADL,QAAQ,CAAC,QAAQ,CAAC;;;;4DAUlB","sourcesContent":["import { BackendProvider } from '@_linked/server-utils/utils/BackendProvider';\nimport { callable } from '@_linked/server-utils/utils/callable';\nimport { LinkedFileStorage } from '@_linked/core/utils/LinkedFileStorage';\nimport { LinkedStorage } from '@_linked/core/utils/LinkedStorage';\nimport { LocalFileStore } from './shapes/filestores/LocalFileStore.js';\nimport {\n authorizeGenericQuery,\n authorizeGraphQuery,\n graphQueryCallError,\n resolveQueryCatalog,\n toGraphQuery,\n toQueryBuilder,\n} from './utils/queryPlane.js';\nimport { ServerCallError } from '@_linked/server-utils/utils/ServerCallError';\nimport path from 'path';\nimport fs from 'fs/promises';\n\nexport default class LincdServerBackendProvider extends BackendProvider {\n async setupBeforeControllers() {\n if (!LinkedFileStorage.getDefaultStore()) {\n LinkedFileStorage.setDefaultStore(\n new LocalFileStore(process.env.NODE_ENV + '-filestore')\n );\n }\n let fileSystemUploadPath = path.join('data', 'filestores');\n try {\n await fs.access(fileSystemUploadPath);\n } catch (err) {\n await fs.mkdir(path.join(fileSystemUploadPath, 'filestores'), {\n recursive: true,\n });\n }\n }\n\n /**\n * Reachability check for a `RemoteDataset` pointed at this server: reads nothing, changes\n * nothing. A plain linked server has no token concept, so it always answers `{ok: true}`;\n * a host that serves the wire with tokens answers 401 for a refused one.\n */\n @callable('public')\n async ping(): Promise<{ ok: true }> {\n return { ok: true };\n }\n\n // ── Generic query execution ──────────────────────────────────────────────\n //\n // These answer `RemoteDataset`: a browser's store calls\n // `Server.call(packageName, {method}, json)` (the PACKAGE form), and a remote app's store\n // posts the same `{args}` body to `{url}/call/@_linked/server/<method>`. Either way the\n // request arrives here on the generic provider rather than through Shape resolution.\n //\n // A query cannot cross the wire live, so the client ships `toJSON()` and `fromJSON()`\n // rehydrates it here into a live, closed query. `LinkedStorage` then routes it by the\n // QUERY's shape, which is what decides the target dataset; the store instance never\n // participates. The host's catalog resolver (`setQueryCatalogResolver`) picks the shape\n // catalog the JSON is decoded in; the builder keeps it for both lowerings.\n //\n // Every query is checked first against the access rules of the stores it\n // maps to, declared in the app's storage config (`withAccess`; a store with\n // no rule requires a session): see utils/queryPlane. INTERIM model, to be\n // rethought. The store runs the builder that was checked. They are declared\n // 'public' because that check, not the RPC layer, decides whether a session\n // is required.\n\n @callable('public')\n async selectQuery(json: any) {\n const query = toQueryBuilder(json, await resolveQueryCatalog(json));\n await authorizeGenericQuery('select', json, query, 'selectQuery');\n return LinkedStorage.selectQuery(query);\n }\n\n @callable('public')\n async askQuery(json: any) {\n const query = toQueryBuilder(json, await resolveQueryCatalog(json));\n await authorizeGenericQuery('ask', json, query, 'askQuery');\n return LinkedStorage.askQuery(query);\n }\n\n @callable('public')\n async updateQuery(json: any) {\n const query = toQueryBuilder(json, await resolveQueryCatalog(json));\n await authorizeGenericQuery('update', json, query, 'updateQuery');\n return LinkedStorage.updateQuery(query);\n }\n\n @callable('public')\n async createQuery(json: any) {\n const query = toQueryBuilder(json, await resolveQueryCatalog(json));\n await authorizeGenericQuery('create', json, query, 'createQuery');\n return LinkedStorage.createQuery(query);\n }\n\n @callable('public')\n async deleteQuery(json: any) {\n const query = toQueryBuilder(json, await resolveQueryCatalog(json));\n await authorizeGenericQuery('delete', json, query, 'deleteQuery');\n return LinkedStorage.deleteQuery(query);\n }\n\n /**\n * A whole-graph operation (`graph_create`, `graph_replace`, `graph_patch`, `graph_drop`), as\n * `RemoteDataset.graphQuery` sends it. The query is plain data: core's `parseGraphQuery` checks\n * it, the `graph` rule of the store its record class routes to decides (no rule refuses), and\n * `LinkedStorage.graphQuery` runs it outside any shape catalog; no catalog is resolved for it,\n * so the check resolves the same store. A store's refusal answers with its code (see\n * `graphQueryCallError`).\n */\n @callable('public')\n async graphQuery(json: any) {\n const query = toGraphQuery(json);\n await authorizeGraphQuery(json, query, 'graphQuery');\n if (!query) throw new ServerCallError(400, 'Invalid graph query');\n try {\n return await LinkedStorage.graphQuery(query);\n } catch (err) {\n throw graphQueryCallError(err);\n }\n }\n}\n"]}
|
|
@@ -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,11 +129,29 @@ 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 into their graphs in 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 ontology graphs (and earlier 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
|
*
|
|
@@ -298,7 +318,7 @@ export declare class LinkedServer extends Shape {
|
|
|
298
318
|
private assertSessionForLevel;
|
|
299
319
|
handleErrors(fn: any): (req: any, res: any, next: any) => Promise<any>;
|
|
300
320
|
handleErrorsJson(fn: any): (req: any, res: any, next: any) => Promise<any>;
|
|
301
|
-
sendError(res: any, statusCode: number, message: any, logMessage?: string): void;
|
|
321
|
+
sendError(res: any, statusCode: number, message: any, logMessage?: string, code?: string): void;
|
|
302
322
|
/**
|
|
303
323
|
* The stylesheets a dev (Vite) page render needs, inlined into
|
|
304
324
|
* `<style id="ssr-css">` so the first paint is styled before Vite's client
|
|
@@ -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 { autoLoadOntologyData } from '@_linked/core/utils/Package';
|
|
40
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,7 +137,8 @@ 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';
|
|
140
|
+
import { bootOrphanScope, materializeShapes } from '../utils/syncShapes.js';
|
|
141
|
+
import { bootSyncsOntologies, loadOntologyCore, runOntologyPhase, ontologyPackageDirs, sourceModuleImporter, shapeSyncOn, syncOntologiesThenShapes, } from '../utils/ontologySync.js';
|
|
142
142
|
import { AdminRequestError, assertReloadablePackages, registerAdminRoutes, } from '../utils/adminChannel.js';
|
|
143
143
|
import { envMs, withTimeout } from '../utils/withTimeout.js';
|
|
144
144
|
import { invalidateSourceUnder } from '../utils/reloadSource.js';
|
|
@@ -192,7 +192,6 @@ function installProcessSetup() {
|
|
|
192
192
|
//
|
|
193
193
|
// global['document'] = document;
|
|
194
194
|
global['reactStaticRenderer'] = renderToStaticMarkup;
|
|
195
|
-
autoLoadOntologyData(true);
|
|
196
195
|
/**
|
|
197
196
|
* How RPC arguments treat a `{__sc}` (live Shape class) marker. No call takes a
|
|
198
197
|
* Shape class from the client: logged in 'warn', refused (400) in 'enforce'.
|
|
@@ -285,6 +284,8 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
285
284
|
* could not be loaded at all.
|
|
286
285
|
*/
|
|
287
286
|
this.linkedPackageDirs = new Map();
|
|
287
|
+
/** The app's own workspace packages (`linkedPackage: true`), by real path. */
|
|
288
|
+
this.workspacePackageDirs = [];
|
|
288
289
|
this.warnedDuplicateInstalls = new Set();
|
|
289
290
|
//from resizedFileName to full resized path (CDN or similar)
|
|
290
291
|
this.resizePathsMap = new Map();
|
|
@@ -360,6 +361,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
360
361
|
this.initPackage();
|
|
361
362
|
this.server = express();
|
|
362
363
|
await this.initBackendProviders();
|
|
364
|
+
await this.syncOntologiesOnBoot();
|
|
363
365
|
await this.materializeShapesIntoStore();
|
|
364
366
|
return this;
|
|
365
367
|
}
|
|
@@ -396,9 +398,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
396
398
|
/** One shape sync into the default dataset; throws when it fails. */
|
|
397
399
|
async syncRegisteredShapes() {
|
|
398
400
|
var _a;
|
|
399
|
-
|
|
400
|
-
const envFlag = process.env.LINKED_SYNC_SHAPES_ON_BOOT;
|
|
401
|
-
if (configFlag === false || envFlag === 'false') {
|
|
401
|
+
if (!shapeSyncOn(process.env, (_a = this.config) === null || _a === void 0 ? void 0 : _a.syncShapesOnBoot)) {
|
|
402
402
|
return { written: 0, skipped: 'disabled' };
|
|
403
403
|
}
|
|
404
404
|
const appData = LinkedStorage.getDefaultDataset();
|
|
@@ -411,8 +411,43 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
411
411
|
return { written: count, orphanScope };
|
|
412
412
|
}
|
|
413
413
|
/**
|
|
414
|
-
*
|
|
415
|
-
*
|
|
414
|
+
* Boot: sync the registered ontologies into their graphs in 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 ontology graphs (and earlier 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
|
|
416
451
|
* changed the app's shape code, so the app — the only process that loads that
|
|
417
452
|
* code — writes its own shapes and their hashes.
|
|
418
453
|
*
|
|
@@ -435,7 +470,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
435
470
|
if (await this.reloadPackageFromDisk(pkg))
|
|
436
471
|
reloaded.push(pkg);
|
|
437
472
|
}
|
|
438
|
-
const result = await this.syncRegisteredShapes();
|
|
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());
|
|
439
474
|
return { ...result, reloaded, shapes: [...getAllShapeClasses().keys()].sort() };
|
|
440
475
|
}, 'shape sync requested by the host'), timeoutMs, `the shape sync did not finish within ${timeoutMs} ms`));
|
|
441
476
|
this.shapeSyncQueue = run.catch(() => undefined);
|
|
@@ -622,6 +657,7 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
622
657
|
// });
|
|
623
658
|
// before controllers
|
|
624
659
|
await this.initBackendProviders();
|
|
660
|
+
await this.syncOntologiesOnBoot();
|
|
625
661
|
await this.materializeShapesIntoStore();
|
|
626
662
|
//START OF EXPRESS ROUTES AND MIDDLEWARE
|
|
627
663
|
//use cors
|
|
@@ -793,6 +829,14 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
793
829
|
// Local workspace packages in this app's dependency tree. These are also
|
|
794
830
|
// imported whole at boot (indexLincdPackage), not only their /backend.
|
|
795
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
|
+
});
|
|
796
840
|
const localPackageMap = new Map(allLocalPackages.map((pkg) => [pkg.packageName, pkg]));
|
|
797
841
|
const relevantPackages = this.filterPackagesByDependencyTree(localPackageMap, this.package);
|
|
798
842
|
// Every linked package in the dependency tree, installed or local, each
|
|
@@ -1775,17 +1819,20 @@ let LinkedServer = class LinkedServer extends Shape {
|
|
|
1775
1819
|
catch (err) {
|
|
1776
1820
|
// A ServerCallError (e.g. 501 for a call no provider handles) carries
|
|
1777
1821
|
// its own status and a message that is safe to send to the client.
|
|
1822
|
+
// A `code` on it (a graph query refusal, see utils/queryPlane) is sent along, so
|
|
1823
|
+
// a remote caller can tell the refusals apart.
|
|
1778
1824
|
if (ServerCallError.is(err)) {
|
|
1779
|
-
|
|
1825
|
+
const code = err.code;
|
|
1826
|
+
return this.sendError(res, err.status, err.message, undefined, typeof code === 'string' ? code : undefined);
|
|
1780
1827
|
}
|
|
1781
1828
|
this.sendError(res, 500, 'internal server error' + (isDevelopment ? ': ' + (err === null || err === void 0 ? void 0 : err.stack) : ''), 'internal server error: ' + (err === null || err === void 0 ? void 0 : err.stack));
|
|
1782
1829
|
}
|
|
1783
1830
|
};
|
|
1784
1831
|
}
|
|
1785
|
-
sendError(res, statusCode = 500, message, logMessage) {
|
|
1832
|
+
sendError(res, statusCode = 500, message, logMessage, code) {
|
|
1786
1833
|
res === null || res === void 0 ? void 0 : res.status(statusCode);
|
|
1787
1834
|
if (message) {
|
|
1788
|
-
res === null || res === void 0 ? void 0 : res.send({ error: message });
|
|
1835
|
+
res === null || res === void 0 ? void 0 : res.send(code ? { error: message, code } : { error: message });
|
|
1789
1836
|
console.warn(paint('red', logMessage || message));
|
|
1790
1837
|
}
|
|
1791
1838
|
}
|