@cyberismo/backend 0.0.26 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +1 -1
- package/dist/app.js +75 -3
- package/dist/app.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/mock.d.ts +8 -1
- package/dist/auth/mock.js +50 -2
- package/dist/auth/mock.js.map +1 -1
- package/dist/domain/project/schema.d.ts +3 -0
- package/dist/domain/project/schema.js +9 -1
- package/dist/domain/project/schema.js.map +1 -1
- package/dist/domain/project/service.d.ts +6 -0
- package/dist/domain/project/service.js +14 -1
- package/dist/domain/project/service.js.map +1 -1
- package/dist/domain/projects/index.d.ts +1 -1
- package/dist/domain/projects/index.js +66 -3
- package/dist/domain/projects/index.js.map +1 -1
- package/dist/domain/projects/schema.d.ts +22 -0
- package/dist/domain/projects/schema.js +40 -0
- package/dist/domain/projects/schema.js.map +1 -0
- package/dist/domain/projects/service.d.ts +37 -0
- package/dist/domain/projects/service.js +53 -0
- package/dist/domain/projects/service.js.map +1 -0
- package/dist/domain/resources/index.js +5 -1
- package/dist/domain/resources/index.js.map +1 -1
- package/dist/domain/resources/service.d.ts +9 -0
- package/dist/domain/resources/service.js +12 -0
- package/dist/domain/resources/service.js.map +1 -1
- package/dist/export.js +5 -11
- package/dist/export.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/main.js +1 -5
- package/dist/main.js.map +1 -1
- package/dist/middleware/zvalidator.d.ts +1 -1
- package/dist/project-registry.d.ts +8 -1
- package/dist/project-registry.js +18 -2
- package/dist/project-registry.js.map +1 -1
- package/dist/public/THIRD-PARTY.txt +1421 -1950
- package/dist/public/assets/architecture-7EHR7CIX-CHU1xuYF.js +1 -0
- package/dist/public/assets/architectureDiagram-3BPJPVTR-BfDrO6_w.js +36 -0
- package/dist/public/assets/array-BifhSqXX.js +1 -0
- package/dist/public/assets/blockDiagram-GPEHLZMM-KVU5YZg5.js +132 -0
- package/dist/public/assets/{c4Diagram-AAUBKEIU-BG8_sPEr.js → c4Diagram-AAUBKEIU-CKZoRo4y.js} +6 -6
- package/dist/public/assets/channel-DylEVeTd.js +1 -0
- package/dist/public/assets/chunk-2J33WTMH-3csjo24p.js +1 -0
- package/dist/public/assets/chunk-3OPIFGDE-BKzRNP07.js +62 -0
- package/dist/public/assets/chunk-4BX2VUAB-ClBqZOcE.js +1 -0
- package/dist/public/assets/chunk-55IACEB6-Bgi2dUOh.js +1 -0
- package/dist/public/assets/chunk-5ZQYHXKU-CECM_AkK.js +2 -0
- package/dist/public/assets/{chunk-727SXJPM-C5ihZMyl.js → chunk-727SXJPM-xJrElvZJ.js} +3 -3
- package/dist/public/assets/{chunk-AQP2D5EJ-XGOtp2xP.js → chunk-AQP2D5EJ-DlQQ44Ki.js} +2 -2
- package/dist/public/assets/chunk-BSJP7CBP-ByoKnyMP.js +1 -0
- package/dist/public/assets/chunk-CSCIHK7Q-DPeQmPB5.js +124 -0
- package/dist/public/assets/{chunk-FMBD7UC4-Da1lR6Mn.js → chunk-FMBD7UC4-Cgl-u-NC.js} +1 -1
- package/dist/public/assets/chunk-L5ZTLDWV-pkYUefHU.js +1 -0
- package/dist/public/assets/chunk-ND2GUHAM-BbBhIALU.js +1 -0
- package/dist/public/assets/chunk-NNHCCRGN-DlpIbxXb.js +159 -0
- package/dist/public/assets/chunk-NZK2D7GU-Bsg3s0FQ.js +1 -0
- package/dist/public/assets/chunk-O5CBEL6O-CLKEM0Ng.js +70 -0
- package/dist/public/assets/chunk-QZHKN3VN-DYbrfjC5.js +1 -0
- package/dist/public/assets/classDiagram-4FO5ZUOK-Dw2NhQGr.js +1 -0
- package/dist/public/assets/classDiagram-v2-Q7XG4LA2-Dw2NhQGr.js +1 -0
- package/dist/public/assets/cose-bilkent-S5V4N54A-BW2eHW0s.js +1 -0
- package/dist/public/assets/{cytoscape.esm-C8YCVR3_.js → cytoscape.esm-FqbQrHcz.js} +1 -1
- package/dist/public/assets/dagre-BM42HDAG-BWzuCoWz.js +4 -0
- package/dist/public/assets/diagram-2AECGRRQ-BO4dhTfd.js +43 -0
- package/dist/public/assets/diagram-5GNKFQAL-v25ju5Ui.js +10 -0
- package/dist/public/assets/diagram-KO2AKTUF-C-khQZwA.js +3 -0
- package/dist/public/assets/diagram-LMA3HP47-D7SSAeUZ.js +24 -0
- package/dist/public/assets/diagram-OG6HWLK6-D2CeL9Qd.js +24 -0
- package/dist/public/assets/dist-Dek0Yhn0.js +1 -0
- package/dist/public/assets/erDiagram-TEJ5UH35-CsShdaJw.js +85 -0
- package/dist/public/assets/eventmodeling-FCH6USID-C_5XBe82.js +1 -0
- package/dist/public/assets/flowDiagram-I6XJVG4X-BSiUVjsY.js +162 -0
- package/dist/public/assets/ganttDiagram-6RSMTGT7-BumhHDWI.js +292 -0
- package/dist/public/assets/gitGraph-WXDBUCRP-D4dBNuhe.js +1 -0
- package/dist/public/assets/gitGraphDiagram-PVQCEYII-BPrVPTyG.js +106 -0
- package/dist/public/assets/index-COSSLZqt.css +1 -0
- package/dist/public/assets/index-WMbgvnqh.js +487 -0
- package/dist/public/assets/info-J43DQDTF-D7lvZ6o6.js +1 -0
- package/dist/public/assets/infoDiagram-5YYISTIA-CEASd4Im.js +2 -0
- package/dist/public/assets/{ishikawaDiagram-YF4QCWOH-DWNWYxz5.js → ishikawaDiagram-YF4QCWOH-BMZVbhq1.js} +6 -6
- package/dist/public/assets/{journeyDiagram-JHISSGLW-I58P5XNg.js → journeyDiagram-JHISSGLW-B3iswT_x.js} +6 -6
- package/dist/public/assets/{kanban-definition-UN3LZRKU-CMRWbDti.js → kanban-definition-UN3LZRKU-xX5kT_P-.js} +18 -18
- package/dist/public/assets/katex-Vhh-h91d.js +257 -0
- package/dist/public/assets/line-DNZMOnJ3.js +1 -0
- package/dist/public/assets/mermaid-parser.core-DFZGVidJ.js +4 -0
- package/dist/public/assets/{mindmap-definition-RKZ34NQL-C47gCcpC.js → mindmap-definition-RKZ34NQL-C77038Zx.js} +29 -29
- package/dist/public/assets/packet-YPE3B663-AbbU2Ze4.js +1 -0
- package/dist/public/assets/path-HTXttWil.js +1 -0
- package/dist/public/assets/pie-LRSECV5Y-DN4QBmSF.js +1 -0
- package/dist/public/assets/pieDiagram-4H26LBE5-C1GhVY4H.js +30 -0
- package/dist/public/assets/{quadrantDiagram-W4KKPZXB-BY8JORvE.js → quadrantDiagram-W4KKPZXB-3v--YO6t.js} +6 -6
- package/dist/public/assets/radar-GUYGQ44K-ej308gGR.js +1 -0
- package/dist/public/assets/{requirementDiagram-4Y6WPE33-XhNBeFwj.js → requirementDiagram-4Y6WPE33-Bcj6wwJW.js} +4 -4
- package/dist/public/assets/rough.esm-CSKSodPl.js +1 -0
- package/dist/public/assets/sankeyDiagram-5OEKKPKP-BHDSc0nY.js +40 -0
- package/dist/public/assets/sequenceDiagram-3UESZ5HK-B7Huaheu.js +162 -0
- package/dist/public/assets/src-CqxF9LGw.js +1 -0
- package/dist/public/assets/stateDiagram-AJRCARHV-C1l1yZDH.js +1 -0
- package/dist/public/assets/stateDiagram-v2-BHNVJYJU-DQC9x5mr.js +1 -0
- package/dist/public/assets/{timeline-definition-PNZ67QCA-BZbaBDRH.js → timeline-definition-PNZ67QCA-CwBz01Qw.js} +16 -16
- package/dist/public/assets/treeView-BLDUP644--ooV0k8a.js +1 -0
- package/dist/public/assets/treemap-LRROVOQU-BKq-VDOX.js +1 -0
- package/dist/public/assets/vennDiagram-CIIHVFJN-DpiZAjsM.js +34 -0
- package/dist/public/assets/wardley-L42UT6IY-VU5ormp0.js +1 -0
- package/dist/public/assets/{wardleyDiagram-YWT4CUSO-CM0yrkHd.js → wardleyDiagram-YWT4CUSO-COVxB67h.js} +4 -4
- package/dist/public/assets/{xychartDiagram-2RQKCTM6-1ZAtqvyQ.js → xychartDiagram-2RQKCTM6-C7lnc5PN.js} +6 -6
- package/dist/public/index.html +15 -2
- package/package.json +8 -7
- package/src/app.ts +93 -2
- package/src/auth/index.ts +1 -1
- package/src/auth/mock.ts +53 -2
- package/src/domain/project/schema.ts +9 -1
- package/src/domain/project/service.ts +22 -1
- package/src/domain/projects/index.ts +115 -3
- package/src/domain/projects/schema.ts +42 -0
- package/src/domain/projects/service.ts +98 -0
- package/src/domain/resources/index.ts +6 -1
- package/src/domain/resources/service.ts +15 -0
- package/src/export.ts +6 -15
- package/src/index.ts +16 -4
- package/src/main.ts +1 -7
- package/src/project-registry.ts +22 -2
- package/dist/public/assets/architecture-7EHR7CIX-BhpB9ddF.js +0 -1
- package/dist/public/assets/architectureDiagram-3BPJPVTR-BQYiU_EO.js +0 -36
- package/dist/public/assets/blockDiagram-GPEHLZMM-DuyikC3X.js +0 -132
- package/dist/public/assets/channel-BxgB7fMy.js +0 -1
- package/dist/public/assets/chunk-2J33WTMH-vNq8B1aw.js +0 -1
- package/dist/public/assets/chunk-4BX2VUAB-DFDBsmSo.js +0 -1
- package/dist/public/assets/chunk-55IACEB6-DCVUQPWM.js +0 -1
- package/dist/public/assets/chunk-ND2GUHAM-ZOvpvr6K.js +0 -1
- package/dist/public/assets/chunk-QZHKN3VN-D33jzvFT.js +0 -1
- package/dist/public/assets/classDiagram-4FO5ZUOK-hWfZv7hZ.js +0 -1
- package/dist/public/assets/classDiagram-v2-Q7XG4LA2-hWfZv7hZ.js +0 -1
- package/dist/public/assets/cose-bilkent-S5V4N54A-DO4z-ix4.js +0 -1
- package/dist/public/assets/dagre-BM42HDAG-DlpRfzgA.js +0 -4
- package/dist/public/assets/diagram-2AECGRRQ-D-t_ImBP.js +0 -43
- package/dist/public/assets/diagram-5GNKFQAL-CBgUMlXz.js +0 -10
- package/dist/public/assets/diagram-KO2AKTUF-XoB2TgQt.js +0 -3
- package/dist/public/assets/diagram-LMA3HP47-D1Sbl_eS.js +0 -24
- package/dist/public/assets/diagram-OG6HWLK6-DKP4aiIY.js +0 -24
- package/dist/public/assets/erDiagram-TEJ5UH35-DYxfHOOK.js +0 -85
- package/dist/public/assets/eventmodeling-FCH6USID-cF_1Mq4g.js +0 -1
- package/dist/public/assets/flowDiagram-I6XJVG4X-BDHPsmlq.js +0 -162
- package/dist/public/assets/ganttDiagram-6RSMTGT7-bGgIvBPN.js +0 -292
- package/dist/public/assets/gitGraph-WXDBUCRP-DOFshjLy.js +0 -1
- package/dist/public/assets/gitGraphDiagram-PVQCEYII-xSwLjGd-.js +0 -106
- package/dist/public/assets/index-DGPv1qic.js +0 -1028
- package/dist/public/assets/index-DvHiopvR.css +0 -1
- package/dist/public/assets/info-J43DQDTF-BuJNK7zQ.js +0 -1
- package/dist/public/assets/infoDiagram-5YYISTIA-BanxuIib.js +0 -2
- package/dist/public/assets/katex-C4eR7coU.js +0 -257
- package/dist/public/assets/mermaid-parser.core-Dz__fM3g.js +0 -161
- package/dist/public/assets/packet-YPE3B663-Cczitw2-.js +0 -1
- package/dist/public/assets/pie-LRSECV5Y-rO-Aqx6h.js +0 -1
- package/dist/public/assets/pieDiagram-4H26LBE5-VZAxHzjD.js +0 -30
- package/dist/public/assets/radar-GUYGQ44K-SSIGuQjW.js +0 -1
- package/dist/public/assets/sankeyDiagram-5OEKKPKP-H7I2OESy.js +0 -40
- package/dist/public/assets/sequenceDiagram-3UESZ5HK-jnTLwq-X.js +0 -162
- package/dist/public/assets/stateDiagram-AJRCARHV-BKcf2bdX.js +0 -1
- package/dist/public/assets/stateDiagram-v2-BHNVJYJU-wpO0gnsG.js +0 -1
- package/dist/public/assets/treeView-BLDUP644-DkGx4HkR.js +0 -1
- package/dist/public/assets/treemap-LRROVOQU-yCyuONQh.js +0 -1
- package/dist/public/assets/vennDiagram-CIIHVFJN-nY9Pep3o.js +0 -34
- package/dist/public/assets/wardley-L42UT6IY-CXWWFUgk.js +0 -1
- package/dist/public/config.json +0 -5
|
@@ -12,11 +12,17 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { Hono } from 'hono';
|
|
15
|
+
import { zValidator } from '../../middleware/zvalidator.js';
|
|
15
16
|
import type { ProjectRegistry } from '../../project-registry.js';
|
|
16
|
-
import { requireRole } from '../../middleware/auth.js';
|
|
17
|
+
import { requireRole, getCurrentUser } from '../../middleware/auth.js';
|
|
17
18
|
import { UserRole } from '../../types.js';
|
|
19
|
+
import { createProjectSchema, cloneProjectSchema } from './schema.js';
|
|
20
|
+
import * as projectsService from './service.js';
|
|
18
21
|
|
|
19
|
-
export function createProjectsRouter(
|
|
22
|
+
export function createProjectsRouter(
|
|
23
|
+
registry: ProjectRegistry,
|
|
24
|
+
multiProjectRoot?: string,
|
|
25
|
+
) {
|
|
20
26
|
const router = new Hono();
|
|
21
27
|
|
|
22
28
|
/**
|
|
@@ -32,8 +38,114 @@ export function createProjectsRouter(registry: ProjectRegistry) {
|
|
|
32
38
|
* description: Unauthorized
|
|
33
39
|
*/
|
|
34
40
|
router.get('/', requireRole(UserRole.Reader), (c) => {
|
|
35
|
-
return c.json(
|
|
41
|
+
return c.json({
|
|
42
|
+
projects: registry.list(),
|
|
43
|
+
canCreateProjects: !!multiProjectRoot,
|
|
44
|
+
});
|
|
36
45
|
});
|
|
37
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @swagger
|
|
49
|
+
* /api/projects:
|
|
50
|
+
* post:
|
|
51
|
+
* summary: Create a new project
|
|
52
|
+
* description: Creates a new project on disk, initializes git, adds default hub
|
|
53
|
+
*/
|
|
54
|
+
router.post(
|
|
55
|
+
'/',
|
|
56
|
+
requireRole(UserRole.Editor),
|
|
57
|
+
zValidator('json', createProjectSchema),
|
|
58
|
+
async (c) => {
|
|
59
|
+
if (!multiProjectRoot) {
|
|
60
|
+
return c.json(
|
|
61
|
+
{ error: 'Project creation is not available in single-project mode' },
|
|
62
|
+
403,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const params = c.req.valid('json');
|
|
67
|
+
|
|
68
|
+
if (registry.has(params.prefix)) {
|
|
69
|
+
return c.json(
|
|
70
|
+
{ error: `Project with prefix '${params.prefix}' already exists` },
|
|
71
|
+
409,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const result = await projectsService.createProject(
|
|
77
|
+
registry,
|
|
78
|
+
multiProjectRoot,
|
|
79
|
+
params,
|
|
80
|
+
getCurrentUser(c),
|
|
81
|
+
);
|
|
82
|
+
return c.json(result, 201);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return c.json(
|
|
85
|
+
{
|
|
86
|
+
error:
|
|
87
|
+
error instanceof Error
|
|
88
|
+
? error.message
|
|
89
|
+
: 'Failed to create project',
|
|
90
|
+
},
|
|
91
|
+
500,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @swagger
|
|
99
|
+
* /api/projects/clone:
|
|
100
|
+
* post:
|
|
101
|
+
* summary: Clone a project from a git repository
|
|
102
|
+
* description: Clones a git repo and registers discovered projects
|
|
103
|
+
*/
|
|
104
|
+
router.post(
|
|
105
|
+
'/clone',
|
|
106
|
+
requireRole(UserRole.Editor),
|
|
107
|
+
zValidator('json', cloneProjectSchema),
|
|
108
|
+
async (c) => {
|
|
109
|
+
if (!multiProjectRoot) {
|
|
110
|
+
return c.json(
|
|
111
|
+
{ error: 'Project cloning is not available in single-project mode' },
|
|
112
|
+
403,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const { url } = c.req.valid('json');
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const result = await projectsService.cloneProject(
|
|
120
|
+
registry,
|
|
121
|
+
multiProjectRoot,
|
|
122
|
+
url,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (result.projects.length === 0) {
|
|
126
|
+
return c.json(
|
|
127
|
+
{
|
|
128
|
+
error: 'All projects in the cloned repository already exist',
|
|
129
|
+
skippedDuplicates: result.skippedDuplicates,
|
|
130
|
+
},
|
|
131
|
+
409,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return c.json(result, 201);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
return c.json(
|
|
138
|
+
{
|
|
139
|
+
error:
|
|
140
|
+
error instanceof Error
|
|
141
|
+
? error.message
|
|
142
|
+
: 'Failed to clone repository',
|
|
143
|
+
},
|
|
144
|
+
500,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
38
150
|
return router;
|
|
39
151
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2026
|
|
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
|
+
import { Validate } from '@cyberismo/data-handler';
|
|
16
|
+
|
|
17
|
+
export const createProjectSchema = z.object({
|
|
18
|
+
name: z
|
|
19
|
+
.string()
|
|
20
|
+
.min(1, 'Project name is required')
|
|
21
|
+
.refine((s) => Validate.isValidProjectName(s), {
|
|
22
|
+
message: 'Invalid project name',
|
|
23
|
+
}),
|
|
24
|
+
prefix: z
|
|
25
|
+
.string()
|
|
26
|
+
.min(3, 'Prefix must be at least 3 characters')
|
|
27
|
+
.max(10, 'Prefix must be at most 10 characters')
|
|
28
|
+
.refine((s) => Validate.validatePrefix(s), {
|
|
29
|
+
message: 'Prefix must contain only lowercase letters',
|
|
30
|
+
}),
|
|
31
|
+
category: z.string().optional().default(''),
|
|
32
|
+
description: z.string().optional().default(''),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const cloneProjectSchema = z.object({
|
|
36
|
+
url: z
|
|
37
|
+
.string()
|
|
38
|
+
.min(1, 'Repository URL is required')
|
|
39
|
+
.refine((s) => s.startsWith('https://') || s.startsWith('git@'), {
|
|
40
|
+
message: 'URL must start with https:// or git@',
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2026
|
|
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 { join } from 'node:path';
|
|
15
|
+
import {
|
|
16
|
+
CommandManager,
|
|
17
|
+
Create,
|
|
18
|
+
scanForProjects,
|
|
19
|
+
} from '@cyberismo/data-handler';
|
|
20
|
+
import type { ProjectRegistry } from '../../project-registry.js';
|
|
21
|
+
|
|
22
|
+
export interface CreateProjectParams {
|
|
23
|
+
name: string;
|
|
24
|
+
prefix: string;
|
|
25
|
+
category?: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CreateProjectResult {
|
|
30
|
+
prefix: string;
|
|
31
|
+
name: string;
|
|
32
|
+
category?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function createProject(
|
|
37
|
+
registry: ProjectRegistry,
|
|
38
|
+
rootPath: string,
|
|
39
|
+
params: CreateProjectParams,
|
|
40
|
+
user?: { name: string; email: string } | null,
|
|
41
|
+
): Promise<CreateProjectResult> {
|
|
42
|
+
const { name, prefix, category, description } = params;
|
|
43
|
+
const projectPath = join(rootPath, prefix);
|
|
44
|
+
|
|
45
|
+
const commands = await CommandManager.createProjectWithDefaults(
|
|
46
|
+
projectPath,
|
|
47
|
+
params,
|
|
48
|
+
{
|
|
49
|
+
...registry.options,
|
|
50
|
+
gitUser: user ?? undefined,
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
registry.add(prefix, commands);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
prefix,
|
|
58
|
+
name,
|
|
59
|
+
category: category || undefined,
|
|
60
|
+
description: description || undefined,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface CloneProjectResult {
|
|
65
|
+
projects: { prefix: string; name: string }[];
|
|
66
|
+
skippedDuplicates?: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function cloneProject(
|
|
70
|
+
registry: ProjectRegistry,
|
|
71
|
+
rootPath: string,
|
|
72
|
+
url: string,
|
|
73
|
+
): Promise<CloneProjectResult> {
|
|
74
|
+
const clonedPath = await Create.cloneProject(url, rootPath);
|
|
75
|
+
const scanned = await scanForProjects(clonedPath);
|
|
76
|
+
|
|
77
|
+
const registered: { prefix: string; name: string }[] = [];
|
|
78
|
+
const skippedDuplicates: string[] = [];
|
|
79
|
+
|
|
80
|
+
for (const project of scanned) {
|
|
81
|
+
if (registry.has(project.prefix)) {
|
|
82
|
+
skippedDuplicates.push(project.prefix);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const commands = new CommandManager(project.path, registry.options);
|
|
86
|
+
await commands.initialize();
|
|
87
|
+
registry.add(project.prefix, commands);
|
|
88
|
+
registered.push({
|
|
89
|
+
prefix: project.prefix,
|
|
90
|
+
name: project.name,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
projects: registered,
|
|
96
|
+
...(skippedDuplicates.length > 0 && { skippedDuplicates }),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { Hono } from 'hono';
|
|
15
|
+
import { ssgParams } from 'hono/ssg';
|
|
15
16
|
import * as resourceService from './service.js';
|
|
16
|
-
import type { ResourceValidationResponse } from '../../types.js';
|
|
17
|
+
import type { AppContext, ResourceValidationResponse } from '../../types.js';
|
|
17
18
|
import { UserRole } from '../../types.js';
|
|
18
19
|
import { resourceParamsSchema } from '../../common/validationSchemas.js';
|
|
19
20
|
import { zValidator } from '../../middleware/zvalidator.js';
|
|
@@ -183,6 +184,10 @@ router.delete(
|
|
|
183
184
|
router.get(
|
|
184
185
|
'/:prefix/workflows/:identifier/graph',
|
|
185
186
|
requireRole(UserRole.Reader),
|
|
187
|
+
ssgParams(async (c: AppContext) => {
|
|
188
|
+
const commands = c.get('commands');
|
|
189
|
+
return resourceService.listWorkflowGraphParams(commands);
|
|
190
|
+
}),
|
|
186
191
|
zValidator('param', workflowGraphParamsSchema),
|
|
187
192
|
zValidator('query', workflowGraphQuerySchema),
|
|
188
193
|
async (c) => {
|
|
@@ -469,6 +469,21 @@ export async function validateResource(
|
|
|
469
469
|
};
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Lists the path params for every workflow resource in the project.
|
|
474
|
+
* @param commands Command manager.
|
|
475
|
+
* @returns One `{ prefix, identifier }` entry per workflow resource.
|
|
476
|
+
*/
|
|
477
|
+
export async function listWorkflowGraphParams(
|
|
478
|
+
commands: CommandManager,
|
|
479
|
+
): Promise<{ prefix: string; identifier: string }[]> {
|
|
480
|
+
const workflows = await commands.showCmd.showResources('workflows');
|
|
481
|
+
return workflows.map((name) => {
|
|
482
|
+
const { prefix, identifier } = resourceName(name);
|
|
483
|
+
return { prefix, identifier };
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
472
487
|
/**
|
|
473
488
|
* Renders the built-in state-machine graph for a single workflow.
|
|
474
489
|
* When `cardKey` is provided, the card's current workflowState is
|
package/src/export.ts
CHANGED
|
@@ -11,15 +11,13 @@
|
|
|
11
11
|
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
import fs, { readFile } from 'node:fs/promises';
|
|
14
|
+
import fs from 'node:fs/promises';
|
|
17
15
|
|
|
18
16
|
import type { CommandManager } from '@cyberismo/data-handler';
|
|
19
17
|
import { createApp } from './app.js';
|
|
20
18
|
import { MockAuthProvider } from './auth/mock.js';
|
|
21
19
|
import type { ProjectRegistry } from './project-registry.js';
|
|
22
|
-
import { cp
|
|
20
|
+
import { cp } from 'node:fs/promises';
|
|
23
21
|
import { staticFrontendDirRelative } from './utils.js';
|
|
24
22
|
import type { QueryResult } from '@cyberismo/data-handler/types/queries';
|
|
25
23
|
import { toSSG } from 'hono/ssg';
|
|
@@ -108,21 +106,14 @@ export async function exportSite(
|
|
|
108
106
|
);
|
|
109
107
|
}
|
|
110
108
|
|
|
109
|
+
if (defaultProject) {
|
|
110
|
+
process.env.CYBERISMO_DEFAULT_PROJECT = defaultProject;
|
|
111
|
+
}
|
|
112
|
+
|
|
111
113
|
const app = createApp(new MockAuthProvider(), registry, opts, true);
|
|
112
114
|
|
|
113
115
|
// copy whole frontend to the same directory
|
|
114
116
|
await cp(staticFrontendDirRelative, exportDir, { recursive: true });
|
|
115
|
-
// read config file and change export to true
|
|
116
|
-
const config = await readFile(path.join(exportDir, 'config.json'), 'utf-8');
|
|
117
|
-
const configJson = JSON.parse(config);
|
|
118
|
-
configJson.staticMode = true;
|
|
119
|
-
if (defaultProject) {
|
|
120
|
-
configJson.defaultProject = defaultProject;
|
|
121
|
-
}
|
|
122
|
-
await writeFile(
|
|
123
|
-
path.join(exportDir, 'config.json'),
|
|
124
|
-
JSON.stringify(configJson),
|
|
125
|
-
);
|
|
126
117
|
|
|
127
118
|
reset();
|
|
128
119
|
|
package/src/index.ts
CHANGED
|
@@ -64,13 +64,22 @@ export async function startServer(
|
|
|
64
64
|
authProvider: AuthProvider,
|
|
65
65
|
registry: ProjectRegistry,
|
|
66
66
|
findPort: boolean = true,
|
|
67
|
+
multiProjectRoot?: string,
|
|
67
68
|
) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
const useOsAssigned = process.env.CYBERISMO_E2E_OSPORT === 'true';
|
|
70
|
+
let port = useOsAssigned
|
|
71
|
+
? 0
|
|
72
|
+
: parseInt(process.env.PORT || DEFAULT_PORT.toString(), 10);
|
|
73
|
+
if (findPort && !useOsAssigned) {
|
|
71
74
|
port = await findFreePort(port, DEFAULT_MAX_PORT);
|
|
72
75
|
}
|
|
73
|
-
const app = createApp(
|
|
76
|
+
const app = createApp(
|
|
77
|
+
authProvider,
|
|
78
|
+
registry,
|
|
79
|
+
undefined,
|
|
80
|
+
false,
|
|
81
|
+
multiProjectRoot,
|
|
82
|
+
);
|
|
74
83
|
startApp(app, port);
|
|
75
84
|
}
|
|
76
85
|
|
|
@@ -87,6 +96,9 @@ function startApp<E extends Env, S extends Schema, P extends string>(
|
|
|
87
96
|
(info) => {
|
|
88
97
|
console.log(`Running Cyberismo app on http://localhost:${info.port}`);
|
|
89
98
|
console.log('Press Control+C to stop.');
|
|
99
|
+
// When spawned with stdio: [..., 'ipc'], publish the bound port to the parent.
|
|
100
|
+
// No-op in normal startup (process.send is undefined without an IPC channel).
|
|
101
|
+
process.send?.({ type: 'listening', port: info.port });
|
|
90
102
|
},
|
|
91
103
|
);
|
|
92
104
|
}
|
package/src/main.ts
CHANGED
|
@@ -91,16 +91,10 @@ if (args.export) {
|
|
|
91
91
|
: undefined,
|
|
92
92
|
});
|
|
93
93
|
} else {
|
|
94
|
-
if (projects.length === 0) {
|
|
95
|
-
console.error(
|
|
96
|
-
`No projects found in "${projectPath}". Cannot start the server without at least one project.`,
|
|
97
|
-
);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
94
|
const autocommit = process.env.CYBERISMO_AUTOCOMMIT === 'true';
|
|
101
95
|
const registry = await ProjectRegistry.fromScannedProjects(projects, {
|
|
102
96
|
autocommit,
|
|
103
97
|
});
|
|
104
98
|
const authProvider = createAuthProvider();
|
|
105
|
-
await startServer(authProvider, registry);
|
|
99
|
+
await startServer(authProvider, registry, true, projectPath);
|
|
106
100
|
}
|
package/src/project-registry.ts
CHANGED
|
@@ -34,8 +34,13 @@ export interface ScannedProject {
|
|
|
34
34
|
|
|
35
35
|
export class ProjectRegistry implements ProjectProvider {
|
|
36
36
|
private projects: Map<string, CommandManager> = new Map();
|
|
37
|
+
readonly options: ConstructorParameters<typeof CommandManager>[1];
|
|
37
38
|
|
|
38
|
-
constructor(
|
|
39
|
+
constructor(
|
|
40
|
+
entries: ProjectRegistryEntry[] = [],
|
|
41
|
+
options?: ConstructorParameters<typeof CommandManager>[1],
|
|
42
|
+
) {
|
|
43
|
+
this.options = options;
|
|
39
44
|
for (const entry of entries) {
|
|
40
45
|
this.add(entry.prefix, entry.commands);
|
|
41
46
|
}
|
|
@@ -82,6 +87,21 @@ export class ProjectRegistry implements ProjectProvider {
|
|
|
82
87
|
this.projects.clear();
|
|
83
88
|
}
|
|
84
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Replace all registered projects atomically. Disposes existing
|
|
92
|
+
* CommandManagers, then installs the new entries. Used by the test-mode
|
|
93
|
+
* reset endpoint to swap project state without restarting the Hono app.
|
|
94
|
+
*/
|
|
95
|
+
async replace(entries: ProjectRegistryEntry[]): Promise<void> {
|
|
96
|
+
for (const commands of this.projects.values()) {
|
|
97
|
+
commands.project.dispose();
|
|
98
|
+
}
|
|
99
|
+
this.projects.clear();
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
this.projects.set(entry.prefix, entry.commands);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
85
105
|
/**
|
|
86
106
|
* Create a single-project registry from a CommandManager.
|
|
87
107
|
* Used by export mode and tests where only one project is needed.
|
|
@@ -105,6 +125,6 @@ export class ProjectRegistry implements ProjectProvider {
|
|
|
105
125
|
await commands.initialize();
|
|
106
126
|
entries.push({ prefix: project.prefix, commands });
|
|
107
127
|
}
|
|
108
|
-
return new ProjectRegistry(entries);
|
|
128
|
+
return new ProjectRegistry(entries, options);
|
|
109
129
|
}
|
|
110
130
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{x as e}from"./mermaid-parser.core-Dz__fM3g.js";export{e as createArchitectureServices};
|