@cyberismo/backend 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +3 -6
- package/dist/app.js.map +1 -1
- package/dist/frontend.d.ts +22 -0
- package/dist/frontend.js +51 -0
- package/dist/frontend.js.map +1 -0
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/public/THIRD-PARTY.txt +1 -1
- package/dist/public/sbom.cdx.json +1 -1
- package/package.json +5 -5
- package/src/app.ts +4 -9
- package/src/frontend.ts +58 -0
- package/src/index.ts +3 -5
package/dist/app.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
import { Hono } from 'hono';
|
|
4
4
|
import { staticFrontendDirRelative } from './utils.js';
|
|
5
|
-
import {
|
|
5
|
+
import { frontendFallback, serveFrontend } from './frontend.js';
|
|
6
6
|
import { attachProjectDirectory } from './middleware/commandManager.js';
|
|
7
7
|
import { errorResponse } from './common/errors.js';
|
|
8
8
|
import calculationsRouter from './domain/calculations/index.js';
|
|
@@ -178,17 +178,14 @@ export function createApp(authProvider, directory, opts, exportPrefixes, multiPr
|
|
|
178
178
|
}
|
|
179
179
|
// MCP endpoint for AI assistant integration
|
|
180
180
|
app.route('/mcp', createMcpRouter(writableProjects(directory)));
|
|
181
|
-
app.use('*',
|
|
182
|
-
root: staticFrontendDirRelative,
|
|
183
|
-
}));
|
|
181
|
+
app.use('*', serveFrontend(staticFrontendDirRelative));
|
|
184
182
|
// serve index.html for all other routes
|
|
185
183
|
app.notFound(async (c) => {
|
|
186
184
|
if (c.req.path.startsWith('/api') ||
|
|
187
185
|
c.req.path.startsWith('/.well-known')) {
|
|
188
186
|
return c.text('Not Found', 404);
|
|
189
187
|
}
|
|
190
|
-
|
|
191
|
-
return c.html(file.toString());
|
|
188
|
+
return frontendFallback(c, path.join(import.meta.dirname, 'public', 'index.html'));
|
|
192
189
|
});
|
|
193
190
|
// Error handling
|
|
194
191
|
// Only server faults are logged; client errors are answered, not logged.
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,yCAAyC;AAEzC,OAAO,EAAE,IAAI,EAA0B,MAAM,MAAM,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Context, MiddlewareHandler } from 'hono';
|
|
2
|
+
/**
|
|
3
|
+
* index.html names the hashed bundles of one build, so the browser must
|
|
4
|
+
* revalidate it on every load. A cached copy from an earlier build would
|
|
5
|
+
* request bundles that no longer exist and leave the page blank.
|
|
6
|
+
*/
|
|
7
|
+
export declare const INDEX_CACHE_CONTROL = "no-cache";
|
|
8
|
+
/** Bundles under /assets/ carry a content hash, so they never change. */
|
|
9
|
+
export declare const ASSET_CACHE_CONTROL = "public, max-age=31536000, immutable";
|
|
10
|
+
/** True for paths of the hashed bundles Vite emits. */
|
|
11
|
+
export declare function isAssetPath(requestPath: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Serves the built frontend from `root`, with cache headers that keep a
|
|
14
|
+
* browser from pairing an old index.html with a newer build.
|
|
15
|
+
*/
|
|
16
|
+
export declare function serveFrontend(root: string): MiddlewareHandler;
|
|
17
|
+
/**
|
|
18
|
+
* Answers a path that matched no route and no file. Client-side routes get
|
|
19
|
+
* index.html; a missing bundle gets a 404, since index.html served as a
|
|
20
|
+
* script fails to load and leaves the page blank.
|
|
21
|
+
*/
|
|
22
|
+
export declare function frontendFallback(c: Context, indexPath: string): Promise<Response>;
|
package/dist/frontend.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Cyberismo Ltd and contributors
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
import { every } from 'hono/combine';
|
|
4
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
/**
|
|
7
|
+
* index.html names the hashed bundles of one build, so the browser must
|
|
8
|
+
* revalidate it on every load. A cached copy from an earlier build would
|
|
9
|
+
* request bundles that no longer exist and leave the page blank.
|
|
10
|
+
*/
|
|
11
|
+
export const INDEX_CACHE_CONTROL = 'no-cache';
|
|
12
|
+
/** Bundles under /assets/ carry a content hash, so they never change. */
|
|
13
|
+
export const ASSET_CACHE_CONTROL = 'public, max-age=31536000, immutable';
|
|
14
|
+
/** True for paths of the hashed bundles Vite emits. */
|
|
15
|
+
export function isAssetPath(requestPath) {
|
|
16
|
+
return requestPath.startsWith('/assets/');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Serves the built frontend from `root`, with cache headers that keep a
|
|
20
|
+
* browser from pairing an old index.html with a newer build.
|
|
21
|
+
*/
|
|
22
|
+
export function serveFrontend(root) {
|
|
23
|
+
// Only files served from disk get these headers, not the responses of
|
|
24
|
+
// later handlers that serveStatic falls through to.
|
|
25
|
+
const servedFromDisk = new WeakSet();
|
|
26
|
+
return every(async (c, next) => {
|
|
27
|
+
await next();
|
|
28
|
+
if (!servedFromDisk.has(c))
|
|
29
|
+
return;
|
|
30
|
+
if (c.res.headers.get('Content-Type')?.startsWith('text/html')) {
|
|
31
|
+
c.res.headers.set('Cache-Control', INDEX_CACHE_CONTROL);
|
|
32
|
+
}
|
|
33
|
+
else if (isAssetPath(c.req.path)) {
|
|
34
|
+
c.res.headers.set('Cache-Control', ASSET_CACHE_CONTROL);
|
|
35
|
+
}
|
|
36
|
+
}, serveStatic({ root, onFound: (_path, c) => void servedFromDisk.add(c) }));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Answers a path that matched no route and no file. Client-side routes get
|
|
40
|
+
* index.html; a missing bundle gets a 404, since index.html served as a
|
|
41
|
+
* script fails to load and leaves the page blank.
|
|
42
|
+
*/
|
|
43
|
+
export async function frontendFallback(c, indexPath) {
|
|
44
|
+
if (isAssetPath(c.req.path)) {
|
|
45
|
+
return c.text('Not Found', 404);
|
|
46
|
+
}
|
|
47
|
+
const file = await readFile(indexPath);
|
|
48
|
+
c.header('Cache-Control', INDEX_CACHE_CONTROL);
|
|
49
|
+
return c.html(file.toString());
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=frontend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontend.js","sourceRoot":"","sources":["../src/frontend.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,yCAAyC;AAGzC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C,yEAAyE;AACzE,MAAM,CAAC,MAAM,mBAAmB,GAAG,qCAAqC,CAAC;AAEzE,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,OAAO,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,cAAc,GAAG,IAAI,OAAO,EAAW,CAAC;IAC9C,OAAO,KAAK,CACV,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QAChB,MAAM,IAAI,EAAE,CAAC;QACb,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO;QACnC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/D,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;QAC1D,CAAC;aAAM,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,EACD,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACzE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,CAAU,EAAE,SAAiB;IAClE,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;IAC/C,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: Cyberismo Ltd and contributors
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
import { Hono } from 'hono';
|
|
4
|
-
import { serveStatic } from '@hono/node-server/serve-static';
|
|
5
4
|
import path from 'node:path';
|
|
6
|
-
import {
|
|
5
|
+
import { frontendFallback, serveFrontend } from './frontend.js';
|
|
7
6
|
import { listen } from './utils.js';
|
|
8
7
|
import { startPolicyPolling } from './overlay.js';
|
|
9
8
|
import { createApp } from './app.js';
|
|
@@ -18,13 +17,12 @@ const MAX_PORT_ATTEMPTS = 100;
|
|
|
18
17
|
*/
|
|
19
18
|
export async function previewSite(dir, findPort = true) {
|
|
20
19
|
const app = new Hono();
|
|
21
|
-
app.use(
|
|
20
|
+
app.use(serveFrontend(dir));
|
|
22
21
|
app.get('*', async (c) => {
|
|
23
22
|
if (c.req.path.startsWith('/api/')) {
|
|
24
23
|
return c.json({ error: 'Resource not found' }, 404);
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
return c.html(file.toString());
|
|
25
|
+
return frontendFallback(c, path.join(dir, 'index.html'));
|
|
28
26
|
});
|
|
29
27
|
const port = parseInt(process.env.PORT || DEFAULT_PORT.toString(), 10);
|
|
30
28
|
await startApp(app, port, findPort);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,yCAAyC;AAGzC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"bomFormat":"CycloneDX","specVersion":"1.6","components":[{"type":"library","name":"react","version":"19.3.1","purl":"pkg:npm/react@19.3.1"},{"type":"library","name":"scheduler","version":"0.28.0","purl":"pkg:npm/scheduler@0.28.0"},{"type":"library","name":"react-dom","version":"19.3.1","purl":"pkg:npm/react-dom@19.3.1"},{"type":"library","name":"react-router","version":"8.5.1","purl":"pkg:npm/react-router@8.5.1"},{"type":"library","name":"@mui/joy","version":"5.0.0-beta.52","purl":"pkg:npm/%40mui/joy@5.0.0-beta.52"},{"type":"library","name":"@mui/utils","version":"5.17.1","purl":"pkg:npm/%40mui/utils@5.17.1"},{"type":"library","name":"@babel/runtime","version":"7.29.7","purl":"pkg:npm/%40babel/runtime@7.29.7"},{"type":"library","name":"@emotion/sheet","version":"1.4.0","purl":"pkg:npm/%40emotion/sheet@1.4.0"},{"type":"library","name":"stylis","version":"4.2.0","purl":"pkg:npm/stylis@4.2.0"},{"type":"library","name":"@emotion/memoize","version":"0.9.0","purl":"pkg:npm/%40emotion/memoize@0.9.0"},{"type":"library","name":"@emotion/cache","version":"11.14.0","purl":"pkg:npm/%40emotion/cache@11.14.0"},{"type":"library","name":"react-is","version":"16.13.1","purl":"pkg:npm/react-is@16.13.1"},{"type":"library","name":"hoist-non-react-statics","version":"3.3.2","purl":"pkg:npm/hoist-non-react-statics@3.3.2"},{"type":"library","name":"@emotion/utils","version":"1.4.2","purl":"pkg:npm/%40emotion/utils@1.4.2"},{"type":"library","name":"@emotion/hash","version":"0.9.2","purl":"pkg:npm/%40emotion/hash@0.9.2"},{"type":"library","name":"@emotion/unitless","version":"0.10.0","purl":"pkg:npm/%40emotion/unitless@0.10.0"},{"type":"library","name":"@emotion/serialize","version":"1.3.3","purl":"pkg:npm/%40emotion/serialize@1.3.3"},{"type":"library","name":"@emotion/use-insertion-effect-with-fallbacks","version":"1.2.0","purl":"pkg:npm/%40emotion/use-insertion-effect-with-fallbacks@1.2.0"},{"type":"library","name":"@emotion/react","version":"11.14.0","purl":"pkg:npm/%40emotion/react@11.14.0"},{"type":"library","name":"@emotion/is-prop-valid","version":"1.4.0","purl":"pkg:npm/%40emotion/is-prop-valid@1.4.0"},{"type":"library","name":"@emotion/styled","version":"11.14.1","purl":"pkg:npm/%40emotion/styled@11.14.1"},{"type":"library","name":"@mui/styled-engine","version":"5.18.0","purl":"pkg:npm/%40mui/styled-engine@5.18.0"},{"type":"library","name":"@mui/system","version":"5.18.0","purl":"pkg:npm/%40mui/system@5.18.0"},{"type":"library","name":"clsx","version":"2.1.1","purl":"pkg:npm/clsx@2.1.1"},{"type":"library","name":"@mui/private-theming","version":"5.17.1","purl":"pkg:npm/%40mui/private-theming@5.17.1"},{"type":"library","name":"@mui/base","version":"5.0.0-beta.40-1","purl":"pkg:npm/%40mui/base@5.0.0-beta.40-1"},{"type":"library","name":"@popperjs/core","version":"2.11.8","purl":"pkg:npm/%40popperjs/core@2.11.8"},{"type":"library","name":"use-sync-external-store","version":"1.6.0","purl":"pkg:npm/use-sync-external-store@1.6.0"},{"type":"library","name":"dequal","version":"2.0.3","purl":"pkg:npm/dequal@2.0.3"},{"type":"library","name":"swr","version":"2.5.1","purl":"pkg:npm/swr@2.5.1"},{"type":"library","name":"react-hook-form","version":"7.91.0","purl":"pkg:npm/react-hook-form@7.91.0"},{"type":"library","name":"@cyberismo/model","version":"1.2.0","purl":"pkg:npm/%40cyberismo/model@1.2.0"},{"type":"library","name":"redux","version":"5.0.1","purl":"pkg:npm/redux@5.0.1"},{"type":"library","name":"immer","version":"11.1.8","purl":"pkg:npm/immer@11.1.8"},{"type":"library","name":"redux-thunk","version":"3.1.0","purl":"pkg:npm/redux-thunk@3.1.0"},{"type":"library","name":"@reduxjs/toolkit","version":"2.13.0","purl":"pkg:npm/%40reduxjs/toolkit@2.13.0"},{"type":"library","name":"@lezer/common","version":"1.5.2","purl":"pkg:npm/%40lezer/common@1.5.2"},{"type":"library","name":"@lezer/highlight","version":"1.2.3","purl":"pkg:npm/%40lezer/highlight@1.2.3"},{"type":"library","name":"@marijn/find-cluster-break","version":"1.0.3","purl":"pkg:npm/%40marijn/find-cluster-break@1.0.3"},{"type":"library","name":"@codemirror/state","version":"6.7.6","purl":"pkg:npm/%40codemirror/state@6.7.6"},{"type":"library","name":"style-mod","version":"4.1.3","purl":"pkg:npm/style-mod@4.1.3"},{"type":"library","name":"w3c-keyname","version":"2.2.8","purl":"pkg:npm/w3c-keyname@2.2.8"},{"type":"library","name":"crelt","version":"1.0.7","purl":"pkg:npm/crelt@1.0.7"},{"type":"library","name":"@codemirror/view","version":"6.43.15","purl":"pkg:npm/%40codemirror/view@6.43.15"},{"type":"library","name":"@codemirror/streamparser","version":"6.0.0","purl":"pkg:npm/%40codemirror/streamparser@6.0.0"},{"type":"library","name":"@codemirror/language","version":"6.13.1","purl":"pkg:npm/%40codemirror/language@6.13.1"},{"type":"library","name":"@uiw/codemirror-themes","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-themes@4.25.12"},{"type":"library","name":"@uiw/codemirror-theme-vscode","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-theme-vscode@4.25.12"},{"type":"library","name":"@uiw/codemirror-theme-github","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-theme-github@4.25.12"},{"type":"library","name":"redux-persist","version":"6.0.0","purl":"pkg:npm/redux-persist@6.0.0"},{"type":"library","name":"@mui/material","version":"9.5.0","purl":"pkg:npm/%40mui/material@9.5.0"},{"type":"library","name":"react-redux","version":"9.3.1","purl":"pkg:npm/react-redux@9.3.1"},{"type":"library","name":"i18next","version":"26.5.12","purl":"pkg:npm/i18next@26.5.12"},{"type":"library","name":"html-parse-stringify","version":"4.0.1","purl":"pkg:npm/html-parse-stringify@4.0.1"},{"type":"library","name":"react-i18next","version":"17.1.9","purl":"pkg:npm/react-i18next@17.1.9"},{"type":"library","name":"@mui/icons-material","version":"9.5.0","purl":"pkg:npm/%40mui/icons-material@9.5.0"},{"type":"library","name":"@asciidoctor/core","version":"4.1.1","purl":"pkg:npm/%40asciidoctor/core@4.1.1"},{"type":"library","name":"date-fns","version":"4.4.0","purl":"pkg:npm/date-fns@4.4.0"},{"type":"library","name":"react-dnd","version":"16.0.1","purl":"pkg:npm/react-dnd@16.0.1"},{"type":"library","name":"@react-dnd/invariant","version":"4.0.2","purl":"pkg:npm/%40react-dnd/invariant@4.0.2"},{"type":"library","name":"dnd-core","version":"16.0.1","purl":"pkg:npm/dnd-core@16.0.1"},{"type":"library","name":"@react-dnd/asap","version":"5.0.2","purl":"pkg:npm/%40react-dnd/asap@5.0.2"},{"type":"library","name":"fast-deep-equal","version":"3.1.3","purl":"pkg:npm/fast-deep-equal@3.1.3"},{"type":"library","name":"@react-dnd/shallowequal","version":"4.0.2","purl":"pkg:npm/%40react-dnd/shallowequal@4.0.2"},{"type":"library","name":"react-arborist","version":"4.0.1","purl":"pkg:npm/react-arborist@4.0.1"},{"type":"library","name":"memoize-one","version":"5.2.1","purl":"pkg:npm/memoize-one@5.2.1"},{"type":"library","name":"react-window","version":"1.8.11","purl":"pkg:npm/react-window@1.8.11"},{"type":"library","name":"react-dnd-html5-backend","version":"16.0.1","purl":"pkg:npm/react-dnd-html5-backend@16.0.1"},{"type":"library","name":"semver","version":"7.8.5","purl":"pkg:npm/semver@7.8.5"},{"type":"library","name":"react-resizable-panels","version":"4.15.2","purl":"pkg:npm/react-resizable-panels@4.15.2"},{"type":"library","name":"node-html-parser","version":"9.0.6","purl":"pkg:npm/node-html-parser@9.0.6"},{"type":"library","name":"html-dom-parser","version":"8.0.2","purl":"pkg:npm/html-dom-parser@8.0.2"},{"type":"library","name":"react-property","version":"2.0.2","purl":"pkg:npm/react-property@2.0.2"},{"type":"library","name":"inline-style-parser","version":"0.2.9","purl":"pkg:npm/inline-style-parser@0.2.9"},{"type":"library","name":"style-to-object","version":"2.0.2","purl":"pkg:npm/style-to-object@2.0.2"},{"type":"library","name":"style-to-js","version":"2.0.2","purl":"pkg:npm/style-to-js@2.0.2"},{"type":"library","name":"html-react-parser","version":"6.1.9","purl":"pkg:npm/html-react-parser@6.1.9"},{"type":"library","name":"domelementtype","version":"3.0.0","purl":"pkg:npm/domelementtype@3.0.0"},{"type":"library","name":"domhandler","version":"6.0.1","purl":"pkg:npm/domhandler@6.0.1"},{"type":"library","name":"d3-array","version":"3.2.4","purl":"pkg:npm/d3-array@3.2.4"},{"type":"library","name":"internmap","version":"2.0.3","purl":"pkg:npm/internmap@2.0.3"},{"type":"library","name":"d3-color","version":"3.1.0","purl":"pkg:npm/d3-color@3.1.0"},{"type":"library","name":"d3-interpolate","version":"3.0.1","purl":"pkg:npm/d3-interpolate@3.0.1"},{"type":"library","name":"d3-timer","version":"3.0.1","purl":"pkg:npm/d3-timer@3.0.1"},{"type":"library","name":"d3-ease","version":"3.0.1","purl":"pkg:npm/d3-ease@3.0.1"},{"type":"library","name":"robust-predicates","version":"3.0.3","purl":"pkg:npm/robust-predicates@3.0.3"},{"type":"library","name":"delaunator","version":"5.1.0","purl":"pkg:npm/delaunator@5.1.0"},{"type":"library","name":"d3-delaunay","version":"6.0.4","purl":"pkg:npm/d3-delaunay@6.0.4"},{"type":"library","name":"d3-dsv","version":"3.0.1","purl":"pkg:npm/d3-dsv@3.0.1"},{"type":"library","name":"d3-force","version":"3.0.0","purl":"pkg:npm/d3-force@3.0.0"},{"type":"library","name":"d3-quadtree","version":"3.0.1","purl":"pkg:npm/d3-quadtree@3.0.1"},{"type":"library","name":"d3-geo","version":"3.1.1","purl":"pkg:npm/d3-geo@3.1.1"},{"type":"library","name":"d3-hierarchy","version":"3.1.2","purl":"pkg:npm/d3-hierarchy@3.1.2"},{"type":"library","name":"d3-scale","version":"4.0.2","purl":"pkg:npm/d3-scale@4.0.2"},{"type":"library","name":"d3-time","version":"3.1.0","purl":"pkg:npm/d3-time@3.1.0"},{"type":"library","name":"d3-time-format","version":"4.1.0","purl":"pkg:npm/d3-time-format@4.1.0"},{"type":"library","name":"d3-scale-chromatic","version":"3.1.0","purl":"pkg:npm/d3-scale-chromatic@3.1.0"},{"type":"library","name":"d3-shape","version":"3.2.0","purl":"pkg:npm/d3-shape@3.2.0"},{"type":"library","name":"mermaid","version":"12.2.0","purl":"pkg:npm/mermaid@12.2.0"},{"type":"library","name":"es-toolkit","version":"1.52.0","purl":"pkg:npm/es-toolkit@1.52.0"},{"type":"library","name":"json-stringify-pretty-compact","version":"4.0.0","purl":"pkg:npm/json-stringify-pretty-compact@4.0.0"},{"type":"library","name":"vega-util","version":"2.1.3","purl":"pkg:npm/vega-util@2.1.3"},{"type":"library","name":"topojson-client","version":"3.1.0","purl":"pkg:npm/topojson-client@3.1.0"},{"type":"library","name":"vega-time","version":"3.3.0","purl":"pkg:npm/vega-time@3.3.0"},{"type":"library","name":"vega-format","version":"2.1.3","purl":"pkg:npm/vega-format@2.1.3"},{"type":"library","name":"vega-loader","version":"5.1.3","purl":"pkg:npm/vega-loader@5.1.3"},{"type":"library","name":"vega-dataflow","version":"6.1.3","purl":"pkg:npm/vega-dataflow@6.1.3"},{"type":"library","name":"vega-statistics","version":"2.0.0","purl":"pkg:npm/vega-statistics@2.0.0"},{"type":"library","name":"vega-transforms","version":"5.2.2","purl":"pkg:npm/vega-transforms@5.2.2"},{"type":"library","name":"vega-canvas","version":"2.0.0","purl":"pkg:npm/vega-canvas@2.0.0"},{"type":"library","name":"vega-scale","version":"8.1.3","purl":"pkg:npm/vega-scale@8.1.3"},{"type":"library","name":"vega-scenegraph","version":"5.3.0","purl":"pkg:npm/vega-scenegraph@5.3.0"},{"type":"library","name":"vega-view-transforms","version":"5.2.2","purl":"pkg:npm/vega-view-transforms@5.2.2"},{"type":"library","name":"vega-encode","version":"5.2.2","purl":"pkg:npm/vega-encode@5.2.2"},{"type":"library","name":"d3-geo-projection","version":"4.0.0","purl":"pkg:npm/d3-geo-projection@4.0.0"},{"type":"library","name":"vega-projection","version":"2.1.3","purl":"pkg:npm/vega-projection@2.1.3"},{"type":"library","name":"vega-geo","version":"5.1.3","purl":"pkg:npm/vega-geo@5.1.3"},{"type":"library","name":"vega-force","version":"5.1.3","purl":"pkg:npm/vega-force@5.1.3"},{"type":"library","name":"vega-hierarchy","version":"5.1.3","purl":"pkg:npm/vega-hierarchy@5.1.3"},{"type":"library","name":"vega-label","version":"2.1.3","purl":"pkg:npm/vega-label@2.1.3"},{"type":"library","name":"vega-regression","version":"2.1.3","purl":"pkg:npm/vega-regression@2.1.3"},{"type":"library","name":"vega-voronoi","version":"5.1.3","purl":"pkg:npm/vega-voronoi@5.1.3"},{"type":"library","name":"vega-wordcloud","version":"5.1.3","purl":"pkg:npm/vega-wordcloud@5.1.3"},{"type":"library","name":"vega-crossfilter","version":"5.1.3","purl":"pkg:npm/vega-crossfilter@5.1.3"},{"type":"library","name":"vega-expression","version":"6.2.2","purl":"pkg:npm/vega-expression@6.2.2"},{"type":"library","name":"vega-selections","version":"6.1.5","purl":"pkg:npm/vega-selections@6.1.5"},{"type":"library","name":"vega-functions","version":"6.2.0","purl":"pkg:npm/vega-functions@6.2.0"},{"type":"library","name":"vega-runtime","version":"7.1.3","purl":"pkg:npm/vega-runtime@7.1.3"},{"type":"library","name":"vega-view","version":"6.2.0","purl":"pkg:npm/vega-view@6.2.0"},{"type":"library","name":"vega-event-selector","version":"4.0.0","purl":"pkg:npm/vega-event-selector@4.0.0"},{"type":"library","name":"vega-parser","version":"7.1.3","purl":"pkg:npm/vega-parser@7.1.3"},{"type":"library","name":"vega","version":"6.4.0","purl":"pkg:npm/vega@6.4.0"},{"type":"library","name":"vega-interpreter","version":"2.3.1","purl":"pkg:npm/vega-interpreter@2.3.1"},{"type":"library","name":"vega-lite","version":"6.5.0","purl":"pkg:npm/vega-lite@6.5.0"},{"type":"library","name":"vega-schema-url-parser","version":"3.0.2","purl":"pkg:npm/vega-schema-url-parser@3.0.2"},{"type":"library","name":"vega-themes","version":"3.0.0","purl":"pkg:npm/vega-themes@3.0.0"},{"type":"library","name":"vega-tooltip","version":"1.0.0","purl":"pkg:npm/vega-tooltip@1.0.0"},{"type":"library","name":"vega-embed","version":"7.1.0","purl":"pkg:npm/vega-embed@7.1.0"},{"type":"library","name":"react-vega","version":"8.0.0","purl":"pkg:npm/react-vega@8.0.0"},{"type":"library","name":"@codemirror/commands","version":"6.11.1","purl":"pkg:npm/%40codemirror/commands@6.11.1"},{"type":"library","name":"@codemirror/search","version":"6.7.0","purl":"pkg:npm/%40codemirror/search@6.7.0"},{"type":"library","name":"@codemirror/autocomplete","version":"6.20.2","purl":"pkg:npm/%40codemirror/autocomplete@6.20.2"},{"type":"library","name":"@codemirror/lint","version":"6.9.6","purl":"pkg:npm/%40codemirror/lint@6.9.6"},{"type":"library","name":"@uiw/codemirror-extensions-basic-setup","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-extensions-basic-setup@4.25.12"},{"type":"library","name":"@codemirror/theme-one-dark","version":"6.1.3","purl":"pkg:npm/%40codemirror/theme-one-dark@6.1.3"},{"type":"library","name":"@uiw/react-codemirror","version":"4.25.12","purl":"pkg:npm/%40uiw/react-codemirror@4.25.12"},{"type":"library","name":"codemirror-asciidoc","version":"2.0.1","purl":"pkg:npm/codemirror-asciidoc@2.0.1"},{"type":"library","name":"marked","version":"18.1.2","purl":"pkg:npm/marked@18.1.2"},{"type":"library","name":"@hookform/resolvers","version":"6.0.2","purl":"pkg:npm/%40hookform/resolvers@6.0.2"},{"type":"library","name":"zod","version":"4.6.7","purl":"pkg:npm/zod@4.6.7"},{"type":"library","name":"khroma","version":"2.1.0","purl":"pkg:npm/khroma@2.1.0"},{"type":"library","name":"@upsetjs/venn.js","version":"2.0.0","purl":"pkg:npm/%40upsetjs/venn.js@2.0.0"},{"type":"library","name":"@chevrotain/utils","version":"13.2.0","purl":"pkg:npm/%40chevrotain/utils@13.2.0"},{"type":"library","name":"@chevrotain/gast","version":"13.2.0","purl":"pkg:npm/%40chevrotain/gast@13.2.0"},{"type":"library","name":"chevrotain","version":"13.2.0","purl":"pkg:npm/chevrotain@13.2.0"},{"type":"library","name":"@chevrotain/regexp-to-ast","version":"13.2.0","purl":"pkg:npm/%40chevrotain/regexp-to-ast@13.2.0"},{"type":"library","name":"d3-sankey","version":"0.12.3","purl":"pkg:npm/d3-sankey@0.12.3"},{"type":"library","name":"d3-path","version":"1.0.9","purl":"pkg:npm/d3-path@1.0.9"},{"type":"library","name":"uuid","version":"14.0.2","purl":"pkg:npm/uuid@14.0.2"},{"type":"library","name":"d3-axis","version":"3.0.0","purl":"pkg:npm/d3-axis@3.0.0"},{"type":"library","name":"dayjs","version":"1.11.23","purl":"pkg:npm/dayjs@1.11.23"},{"type":"library","name":"layout-base","version":"1.0.2","purl":"pkg:npm/layout-base@1.0.2"},{"type":"library","name":"cose-base","version":"1.0.3","purl":"pkg:npm/cose-base@1.0.3"},{"type":"library","name":"cytoscape-cose-bilkent","version":"4.1.0","purl":"pkg:npm/cytoscape-cose-bilkent@4.1.0"},{"type":"library","name":"lodash-es","version":"4.18.1","purl":"pkg:npm/lodash-es@4.18.1"},{"type":"library","name":"dagre-d3-es","version":"7.0.14","purl":"pkg:npm/dagre-d3-es@7.0.14"},{"type":"library","name":"elkjs","version":"0.9.3","purl":"pkg:npm/elkjs@0.9.3"},{"type":"library","name":"cytoscape-fcose","version":"2.2.0","purl":"pkg:npm/cytoscape-fcose@2.2.0"},{"type":"library","name":"katex","version":"0.18.10","purl":"pkg:npm/katex@0.18.10"},{"type":"library","name":"dompurify","version":"3.4.17","purl":"pkg:npm/dompurify@3.4.17"},{"type":"library","name":"d3-dispatch","version":"3.0.1","purl":"pkg:npm/d3-dispatch@3.0.1"},{"type":"library","name":"d3-selection","version":"3.0.0","purl":"pkg:npm/d3-selection@3.0.0"},{"type":"library","name":"d3-transition","version":"3.0.1","purl":"pkg:npm/d3-transition@3.0.1"},{"type":"library","name":"d3-brush","version":"3.0.0","purl":"pkg:npm/d3-brush@3.0.0"},{"type":"library","name":"d3-zoom","version":"3.0.0","purl":"pkg:npm/d3-zoom@3.0.0"},{"type":"library","name":"d3-format","version":"3.1.2","purl":"pkg:npm/d3-format@3.1.2"},{"type":"library","name":"@braintree/sanitize-url","version":"7.1.2","purl":"pkg:npm/%40braintree/sanitize-url@7.1.2"},{"type":"library","name":"@iconify/utils","version":"3.1.4","purl":"pkg:npm/%40iconify/utils@3.1.4"},{"type":"library","name":"ts-dedent","version":"2.3.0","purl":"pkg:npm/ts-dedent@2.3.0"},{"type":"library","name":"roughjs","version":"4.6.6","purl":"pkg:npm/roughjs@4.6.6"},{"type":"library","name":"@mermaid-js/parser","version":"2.0.1","purl":"pkg:npm/%40mermaid-js/parser@2.0.1"},{"type":"library","name":"cytoscape","version":"3.34.2","purl":"pkg:npm/cytoscape@3.34.2"}]}
|
|
1
|
+
{"bomFormat":"CycloneDX","specVersion":"1.6","components":[{"type":"library","name":"react","version":"19.3.1","purl":"pkg:npm/react@19.3.1"},{"type":"library","name":"scheduler","version":"0.28.0","purl":"pkg:npm/scheduler@0.28.0"},{"type":"library","name":"react-dom","version":"19.3.1","purl":"pkg:npm/react-dom@19.3.1"},{"type":"library","name":"react-router","version":"8.5.1","purl":"pkg:npm/react-router@8.5.1"},{"type":"library","name":"@mui/joy","version":"5.0.0-beta.52","purl":"pkg:npm/%40mui/joy@5.0.0-beta.52"},{"type":"library","name":"@mui/utils","version":"5.17.1","purl":"pkg:npm/%40mui/utils@5.17.1"},{"type":"library","name":"@babel/runtime","version":"7.29.7","purl":"pkg:npm/%40babel/runtime@7.29.7"},{"type":"library","name":"@emotion/sheet","version":"1.4.0","purl":"pkg:npm/%40emotion/sheet@1.4.0"},{"type":"library","name":"stylis","version":"4.2.0","purl":"pkg:npm/stylis@4.2.0"},{"type":"library","name":"@emotion/memoize","version":"0.9.0","purl":"pkg:npm/%40emotion/memoize@0.9.0"},{"type":"library","name":"@emotion/cache","version":"11.14.0","purl":"pkg:npm/%40emotion/cache@11.14.0"},{"type":"library","name":"react-is","version":"16.13.1","purl":"pkg:npm/react-is@16.13.1"},{"type":"library","name":"hoist-non-react-statics","version":"3.3.2","purl":"pkg:npm/hoist-non-react-statics@3.3.2"},{"type":"library","name":"@emotion/utils","version":"1.4.2","purl":"pkg:npm/%40emotion/utils@1.4.2"},{"type":"library","name":"@emotion/hash","version":"0.9.2","purl":"pkg:npm/%40emotion/hash@0.9.2"},{"type":"library","name":"@emotion/unitless","version":"0.10.0","purl":"pkg:npm/%40emotion/unitless@0.10.0"},{"type":"library","name":"@emotion/serialize","version":"1.3.3","purl":"pkg:npm/%40emotion/serialize@1.3.3"},{"type":"library","name":"@emotion/use-insertion-effect-with-fallbacks","version":"1.2.0","purl":"pkg:npm/%40emotion/use-insertion-effect-with-fallbacks@1.2.0"},{"type":"library","name":"@emotion/react","version":"11.14.0","purl":"pkg:npm/%40emotion/react@11.14.0"},{"type":"library","name":"@emotion/is-prop-valid","version":"1.4.0","purl":"pkg:npm/%40emotion/is-prop-valid@1.4.0"},{"type":"library","name":"@emotion/styled","version":"11.14.1","purl":"pkg:npm/%40emotion/styled@11.14.1"},{"type":"library","name":"@mui/styled-engine","version":"5.18.0","purl":"pkg:npm/%40mui/styled-engine@5.18.0"},{"type":"library","name":"@mui/system","version":"5.18.0","purl":"pkg:npm/%40mui/system@5.18.0"},{"type":"library","name":"clsx","version":"2.1.1","purl":"pkg:npm/clsx@2.1.1"},{"type":"library","name":"@mui/private-theming","version":"5.17.1","purl":"pkg:npm/%40mui/private-theming@5.17.1"},{"type":"library","name":"@mui/base","version":"5.0.0-beta.40-1","purl":"pkg:npm/%40mui/base@5.0.0-beta.40-1"},{"type":"library","name":"@popperjs/core","version":"2.11.8","purl":"pkg:npm/%40popperjs/core@2.11.8"},{"type":"library","name":"use-sync-external-store","version":"1.6.0","purl":"pkg:npm/use-sync-external-store@1.6.0"},{"type":"library","name":"dequal","version":"2.0.3","purl":"pkg:npm/dequal@2.0.3"},{"type":"library","name":"swr","version":"2.5.1","purl":"pkg:npm/swr@2.5.1"},{"type":"library","name":"react-hook-form","version":"7.91.0","purl":"pkg:npm/react-hook-form@7.91.0"},{"type":"library","name":"@cyberismo/model","version":"1.3.1","purl":"pkg:npm/%40cyberismo/model@1.3.1"},{"type":"library","name":"redux","version":"5.0.1","purl":"pkg:npm/redux@5.0.1"},{"type":"library","name":"immer","version":"11.1.8","purl":"pkg:npm/immer@11.1.8"},{"type":"library","name":"redux-thunk","version":"3.1.0","purl":"pkg:npm/redux-thunk@3.1.0"},{"type":"library","name":"@reduxjs/toolkit","version":"2.13.0","purl":"pkg:npm/%40reduxjs/toolkit@2.13.0"},{"type":"library","name":"@lezer/common","version":"1.5.2","purl":"pkg:npm/%40lezer/common@1.5.2"},{"type":"library","name":"@lezer/highlight","version":"1.2.3","purl":"pkg:npm/%40lezer/highlight@1.2.3"},{"type":"library","name":"@marijn/find-cluster-break","version":"1.0.3","purl":"pkg:npm/%40marijn/find-cluster-break@1.0.3"},{"type":"library","name":"@codemirror/state","version":"6.7.6","purl":"pkg:npm/%40codemirror/state@6.7.6"},{"type":"library","name":"style-mod","version":"4.1.3","purl":"pkg:npm/style-mod@4.1.3"},{"type":"library","name":"w3c-keyname","version":"2.2.8","purl":"pkg:npm/w3c-keyname@2.2.8"},{"type":"library","name":"crelt","version":"1.0.7","purl":"pkg:npm/crelt@1.0.7"},{"type":"library","name":"@codemirror/view","version":"6.43.15","purl":"pkg:npm/%40codemirror/view@6.43.15"},{"type":"library","name":"@codemirror/streamparser","version":"6.0.0","purl":"pkg:npm/%40codemirror/streamparser@6.0.0"},{"type":"library","name":"@codemirror/language","version":"6.13.1","purl":"pkg:npm/%40codemirror/language@6.13.1"},{"type":"library","name":"@uiw/codemirror-themes","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-themes@4.25.12"},{"type":"library","name":"@uiw/codemirror-theme-vscode","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-theme-vscode@4.25.12"},{"type":"library","name":"@uiw/codemirror-theme-github","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-theme-github@4.25.12"},{"type":"library","name":"redux-persist","version":"6.0.0","purl":"pkg:npm/redux-persist@6.0.0"},{"type":"library","name":"@mui/material","version":"9.5.0","purl":"pkg:npm/%40mui/material@9.5.0"},{"type":"library","name":"react-redux","version":"9.3.1","purl":"pkg:npm/react-redux@9.3.1"},{"type":"library","name":"i18next","version":"26.5.12","purl":"pkg:npm/i18next@26.5.12"},{"type":"library","name":"html-parse-stringify","version":"4.0.1","purl":"pkg:npm/html-parse-stringify@4.0.1"},{"type":"library","name":"react-i18next","version":"17.1.9","purl":"pkg:npm/react-i18next@17.1.9"},{"type":"library","name":"@mui/icons-material","version":"9.5.0","purl":"pkg:npm/%40mui/icons-material@9.5.0"},{"type":"library","name":"@asciidoctor/core","version":"4.1.1","purl":"pkg:npm/%40asciidoctor/core@4.1.1"},{"type":"library","name":"date-fns","version":"4.4.0","purl":"pkg:npm/date-fns@4.4.0"},{"type":"library","name":"react-dnd","version":"16.0.1","purl":"pkg:npm/react-dnd@16.0.1"},{"type":"library","name":"@react-dnd/invariant","version":"4.0.2","purl":"pkg:npm/%40react-dnd/invariant@4.0.2"},{"type":"library","name":"dnd-core","version":"16.0.1","purl":"pkg:npm/dnd-core@16.0.1"},{"type":"library","name":"@react-dnd/asap","version":"5.0.2","purl":"pkg:npm/%40react-dnd/asap@5.0.2"},{"type":"library","name":"fast-deep-equal","version":"3.1.3","purl":"pkg:npm/fast-deep-equal@3.1.3"},{"type":"library","name":"@react-dnd/shallowequal","version":"4.0.2","purl":"pkg:npm/%40react-dnd/shallowequal@4.0.2"},{"type":"library","name":"react-arborist","version":"4.0.1","purl":"pkg:npm/react-arborist@4.0.1"},{"type":"library","name":"memoize-one","version":"5.2.1","purl":"pkg:npm/memoize-one@5.2.1"},{"type":"library","name":"react-window","version":"1.8.11","purl":"pkg:npm/react-window@1.8.11"},{"type":"library","name":"react-dnd-html5-backend","version":"16.0.1","purl":"pkg:npm/react-dnd-html5-backend@16.0.1"},{"type":"library","name":"semver","version":"7.8.5","purl":"pkg:npm/semver@7.8.5"},{"type":"library","name":"react-resizable-panels","version":"4.15.2","purl":"pkg:npm/react-resizable-panels@4.15.2"},{"type":"library","name":"node-html-parser","version":"9.0.6","purl":"pkg:npm/node-html-parser@9.0.6"},{"type":"library","name":"html-dom-parser","version":"8.0.2","purl":"pkg:npm/html-dom-parser@8.0.2"},{"type":"library","name":"react-property","version":"2.0.2","purl":"pkg:npm/react-property@2.0.2"},{"type":"library","name":"inline-style-parser","version":"0.2.9","purl":"pkg:npm/inline-style-parser@0.2.9"},{"type":"library","name":"style-to-object","version":"2.0.2","purl":"pkg:npm/style-to-object@2.0.2"},{"type":"library","name":"style-to-js","version":"2.0.2","purl":"pkg:npm/style-to-js@2.0.2"},{"type":"library","name":"html-react-parser","version":"6.1.9","purl":"pkg:npm/html-react-parser@6.1.9"},{"type":"library","name":"domelementtype","version":"3.0.0","purl":"pkg:npm/domelementtype@3.0.0"},{"type":"library","name":"domhandler","version":"6.0.1","purl":"pkg:npm/domhandler@6.0.1"},{"type":"library","name":"d3-array","version":"3.2.4","purl":"pkg:npm/d3-array@3.2.4"},{"type":"library","name":"internmap","version":"2.0.3","purl":"pkg:npm/internmap@2.0.3"},{"type":"library","name":"d3-color","version":"3.1.0","purl":"pkg:npm/d3-color@3.1.0"},{"type":"library","name":"d3-interpolate","version":"3.0.1","purl":"pkg:npm/d3-interpolate@3.0.1"},{"type":"library","name":"d3-timer","version":"3.0.1","purl":"pkg:npm/d3-timer@3.0.1"},{"type":"library","name":"d3-ease","version":"3.0.1","purl":"pkg:npm/d3-ease@3.0.1"},{"type":"library","name":"robust-predicates","version":"3.0.3","purl":"pkg:npm/robust-predicates@3.0.3"},{"type":"library","name":"delaunator","version":"5.1.0","purl":"pkg:npm/delaunator@5.1.0"},{"type":"library","name":"d3-delaunay","version":"6.0.4","purl":"pkg:npm/d3-delaunay@6.0.4"},{"type":"library","name":"d3-dsv","version":"3.0.1","purl":"pkg:npm/d3-dsv@3.0.1"},{"type":"library","name":"d3-force","version":"3.0.0","purl":"pkg:npm/d3-force@3.0.0"},{"type":"library","name":"d3-quadtree","version":"3.0.1","purl":"pkg:npm/d3-quadtree@3.0.1"},{"type":"library","name":"d3-geo","version":"3.1.1","purl":"pkg:npm/d3-geo@3.1.1"},{"type":"library","name":"d3-hierarchy","version":"3.1.2","purl":"pkg:npm/d3-hierarchy@3.1.2"},{"type":"library","name":"d3-scale","version":"4.0.2","purl":"pkg:npm/d3-scale@4.0.2"},{"type":"library","name":"d3-time","version":"3.1.0","purl":"pkg:npm/d3-time@3.1.0"},{"type":"library","name":"d3-time-format","version":"4.1.0","purl":"pkg:npm/d3-time-format@4.1.0"},{"type":"library","name":"d3-scale-chromatic","version":"3.1.0","purl":"pkg:npm/d3-scale-chromatic@3.1.0"},{"type":"library","name":"d3-shape","version":"3.2.0","purl":"pkg:npm/d3-shape@3.2.0"},{"type":"library","name":"mermaid","version":"12.2.0","purl":"pkg:npm/mermaid@12.2.0"},{"type":"library","name":"es-toolkit","version":"1.52.0","purl":"pkg:npm/es-toolkit@1.52.0"},{"type":"library","name":"json-stringify-pretty-compact","version":"4.0.0","purl":"pkg:npm/json-stringify-pretty-compact@4.0.0"},{"type":"library","name":"vega-util","version":"2.1.3","purl":"pkg:npm/vega-util@2.1.3"},{"type":"library","name":"topojson-client","version":"3.1.0","purl":"pkg:npm/topojson-client@3.1.0"},{"type":"library","name":"vega-time","version":"3.3.0","purl":"pkg:npm/vega-time@3.3.0"},{"type":"library","name":"vega-format","version":"2.1.3","purl":"pkg:npm/vega-format@2.1.3"},{"type":"library","name":"vega-loader","version":"5.1.3","purl":"pkg:npm/vega-loader@5.1.3"},{"type":"library","name":"vega-dataflow","version":"6.1.3","purl":"pkg:npm/vega-dataflow@6.1.3"},{"type":"library","name":"vega-statistics","version":"2.0.0","purl":"pkg:npm/vega-statistics@2.0.0"},{"type":"library","name":"vega-transforms","version":"5.2.2","purl":"pkg:npm/vega-transforms@5.2.2"},{"type":"library","name":"vega-canvas","version":"2.0.0","purl":"pkg:npm/vega-canvas@2.0.0"},{"type":"library","name":"vega-scale","version":"8.1.3","purl":"pkg:npm/vega-scale@8.1.3"},{"type":"library","name":"vega-scenegraph","version":"5.3.0","purl":"pkg:npm/vega-scenegraph@5.3.0"},{"type":"library","name":"vega-view-transforms","version":"5.2.2","purl":"pkg:npm/vega-view-transforms@5.2.2"},{"type":"library","name":"vega-encode","version":"5.2.2","purl":"pkg:npm/vega-encode@5.2.2"},{"type":"library","name":"d3-geo-projection","version":"4.0.0","purl":"pkg:npm/d3-geo-projection@4.0.0"},{"type":"library","name":"vega-projection","version":"2.1.3","purl":"pkg:npm/vega-projection@2.1.3"},{"type":"library","name":"vega-geo","version":"5.1.3","purl":"pkg:npm/vega-geo@5.1.3"},{"type":"library","name":"vega-force","version":"5.1.3","purl":"pkg:npm/vega-force@5.1.3"},{"type":"library","name":"vega-hierarchy","version":"5.1.3","purl":"pkg:npm/vega-hierarchy@5.1.3"},{"type":"library","name":"vega-label","version":"2.1.3","purl":"pkg:npm/vega-label@2.1.3"},{"type":"library","name":"vega-regression","version":"2.1.3","purl":"pkg:npm/vega-regression@2.1.3"},{"type":"library","name":"vega-voronoi","version":"5.1.3","purl":"pkg:npm/vega-voronoi@5.1.3"},{"type":"library","name":"vega-wordcloud","version":"5.1.3","purl":"pkg:npm/vega-wordcloud@5.1.3"},{"type":"library","name":"vega-crossfilter","version":"5.1.3","purl":"pkg:npm/vega-crossfilter@5.1.3"},{"type":"library","name":"vega-expression","version":"6.2.2","purl":"pkg:npm/vega-expression@6.2.2"},{"type":"library","name":"vega-selections","version":"6.1.5","purl":"pkg:npm/vega-selections@6.1.5"},{"type":"library","name":"vega-functions","version":"6.2.0","purl":"pkg:npm/vega-functions@6.2.0"},{"type":"library","name":"vega-runtime","version":"7.1.3","purl":"pkg:npm/vega-runtime@7.1.3"},{"type":"library","name":"vega-view","version":"6.2.0","purl":"pkg:npm/vega-view@6.2.0"},{"type":"library","name":"vega-event-selector","version":"4.0.0","purl":"pkg:npm/vega-event-selector@4.0.0"},{"type":"library","name":"vega-parser","version":"7.1.3","purl":"pkg:npm/vega-parser@7.1.3"},{"type":"library","name":"vega","version":"6.4.0","purl":"pkg:npm/vega@6.4.0"},{"type":"library","name":"vega-interpreter","version":"2.3.1","purl":"pkg:npm/vega-interpreter@2.3.1"},{"type":"library","name":"vega-lite","version":"6.5.0","purl":"pkg:npm/vega-lite@6.5.0"},{"type":"library","name":"vega-schema-url-parser","version":"3.0.2","purl":"pkg:npm/vega-schema-url-parser@3.0.2"},{"type":"library","name":"vega-themes","version":"3.0.0","purl":"pkg:npm/vega-themes@3.0.0"},{"type":"library","name":"vega-tooltip","version":"1.0.0","purl":"pkg:npm/vega-tooltip@1.0.0"},{"type":"library","name":"vega-embed","version":"7.1.0","purl":"pkg:npm/vega-embed@7.1.0"},{"type":"library","name":"react-vega","version":"8.0.0","purl":"pkg:npm/react-vega@8.0.0"},{"type":"library","name":"@codemirror/commands","version":"6.11.1","purl":"pkg:npm/%40codemirror/commands@6.11.1"},{"type":"library","name":"@codemirror/search","version":"6.7.0","purl":"pkg:npm/%40codemirror/search@6.7.0"},{"type":"library","name":"@codemirror/autocomplete","version":"6.20.2","purl":"pkg:npm/%40codemirror/autocomplete@6.20.2"},{"type":"library","name":"@codemirror/lint","version":"6.9.6","purl":"pkg:npm/%40codemirror/lint@6.9.6"},{"type":"library","name":"@uiw/codemirror-extensions-basic-setup","version":"4.25.12","purl":"pkg:npm/%40uiw/codemirror-extensions-basic-setup@4.25.12"},{"type":"library","name":"@codemirror/theme-one-dark","version":"6.1.3","purl":"pkg:npm/%40codemirror/theme-one-dark@6.1.3"},{"type":"library","name":"@uiw/react-codemirror","version":"4.25.12","purl":"pkg:npm/%40uiw/react-codemirror@4.25.12"},{"type":"library","name":"codemirror-asciidoc","version":"2.0.1","purl":"pkg:npm/codemirror-asciidoc@2.0.1"},{"type":"library","name":"marked","version":"18.1.2","purl":"pkg:npm/marked@18.1.2"},{"type":"library","name":"@hookform/resolvers","version":"6.0.2","purl":"pkg:npm/%40hookform/resolvers@6.0.2"},{"type":"library","name":"zod","version":"4.6.7","purl":"pkg:npm/zod@4.6.7"},{"type":"library","name":"khroma","version":"2.1.0","purl":"pkg:npm/khroma@2.1.0"},{"type":"library","name":"@upsetjs/venn.js","version":"2.0.0","purl":"pkg:npm/%40upsetjs/venn.js@2.0.0"},{"type":"library","name":"@chevrotain/utils","version":"13.2.0","purl":"pkg:npm/%40chevrotain/utils@13.2.0"},{"type":"library","name":"@chevrotain/gast","version":"13.2.0","purl":"pkg:npm/%40chevrotain/gast@13.2.0"},{"type":"library","name":"chevrotain","version":"13.2.0","purl":"pkg:npm/chevrotain@13.2.0"},{"type":"library","name":"@chevrotain/regexp-to-ast","version":"13.2.0","purl":"pkg:npm/%40chevrotain/regexp-to-ast@13.2.0"},{"type":"library","name":"d3-sankey","version":"0.12.3","purl":"pkg:npm/d3-sankey@0.12.3"},{"type":"library","name":"d3-path","version":"1.0.9","purl":"pkg:npm/d3-path@1.0.9"},{"type":"library","name":"uuid","version":"14.0.2","purl":"pkg:npm/uuid@14.0.2"},{"type":"library","name":"d3-axis","version":"3.0.0","purl":"pkg:npm/d3-axis@3.0.0"},{"type":"library","name":"dayjs","version":"1.11.23","purl":"pkg:npm/dayjs@1.11.23"},{"type":"library","name":"layout-base","version":"1.0.2","purl":"pkg:npm/layout-base@1.0.2"},{"type":"library","name":"cose-base","version":"1.0.3","purl":"pkg:npm/cose-base@1.0.3"},{"type":"library","name":"cytoscape-cose-bilkent","version":"4.1.0","purl":"pkg:npm/cytoscape-cose-bilkent@4.1.0"},{"type":"library","name":"lodash-es","version":"4.18.1","purl":"pkg:npm/lodash-es@4.18.1"},{"type":"library","name":"dagre-d3-es","version":"7.0.14","purl":"pkg:npm/dagre-d3-es@7.0.14"},{"type":"library","name":"elkjs","version":"0.9.3","purl":"pkg:npm/elkjs@0.9.3"},{"type":"library","name":"cytoscape-fcose","version":"2.2.0","purl":"pkg:npm/cytoscape-fcose@2.2.0"},{"type":"library","name":"katex","version":"0.18.10","purl":"pkg:npm/katex@0.18.10"},{"type":"library","name":"dompurify","version":"3.4.17","purl":"pkg:npm/dompurify@3.4.17"},{"type":"library","name":"d3-dispatch","version":"3.0.1","purl":"pkg:npm/d3-dispatch@3.0.1"},{"type":"library","name":"d3-selection","version":"3.0.0","purl":"pkg:npm/d3-selection@3.0.0"},{"type":"library","name":"d3-transition","version":"3.0.1","purl":"pkg:npm/d3-transition@3.0.1"},{"type":"library","name":"d3-brush","version":"3.0.0","purl":"pkg:npm/d3-brush@3.0.0"},{"type":"library","name":"d3-zoom","version":"3.0.0","purl":"pkg:npm/d3-zoom@3.0.0"},{"type":"library","name":"d3-format","version":"3.1.2","purl":"pkg:npm/d3-format@3.1.2"},{"type":"library","name":"@braintree/sanitize-url","version":"7.1.2","purl":"pkg:npm/%40braintree/sanitize-url@7.1.2"},{"type":"library","name":"@iconify/utils","version":"3.1.4","purl":"pkg:npm/%40iconify/utils@3.1.4"},{"type":"library","name":"ts-dedent","version":"2.3.0","purl":"pkg:npm/ts-dedent@2.3.0"},{"type":"library","name":"roughjs","version":"4.6.6","purl":"pkg:npm/roughjs@4.6.6"},{"type":"library","name":"@mermaid-js/parser","version":"2.0.1","purl":"pkg:npm/%40mermaid-js/parser@2.0.1"},{"type":"library","name":"cytoscape","version":"3.34.2","purl":"pkg:npm/cytoscape@3.34.2"}]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyberismo/backend",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Express backend for Cyberismo",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"keywords": [],
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
"node": ">=22"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@cyberismo/assets": "1.3.
|
|
20
|
-
"@cyberismo/data-handler": "1.3.
|
|
21
|
-
"@cyberismo/mcp": "1.3.
|
|
22
|
-
"@cyberismo/model": "1.
|
|
19
|
+
"@cyberismo/assets": "1.3.1",
|
|
20
|
+
"@cyberismo/data-handler": "1.3.1",
|
|
21
|
+
"@cyberismo/mcp": "1.3.1",
|
|
22
|
+
"@cyberismo/model": "1.3.1",
|
|
23
23
|
"@hono/mcp": "^0.3.5",
|
|
24
24
|
"@hono/node-server": "^2.1.5",
|
|
25
25
|
"@hono/zod-validator": "^0.9.1",
|
package/src/app.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { Hono, type MiddlewareHandler } from 'hono';
|
|
5
5
|
import { staticFrontendDirRelative } from './utils.js';
|
|
6
|
-
import {
|
|
6
|
+
import { frontendFallback, serveFrontend } from './frontend.js';
|
|
7
7
|
import { attachProjectDirectory } from './middleware/commandManager.js';
|
|
8
8
|
import { errorResponse } from './common/errors.js';
|
|
9
9
|
import calculationsRouter from './domain/calculations/index.js';
|
|
@@ -222,12 +222,7 @@ export function createApp(
|
|
|
222
222
|
// MCP endpoint for AI assistant integration
|
|
223
223
|
app.route('/mcp', createMcpRouter(writableProjects(directory)));
|
|
224
224
|
|
|
225
|
-
app.use(
|
|
226
|
-
'*',
|
|
227
|
-
serveStatic({
|
|
228
|
-
root: staticFrontendDirRelative,
|
|
229
|
-
}),
|
|
230
|
-
);
|
|
225
|
+
app.use('*', serveFrontend(staticFrontendDirRelative));
|
|
231
226
|
|
|
232
227
|
// serve index.html for all other routes
|
|
233
228
|
app.notFound(async (c) => {
|
|
@@ -237,10 +232,10 @@ export function createApp(
|
|
|
237
232
|
) {
|
|
238
233
|
return c.text('Not Found', 404);
|
|
239
234
|
}
|
|
240
|
-
|
|
235
|
+
return frontendFallback(
|
|
236
|
+
c,
|
|
241
237
|
path.join(import.meta.dirname, 'public', 'index.html'),
|
|
242
238
|
);
|
|
243
|
-
return c.html(file.toString());
|
|
244
239
|
});
|
|
245
240
|
// Error handling
|
|
246
241
|
// Only server faults are logged; client errors are answered, not logged.
|
package/src/frontend.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Cyberismo Ltd and contributors
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
|
|
4
|
+
import type { Context, MiddlewareHandler } from 'hono';
|
|
5
|
+
import { every } from 'hono/combine';
|
|
6
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
7
|
+
import { readFile } from 'node:fs/promises';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* index.html names the hashed bundles of one build, so the browser must
|
|
11
|
+
* revalidate it on every load. A cached copy from an earlier build would
|
|
12
|
+
* request bundles that no longer exist and leave the page blank.
|
|
13
|
+
*/
|
|
14
|
+
export const INDEX_CACHE_CONTROL = 'no-cache';
|
|
15
|
+
|
|
16
|
+
/** Bundles under /assets/ carry a content hash, so they never change. */
|
|
17
|
+
export const ASSET_CACHE_CONTROL = 'public, max-age=31536000, immutable';
|
|
18
|
+
|
|
19
|
+
/** True for paths of the hashed bundles Vite emits. */
|
|
20
|
+
export function isAssetPath(requestPath: string): boolean {
|
|
21
|
+
return requestPath.startsWith('/assets/');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Serves the built frontend from `root`, with cache headers that keep a
|
|
26
|
+
* browser from pairing an old index.html with a newer build.
|
|
27
|
+
*/
|
|
28
|
+
export function serveFrontend(root: string): MiddlewareHandler {
|
|
29
|
+
// Only files served from disk get these headers, not the responses of
|
|
30
|
+
// later handlers that serveStatic falls through to.
|
|
31
|
+
const servedFromDisk = new WeakSet<Context>();
|
|
32
|
+
return every(
|
|
33
|
+
async (c, next) => {
|
|
34
|
+
await next();
|
|
35
|
+
if (!servedFromDisk.has(c)) return;
|
|
36
|
+
if (c.res.headers.get('Content-Type')?.startsWith('text/html')) {
|
|
37
|
+
c.res.headers.set('Cache-Control', INDEX_CACHE_CONTROL);
|
|
38
|
+
} else if (isAssetPath(c.req.path)) {
|
|
39
|
+
c.res.headers.set('Cache-Control', ASSET_CACHE_CONTROL);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
serveStatic({ root, onFound: (_path, c) => void servedFromDisk.add(c) }),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Answers a path that matched no route and no file. Client-side routes get
|
|
48
|
+
* index.html; a missing bundle gets a 404, since index.html served as a
|
|
49
|
+
* script fails to load and leaves the page blank.
|
|
50
|
+
*/
|
|
51
|
+
export async function frontendFallback(c: Context, indexPath: string) {
|
|
52
|
+
if (isAssetPath(c.req.path)) {
|
|
53
|
+
return c.text('Not Found', 404);
|
|
54
|
+
}
|
|
55
|
+
const file = await readFile(indexPath);
|
|
56
|
+
c.header('Cache-Control', INDEX_CACHE_CONTROL);
|
|
57
|
+
return c.html(file.toString());
|
|
58
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import type { Env, Schema } from 'hono';
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
|
-
import { serveStatic } from '@hono/node-server/serve-static';
|
|
7
6
|
import path from 'node:path';
|
|
8
|
-
import {
|
|
7
|
+
import { frontendFallback, serveFrontend } from './frontend.js';
|
|
9
8
|
import { listen } from './utils.js';
|
|
10
9
|
import { startPolicyPolling } from './overlay.js';
|
|
11
10
|
import { createApp } from './app.js';
|
|
@@ -26,13 +25,12 @@ const MAX_PORT_ATTEMPTS = 100;
|
|
|
26
25
|
*/
|
|
27
26
|
export async function previewSite(dir: string, findPort: boolean = true) {
|
|
28
27
|
const app = new Hono();
|
|
29
|
-
app.use(
|
|
28
|
+
app.use(serveFrontend(dir));
|
|
30
29
|
app.get('*', async (c) => {
|
|
31
30
|
if (c.req.path.startsWith('/api/')) {
|
|
32
31
|
return c.json({ error: 'Resource not found' }, 404);
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
return c.html(file.toString());
|
|
33
|
+
return frontendFallback(c, path.join(dir, 'index.html'));
|
|
36
34
|
});
|
|
37
35
|
|
|
38
36
|
const port = parseInt(process.env.PORT || DEFAULT_PORT.toString(), 10);
|