@cyberismo/backend 0.0.15 → 0.0.17
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.d.ts +21 -0
- package/dist/app.js +11 -3
- package/dist/app.js.map +1 -1
- package/dist/common/validationSchemas.d.ts +48 -0
- package/dist/domain/calculations/index.d.ts +15 -0
- package/dist/domain/calculations/schema.d.ts +16 -0
- package/dist/domain/calculations/service.d.ts +14 -0
- package/dist/domain/cardTypes/index.d.ts +15 -0
- package/dist/domain/cardTypes/schema.d.ts +17 -0
- package/dist/domain/cardTypes/service.d.ts +15 -0
- package/dist/domain/cards/index.d.ts +15 -0
- package/dist/domain/cards/index.js +22 -6
- package/dist/domain/cards/index.js.map +1 -1
- package/dist/domain/cards/lib.d.ts +29 -0
- package/dist/domain/cards/lib.js +73 -2
- package/dist/domain/cards/lib.js.map +1 -1
- package/dist/domain/cards/service.d.ts +61 -0
- package/dist/domain/cards/service.js +20 -12
- package/dist/domain/cards/service.js.map +1 -1
- package/dist/domain/fieldTypes/index.d.ts +15 -0
- package/dist/domain/fieldTypes/schema.d.ts +28 -0
- package/dist/domain/fieldTypes/service.d.ts +16 -0
- package/dist/domain/graphModels/index.d.ts +15 -0
- package/dist/domain/graphModels/schema.d.ts +16 -0
- package/dist/domain/graphModels/service.d.ts +14 -0
- package/dist/domain/graphViews/index.d.ts +15 -0
- package/dist/domain/graphViews/schema.d.ts +4 -0
- package/dist/domain/graphViews/service.d.ts +14 -0
- package/dist/domain/labels/index.d.ts +15 -0
- package/dist/domain/labels/index.js +33 -0
- package/dist/domain/labels/index.js.map +1 -0
- package/dist/domain/labels/service.d.ts +19 -0
- package/dist/domain/labels/service.js +21 -0
- package/dist/domain/labels/service.js.map +1 -0
- package/dist/domain/linkTypes/index.d.ts +15 -0
- package/dist/domain/linkTypes/schema.d.ts +16 -0
- package/dist/domain/linkTypes/service.d.ts +15 -0
- package/dist/domain/logicPrograms/index.d.ts +15 -0
- package/dist/domain/logicPrograms/service.d.ts +15 -0
- package/dist/domain/project/index.d.ts +15 -0
- package/dist/domain/project/index.js +42 -0
- package/dist/domain/project/index.js.map +1 -0
- package/dist/domain/project/schema.d.ts +20 -0
- package/dist/domain/project/schema.js +21 -0
- package/dist/domain/project/schema.js.map +1 -0
- package/dist/domain/project/service.d.ts +30 -0
- package/dist/domain/project/service.js +54 -0
- package/dist/domain/project/service.js.map +1 -0
- package/dist/domain/reports/index.d.ts +15 -0
- package/dist/domain/reports/schema.d.ts +16 -0
- package/dist/domain/reports/service.d.ts +14 -0
- package/dist/domain/resources/index.d.ts +15 -0
- package/dist/domain/resources/schema.d.ts +60 -0
- package/dist/domain/resources/service.d.ts +36 -0
- package/dist/domain/resources/service.js +60 -31
- package/dist/domain/resources/service.js.map +1 -1
- package/dist/domain/templates/index.d.ts +15 -0
- package/dist/domain/templates/index.js +1 -1
- package/dist/domain/templates/index.js.map +1 -1
- package/dist/domain/templates/schema.d.ts +22 -0
- package/dist/domain/templates/service.d.ts +16 -0
- package/dist/domain/tree/index.d.ts +15 -0
- package/dist/domain/tree/index.js +3 -2
- package/dist/domain/tree/index.js.map +1 -1
- package/dist/domain/tree/service.d.ts +22 -0
- package/dist/domain/tree/service.js +10 -2
- package/dist/domain/tree/service.js.map +1 -1
- package/dist/domain/workflows/index.d.ts +15 -0
- package/dist/domain/workflows/schema.d.ts +16 -0
- package/dist/domain/workflows/service.d.ts +14 -0
- package/dist/export.d.ts +42 -0
- package/dist/export.js +48 -152
- package/dist/export.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +1 -0
- package/dist/middleware/commandManager.d.ts +20 -0
- package/dist/middleware/tree.d.ts +9 -0
- package/dist/middleware/tree.js +13 -0
- package/dist/middleware/tree.js.map +1 -0
- package/dist/middleware/zvalidator.d.ts +9 -0
- package/dist/public/THIRD-PARTY.txt +77 -83
- package/dist/public/assets/index-BrNy_4vV.js +163198 -0
- package/dist/public/index.html +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.js +0 -32
- package/dist/utils.js.map +1 -1
- package/package.json +14 -8
- package/src/app.ts +13 -4
- package/src/domain/cards/index.ts +31 -6
- package/src/domain/cards/lib.ts +93 -3
- package/src/domain/cards/service.ts +36 -24
- package/src/domain/labels/index.ts +36 -0
- package/src/domain/labels/service.ts +23 -0
- package/src/domain/project/index.ts +58 -0
- package/src/domain/project/schema.ts +23 -0
- package/src/domain/project/service.ts +88 -0
- package/src/domain/resources/service.ts +87 -41
- package/src/domain/templates/index.ts +1 -1
- package/src/domain/tree/index.ts +10 -3
- package/src/domain/tree/service.ts +15 -1
- package/src/export.ts +59 -192
- package/src/index.ts +5 -1
- package/src/middleware/tree.ts +17 -0
- package/src/types.ts +13 -0
- package/src/utils.ts +0 -39
- package/dist/public/assets/index-Dtn1rQ-9.js +0 -163921
package/dist/public/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
name="msapplication-TileImage"
|
|
12
12
|
content="/cropped-favicon-270x270.png"
|
|
13
13
|
/>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-BrNy_4vV.js"></script>
|
|
15
15
|
<link rel="stylesheet" crossorigin href="/assets/index-DnK7MBer.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2025
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License version 3 as published by
|
|
6
|
+
the Free Software Foundation.
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
8
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
9
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
10
|
+
details. You should have received a copy of the GNU Affero General Public
|
|
11
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
|
+
*/
|
|
13
|
+
import type { Context } from 'hono';
|
|
14
|
+
export interface ResourceFileContentResponse {
|
|
15
|
+
content: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ResourceValidationResponse {
|
|
18
|
+
errors: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface TreeOptions {
|
|
21
|
+
recursive?: boolean;
|
|
22
|
+
cardKey?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface AppVars {
|
|
25
|
+
tree?: TreeOptions;
|
|
26
|
+
}
|
|
27
|
+
export type AppContext = Context<{
|
|
28
|
+
Variables: AppVars;
|
|
29
|
+
}>;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The relative path to the static frontend directory.
|
|
3
|
+
*/
|
|
4
|
+
export declare const staticFrontendDirRelative: string;
|
|
5
|
+
/**
|
|
6
|
+
* Finds a free port.
|
|
7
|
+
* @param port - The port to start looking for.
|
|
8
|
+
* @param maxAttempts - The maximum number of attempts to find a free port.
|
|
9
|
+
* @returns The free port.
|
|
10
|
+
*/
|
|
11
|
+
export declare function findFreePort(minPort: number, maxPort: number): Promise<number>;
|
package/dist/utils.js
CHANGED
|
@@ -12,38 +12,6 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import path from 'node:path';
|
|
14
14
|
import { createServer } from 'node:net';
|
|
15
|
-
/**
|
|
16
|
-
* Runs promises in parallel, but only maxConcurrent at a time.
|
|
17
|
-
* @param promises - Array of promises to run in parallel
|
|
18
|
-
* @param maxConcurrent - Maximum number of promises to run at a time
|
|
19
|
-
* @returns - Promise that resolves when all promises have resolved
|
|
20
|
-
*/
|
|
21
|
-
export async function runInParallel(promises, maxConcurrent = 2) {
|
|
22
|
-
const waitingPromises = [];
|
|
23
|
-
const wrappedPromises = promises.map((fn) => async () => {
|
|
24
|
-
await fn();
|
|
25
|
-
const next = waitingPromises.shift();
|
|
26
|
-
if (next) {
|
|
27
|
-
await next();
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
const runningPromises = wrappedPromises.slice(0, maxConcurrent);
|
|
31
|
-
waitingPromises.push(...wrappedPromises.slice(maxConcurrent));
|
|
32
|
-
return Promise.all(runningPromises.map((p) => p()));
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Runs a callback and returns the result or undefined if it throws.
|
|
36
|
-
* @param cb - The callback to run.
|
|
37
|
-
* @returns The result of the callback or undefined if it throws.
|
|
38
|
-
*/
|
|
39
|
-
export async function runCbSafely(cb) {
|
|
40
|
-
try {
|
|
41
|
-
return await cb();
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// All exceptions are ignored.
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
15
|
/**
|
|
48
16
|
* The relative path to the static frontend directory.
|
|
49
17
|
*/
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AACF,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AACF,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,EAAE,EACb,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAC5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,OAAe;IAEf,KAAK,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;YAClB,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC/D,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,yCAAyC,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YACvB,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QACH,UAAU,CAAC,GAAG,EAAE;YACd,MAAM,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;QAC7D,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyberismo/backend",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Express backend for Cyberismo",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"keywords": [],
|
|
7
|
-
"author": "",
|
|
7
|
+
"author": "sami.merila@cyberismo.com",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
|
+
"homepage": "https://github.com/CyberismoCom/cyberismo",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/CyberismoCom/cyberismo.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": "https://github.com/CyberismoCom/cyberismo/issues",
|
|
9
15
|
"dependencies": {
|
|
10
16
|
"@asciidoctor/core": "^3.0.4",
|
|
11
17
|
"@hono/node-server": "^1.19.2",
|
|
12
|
-
"@hono/zod-validator": "^0.7.
|
|
18
|
+
"@hono/zod-validator": "^0.7.5",
|
|
13
19
|
"@types/mime-types": "^3.0.1",
|
|
14
20
|
"dotenv": "^17.2.3",
|
|
15
|
-
"hono": "^4.10.
|
|
16
|
-
"mime-types": "^3.0.
|
|
17
|
-
"zod": "^4.1.
|
|
18
|
-
"@cyberismo/data-handler": "0.0.
|
|
21
|
+
"hono": "^4.10.7",
|
|
22
|
+
"mime-types": "^3.0.2",
|
|
23
|
+
"zod": "^4.1.13",
|
|
24
|
+
"@cyberismo/data-handler": "0.0.17"
|
|
19
25
|
},
|
|
20
26
|
"devDependencies": {
|
|
21
27
|
"@cyberismo/app": "0.0.2"
|
|
@@ -36,7 +42,7 @@
|
|
|
36
42
|
"debug": "tsx --inspect-brk src/main.ts",
|
|
37
43
|
"export": "pnpm build && node dist/main.js --export",
|
|
38
44
|
"build": "tsc -p tsconfig.build.json && shx rm -rf ./dist/public && shx cp -r ../app/dist ./dist/public",
|
|
39
|
-
"test": "vitest run",
|
|
45
|
+
"test": "vitest run --silent",
|
|
40
46
|
"lint": "eslint ."
|
|
41
47
|
}
|
|
42
48
|
}
|
package/src/app.ts
CHANGED
|
@@ -26,18 +26,22 @@ import reportsRouter from './domain/reports/index.js';
|
|
|
26
26
|
import templatesRouter from './domain/templates/index.js';
|
|
27
27
|
import treeRouter from './domain/tree/index.js';
|
|
28
28
|
import workflowsRouter from './domain/workflows/index.js';
|
|
29
|
+
import labelsRouter from './domain/labels/index.js';
|
|
29
30
|
import { readFile } from 'node:fs/promises';
|
|
30
31
|
import path from 'node:path';
|
|
31
|
-
import { isSSGContext } from './export.js';
|
|
32
32
|
import resourcesRouter from './domain/resources/index.js';
|
|
33
33
|
import logicProgramsRouter from './domain/logicPrograms/index.js';
|
|
34
|
+
import { isSSGContext } from 'hono/ssg';
|
|
35
|
+
import type { AppVars, TreeOptions } from './types.js';
|
|
36
|
+
import treeMiddleware from './middleware/tree.js';
|
|
37
|
+
import projectRouter from './domain/project/index.js';
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* Create the Hono app for the backend
|
|
37
41
|
* @param projectPath - Path to the project
|
|
38
42
|
*/
|
|
39
|
-
export function createApp(projectPath?: string) {
|
|
40
|
-
const app = new Hono();
|
|
43
|
+
export function createApp(projectPath?: string, opts?: TreeOptions) {
|
|
44
|
+
const app = new Hono<{ Variables: AppVars }>();
|
|
41
45
|
|
|
42
46
|
app.use('/api', cors());
|
|
43
47
|
|
|
@@ -48,6 +52,7 @@ export function createApp(projectPath?: string) {
|
|
|
48
52
|
}),
|
|
49
53
|
);
|
|
50
54
|
|
|
55
|
+
app.use(treeMiddleware(opts));
|
|
51
56
|
// Attach CommandManager to all requests
|
|
52
57
|
app.use(attachCommandManager(projectPath));
|
|
53
58
|
|
|
@@ -65,6 +70,8 @@ export function createApp(projectPath?: string) {
|
|
|
65
70
|
app.route('/api/workflows', workflowsRouter);
|
|
66
71
|
app.route('/api/resources', resourcesRouter);
|
|
67
72
|
app.route('/api/logicPrograms', logicProgramsRouter);
|
|
73
|
+
app.route('/api/labels', labelsRouter);
|
|
74
|
+
app.route('/api/project', projectRouter);
|
|
68
75
|
|
|
69
76
|
// serve index.html for all other routes
|
|
70
77
|
app.notFound(async (c) => {
|
|
@@ -79,7 +86,9 @@ export function createApp(projectPath?: string) {
|
|
|
79
86
|
// Error handling
|
|
80
87
|
app.onError((err, c) => {
|
|
81
88
|
if (!isSSGContext(c)) {
|
|
82
|
-
|
|
89
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
90
|
+
console.error(err.stack);
|
|
91
|
+
}
|
|
83
92
|
}
|
|
84
93
|
return c.json(
|
|
85
94
|
{
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
import { type Context, Hono } from 'hono';
|
|
15
15
|
import type { ContentfulStatusCode } from 'hono/utils/http-status';
|
|
16
|
-
import { ssgParams, isSSGContext } from '../../export.js';
|
|
17
16
|
import { getCardDetails } from './lib.js';
|
|
18
17
|
import * as cardService from './service.js';
|
|
18
|
+
import { isSSGContext, ssgParams } from 'hono/ssg';
|
|
19
|
+
import type { AppContext } from '../../types.js';
|
|
19
20
|
|
|
20
21
|
const router = new Hono();
|
|
21
22
|
|
|
@@ -58,6 +59,12 @@ router.get('/', async (c) => {
|
|
|
58
59
|
* in: path
|
|
59
60
|
* required: true
|
|
60
61
|
* description: Card key (string)
|
|
62
|
+
* - name: raw
|
|
63
|
+
* in: query
|
|
64
|
+
* required: false
|
|
65
|
+
* schema:
|
|
66
|
+
* type: boolean
|
|
67
|
+
* description: When true, returns the raw card data without triggering calculations
|
|
61
68
|
* responses:
|
|
62
69
|
* 200:
|
|
63
70
|
* description: Object containing card details. See lib/api/types.ts/CardResponse for the structure.
|
|
@@ -68,10 +75,11 @@ router.get('/', async (c) => {
|
|
|
68
75
|
*/
|
|
69
76
|
router.get(
|
|
70
77
|
'/:key',
|
|
71
|
-
ssgParams(async (c:
|
|
78
|
+
ssgParams(async (c: AppContext) => {
|
|
72
79
|
const commands = c.get('commands');
|
|
73
|
-
const
|
|
74
|
-
|
|
80
|
+
const opts = c.get('tree');
|
|
81
|
+
const cards = await cardService.findAllCards(commands, opts);
|
|
82
|
+
return cards.map((card) => ({ key: card.key }));
|
|
75
83
|
}),
|
|
76
84
|
async (c) => {
|
|
77
85
|
const key = c.req.param('key');
|
|
@@ -79,10 +87,13 @@ router.get(
|
|
|
79
87
|
return c.text('No search key', 400);
|
|
80
88
|
}
|
|
81
89
|
|
|
90
|
+
const raw = c.req.query('raw');
|
|
91
|
+
|
|
82
92
|
const result = await getCardDetails(
|
|
83
93
|
c.get('commands'),
|
|
84
94
|
key,
|
|
85
95
|
isSSGContext(c),
|
|
96
|
+
raw?.toLowerCase() === 'true' ? true : false,
|
|
86
97
|
);
|
|
87
98
|
if (result.status === 200) {
|
|
88
99
|
return c.json(result.data);
|
|
@@ -117,6 +128,12 @@ router.get(
|
|
|
117
128
|
* type: object
|
|
118
129
|
* required: false
|
|
119
130
|
* description: New metadata for the card. Must be an object with key-value pairs.
|
|
131
|
+
* - name: raw
|
|
132
|
+
* in: query
|
|
133
|
+
* required: false
|
|
134
|
+
* schema:
|
|
135
|
+
* type: boolean
|
|
136
|
+
* description: When true, returns the raw card data without triggering calculations
|
|
120
137
|
* responses:
|
|
121
138
|
* 200:
|
|
122
139
|
* description: Object containing card details, same as GET. See definitions.ts/CardDetails for the structure.
|
|
@@ -134,10 +151,18 @@ router.patch('/:key', async (c) => {
|
|
|
134
151
|
return c.text('No search key', 400);
|
|
135
152
|
}
|
|
136
153
|
|
|
154
|
+
const raw = c.req.query('raw');
|
|
155
|
+
|
|
137
156
|
const body = await c.req.json();
|
|
138
157
|
|
|
139
158
|
try {
|
|
140
|
-
|
|
159
|
+
await cardService.updateCard(commands, key, body);
|
|
160
|
+
const result = await getCardDetails(
|
|
161
|
+
c.get('commands'),
|
|
162
|
+
key,
|
|
163
|
+
isSSGContext(c),
|
|
164
|
+
raw?.toLowerCase() === 'true' ? true : false,
|
|
165
|
+
);
|
|
141
166
|
if (result.status === 200) {
|
|
142
167
|
return c.json(result.data);
|
|
143
168
|
} else {
|
|
@@ -587,7 +612,7 @@ router.get(
|
|
|
587
612
|
'/:key/a/:attachment',
|
|
588
613
|
ssgParams(async (c: Context) => {
|
|
589
614
|
const commands = c.get('commands');
|
|
590
|
-
return await cardService.
|
|
615
|
+
return await cardService.findRelevantAttachments(commands, c.get('tree'));
|
|
591
616
|
}),
|
|
592
617
|
(c) => {
|
|
593
618
|
const commands = c.get('commands');
|
package/src/domain/cards/lib.ts
CHANGED
|
@@ -15,6 +15,8 @@ import Processor from '@asciidoctor/core';
|
|
|
15
15
|
import type { Card } from '@cyberismo/data-handler/interfaces/project-interfaces';
|
|
16
16
|
import { type CommandManager, evaluateMacros } from '@cyberismo/data-handler';
|
|
17
17
|
import { getCardQueryResult } from '../../export.js';
|
|
18
|
+
import type { TreeOptions } from '../../types.js';
|
|
19
|
+
import type { QueryResult } from '@cyberismo/data-handler/types/queries';
|
|
18
20
|
|
|
19
21
|
interface result {
|
|
20
22
|
status: number;
|
|
@@ -25,9 +27,10 @@ interface result {
|
|
|
25
27
|
export async function getCardDetails(
|
|
26
28
|
commands: CommandManager,
|
|
27
29
|
key: string,
|
|
28
|
-
staticMode
|
|
30
|
+
staticMode: boolean,
|
|
31
|
+
raw: boolean,
|
|
29
32
|
): Promise<result> {
|
|
30
|
-
let cardDetailsResponse: Card
|
|
33
|
+
let cardDetailsResponse: Card;
|
|
31
34
|
try {
|
|
32
35
|
cardDetailsResponse = commands.showCmd.showCardDetails(key);
|
|
33
36
|
} catch {
|
|
@@ -39,7 +42,7 @@ export async function getCardDetails(
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
// always parse for now if not in export mode
|
|
42
|
-
if (!staticMode) {
|
|
45
|
+
if (!staticMode && !raw) {
|
|
43
46
|
await commands.calculateCmd.generate();
|
|
44
47
|
}
|
|
45
48
|
|
|
@@ -65,6 +68,66 @@ export async function getCardDetails(
|
|
|
65
68
|
})
|
|
66
69
|
.toString();
|
|
67
70
|
|
|
71
|
+
if (raw) {
|
|
72
|
+
if (!cardDetailsResponse.metadata) {
|
|
73
|
+
throw new Error('Card has no metadata');
|
|
74
|
+
}
|
|
75
|
+
const cardType = await commands.showCmd.showResource(
|
|
76
|
+
cardDetailsResponse.metadata.cardType,
|
|
77
|
+
'cardTypes',
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const fields = [];
|
|
81
|
+
let i = 0;
|
|
82
|
+
for (const customField of cardType.customFields) {
|
|
83
|
+
const fieldType = await commands.showCmd.showResource(
|
|
84
|
+
customField.name,
|
|
85
|
+
'fieldTypes',
|
|
86
|
+
);
|
|
87
|
+
fields.push({
|
|
88
|
+
key: customField.name,
|
|
89
|
+
visibility: 'always',
|
|
90
|
+
index: i++,
|
|
91
|
+
fieldDisplayName: fieldType.displayName,
|
|
92
|
+
fieldDescription: fieldType.description,
|
|
93
|
+
dataType: fieldType.dataType,
|
|
94
|
+
isCalculated: customField.isCalculated,
|
|
95
|
+
value: cardDetailsResponse.metadata[customField.name],
|
|
96
|
+
enumValues: fieldType.enumValues ?? [],
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
status: 200,
|
|
101
|
+
data: {
|
|
102
|
+
key: cardDetailsResponse.key,
|
|
103
|
+
rank: cardDetailsResponse.metadata?.rank,
|
|
104
|
+
title: cardDetailsResponse.metadata?.title || '',
|
|
105
|
+
cardType: cardDetailsResponse.metadata?.cardType || '',
|
|
106
|
+
cardTypeDisplayName: cardDetailsResponse.metadata.cardType,
|
|
107
|
+
workflowState: '',
|
|
108
|
+
lastUpdated: cardDetailsResponse.metadata.lastUpdated,
|
|
109
|
+
fields,
|
|
110
|
+
labels: cardDetailsResponse.metadata?.labels || [],
|
|
111
|
+
links: [],
|
|
112
|
+
notifications: [],
|
|
113
|
+
policyChecks: {
|
|
114
|
+
successes: [],
|
|
115
|
+
failures: [],
|
|
116
|
+
},
|
|
117
|
+
deniedOperations: {
|
|
118
|
+
transition: [],
|
|
119
|
+
move: [],
|
|
120
|
+
delete: [],
|
|
121
|
+
editField: [],
|
|
122
|
+
editContent: [],
|
|
123
|
+
},
|
|
124
|
+
rawContent: cardDetailsResponse.content || '',
|
|
125
|
+
parsedContent: htmlContent,
|
|
126
|
+
attachments: cardDetailsResponse.attachments,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
68
131
|
const card = staticMode
|
|
69
132
|
? await getCardQueryResult(commands.project.basePath, key)
|
|
70
133
|
: await commands.calculateCmd.runQuery('card', 'localApp', {
|
|
@@ -84,3 +147,30 @@ export async function getCardDetails(
|
|
|
84
147
|
},
|
|
85
148
|
};
|
|
86
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Returns all cards from a tree query, flattened.
|
|
152
|
+
* @param commands the command manager used for the query
|
|
153
|
+
* @param options optional tree query options
|
|
154
|
+
* @returns a promise that resolves to an array of all cards
|
|
155
|
+
*/
|
|
156
|
+
export async function allCards(
|
|
157
|
+
commands: CommandManager,
|
|
158
|
+
options?: TreeOptions,
|
|
159
|
+
): Promise<QueryResult<'tree'>[]> {
|
|
160
|
+
const fetchedCards = await commands.calculateCmd.runQuery(
|
|
161
|
+
'tree',
|
|
162
|
+
'exportedSite',
|
|
163
|
+
options || {},
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
function flattenCards(cards: QueryResult<'tree'>[]): QueryResult<'tree'>[] {
|
|
167
|
+
return cards.reduce<QueryResult<'tree'>[]>((acc, curr) => {
|
|
168
|
+
acc.push(curr);
|
|
169
|
+
if (curr.children && curr.children.length > 0) {
|
|
170
|
+
acc.push(...flattenCards(curr.children));
|
|
171
|
+
}
|
|
172
|
+
return acc;
|
|
173
|
+
}, []);
|
|
174
|
+
}
|
|
175
|
+
return flattenCards(fetchedCards);
|
|
176
|
+
}
|
|
@@ -12,12 +12,10 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import Processor from '@asciidoctor/core';
|
|
15
|
-
import {
|
|
16
|
-
CardLocation,
|
|
17
|
-
type MetadataContent,
|
|
18
|
-
} from '@cyberismo/data-handler/interfaces/project-interfaces';
|
|
15
|
+
import { type MetadataContent } from '@cyberismo/data-handler/interfaces/project-interfaces';
|
|
19
16
|
import { type CommandManager, evaluateMacros } from '@cyberismo/data-handler';
|
|
20
|
-
import {
|
|
17
|
+
import { allCards } from './lib.js';
|
|
18
|
+
import type { TreeOptions } from '../../types.js';
|
|
21
19
|
|
|
22
20
|
export async function getProjectInfo(commands: CommandManager) {
|
|
23
21
|
const projectResponse = await commands.showCmd.showProject();
|
|
@@ -94,8 +92,6 @@ export async function updateCard(
|
|
|
94
92
|
if (errors.length > 0) {
|
|
95
93
|
throw new Error(errors.join('\n'));
|
|
96
94
|
}
|
|
97
|
-
|
|
98
|
-
return await getCardDetails(commands, key);
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
export async function deleteCard(commands: CommandManager, key: string) {
|
|
@@ -221,23 +217,39 @@ export function getAttachment(
|
|
|
221
217
|
return commands.showCmd.showAttachment(key, filename);
|
|
222
218
|
}
|
|
223
219
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
return
|
|
220
|
+
/**
|
|
221
|
+
* Used for exporting cards, thus static mode is assumed
|
|
222
|
+
* @param commandsthe command manager used for the query
|
|
223
|
+
* @param options optional tree query options
|
|
224
|
+
* @returns all cards in a flattened array
|
|
225
|
+
*/
|
|
226
|
+
export async function findAllCards(
|
|
227
|
+
commands: CommandManager,
|
|
228
|
+
options?: TreeOptions,
|
|
229
|
+
): ReturnType<typeof allCards> {
|
|
230
|
+
return allCards(commands, options);
|
|
235
231
|
}
|
|
236
|
-
|
|
237
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Gets all attachments that are required for rendering the wanted cards
|
|
234
|
+
* @param commands the command manager used for the query
|
|
235
|
+
* @param options optional tree query options
|
|
236
|
+
* @returns all attachments for cards returned by the tree query
|
|
237
|
+
*/
|
|
238
|
+
export async function findRelevantAttachments(
|
|
239
|
+
commands: CommandManager,
|
|
240
|
+
options?: TreeOptions,
|
|
241
|
+
) {
|
|
242
|
+
const cards = new Set<string>(
|
|
243
|
+
(await allCards(commands, options)).map((c) => c.key),
|
|
244
|
+
);
|
|
238
245
|
const attachments = await commands.showCmd.showAttachments();
|
|
239
|
-
return attachments
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
246
|
+
return attachments
|
|
247
|
+
.filter(
|
|
248
|
+
(attachment) =>
|
|
249
|
+
cards.has(attachment.card) && attachment.mimeType?.startsWith('image/'),
|
|
250
|
+
)
|
|
251
|
+
.map((attachment) => ({
|
|
252
|
+
key: attachment.card,
|
|
253
|
+
attachment: attachment.fileName,
|
|
254
|
+
}));
|
|
243
255
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2025
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License version 3 as published by
|
|
6
|
+
the Free Software Foundation.
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
8
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
9
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
10
|
+
details. You should have received a copy of the GNU Affero General Public
|
|
11
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Hono } from 'hono';
|
|
15
|
+
import * as labelsService from './service.js';
|
|
16
|
+
|
|
17
|
+
const router = new Hono();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @swagger
|
|
21
|
+
* /api/labels:
|
|
22
|
+
* get:
|
|
23
|
+
* summary: Returns all unique labels defined in the project.
|
|
24
|
+
* responses:
|
|
25
|
+
* 200:
|
|
26
|
+
* description: List of label strings.
|
|
27
|
+
* 500:
|
|
28
|
+
* description: Internal server error
|
|
29
|
+
*/
|
|
30
|
+
router.get('/', (c) => {
|
|
31
|
+
const commands = c.get('commands');
|
|
32
|
+
const labels = labelsService.getLabels(commands);
|
|
33
|
+
return c.json(labels);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default router;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2025
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License version 3 as published by
|
|
6
|
+
the Free Software Foundation.
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
8
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
9
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
10
|
+
details. You should have received a copy of the GNU Affero General Public
|
|
11
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { CommandManager } from '@cyberismo/data-handler';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Returns all unique labels available in the project.
|
|
18
|
+
* @param commands command manager used for the query
|
|
19
|
+
* @returns a list of labels
|
|
20
|
+
*/
|
|
21
|
+
export function getLabels(commands: CommandManager): string[] {
|
|
22
|
+
return commands.showCmd.showLabels().sort();
|
|
23
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2025
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License version 3 as published by
|
|
6
|
+
the Free Software Foundation.
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
8
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
9
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
10
|
+
details. You should have received a copy of the GNU Affero General Public
|
|
11
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Hono } from 'hono';
|
|
15
|
+
import { zValidator } from '../../middleware/zvalidator.js';
|
|
16
|
+
import { moduleParamSchema, updateProjectSchema } from './schema.js';
|
|
17
|
+
import * as projectService from './service.js';
|
|
18
|
+
|
|
19
|
+
const router = new Hono();
|
|
20
|
+
|
|
21
|
+
router.get('/', async (c) => {
|
|
22
|
+
const commands = c.get('commands');
|
|
23
|
+
|
|
24
|
+
const project = await projectService.getProject(commands);
|
|
25
|
+
return c.json(project);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
router.patch('/', zValidator('json', updateProjectSchema), async (c) => {
|
|
29
|
+
const commands = c.get('commands');
|
|
30
|
+
const updates = c.req.valid('json');
|
|
31
|
+
|
|
32
|
+
const project = await projectService.updateProject(commands, updates);
|
|
33
|
+
return c.json(project);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
router.post(
|
|
37
|
+
'/modules/:module/update',
|
|
38
|
+
zValidator('param', moduleParamSchema),
|
|
39
|
+
async (c) => {
|
|
40
|
+
const commands = c.get('commands');
|
|
41
|
+
const { module } = c.req.valid('param');
|
|
42
|
+
await projectService.updateModule(commands, module);
|
|
43
|
+
return c.json({ message: 'Module updated' });
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
router.delete(
|
|
48
|
+
'/modules/:module',
|
|
49
|
+
zValidator('param', moduleParamSchema),
|
|
50
|
+
async (c) => {
|
|
51
|
+
const commands = c.get('commands');
|
|
52
|
+
const { module } = c.req.valid('param');
|
|
53
|
+
await projectService.deleteModule(commands, module);
|
|
54
|
+
return c.json({ message: 'Module removed' });
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
export default router;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2025
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License version 3 as published by
|
|
6
|
+
the Free Software Foundation.
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
8
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
9
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
10
|
+
details. You should have received a copy of the GNU Affero General Public
|
|
11
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
|
|
16
|
+
export const moduleParamSchema = z.object({
|
|
17
|
+
module: z.string().min(1),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const updateProjectSchema = z.object({
|
|
21
|
+
name: z.string().optional(),
|
|
22
|
+
cardKeyPrefix: z.string().optional(),
|
|
23
|
+
});
|