@cyberismo/backend 0.0.23 → 0.0.24
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/domain/cards/index.js +63 -1
- package/dist/domain/cards/index.js.map +1 -1
- package/dist/domain/cards/lib.js +3 -0
- package/dist/domain/cards/lib.js.map +1 -1
- package/dist/domain/cards/schema.d.ts +8 -0
- package/dist/domain/cards/schema.js +7 -0
- package/dist/domain/cards/schema.js.map +1 -1
- package/dist/domain/cards/service.d.ts +2 -0
- package/dist/domain/cards/service.js +16 -0
- package/dist/domain/cards/service.js.map +1 -1
- package/dist/domain/project/service.js +1 -1
- package/dist/domain/project/service.js.map +1 -1
- package/dist/domain/resources/index.js +63 -1
- package/dist/domain/resources/index.js.map +1 -1
- package/dist/domain/resources/schema.d.ts +9 -0
- package/dist/domain/resources/schema.js +8 -1
- package/dist/domain/resources/schema.js.map +1 -1
- package/dist/domain/resources/service.d.ts +12 -0
- package/dist/domain/resources/service.js +47 -4
- package/dist/domain/resources/service.js.map +1 -1
- package/dist/public/THIRD-PARTY.txt +3594 -1626
- package/dist/public/assets/arc-DFTvTCxD.js +1 -0
- package/dist/public/assets/architecture-YZFGNWBL-DsWVZJri.js +1 -0
- package/dist/public/assets/architectureDiagram-Q4EWVU46-AN0fWZIG.js +36 -0
- package/dist/public/assets/array-xS8TccZC.js +1 -0
- package/dist/public/assets/blockDiagram-DXYQGD6D-RrIidZT3.js +132 -0
- package/dist/public/assets/c4Diagram-AHTNJAMY-CW7AUKhY.js +10 -0
- package/dist/public/assets/channel-BxffgrNT.js +1 -0
- package/dist/public/assets/chunk-2KRD3SAO-D5XH6bj9.js +1 -0
- package/dist/public/assets/chunk-336JU56O-CVDEj5x8.js +2 -0
- package/dist/public/assets/chunk-426QAEUC-CIWkCWTf.js +1 -0
- package/dist/public/assets/chunk-4BX2VUAB-O8dxzEpn.js +1 -0
- package/dist/public/assets/chunk-4TB4RGXK-Bt4fWDlh.js +206 -0
- package/dist/public/assets/chunk-55IACEB6-R-yr7oHq.js +1 -0
- package/dist/public/assets/chunk-5FUZZQ4R-D7L4hZzZ.js +62 -0
- package/dist/public/assets/chunk-5PVQY5BW-D46cRkay.js +2 -0
- package/dist/public/assets/chunk-67CJDMHE-1fLguPDq.js +1 -0
- package/dist/public/assets/chunk-7N4EOEYR-BPbEiVZr.js +1 -0
- package/dist/public/assets/chunk-AA7GKIK3-DZOqN73n.js +1 -0
- package/dist/public/assets/chunk-BSJP7CBP-BQPMRa-Q.js +1 -0
- package/dist/public/assets/chunk-CFjPhJqf.js +1 -0
- package/dist/public/assets/chunk-CIAEETIT-CoKBG93U.js +1 -0
- package/dist/public/assets/chunk-EDXVE4YY-BxmMvdBY.js +1 -0
- package/dist/public/assets/chunk-ENJZ2VHE-BrjxYY_T.js +10 -0
- package/dist/public/assets/chunk-FMBD7UC4-DChB7ne2.js +15 -0
- package/dist/public/assets/chunk-FOC6F5B3-DyK4SoM2.js +1 -0
- package/dist/public/assets/chunk-ICPOFSXX-6-ABzkfw.js +122 -0
- package/dist/public/assets/chunk-K5T4RW27-432kjUXO.js +94 -0
- package/dist/public/assets/chunk-KGLVRYIC-ChpiuJys.js +1 -0
- package/dist/public/assets/chunk-LIHQZDEY-C65uflEj.js +1 -0
- package/dist/public/assets/chunk-ORNJ4GCN-DPvOqXKg.js +1 -0
- package/dist/public/assets/chunk-OYMX7WX6-BecMUsrL.js +231 -0
- package/dist/public/assets/chunk-QZHKN3VN-d1i_Lm1t.js +1 -0
- package/dist/public/assets/chunk-U2HBQHQK-C6yvwOAo.js +70 -0
- package/dist/public/assets/chunk-X2U36JSP-D1C3tOED.js +1 -0
- package/dist/public/assets/chunk-XPW4576I-BH37LuuF.js +32 -0
- package/dist/public/assets/chunk-YZCP3GAM-D83gHdmx.js +1 -0
- package/dist/public/assets/chunk-ZZ45TVLE-DrCjtkdu.js +1 -0
- package/dist/public/assets/classDiagram-6PBFFD2Q-CRYacdjd.js +1 -0
- package/dist/public/assets/classDiagram-v2-HSJHXN6E-qOJXC_A9.js +1 -0
- package/dist/public/assets/clone-Bno0nirE.js +1 -0
- package/dist/public/assets/colors-DZGTowqM.js +1 -0
- package/dist/public/assets/cose-bilkent-S5V4N54A-BdSMsFO7.js +1 -0
- package/dist/public/assets/cytoscape.esm-DpmcErfs.js +321 -0
- package/dist/public/assets/dagre-D0KOcyEK.js +1 -0
- package/dist/public/assets/dagre-KV5264BT-C_l1Bck_.js +4 -0
- package/dist/public/assets/defaultLocale-B6dPnyNg.js +1 -0
- package/dist/public/assets/diagram-5BDNPKRD-D6FxiIv1.js +10 -0
- package/dist/public/assets/diagram-G4DWMVQ6-COGBv7tQ.js +24 -0
- package/dist/public/assets/diagram-MMDJMWI5-U6E9w334.js +43 -0
- package/dist/public/assets/diagram-TYMM5635-Tvfdnlo4.js +24 -0
- package/dist/public/assets/dist-C6vvxvVV.js +1 -0
- package/dist/public/assets/erDiagram-SMLLAGMA-VcPXkmy9.js +85 -0
- package/dist/public/assets/flatten-BKeNCJRx.js +1 -0
- package/dist/public/assets/flowDiagram-DWJPFMVM-PRQdlypB.js +162 -0
- package/dist/public/assets/ganttDiagram-T4ZO3ILL-CSVaTciZ.js +292 -0
- package/dist/public/assets/gitGraph-7Q5UKJZL-C6GVmHC4.js +1 -0
- package/dist/public/assets/gitGraphDiagram-UUTBAWPF-DMa-Gcy1.js +106 -0
- package/dist/public/assets/graphlib-BYojtb6k.js +1 -0
- package/dist/public/assets/identity-nF-8qK2-.js +1 -0
- package/dist/public/assets/index-oVbUFngg.js +737 -0
- package/dist/public/assets/info-OMHHGYJF-CjsmQeYR.js +1 -0
- package/dist/public/assets/infoDiagram-42DDH7IO-COL_Na4w.js +2 -0
- package/dist/public/assets/init-B9nbfZCT.js +1 -0
- package/dist/public/assets/isEmpty-Di-NpihJ.js +1 -0
- package/dist/public/assets/ishikawaDiagram-UXIWVN3A-B3HoSFaq.js +70 -0
- package/dist/public/assets/journeyDiagram-VCZTEJTY-kH30WNF3.js +139 -0
- package/dist/public/assets/kanban-definition-6JOO6SKY-RdjEsejt.js +89 -0
- package/dist/public/assets/katex-Bfn1OZEl.js +257 -0
- package/dist/public/assets/line-DrKJYWGi.js +1 -0
- package/dist/public/assets/linear-C8MDrvxz.js +1 -0
- package/dist/public/assets/mermaid-parser.core-BeZK8g2G.js +4 -0
- package/dist/public/assets/mindmap-definition-QFDTVHPH-CNWWI4MF.js +96 -0
- package/dist/public/assets/ordinal-BXaEVJbT.js +1 -0
- package/dist/public/assets/packet-4T2RLAQJ-Dq0Z9G3r.js +1 -0
- package/dist/public/assets/path-C7Bv0Qdk.js +1 -0
- package/dist/public/assets/pie-ZZUOXDRM-Coeb8Atk.js +1 -0
- package/dist/public/assets/pieDiagram-DEJITSTG-CrDW-30P.js +30 -0
- package/dist/public/assets/quadrantDiagram-34T5L4WZ-BoDA5WQ-.js +7 -0
- package/dist/public/assets/radar-PYXPWWZC-BF2NN2TG.js +1 -0
- package/dist/public/assets/range-DuD7Go1R.js +1 -0
- package/dist/public/assets/reduce-5tLTMRkg.js +1 -0
- package/dist/public/assets/requirementDiagram-MS252O5E-BnG7epLH.js +84 -0
- package/dist/public/assets/rough.esm-DE7XMpOC.js +1 -0
- package/dist/public/assets/sankeyDiagram-XADWPNL6-oyTFoxhB.js +10 -0
- package/dist/public/assets/sequenceDiagram-FGHM5R23-hwG2jT_2.js +157 -0
- package/dist/public/assets/src-ps-3oTnY.js +1 -0
- package/dist/public/assets/stateDiagram-FHFEXIEX-BiYqw63j.js +1 -0
- package/dist/public/assets/stateDiagram-v2-QKLJ7IA2-CggSrcDh.js +1 -0
- package/dist/public/assets/time-Bgnk7ODM.js +1 -0
- package/dist/public/assets/timeline-definition-GMOUNBTQ-9MnBod43.js +120 -0
- package/dist/public/assets/treeView-SZITEDCU-IRdgIoRV.js +1 -0
- package/dist/public/assets/treemap-DK8fitek.js +1 -0
- package/dist/public/assets/treemap-W4RFUUIX-C-JBwyWW.js +1 -0
- package/dist/public/assets/vennDiagram-DHZGUBPP-sEA6JNL-.js +34 -0
- package/dist/public/assets/wardley-RL74JXVD-DdU04Q7E.js +1 -0
- package/dist/public/assets/wardleyDiagram-NUSXRM2D-Dws321pY.js +20 -0
- package/dist/public/assets/xychartDiagram-5P7HB3ND-BcqyvmmW.js +7 -0
- package/dist/public/index.html +30 -1
- package/package.json +7 -7
- package/src/domain/cards/index.ts +73 -0
- package/src/domain/cards/lib.ts +4 -0
- package/src/domain/cards/schema.ts +9 -0
- package/src/domain/cards/service.ts +26 -1
- package/src/domain/project/service.ts +1 -1
- package/src/domain/resources/index.ts +74 -0
- package/src/domain/resources/schema.ts +14 -0
- package/src/domain/resources/service.ts +50 -4
- package/dist/public/assets/index-Cdn_jRWy.js +0 -720
package/dist/public/index.html
CHANGED
|
@@ -11,7 +11,36 @@
|
|
|
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-oVbUFngg.js"></script>
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-CFjPhJqf.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/src-ps-3oTnY.js">
|
|
17
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-ICPOFSXX-6-ABzkfw.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/assets/dist-C6vvxvVV.js">
|
|
19
|
+
<link rel="modulepreload" crossorigin href="/assets/identity-nF-8qK2-.js">
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-5PVQY5BW-D46cRkay.js">
|
|
21
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-U2HBQHQK-C6yvwOAo.js">
|
|
22
|
+
<link rel="modulepreload" crossorigin href="/assets/defaultLocale-B6dPnyNg.js">
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/assets/init-B9nbfZCT.js">
|
|
24
|
+
<link rel="modulepreload" crossorigin href="/assets/linear-C8MDrvxz.js">
|
|
25
|
+
<link rel="modulepreload" crossorigin href="/assets/time-Bgnk7ODM.js">
|
|
26
|
+
<link rel="modulepreload" crossorigin href="/assets/range-DuD7Go1R.js">
|
|
27
|
+
<link rel="modulepreload" crossorigin href="/assets/treemap-DK8fitek.js">
|
|
28
|
+
<link rel="modulepreload" crossorigin href="/assets/path-C7Bv0Qdk.js">
|
|
29
|
+
<link rel="modulepreload" crossorigin href="/assets/colors-DZGTowqM.js">
|
|
30
|
+
<link rel="modulepreload" crossorigin href="/assets/ordinal-BXaEVJbT.js">
|
|
31
|
+
<link rel="modulepreload" crossorigin href="/assets/arc-DFTvTCxD.js">
|
|
32
|
+
<link rel="modulepreload" crossorigin href="/assets/array-xS8TccZC.js">
|
|
33
|
+
<link rel="modulepreload" crossorigin href="/assets/line-DrKJYWGi.js">
|
|
34
|
+
<link rel="modulepreload" crossorigin href="/assets/isEmpty-Di-NpihJ.js">
|
|
35
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-X2U36JSP-D1C3tOED.js">
|
|
36
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-ZZ45TVLE-DrCjtkdu.js">
|
|
37
|
+
<link rel="modulepreload" crossorigin href="/assets/rough.esm-DE7XMpOC.js">
|
|
38
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-5FUZZQ4R-D7L4hZzZ.js">
|
|
39
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-BSJP7CBP-BQPMRa-Q.js">
|
|
40
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-ENJZ2VHE-BrjxYY_T.js">
|
|
41
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-336JU56O-CVDEj5x8.js">
|
|
42
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-426QAEUC-CIWkCWTf.js">
|
|
43
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-XPW4576I-BH37LuuF.js">
|
|
15
44
|
<link rel="stylesheet" crossorigin href="/assets/index-ypsafPwV.css">
|
|
16
45
|
</head>
|
|
17
46
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyberismo/backend",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"description": "Express backend for Cyberismo",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"keywords": [],
|
|
@@ -14,17 +14,17 @@
|
|
|
14
14
|
"bugs": "https://github.com/CyberismoCom/cyberismo/issues",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@asciidoctor/core": "^3.0.4",
|
|
17
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
18
|
-
"@hono/node-server": "^1.19.
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
18
|
+
"@hono/node-server": "^1.19.13",
|
|
19
19
|
"@hono/zod-validator": "^0.7.6",
|
|
20
20
|
"@types/mime-types": "^3.0.1",
|
|
21
21
|
"dotenv": "^17.3.1",
|
|
22
|
-
"hono": "^4.12.
|
|
23
|
-
"jose": "^6.
|
|
22
|
+
"hono": "^4.12.14",
|
|
23
|
+
"jose": "^6.2.3",
|
|
24
24
|
"mime-types": "^3.0.2",
|
|
25
25
|
"zod": "^4.3.6",
|
|
26
|
-
"@cyberismo/
|
|
27
|
-
"@cyberismo/
|
|
26
|
+
"@cyberismo/data-handler": "0.0.24",
|
|
27
|
+
"@cyberismo/mcp": "0.0.24"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@cyberismo/app": "0.0.2"
|
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
createLinkSchema,
|
|
27
27
|
removeLinkSchema,
|
|
28
28
|
updateLinkSchema,
|
|
29
|
+
exportCardPdfSchema,
|
|
30
|
+
type ExportCardPdfRequestBody,
|
|
29
31
|
} from './schema.js';
|
|
30
32
|
|
|
31
33
|
const router = new Hono();
|
|
@@ -58,6 +60,77 @@ router.get('/', requireRole(UserRole.Reader), async (c) => {
|
|
|
58
60
|
}
|
|
59
61
|
});
|
|
60
62
|
|
|
63
|
+
/**
|
|
64
|
+
* @swagger
|
|
65
|
+
* /api/cards/export-pdf:
|
|
66
|
+
* post:
|
|
67
|
+
* summary: Export a card as a PDF
|
|
68
|
+
* description: Exports the specified card as a PDF
|
|
69
|
+
* parameters:
|
|
70
|
+
* - name: key
|
|
71
|
+
* in: path
|
|
72
|
+
* required: true
|
|
73
|
+
* description: Card key (string)
|
|
74
|
+
* requestBody:
|
|
75
|
+
* content:
|
|
76
|
+
* application/json:
|
|
77
|
+
* schema:
|
|
78
|
+
* type: object
|
|
79
|
+
* properties:
|
|
80
|
+
* title:
|
|
81
|
+
* type: string
|
|
82
|
+
* description: Title of the exported PDF
|
|
83
|
+
* name:
|
|
84
|
+
* type: string
|
|
85
|
+
* description: Name of the exported PDF
|
|
86
|
+
* exportChildCards:
|
|
87
|
+
* type: boolean
|
|
88
|
+
* description: Whether to export child cards
|
|
89
|
+
* version:
|
|
90
|
+
* type: string
|
|
91
|
+
* description: Version of the exported PDF (optional)
|
|
92
|
+
* responses:
|
|
93
|
+
* 200:
|
|
94
|
+
* description: Card exported successfully
|
|
95
|
+
* 400:
|
|
96
|
+
* description: Missing or invalid parameters.
|
|
97
|
+
* 500:
|
|
98
|
+
* description: project_path not set
|
|
99
|
+
*/
|
|
100
|
+
router.post(
|
|
101
|
+
'/export-pdf',
|
|
102
|
+
requireRole(UserRole.Reader),
|
|
103
|
+
zValidator('json', exportCardPdfSchema),
|
|
104
|
+
async (c) => {
|
|
105
|
+
const commands = c.get('commands');
|
|
106
|
+
const body = (await c.req.json()) as ExportCardPdfRequestBody;
|
|
107
|
+
try {
|
|
108
|
+
const result = await cardService.exportCard(commands, {
|
|
109
|
+
cardKey: body.cardKey,
|
|
110
|
+
title: body.title,
|
|
111
|
+
name: body.name,
|
|
112
|
+
recursive: body.exportChildCards,
|
|
113
|
+
version: body.version,
|
|
114
|
+
});
|
|
115
|
+
return new Response(result, {
|
|
116
|
+
status: 200,
|
|
117
|
+
headers: {
|
|
118
|
+
'Content-Type': 'application/pdf',
|
|
119
|
+
'Cache-Control': 'no-store',
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
} catch (error) {
|
|
123
|
+
return c.json(
|
|
124
|
+
{
|
|
125
|
+
error:
|
|
126
|
+
error instanceof Error ? error.message : 'Failed to export card',
|
|
127
|
+
},
|
|
128
|
+
500,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
|
|
61
134
|
/**
|
|
62
135
|
* @swagger
|
|
63
136
|
* /api/cards/{key}:
|
package/src/domain/cards/lib.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
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
|
+
import { preprocessMermaidBlocksForHtml } from '@cyberismo/data-handler/utils/mermaid-renderer';
|
|
17
18
|
import { getCardQueryResult } from '../../export.js';
|
|
18
19
|
import type { TreeOptions } from '../../types.js';
|
|
19
20
|
import type { QueryResult } from '@cyberismo/data-handler/types/queries';
|
|
@@ -57,6 +58,9 @@ export async function getCardDetails(
|
|
|
57
58
|
asciidocContent = `Macro error: ${error instanceof Error ? error.message : 'Unknown error'}\n\n${asciidocContent}`;
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
// Convert [mermaid] AsciiDoc blocks to passthrough HTML before asciidoctor processes them
|
|
62
|
+
asciidocContent = preprocessMermaidBlocksForHtml(asciidocContent);
|
|
63
|
+
|
|
60
64
|
const htmlContent = Processor()
|
|
61
65
|
.convert(asciidocContent, {
|
|
62
66
|
safe: 'safe',
|
|
@@ -39,3 +39,12 @@ export const updateLinkSchema = z.object({
|
|
|
39
39
|
previousDirection: linkDirection,
|
|
40
40
|
previousDescription: z.string().optional(),
|
|
41
41
|
});
|
|
42
|
+
export const exportCardPdfSchema = z.object({
|
|
43
|
+
title: z.string().min(1),
|
|
44
|
+
name: z.string().min(1),
|
|
45
|
+
cardKey: z.string(),
|
|
46
|
+
exportChildCards: z.boolean(),
|
|
47
|
+
version: z.string().min(1).optional(),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export type ExportCardPdfRequestBody = z.infer<typeof exportCardPdfSchema>;
|
|
@@ -12,9 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import Processor from '@asciidoctor/core';
|
|
15
|
-
import
|
|
15
|
+
import type {
|
|
16
|
+
ExportPdfOptions,
|
|
17
|
+
MetadataContent,
|
|
18
|
+
} from '@cyberismo/data-handler/interfaces/project-interfaces';
|
|
16
19
|
import type { attachmentPayload } from '@cyberismo/data-handler/interfaces/request-status-interfaces';
|
|
17
20
|
import { type CommandManager, evaluateMacros } from '@cyberismo/data-handler';
|
|
21
|
+
import { preprocessMermaidBlocksForHtml } from '@cyberismo/data-handler/utils/mermaid-renderer';
|
|
18
22
|
import { allCards } from './lib.js';
|
|
19
23
|
import type { TreeOptions } from '../../types.js';
|
|
20
24
|
|
|
@@ -120,11 +124,19 @@ export async function uploadAttachments(
|
|
|
120
124
|
};
|
|
121
125
|
}
|
|
122
126
|
|
|
127
|
+
function validateAttachmentFileName(filename: string): void {
|
|
128
|
+
const decoded = decodeURIComponent(filename);
|
|
129
|
+
if (/(^|[/\\])\.\.([/\\]|$)/.test(decoded)) {
|
|
130
|
+
throw new Error('Invalid attachment filename');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
123
134
|
export async function removeAttachment(
|
|
124
135
|
commands: CommandManager,
|
|
125
136
|
key: string,
|
|
126
137
|
filename: string,
|
|
127
138
|
) {
|
|
139
|
+
validateAttachmentFileName(filename);
|
|
128
140
|
await commands.removeCmd.remove('attachment', key, filename);
|
|
129
141
|
return { message: 'Attachment removed successfully' };
|
|
130
142
|
}
|
|
@@ -134,6 +146,7 @@ export async function openAttachment(
|
|
|
134
146
|
key: string,
|
|
135
147
|
filename: string,
|
|
136
148
|
) {
|
|
149
|
+
validateAttachmentFileName(filename);
|
|
137
150
|
await commands.showCmd.openAttachment(key, filename);
|
|
138
151
|
return { message: 'Attachment opened successfully' };
|
|
139
152
|
}
|
|
@@ -156,6 +169,9 @@ export async function parseContent(
|
|
|
156
169
|
asciidocContent = `Macro error: ${error instanceof Error ? error.message : 'Unknown error'}\n\n${content}`;
|
|
157
170
|
}
|
|
158
171
|
|
|
172
|
+
// Convert [mermaid] AsciiDoc blocks to passthrough HTML before asciidoctor processes them
|
|
173
|
+
asciidocContent = preprocessMermaidBlocksForHtml(asciidocContent);
|
|
174
|
+
|
|
159
175
|
const processor = Processor();
|
|
160
176
|
const parsedContent = processor
|
|
161
177
|
.convert(asciidocContent, {
|
|
@@ -259,6 +275,7 @@ export async function getAttachment(
|
|
|
259
275
|
key: string,
|
|
260
276
|
filename: string,
|
|
261
277
|
): Promise<attachmentPayload> {
|
|
278
|
+
validateAttachmentFileName(filename);
|
|
262
279
|
return commands.showCmd.showAttachment(key, filename);
|
|
263
280
|
}
|
|
264
281
|
|
|
@@ -298,3 +315,11 @@ export async function findRelevantAttachments(
|
|
|
298
315
|
attachment: attachment.fileName,
|
|
299
316
|
}));
|
|
300
317
|
}
|
|
318
|
+
|
|
319
|
+
export async function exportCard(
|
|
320
|
+
commands: CommandManager,
|
|
321
|
+
options: ExportPdfOptions,
|
|
322
|
+
): Promise<Buffer> {
|
|
323
|
+
const result = await commands.exportCmd.exportPdfBuffer(options);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
@@ -57,7 +57,7 @@ export async function getProject(
|
|
|
57
57
|
const project = await commands.showCmd.showProject();
|
|
58
58
|
const modules = await commands.showCmd.showModules();
|
|
59
59
|
const moduleDetails = await Promise.all(
|
|
60
|
-
modules.map((mod) => toModuleInfo(commands, mod)),
|
|
60
|
+
modules.map((mod) => toModuleInfo(commands, mod.name)),
|
|
61
61
|
);
|
|
62
62
|
|
|
63
63
|
return {
|
|
@@ -20,6 +20,8 @@ import { zValidator } from '../../middleware/zvalidator.js';
|
|
|
20
20
|
import {
|
|
21
21
|
validateResourceParamsSchema,
|
|
22
22
|
updateOperationBodySchema,
|
|
23
|
+
workflowGraphParamsSchema,
|
|
24
|
+
workflowGraphQuerySchema,
|
|
23
25
|
} from './schema.js';
|
|
24
26
|
import { requireRole } from '../../middleware/auth.js';
|
|
25
27
|
|
|
@@ -132,6 +134,78 @@ router.delete(
|
|
|
132
134
|
},
|
|
133
135
|
);
|
|
134
136
|
|
|
137
|
+
/**
|
|
138
|
+
* @swagger
|
|
139
|
+
* /api/resources/{prefix}/workflows/{identifier}/graph:
|
|
140
|
+
* get:
|
|
141
|
+
* summary: Render the state-machine graph for a workflow
|
|
142
|
+
* description: Returns a base64-encoded sanitized SVG of the workflow's
|
|
143
|
+
* state-machine diagram, rendered with the built-in
|
|
144
|
+
* workflow graph model and view. When the optional `card`
|
|
145
|
+
* query parameter is provided, the diagram highlights
|
|
146
|
+
* that card's current workflowState.
|
|
147
|
+
* parameters:
|
|
148
|
+
* - in: path
|
|
149
|
+
* name: prefix
|
|
150
|
+
* required: true
|
|
151
|
+
* schema:
|
|
152
|
+
* type: string
|
|
153
|
+
* - in: path
|
|
154
|
+
* name: identifier
|
|
155
|
+
* required: true
|
|
156
|
+
* schema:
|
|
157
|
+
* type: string
|
|
158
|
+
* - in: query
|
|
159
|
+
* name: card
|
|
160
|
+
* required: false
|
|
161
|
+
* schema:
|
|
162
|
+
* type: string
|
|
163
|
+
* description: Card key whose current workflowState should be
|
|
164
|
+
* highlighted in the rendered diagram.
|
|
165
|
+
* responses:
|
|
166
|
+
* 200:
|
|
167
|
+
* description: Rendered diagram
|
|
168
|
+
* content:
|
|
169
|
+
* application/json:
|
|
170
|
+
* schema:
|
|
171
|
+
* type: object
|
|
172
|
+
* properties:
|
|
173
|
+
* svg:
|
|
174
|
+
* type: string
|
|
175
|
+
* description: Base64-encoded SVG document.
|
|
176
|
+
* 400:
|
|
177
|
+
* description: Invalid path parameters
|
|
178
|
+
* 404:
|
|
179
|
+
* description: Workflow or card not found
|
|
180
|
+
* 500:
|
|
181
|
+
* description: Server error
|
|
182
|
+
*/
|
|
183
|
+
router.get(
|
|
184
|
+
'/:prefix/workflows/:identifier/graph',
|
|
185
|
+
requireRole(UserRole.Reader),
|
|
186
|
+
zValidator('param', workflowGraphParamsSchema),
|
|
187
|
+
zValidator('query', workflowGraphQuerySchema),
|
|
188
|
+
async (c) => {
|
|
189
|
+
const commands = c.get('commands');
|
|
190
|
+
const { prefix, identifier } = c.req.valid('param');
|
|
191
|
+
const { card } = c.req.valid('query');
|
|
192
|
+
const workflowName = `${prefix}/workflows/${identifier}`;
|
|
193
|
+
try {
|
|
194
|
+
const svg = await resourceService.getWorkflowGraph(
|
|
195
|
+
commands,
|
|
196
|
+
workflowName,
|
|
197
|
+
card,
|
|
198
|
+
);
|
|
199
|
+
return c.json({ svg });
|
|
200
|
+
} catch (error) {
|
|
201
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
202
|
+
return c.json({ error: error.message }, 404);
|
|
203
|
+
}
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
|
|
135
209
|
router.post(
|
|
136
210
|
'/:prefix/:type/:identifier/operation',
|
|
137
211
|
requireRole(UserRole.Admin),
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import {
|
|
3
|
+
identifierSchema,
|
|
3
4
|
resourceParamsSchema,
|
|
4
5
|
resourceTypes,
|
|
5
6
|
} from '../../common/validationSchemas.js';
|
|
6
7
|
|
|
8
|
+
export const workflowGraphParamsSchema = z.object({
|
|
9
|
+
prefix: z.string(),
|
|
10
|
+
identifier: identifierSchema,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type WorkflowGraphParams = z.infer<typeof workflowGraphParamsSchema>;
|
|
14
|
+
|
|
15
|
+
export const workflowGraphQuerySchema = z.object({
|
|
16
|
+
card: z.string().optional(),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export type WorkflowGraphQuery = z.infer<typeof workflowGraphQuerySchema>;
|
|
20
|
+
|
|
7
21
|
export const resourceFileParamsSchema = resourceParamsSchema.extend({
|
|
8
22
|
file: z.string(),
|
|
9
23
|
});
|
|
@@ -42,14 +42,14 @@ const resourceTypes: ResourceFolderType[] = [
|
|
|
42
42
|
|
|
43
43
|
async function getModules(commands: CommandManager) {
|
|
44
44
|
try {
|
|
45
|
-
const
|
|
45
|
+
const modules = await commands.showCmd.showModules();
|
|
46
46
|
return Promise.all(
|
|
47
|
-
|
|
47
|
+
modules.map(async (mod) => {
|
|
48
48
|
try {
|
|
49
|
-
const module = await commands.showCmd.showModule(
|
|
49
|
+
const module = await commands.showCmd.showModule(mod.name);
|
|
50
50
|
return { name: module.name, cardKeyPrefix: module.cardKeyPrefix };
|
|
51
51
|
} catch {
|
|
52
|
-
return { name:
|
|
52
|
+
return { name: mod.name, cardKeyPrefix: mod.name };
|
|
53
53
|
}
|
|
54
54
|
}),
|
|
55
55
|
);
|
|
@@ -467,6 +467,52 @@ export async function validateResource(
|
|
|
467
467
|
};
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Renders the built-in state-machine graph for a single workflow.
|
|
472
|
+
* When `cardKey` is provided, the card's current workflowState is
|
|
473
|
+
* highlighted in the diagram. The workflow lookup, card lookup and
|
|
474
|
+
* graph rendering all run inside the same consistency window so the
|
|
475
|
+
* highlighted state matches the diagram even if the card is being
|
|
476
|
+
* transitioned concurrently.
|
|
477
|
+
* @returns base64-encoded sanitized SVG.
|
|
478
|
+
* @throws Error with 'not found' in the message when the workflow or
|
|
479
|
+
* card cannot be resolved.
|
|
480
|
+
*/
|
|
481
|
+
export async function getWorkflowGraph(
|
|
482
|
+
commands: CommandManager,
|
|
483
|
+
workflowName: string,
|
|
484
|
+
cardKey?: string,
|
|
485
|
+
): Promise<string> {
|
|
486
|
+
return commands.consistent(async () => {
|
|
487
|
+
try {
|
|
488
|
+
await commands.showCmd.showResource(workflowName, 'workflows');
|
|
489
|
+
} catch (error) {
|
|
490
|
+
if (error instanceof Error && error.message.includes('does not exist')) {
|
|
491
|
+
throw new Error(`Workflow '${workflowName}' not found`, {
|
|
492
|
+
cause: error,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
497
|
+
let currentState: string | undefined;
|
|
498
|
+
if (cardKey) {
|
|
499
|
+
let card;
|
|
500
|
+
try {
|
|
501
|
+
card = await commands.showCmd.showCardDetails(cardKey);
|
|
502
|
+
} catch (error) {
|
|
503
|
+
throw new Error(`Card '${cardKey}' not found`, { cause: error });
|
|
504
|
+
}
|
|
505
|
+
if (!card?.metadata) {
|
|
506
|
+
throw new Error(`Card '${cardKey}' not found`);
|
|
507
|
+
}
|
|
508
|
+
currentState = card.metadata.workflowState;
|
|
509
|
+
}
|
|
510
|
+
return commands.calculateCmd.runWorkflowGraph(workflowName, {
|
|
511
|
+
currentState,
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
470
516
|
/**
|
|
471
517
|
* Perform an updateOperation on a resource key.
|
|
472
518
|
* This delegates to data-handler Update.applyResourceOperation.
|