@cyberismo/backend 0.0.21 → 0.0.22
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 +5 -2
- package/dist/app.js +22 -9
- package/dist/app.js.map +1 -1
- package/dist/auth/index.d.ts +16 -0
- package/dist/auth/index.js +15 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/keycloak.d.ts +27 -0
- package/dist/auth/keycloak.js +81 -0
- package/dist/auth/keycloak.js.map +1 -0
- package/dist/auth/mock.d.ts +23 -0
- package/dist/auth/mock.js +28 -0
- package/dist/auth/mock.js.map +1 -0
- package/dist/auth/types.d.ts +16 -0
- package/dist/auth/types.js +14 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/domain/auth/index.d.ts +14 -0
- package/dist/domain/auth/index.js +30 -0
- package/dist/domain/auth/index.js.map +1 -0
- package/dist/domain/calculations/index.js +3 -1
- package/dist/domain/calculations/index.js.map +1 -1
- package/dist/domain/calculations/service.js +13 -11
- package/dist/domain/calculations/service.js.map +1 -1
- package/dist/domain/cardTypes/index.js +5 -3
- package/dist/domain/cardTypes/index.js.map +1 -1
- package/dist/domain/cardTypes/service.js +24 -72
- package/dist/domain/cardTypes/service.js.map +1 -1
- package/dist/domain/cards/index.js +19 -15
- package/dist/domain/cards/index.js.map +1 -1
- package/dist/domain/cards/lib.js +95 -93
- package/dist/domain/cards/lib.js.map +1 -1
- package/dist/domain/cards/service.d.ts +2 -1
- package/dist/domain/cards/service.js +60 -87
- package/dist/domain/cards/service.js.map +1 -1
- package/dist/domain/fieldTypes/index.js +4 -2
- package/dist/domain/fieldTypes/index.js.map +1 -1
- package/dist/domain/graphModels/index.js +3 -1
- package/dist/domain/graphModels/index.js.map +1 -1
- package/dist/domain/graphViews/index.js +3 -1
- package/dist/domain/graphViews/index.js.map +1 -1
- package/dist/domain/labels/index.js +4 -2
- package/dist/domain/labels/index.js.map +1 -1
- package/dist/domain/labels/service.d.ts +1 -1
- package/dist/domain/labels/service.js +2 -2
- package/dist/domain/labels/service.js.map +1 -1
- package/dist/domain/linkTypes/index.js +4 -2
- package/dist/domain/linkTypes/index.js.map +1 -1
- package/dist/domain/logicPrograms/index.js +3 -1
- package/dist/domain/logicPrograms/index.js.map +1 -1
- package/dist/domain/mcp/index.d.ts +15 -0
- package/dist/domain/mcp/index.js +127 -0
- package/dist/domain/mcp/index.js.map +1 -0
- package/dist/domain/project/index.js +7 -5
- package/dist/domain/project/index.js.map +1 -1
- package/dist/domain/project/service.js +18 -14
- package/dist/domain/project/service.js.map +1 -1
- package/dist/domain/reports/index.js +3 -1
- package/dist/domain/reports/index.js.map +1 -1
- package/dist/domain/resources/index.js +6 -4
- package/dist/domain/resources/index.js.map +1 -1
- package/dist/domain/resources/service.js +66 -64
- package/dist/domain/resources/service.js.map +1 -1
- package/dist/domain/templates/index.js +5 -3
- package/dist/domain/templates/index.js.map +1 -1
- package/dist/domain/tree/index.js +3 -1
- package/dist/domain/tree/index.js.map +1 -1
- package/dist/domain/workflows/index.js +3 -1
- package/dist/domain/workflows/index.js.map +1 -1
- package/dist/export.d.ts +6 -5
- package/dist/export.js +15 -11
- package/dist/export.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/main.js +29 -2
- package/dist/main.js.map +1 -1
- package/dist/middleware/auth.d.ts +40 -0
- package/dist/middleware/auth.js +68 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/commandManager.d.ts +2 -2
- package/dist/middleware/commandManager.js +9 -11
- package/dist/middleware/commandManager.js.map +1 -1
- package/dist/public/THIRD-PARTY.txt +37 -11
- package/dist/public/assets/index-B_lh6qtv.css +1 -0
- package/dist/public/assets/{index-Ca10XaMv.js → index-CEol8Bfi.js} +43823 -43030
- package/dist/public/config.json +1 -0
- package/dist/public/index.html +2 -2
- package/dist/types.d.ts +25 -0
- package/dist/types.js +13 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -5
- package/src/app.ts +34 -14
- package/src/auth/index.ts +17 -0
- package/src/auth/keycloak.ts +109 -0
- package/src/auth/mock.ts +38 -0
- package/src/auth/types.ts +18 -0
- package/src/domain/auth/index.ts +35 -0
- package/src/domain/calculations/index.ts +13 -6
- package/src/domain/calculations/service.ts +16 -14
- package/src/domain/cardTypes/index.ts +24 -16
- package/src/domain/cardTypes/service.ts +41 -95
- package/src/domain/cards/index.ts +62 -44
- package/src/domain/cards/lib.ts +105 -100
- package/src/domain/cards/service.ts +73 -89
- package/src/domain/fieldTypes/index.ts +23 -16
- package/src/domain/graphModels/index.ts +13 -6
- package/src/domain/graphViews/index.ts +13 -6
- package/src/domain/labels/index.ts +5 -2
- package/src/domain/labels/service.ts +2 -2
- package/src/domain/linkTypes/index.ts +14 -7
- package/src/domain/logicPrograms/index.ts +3 -0
- package/src/domain/mcp/index.ts +159 -0
- package/src/domain/project/index.ts +17 -8
- package/src/domain/project/service.ts +20 -16
- package/src/domain/reports/index.ts +13 -6
- package/src/domain/resources/index.ts +6 -1
- package/src/domain/resources/service.ts +102 -97
- package/src/domain/templates/index.ts +31 -19
- package/src/domain/tree/index.ts +3 -1
- package/src/domain/workflows/index.ts +13 -6
- package/src/export.ts +16 -13
- package/src/index.ts +10 -3
- package/src/main.ts +44 -2
- package/src/middleware/auth.ts +90 -0
- package/src/middleware/commandManager.ts +11 -14
- package/src/types.ts +27 -0
- package/dist/public/assets/index-CRSBseQM.css +0 -1
|
@@ -54,126 +54,72 @@ export async function updateFieldVisibility(
|
|
|
54
54
|
): Promise<void> {
|
|
55
55
|
const { fieldName, group: targetGroup, index: targetIndex } = body;
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
await commands.atomic(async () => {
|
|
58
|
+
// Read is now inside the write lock
|
|
59
|
+
const cardType = await commands.showCmd.showResource(
|
|
60
|
+
cardTypeName,
|
|
61
|
+
'cardTypes',
|
|
62
|
+
);
|
|
63
|
+
if (!cardType) {
|
|
64
|
+
throw new Error(`Card type '${cardTypeName}' not found`);
|
|
65
|
+
}
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const customFields = cardType.customFields || [];
|
|
68
|
+
const alwaysVisibleFields = cardType.alwaysVisibleFields || [];
|
|
69
|
+
const optionallyVisibleFields = cardType.optionallyVisibleFields || [];
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
);
|
|
74
|
-
if (!fieldExists) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
`Field '${fieldName}' does not exist in card type '${cardTypeName}'. `,
|
|
71
|
+
// Validate that the field exists in customFields
|
|
72
|
+
const fieldExists = customFields.some(
|
|
73
|
+
(f: { name: string }) => f.name === fieldName,
|
|
77
74
|
);
|
|
78
|
-
|
|
75
|
+
if (!fieldExists) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Field '${fieldName}' does not exist in card type '${cardTypeName}'. `,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
const currentGroup = getCurrentGroup(
|
|
82
|
+
alwaysVisibleFields,
|
|
83
|
+
optionallyVisibleFields,
|
|
84
|
+
fieldName,
|
|
85
|
+
);
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
// If same group, just handle reordering
|
|
88
|
+
if (currentGroup === targetGroup) {
|
|
89
|
+
if (targetGroup !== 'hidden' && targetIndex !== undefined) {
|
|
90
|
+
await commands.updateCmd.applyResourceOperation(
|
|
91
|
+
cardTypeName,
|
|
92
|
+
{ key: groupToKey[targetGroup] },
|
|
93
|
+
{ name: 'rank', target: fieldName, newIndex: targetIndex },
|
|
94
|
+
);
|
|
95
|
+
}
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
if (targetIndex !== undefined) {
|
|
94
|
-
await commands.updateCmd.applyResourceOperation(
|
|
95
|
-
cardTypeName,
|
|
96
|
-
{
|
|
97
|
-
key: groupToKey[targetGroup],
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: 'rank',
|
|
101
|
-
target: fieldName,
|
|
102
|
-
newIndex: targetIndex,
|
|
103
|
-
},
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Different group - need to remove from old and add to new
|
|
110
|
-
let removedFromOld = false;
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
99
|
// Remove from current group (if not hidden)
|
|
114
100
|
if (currentGroup !== 'hidden') {
|
|
115
101
|
await commands.updateCmd.applyResourceOperation(
|
|
116
102
|
cardTypeName,
|
|
117
|
-
{
|
|
118
|
-
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
name: 'remove',
|
|
122
|
-
target: fieldName,
|
|
123
|
-
},
|
|
103
|
+
{ key: groupToKey[currentGroup] },
|
|
104
|
+
{ name: 'remove', target: fieldName },
|
|
124
105
|
);
|
|
125
|
-
removedFromOld = true;
|
|
126
106
|
}
|
|
127
107
|
|
|
128
108
|
// Add to new group (if not hidden)
|
|
129
109
|
if (targetGroup !== 'hidden') {
|
|
130
110
|
await commands.updateCmd.applyResourceOperation(
|
|
131
111
|
cardTypeName,
|
|
132
|
-
{
|
|
133
|
-
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
name: 'add',
|
|
137
|
-
target: fieldName,
|
|
138
|
-
},
|
|
112
|
+
{ key: groupToKey[targetGroup] },
|
|
113
|
+
{ name: 'add', target: fieldName },
|
|
139
114
|
);
|
|
140
115
|
|
|
141
|
-
// Reorder if index specified
|
|
142
116
|
if (targetIndex !== undefined) {
|
|
143
117
|
await commands.updateCmd.applyResourceOperation(
|
|
144
118
|
cardTypeName,
|
|
145
|
-
{
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
name: 'rank',
|
|
150
|
-
target: fieldName,
|
|
151
|
-
newIndex: targetIndex,
|
|
152
|
-
},
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
} catch (error) {
|
|
157
|
-
// Attempt rollback if we removed from old group but failed to add to new
|
|
158
|
-
if (removedFromOld && currentGroup !== 'hidden') {
|
|
159
|
-
try {
|
|
160
|
-
await commands.updateCmd.applyResourceOperation(
|
|
161
|
-
cardTypeName,
|
|
162
|
-
{
|
|
163
|
-
key: groupToKey[currentGroup],
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
name: 'add',
|
|
167
|
-
target: fieldName,
|
|
168
|
-
},
|
|
169
|
-
);
|
|
170
|
-
} catch {
|
|
171
|
-
// Rollback failed - log but throw original error
|
|
172
|
-
console.error(
|
|
173
|
-
`Rollback failed for field '${fieldName}' in card type '${cardTypeName}'`,
|
|
119
|
+
{ key: groupToKey[targetGroup] },
|
|
120
|
+
{ name: 'rank', target: fieldName, newIndex: targetIndex },
|
|
174
121
|
);
|
|
175
122
|
}
|
|
176
123
|
}
|
|
177
|
-
|
|
178
|
-
}
|
|
124
|
+
}, `Update field visibility for ${cardTypeName}`);
|
|
179
125
|
}
|
|
@@ -17,6 +17,8 @@ import { getCardDetails } from './lib.js';
|
|
|
17
17
|
import * as cardService from './service.js';
|
|
18
18
|
import { isSSGContext, ssgParams } from 'hono/ssg';
|
|
19
19
|
import type { AppContext } from '../../types.js';
|
|
20
|
+
import { UserRole } from '../../types.js';
|
|
21
|
+
import { requireRole } from '../../middleware/auth.js';
|
|
20
22
|
|
|
21
23
|
const router = new Hono();
|
|
22
24
|
|
|
@@ -34,7 +36,7 @@ const router = new Hono();
|
|
|
34
36
|
* 500:
|
|
35
37
|
* description: project_path not set.
|
|
36
38
|
*/
|
|
37
|
-
router.get('/', async (c) => {
|
|
39
|
+
router.get('/', requireRole(UserRole.Reader), async (c) => {
|
|
38
40
|
const commands = c.get('commands');
|
|
39
41
|
|
|
40
42
|
try {
|
|
@@ -75,6 +77,7 @@ router.get('/', async (c) => {
|
|
|
75
77
|
*/
|
|
76
78
|
router.get(
|
|
77
79
|
'/:key',
|
|
80
|
+
requireRole(UserRole.Reader),
|
|
78
81
|
ssgParams(async (c: AppContext) => {
|
|
79
82
|
const commands = c.get('commands');
|
|
80
83
|
const opts = c.get('tree');
|
|
@@ -144,7 +147,7 @@ router.get(
|
|
|
144
147
|
* 500:
|
|
145
148
|
* description: project_path not set.
|
|
146
149
|
*/
|
|
147
|
-
router.patch('/:key', async (c) => {
|
|
150
|
+
router.patch('/:key', requireRole(UserRole.Editor), async (c) => {
|
|
148
151
|
const commands = c.get('commands');
|
|
149
152
|
const key = c.req.param('key');
|
|
150
153
|
if (!key) {
|
|
@@ -201,7 +204,7 @@ router.patch('/:key', async (c) => {
|
|
|
201
204
|
* 500:
|
|
202
205
|
* description: project_path not set.
|
|
203
206
|
*/
|
|
204
|
-
router.delete('/:key', async (c) => {
|
|
207
|
+
router.delete('/:key', requireRole(UserRole.Editor), async (c) => {
|
|
205
208
|
const commands = c.get('commands');
|
|
206
209
|
const key = c.req.param('key');
|
|
207
210
|
if (!key) {
|
|
@@ -244,7 +247,7 @@ router.delete('/:key', async (c) => {
|
|
|
244
247
|
* 500:
|
|
245
248
|
* description: project_path not set
|
|
246
249
|
*/
|
|
247
|
-
router.post('/:key', async (c) => {
|
|
250
|
+
router.post('/:key', requireRole(UserRole.Editor), async (c) => {
|
|
248
251
|
const key = c.req.param('key');
|
|
249
252
|
if (!key) {
|
|
250
253
|
return c.text('No search key', 400);
|
|
@@ -300,7 +303,7 @@ router.post('/:key', async (c) => {
|
|
|
300
303
|
* 500:
|
|
301
304
|
* description: Server error
|
|
302
305
|
*/
|
|
303
|
-
router.post('/:key/attachments', async (c) => {
|
|
306
|
+
router.post('/:key/attachments', requireRole(UserRole.Editor), async (c) => {
|
|
304
307
|
const commands = c.get('commands');
|
|
305
308
|
const key = c.req.param('key');
|
|
306
309
|
|
|
@@ -354,25 +357,33 @@ router.post('/:key/attachments', async (c) => {
|
|
|
354
357
|
* 500:
|
|
355
358
|
* description: Server error
|
|
356
359
|
*/
|
|
357
|
-
router.delete(
|
|
358
|
-
|
|
359
|
-
|
|
360
|
+
router.delete(
|
|
361
|
+
'/:key/attachments/:filename',
|
|
362
|
+
requireRole(UserRole.Editor),
|
|
363
|
+
async (c) => {
|
|
364
|
+
const commands = c.get('commands');
|
|
365
|
+
const { key, filename } = c.req.param();
|
|
360
366
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
367
|
+
try {
|
|
368
|
+
const result = await cardService.removeAttachment(
|
|
369
|
+
commands,
|
|
370
|
+
key,
|
|
371
|
+
filename,
|
|
372
|
+
);
|
|
373
|
+
return c.json(result);
|
|
374
|
+
} catch (error) {
|
|
375
|
+
return c.json(
|
|
376
|
+
{
|
|
377
|
+
error:
|
|
378
|
+
error instanceof Error
|
|
379
|
+
? error.message
|
|
380
|
+
: 'Failed to remove attachment',
|
|
381
|
+
},
|
|
382
|
+
500,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
);
|
|
376
387
|
|
|
377
388
|
/**
|
|
378
389
|
* @swagger
|
|
@@ -398,23 +409,29 @@ router.delete('/:key/attachments/:filename', async (c) => {
|
|
|
398
409
|
* 500:
|
|
399
410
|
* description: Server error
|
|
400
411
|
*/
|
|
401
|
-
router.post(
|
|
402
|
-
|
|
403
|
-
|
|
412
|
+
router.post(
|
|
413
|
+
'/:key/attachments/:filename/open',
|
|
414
|
+
requireRole(UserRole.Reader),
|
|
415
|
+
async (c) => {
|
|
416
|
+
const commands = c.get('commands');
|
|
417
|
+
const { key, filename } = c.req.param();
|
|
404
418
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
419
|
+
try {
|
|
420
|
+
const result = await cardService.openAttachment(commands, key, filename);
|
|
421
|
+
return c.json(result);
|
|
422
|
+
} catch (error) {
|
|
423
|
+
return c.json(
|
|
424
|
+
{
|
|
425
|
+
error:
|
|
426
|
+
error instanceof Error
|
|
427
|
+
? error.message
|
|
428
|
+
: 'Failed to open attachment',
|
|
429
|
+
},
|
|
430
|
+
500,
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
);
|
|
418
435
|
|
|
419
436
|
/**
|
|
420
437
|
* @swagger
|
|
@@ -443,7 +460,7 @@ router.post('/:key/attachments/:filename/open', async (c) => {
|
|
|
443
460
|
* 500:
|
|
444
461
|
* description: Server error
|
|
445
462
|
*/
|
|
446
|
-
router.post('/:key/parse', async (c) => {
|
|
463
|
+
router.post('/:key/parse', requireRole(UserRole.Reader), async (c) => {
|
|
447
464
|
const commands = c.get('commands');
|
|
448
465
|
const key = c.req.param('key');
|
|
449
466
|
const { content } = await c.req.json();
|
|
@@ -497,7 +514,7 @@ router.post('/:key/parse', async (c) => {
|
|
|
497
514
|
* 500:
|
|
498
515
|
* description: Server error
|
|
499
516
|
*/
|
|
500
|
-
router.post('/:key/links', async (c) => {
|
|
517
|
+
router.post('/:key/links', requireRole(UserRole.Editor), async (c) => {
|
|
501
518
|
const commands = c.get('commands');
|
|
502
519
|
const key = c.req.param('key');
|
|
503
520
|
const { toCard, linkType, description } = await c.req.json();
|
|
@@ -556,7 +573,7 @@ router.post('/:key/links', async (c) => {
|
|
|
556
573
|
* 500:
|
|
557
574
|
* description: Server error
|
|
558
575
|
*/
|
|
559
|
-
router.delete('/:key/links', async (c) => {
|
|
576
|
+
router.delete('/:key/links', requireRole(UserRole.Editor), async (c) => {
|
|
560
577
|
const commands = c.get('commands');
|
|
561
578
|
const key = c.req.param('key');
|
|
562
579
|
const { toCard, linkType, description } = await c.req.json();
|
|
@@ -610,11 +627,12 @@ router.delete('/:key/links', async (c) => {
|
|
|
610
627
|
*/
|
|
611
628
|
router.get(
|
|
612
629
|
'/:key/a/:attachment',
|
|
630
|
+
requireRole(UserRole.Reader),
|
|
613
631
|
ssgParams(async (c: Context) => {
|
|
614
632
|
const commands = c.get('commands');
|
|
615
633
|
return await cardService.findRelevantAttachments(commands, c.get('tree'));
|
|
616
634
|
}),
|
|
617
|
-
(c) => {
|
|
635
|
+
async (c) => {
|
|
618
636
|
const commands = c.get('commands');
|
|
619
637
|
const { key, attachment } = c.req.param();
|
|
620
638
|
const filename = decodeURI(attachment);
|
|
@@ -624,7 +642,7 @@ router.get(
|
|
|
624
642
|
}
|
|
625
643
|
|
|
626
644
|
try {
|
|
627
|
-
const attachmentResponse = cardService.getAttachment(
|
|
645
|
+
const attachmentResponse = await cardService.getAttachment(
|
|
628
646
|
commands,
|
|
629
647
|
key,
|
|
630
648
|
filename,
|
package/src/domain/cards/lib.ts
CHANGED
|
@@ -30,122 +30,127 @@ export async function getCardDetails(
|
|
|
30
30
|
staticMode: boolean,
|
|
31
31
|
raw: boolean,
|
|
32
32
|
): Promise<result> {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
return commands.consistent(async () => {
|
|
34
|
+
let cardDetailsResponse: Card;
|
|
35
|
+
try {
|
|
36
|
+
cardDetailsResponse = await commands.showCmd.showCardDetails(key);
|
|
37
|
+
} catch {
|
|
38
|
+
return { status: 400, message: `Card ${key} not found from project` };
|
|
39
|
+
}
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
if (!cardDetailsResponse) {
|
|
42
|
+
return { status: 400, message: `Card ${key} not found from project` };
|
|
43
|
+
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
// always parse for now if not in export mode
|
|
46
|
+
if (!staticMode && !raw) {
|
|
47
|
+
await commands.calculateCmd.generate();
|
|
48
|
+
}
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
let asciidocContent = '';
|
|
51
|
+
try {
|
|
52
|
+
asciidocContent = await evaluateMacros(
|
|
53
|
+
cardDetailsResponse.content || '',
|
|
54
|
+
{
|
|
55
|
+
context: staticMode ? 'exportedSite' : 'localApp',
|
|
56
|
+
mode: staticMode ? 'staticSite' : 'inject',
|
|
57
|
+
project: commands.project,
|
|
58
|
+
cardKey: key,
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
asciidocContent = `Macro error: ${error instanceof Error ? error.message : 'Unknown error'}\n\n${asciidocContent}`;
|
|
63
|
+
}
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
const htmlContent = Processor()
|
|
66
|
+
.convert(asciidocContent, {
|
|
67
|
+
safe: 'safe',
|
|
68
|
+
attributes: {
|
|
69
|
+
imagesdir: `/api/cards/${key}/a`,
|
|
70
|
+
icons: 'font',
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
.toString();
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
if (raw) {
|
|
76
|
+
if (!cardDetailsResponse.metadata) {
|
|
77
|
+
throw new Error('Card has no metadata');
|
|
78
|
+
}
|
|
79
|
+
const cardType = await commands.showCmd.showResource(
|
|
80
|
+
cardDetailsResponse.metadata.cardType,
|
|
81
|
+
'cardTypes',
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const fields = [];
|
|
85
|
+
let i = 0;
|
|
86
|
+
for (const customField of cardType.customFields) {
|
|
87
|
+
const fieldType = await commands.showCmd.showResource(
|
|
88
|
+
customField.name,
|
|
89
|
+
'fieldTypes',
|
|
90
|
+
);
|
|
91
|
+
fields.push({
|
|
92
|
+
key: customField.name,
|
|
93
|
+
visibility: 'always',
|
|
94
|
+
index: i++,
|
|
95
|
+
fieldDisplayName: fieldType.displayName,
|
|
96
|
+
fieldDescription: fieldType.description,
|
|
97
|
+
dataType: fieldType.dataType,
|
|
98
|
+
isCalculated: customField.isCalculated,
|
|
99
|
+
value: cardDetailsResponse.metadata[customField.name],
|
|
100
|
+
enumValues: fieldType.enumValues ?? [],
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
status: 200,
|
|
105
|
+
data: {
|
|
106
|
+
key: cardDetailsResponse.key,
|
|
107
|
+
rank: cardDetailsResponse.metadata?.rank,
|
|
108
|
+
title: cardDetailsResponse.metadata?.title || '',
|
|
109
|
+
cardType: cardDetailsResponse.metadata?.cardType || '',
|
|
110
|
+
cardTypeDisplayName: cardDetailsResponse.metadata.cardType,
|
|
111
|
+
workflowState: '',
|
|
112
|
+
lastUpdated: cardDetailsResponse.metadata.lastUpdated,
|
|
113
|
+
fields,
|
|
114
|
+
labels: cardDetailsResponse.metadata?.labels || [],
|
|
115
|
+
links: [],
|
|
116
|
+
notifications: [],
|
|
117
|
+
policyChecks: {
|
|
118
|
+
successes: [],
|
|
119
|
+
failures: [],
|
|
120
|
+
},
|
|
121
|
+
deniedOperations: {
|
|
122
|
+
transition: [],
|
|
123
|
+
move: [],
|
|
124
|
+
delete: [],
|
|
125
|
+
editField: [],
|
|
126
|
+
editContent: [],
|
|
127
|
+
},
|
|
128
|
+
rawContent: cardDetailsResponse.content || '',
|
|
129
|
+
parsedContent: htmlContent,
|
|
130
|
+
attachments: cardDetailsResponse.attachments,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
74
133
|
}
|
|
75
|
-
const cardType = await commands.showCmd.showResource(
|
|
76
|
-
cardDetailsResponse.metadata.cardType,
|
|
77
|
-
'cardTypes',
|
|
78
|
-
);
|
|
79
134
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
});
|
|
135
|
+
const card = staticMode
|
|
136
|
+
? await getCardQueryResult(commands, key)
|
|
137
|
+
: await commands.calculateCmd.runQuery('card', 'localApp', {
|
|
138
|
+
cardKey: key,
|
|
139
|
+
});
|
|
140
|
+
if (card.length !== 1) {
|
|
141
|
+
throw new Error('Query failed. Check card-query syntax');
|
|
98
142
|
}
|
|
143
|
+
|
|
99
144
|
return {
|
|
100
145
|
status: 200,
|
|
101
146
|
data: {
|
|
102
|
-
|
|
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
|
-
},
|
|
147
|
+
...card[0],
|
|
124
148
|
rawContent: cardDetailsResponse.content || '',
|
|
125
149
|
parsedContent: htmlContent,
|
|
126
150
|
attachments: cardDetailsResponse.attachments,
|
|
127
151
|
},
|
|
128
152
|
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const card = staticMode
|
|
132
|
-
? await getCardQueryResult(commands.project.basePath, key)
|
|
133
|
-
: await commands.calculateCmd.runQuery('card', 'localApp', {
|
|
134
|
-
cardKey: key,
|
|
135
|
-
});
|
|
136
|
-
if (card.length !== 1) {
|
|
137
|
-
throw new Error('Query failed. Check card-query syntax');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return {
|
|
141
|
-
status: 200,
|
|
142
|
-
data: {
|
|
143
|
-
...card[0],
|
|
144
|
-
rawContent: cardDetailsResponse.content || '',
|
|
145
|
-
parsedContent: htmlContent,
|
|
146
|
-
attachments: cardDetailsResponse.attachments,
|
|
147
|
-
},
|
|
148
|
-
};
|
|
153
|
+
});
|
|
149
154
|
}
|
|
150
155
|
/**
|
|
151
156
|
* Returns all cards from a tree query, flattened.
|