@inharness-ai/claude4spec 1.0.18 → 1.0.19
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/.claude/skills/c4s-brief-implementer/SKILL.md +11 -0
- package/.claude/skills/c4s-spec-reader/SKILL.md +14 -0
- package/CHANGELOG.md +12 -0
- package/dist/bin/c4s/commands/tagged-list-mixed.js +2 -0
- package/dist/bin/c4s/commands/tagged-list-mixed.js.map +1 -1
- package/dist/client/assets/{arc-BoIjQ4Rl.js → arc-Y_Y7YYxJ.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-BxBVRaEg.js → architectureDiagram-3BPJPVTR-BvfJSQGS.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-CUZNbllz.js → blockDiagram-GPEHLZMM-0ER_5Ga5.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CvuTKwEz.js → c4Diagram-AAUBKEIU-CulSeIur.js} +1 -1
- package/dist/client/assets/channel-COuoa9K9.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CEO4c2pf.js → chunk-2J33WTMH-BR0UTxIH.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-Bu8DCHu0.js → chunk-4BX2VUAB-C3CE1iTm.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DIN8FXXB.js → chunk-55IACEB6-WYG0SMCq.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DArSpufF.js → chunk-727SXJPM-CFxvH3KU.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DvyQ3boK.js → chunk-AQP2D5EJ-CW3tCRq5.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DzYhHpnC.js → chunk-FMBD7UC4-DhWed3oG.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-DocECmh1.js → chunk-ND2GUHAM-wKw1Twd3.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-cUsgOLYm.js → chunk-QZHKN3VN-N2YJn9Rv.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BESpN0be.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BESpN0be.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BXlU_dXh.js → cose-bilkent-S5V4N54A-BwTia-tr.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-CmrHrBPK.js → dagre-BM42HDAG-qaDS43Ui.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-CV4Tc8wQ.js → diagram-2AECGRRQ-D_kuEzAN.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-BiBsPCGc.js → diagram-5GNKFQAL-BYj6JmFh.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DA09S_op.js → diagram-KO2AKTUF-C5GerpKU.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DBaod99I.js → diagram-LMA3HP47-BCCWR_VJ.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-ClJXH4o0.js → diagram-OG6HWLK6-zQ3cOHd6.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-9ic-AAly.js → erDiagram-TEJ5UH35-CXGKcFZT.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-8UWNEpWY.js → flowDiagram-I6XJVG4X-CtZxh2DT.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-ZMUkzsKr.js → ganttDiagram-6RSMTGT7-BUdwVJfD.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-5MgsfBQ-.js → gitGraphDiagram-PVQCEYII-DAJUpS0c.js} +1 -1
- package/dist/client/assets/{index-B3XLrPs9.js → index-CSz40CWW.js} +1 -1
- package/dist/client/assets/{index-D7DH-SO5.js → index-g9hdRfKL.js} +1 -1
- package/dist/client/assets/{index-BSPNo0Xa.js → index-nd9N-ch1.js} +176 -179
- package/dist/client/assets/{infoDiagram-5YYISTIA-DnoyGZzF.js → infoDiagram-5YYISTIA-Dkqaeq-d.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DXzuF94t.js → ishikawaDiagram-YF4QCWOH-BDZbcL20.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-AEPglDXi.js → journeyDiagram-JHISSGLW-DQ8LraKA.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-D0-kFv2f.js → kanban-definition-UN3LZRKU-CQOW2Mao.js} +1 -1
- package/dist/client/assets/{linear-CZwFXsxu.js → linear-B-ZW0b9t.js} +1 -1
- package/dist/client/assets/{mermaid.core-BikmxM36.js → mermaid.core-BdFxxBuE.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-C95lTdDB.js → mindmap-definition-RKZ34NQL-CcsZCub_.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-CMeXZFX8.js → pieDiagram-4H26LBE5-DpFgB1Qa.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D1dG1F2s.js → quadrantDiagram-W4KKPZXB-CItGhZSD.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-RPNqJRNK.js → requirementDiagram-4Y6WPE33-CMfRtv6V.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DQ4EB8Xb.js → sankeyDiagram-5OEKKPKP-LUqs9QQq.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Dn-VJOlP.js → sequenceDiagram-3UESZ5HK-BZt_Nz-I.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CCpprZJO.js → stateDiagram-AJRCARHV-DDCaA4Lh.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DfEoRDHz.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-h0cUr7kp.js → timeline-definition-PNZ67QCA-Chrt6eh8.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BTZzKsPH.js → vennDiagram-CIIHVFJN-7L-WzZJY.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-D1eOaFAH.js → wardley-L42UT6IY-CTNWz-UZ.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-wsnKkjjR.js → wardleyDiagram-YWT4CUSO-BIhHmbRz.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-BCebuOGO.js → xychartDiagram-2RQKCTM6-eqxCYjS7.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/server/db/migrations/040_diagram.sql +17 -0
- package/dist/server/domain/raw-entity-reader.d.ts +1 -1
- package/dist/server/domain/raw-entity-reader.js +5 -1
- package/dist/server/domain/raw-entity-reader.js.map +1 -1
- package/dist/server/entities/diagram/mcp-server.d.ts +10 -0
- package/dist/server/entities/diagram/mcp-server.js +141 -0
- package/dist/server/entities/diagram/mcp-server.js.map +1 -0
- package/dist/server/entities/diagram/plugin.d.ts +3 -0
- package/dist/server/entities/diagram/plugin.js +41 -0
- package/dist/server/entities/diagram/plugin.js.map +1 -0
- package/dist/server/entities/diagram/routes.d.ts +5 -0
- package/dist/server/entities/diagram/routes.js +83 -0
- package/dist/server/entities/diagram/routes.js.map +1 -0
- package/dist/server/entities/diagram/serializer.d.ts +11 -0
- package/dist/server/entities/diagram/serializer.js +147 -0
- package/dist/server/entities/diagram/serializer.js.map +1 -0
- package/dist/server/entities/diagram/services.d.ts +40 -0
- package/dist/server/entities/diagram/services.js +202 -0
- package/dist/server/entities/diagram/services.js.map +1 -0
- package/dist/server/entities/diagram/system-prompt.d.ts +2 -0
- package/dist/server/entities/diagram/system-prompt.js +15 -0
- package/dist/server/entities/diagram/system-prompt.js.map +1 -0
- package/dist/server/entities/diagram/validate.d.ts +9 -0
- package/dist/server/entities/diagram/validate.js +35 -0
- package/dist/server/entities/diagram/validate.js.map +1 -0
- package/dist/server/external-skills/brief-implementer-template.d.ts +1 -1
- package/dist/server/external-skills/brief-implementer-template.js +11 -0
- package/dist/server/external-skills/brief-implementer-template.js.map +1 -1
- package/dist/server/external-skills/spec-reader-template.d.ts +1 -1
- package/dist/server/external-skills/spec-reader-template.js +14 -0
- package/dist/server/external-skills/spec-reader-template.js.map +1 -1
- package/dist/server/mcp/c4s-reader.js +2 -0
- package/dist/server/mcp/c4s-reader.js.map +1 -1
- package/dist/server/serialization/registerAll.js +2 -0
- package/dist/server/serialization/registerAll.js.map +1 -1
- package/dist/server/serialization/writer.d.ts +2 -1
- package/dist/server/services/chat-context.js +5 -15
- package/dist/server/services/chat-context.js.map +1 -1
- package/dist/server/services/entity-indexer.js +4 -0
- package/dist/server/services/entity-indexer.js.map +1 -1
- package/dist/server/services/entity-store.js +9 -1
- package/dist/server/services/entity-store.js.map +1 -1
- package/dist/server/services/entity-writer.d.ts +2 -0
- package/dist/server/services/entity-writer.js +12 -0
- package/dist/server/services/entity-writer.js.map +1 -1
- package/dist/server/services/references.js +10 -0
- package/dist/server/services/references.js.map +1 -1
- package/dist/server/workspace/project-context.js +9 -0
- package/dist/server/workspace/project-context.js.map +1 -1
- package/dist/shared/entities.d.ts +43 -1
- package/dist/shared/entities.js.map +1 -1
- package/dist/shared/xml-tags.d.ts +3 -3
- package/dist/shared/xml-tags.js +10 -4
- package/dist/shared/xml-tags.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/channel-Ba45UACg.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DigWu50-.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DigWu50-.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DZMO7v7d.js +0 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createMcpServer, mcpTool } from '@inharness-ai/agent-adapters';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { validateDiagramSource } from './validate.js';
|
|
4
|
+
import { DomainError } from '../../services/tags.js';
|
|
5
|
+
const formatSchema = z.enum(['mermaid', 'd2']);
|
|
6
|
+
export function createDiagramToolsServer(deps) {
|
|
7
|
+
const ok = (payload) => ({
|
|
8
|
+
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
9
|
+
});
|
|
10
|
+
const fail = (err) => {
|
|
11
|
+
const code = err instanceof DomainError ? err.code : 'INTERNAL';
|
|
12
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: 'text', text: JSON.stringify({ error: message, code }) }],
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
const createDiagram = mcpTool('create_diagram', 'Create a new diagram entity. The DSL `source` is the source of truth (rendered live on pages). ' +
|
|
19
|
+
'A page references the diagram via a self-closing `<diagram slug="…" caption="…"/>` tag — `caption` is a ' +
|
|
20
|
+
'per-reference attribute, NOT stored here. Slug: explicit `slug` | slugify(`caption`) | diagram-<nanoid>. ' +
|
|
21
|
+
'`source` is validated with mermaid.parse() → warnings only, never blocks.', {
|
|
22
|
+
source: z.string().optional().describe('DSL body (mermaid). May be empty (placeholder).'),
|
|
23
|
+
format: formatSchema.optional().describe("Diagram language (default 'mermaid')."),
|
|
24
|
+
caption: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Transient — seeds the slug only (slugify(caption)); NOT persisted on the entity.'),
|
|
28
|
+
slug: z.string().optional().describe('Explicit slug; collisions get a -2/-3 suffix.'),
|
|
29
|
+
tags: z.array(z.string()).optional().describe('Tag slugs; non-existent tags are auto-created.'),
|
|
30
|
+
}, async (args) => {
|
|
31
|
+
try {
|
|
32
|
+
const input = {
|
|
33
|
+
source: args.source,
|
|
34
|
+
format: args.format,
|
|
35
|
+
caption: args.caption,
|
|
36
|
+
slug: args.slug,
|
|
37
|
+
tags: args.tags,
|
|
38
|
+
};
|
|
39
|
+
const diagram = deps.diagramService.create(input, 'agent');
|
|
40
|
+
const warnings = await validateDiagramSource(diagram.format, diagram.source);
|
|
41
|
+
deps.ws.broadcast({ kind: 'entity:changed', entityType: 'diagram', slug: diagram.slug });
|
|
42
|
+
return ok({
|
|
43
|
+
id: diagram.slug,
|
|
44
|
+
slug: diagram.slug,
|
|
45
|
+
type: 'diagram',
|
|
46
|
+
...(warnings.length ? { warnings } : {}),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return fail(err);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const getDiagram = mcpTool('get_diagram', 'Get a diagram by slug (format, source, tags).', { slug: z.string() }, async (args) => {
|
|
54
|
+
const diagram = deps.diagramService.getBySlug(String(args.slug));
|
|
55
|
+
if (!diagram)
|
|
56
|
+
return fail(new DomainError('NOT_FOUND', `diagram '${args.slug}' not found`));
|
|
57
|
+
return ok(diagram);
|
|
58
|
+
});
|
|
59
|
+
const updateDiagram = mcpTool('update_diagram', 'Update a diagram (partial). Slug is stable; rename only via newSlug (auto-propagates page references). ' +
|
|
60
|
+
'`source` is validated with mermaid.parse() → warnings only, never blocks.', {
|
|
61
|
+
slug: z.string(),
|
|
62
|
+
data: z
|
|
63
|
+
.object({
|
|
64
|
+
source: z.string().optional(),
|
|
65
|
+
format: formatSchema.optional(),
|
|
66
|
+
})
|
|
67
|
+
.describe('Partial fields to update.'),
|
|
68
|
+
newSlug: z.string().optional().describe('Explicit slug rename.'),
|
|
69
|
+
}, async (args) => {
|
|
70
|
+
try {
|
|
71
|
+
const data = args.data;
|
|
72
|
+
const input = {
|
|
73
|
+
source: data.source,
|
|
74
|
+
format: data.format,
|
|
75
|
+
newSlug: args.newSlug,
|
|
76
|
+
};
|
|
77
|
+
const { diagram, previousSlug } = deps.diagramService.update(String(args.slug), input, 'agent');
|
|
78
|
+
if (diagram.slug !== previousSlug) {
|
|
79
|
+
await deps.referencesService.propagateSlugChange('diagram', previousSlug, diagram.slug);
|
|
80
|
+
}
|
|
81
|
+
const warnings = await validateDiagramSource(diagram.format, diagram.source);
|
|
82
|
+
deps.ws.broadcast({ kind: 'entity:changed', entityType: 'diagram', slug: diagram.slug });
|
|
83
|
+
return ok({ slug: diagram.slug, updated: true, ...(warnings.length ? { warnings } : {}) });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
return fail(err);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const deleteDiagram = mcpTool('delete_diagram', 'Delete a diagram. Returns pages with now-broken `<diagram/>` references.', { slug: z.string() }, async (args) => {
|
|
90
|
+
try {
|
|
91
|
+
const slug = String(args.slug);
|
|
92
|
+
const refs = await deps.referencesService.findReferences('diagram', slug);
|
|
93
|
+
deps.diagramService.remove(slug, 'agent', refs.map((r) => ({
|
|
94
|
+
pagePath: r.pagePath,
|
|
95
|
+
tagType: r.tagType,
|
|
96
|
+
line: r.line,
|
|
97
|
+
slug,
|
|
98
|
+
type: 'diagram',
|
|
99
|
+
})));
|
|
100
|
+
deps.ws.broadcast({ kind: 'entity:changed', entityType: 'diagram', slug });
|
|
101
|
+
return ok({
|
|
102
|
+
deleted: true,
|
|
103
|
+
brokenReferences: refs.map((r) => ({ pagePath: r.pagePath, count: 1 })),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
return fail(err);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
const listDiagrams = mcpTool('list_diagrams', 'List diagrams with optional tag/search filtering. Returns slug, format, tags and a total.', {
|
|
111
|
+
tags: z.array(z.string()).optional(),
|
|
112
|
+
tagFilter: z.enum(['and', 'or']).optional(),
|
|
113
|
+
search: z.string().optional(),
|
|
114
|
+
limit: z.number().optional(),
|
|
115
|
+
offset: z.number().optional(),
|
|
116
|
+
}, async (args) => {
|
|
117
|
+
try {
|
|
118
|
+
const query = {
|
|
119
|
+
tags: args.tags,
|
|
120
|
+
tagFilter: args.tagFilter,
|
|
121
|
+
search: args.search,
|
|
122
|
+
limit: args.limit,
|
|
123
|
+
offset: args.offset,
|
|
124
|
+
};
|
|
125
|
+
const diagrams = deps.diagramService.list(query);
|
|
126
|
+
const total = deps.diagramService.count(query);
|
|
127
|
+
return ok({
|
|
128
|
+
diagrams: diagrams.map((d) => ({ slug: d.slug, format: d.format, tags: d.tags })),
|
|
129
|
+
total,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
return fail(err);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return createMcpServer({
|
|
137
|
+
name: 'diagram-tools',
|
|
138
|
+
tools: [createDiagram, getDiagram, updateDiagram, deleteDiagram, listDiagrams],
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../../../src/server/entities/diagram/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
import { slugify } from '../../services/slug.js';
|
|
3
|
+
import { diagramSerializer } from './serializer.js';
|
|
4
|
+
import { diagramSystemPrompt } from './system-prompt.js';
|
|
5
|
+
import { diagramsRouter } from './routes.js';
|
|
6
|
+
import { DiagramService } from './services.js';
|
|
7
|
+
import { createDiagramToolsServer } from './mcp-server.js';
|
|
8
|
+
export const diagramBackendModule = {
|
|
9
|
+
type: 'diagram',
|
|
10
|
+
table: 'diagram',
|
|
11
|
+
label: 'Diagram',
|
|
12
|
+
labelPlural: 'Diagrams',
|
|
13
|
+
// After design-system (60) — diagrams sit at the end of ELEMENTS.
|
|
14
|
+
displayOrder: 70,
|
|
15
|
+
pathPrefix: '/diagrams',
|
|
16
|
+
// Decyzja #1: explicit slug | slugify(caption) | diagram-<nanoid(8)>.
|
|
17
|
+
// The service does the authoritative generation (with collision suffixing);
|
|
18
|
+
// this manifest helper mirrors the fallback for generic callers.
|
|
19
|
+
slugFrom: (data) => {
|
|
20
|
+
const d = (data ?? {});
|
|
21
|
+
return d.slug?.trim() || (d.caption ? slugify(d.caption) : `diagram-${nanoid(8)}`);
|
|
22
|
+
},
|
|
23
|
+
serializer: diagramSerializer,
|
|
24
|
+
systemPrompt: diagramSystemPrompt,
|
|
25
|
+
backend: {
|
|
26
|
+
mount(ctx) {
|
|
27
|
+
const service = new DiagramService(ctx.db, ctx.tagsService, ctx.versionService, ctx.entityStore);
|
|
28
|
+
ctx.app.use(`${diagramBackendModule.pathPrefix}`, diagramsRouter(service, ctx.referencesService, ctx.ws));
|
|
29
|
+
ctx.registerMcpServer(`${diagramBackendModule.type}-tools`, () => createDiagramToolsServer({
|
|
30
|
+
diagramService: service,
|
|
31
|
+
referencesService: ctx.referencesService,
|
|
32
|
+
ws: ctx.ws,
|
|
33
|
+
}));
|
|
34
|
+
ctx.registerEntityService(diagramBackendModule.type, service);
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export function onRegister(registry) {
|
|
39
|
+
registry.registerEntityModule(diagramBackendModule);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../../src/server/entities/diagram/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,CAAC,MAAM,oBAAoB,GAAkB;IACjD,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,UAAU;IACvB,kEAAkE;IAClE,YAAY,EAAE,EAAE;IAChB,UAAU,EAAE,WAAW;IACvB,sEAAsE;IACtE,4EAA4E;IAC5E,iEAAiE;IACjE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAwC,CAAC;QAC9D,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,UAAU,EAAE,iBAA8C;IAC1D,YAAY,EAAE,mBAAmB;IACjC,OAAO,EAAE;QACP,KAAK,CAAC,GAAG;YACP,MAAM,OAAO,GAAG,IAAI,cAAc,CAChC,GAAG,CAAC,EAAE,EACN,GAAG,CAAC,WAAW,EACf,GAAG,CAAC,cAAc,EAClB,GAAG,CAAC,WAAW,CAChB,CAAC;YACF,GAAG,CAAC,GAAG,CAAC,GAAG,CACT,GAAG,oBAAoB,CAAC,UAAU,EAAE,EACpC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,iBAAiB,EAAE,GAAG,CAAC,EAAE,CAAC,CACvD,CAAC;YACF,GAAG,CAAC,iBAAiB,CACnB,GAAG,oBAAoB,CAAC,IAAI,QAAQ,EACpC,GAAG,EAAE,CACH,wBAAwB,CAAC;gBACvB,cAAc,EAAE,OAAO;gBACvB,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;gBACxC,EAAE,EAAE,GAAG,CAAC,EAAE;aACX,CAAC,CACL,CAAC;YACF,GAAG,CAAC,qBAAqB,CAAC,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;KACF;CACF,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,QAAwB;IACjD,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import type { DiagramService } from './services.js';
|
|
3
|
+
import type { ReferencesService } from '../../services/references.js';
|
|
4
|
+
import type { WsEmitter } from '../../ws/project-emitter.js';
|
|
5
|
+
export declare function diagramsRouter(service: DiagramService, references: ReferencesService, ws: WsEmitter): Router;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { validateDiagramSource } from './validate.js';
|
|
3
|
+
import { errorHandler } from '../../routes/errors.js';
|
|
4
|
+
export function diagramsRouter(service, references, ws) {
|
|
5
|
+
const router = Router();
|
|
6
|
+
router.get('/', (req, res, next) => {
|
|
7
|
+
try {
|
|
8
|
+
const q = req.query;
|
|
9
|
+
const tags = typeof q.tags === 'string' ? q.tags.split(',').filter(Boolean) : undefined;
|
|
10
|
+
const filter = q.tagFilter === 'and' || q.tagFilter === 'or' ? q.tagFilter : undefined;
|
|
11
|
+
const query = {
|
|
12
|
+
tags,
|
|
13
|
+
tagFilter: filter,
|
|
14
|
+
search: typeof q.search === 'string' ? q.search : undefined,
|
|
15
|
+
limit: q.limit ? Number(q.limit) : undefined,
|
|
16
|
+
offset: q.offset ? Number(q.offset) : undefined,
|
|
17
|
+
};
|
|
18
|
+
res.json({ diagrams: service.list(query) });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
next(err);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
router.post('/', async (req, res, next) => {
|
|
25
|
+
try {
|
|
26
|
+
const body = req.body;
|
|
27
|
+
const diagram = service.create(body, 'user');
|
|
28
|
+
const warnings = await validateDiagramSource(diagram.format, diagram.source);
|
|
29
|
+
ws.broadcast({ kind: 'entity:changed', entityType: 'diagram', slug: diagram.slug });
|
|
30
|
+
res.status(201).json({ ...diagram, warnings });
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
next(err);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
router.get('/:slug', (req, res, next) => {
|
|
37
|
+
try {
|
|
38
|
+
const diagram = service.getBySlug(req.params.slug);
|
|
39
|
+
if (!diagram)
|
|
40
|
+
return res.status(404).json({ error: { code: 'NOT_FOUND', message: 'diagram not found' } });
|
|
41
|
+
res.json(diagram);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
next(err);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
router.patch('/:slug', async (req, res, next) => {
|
|
48
|
+
try {
|
|
49
|
+
const body = req.body;
|
|
50
|
+
const { diagram, previousSlug } = service.update(req.params.slug, body, 'user');
|
|
51
|
+
if (diagram.slug !== previousSlug) {
|
|
52
|
+
await references.propagateSlugChange('diagram', previousSlug, diagram.slug);
|
|
53
|
+
}
|
|
54
|
+
const warnings = await validateDiagramSource(diagram.format, diagram.source);
|
|
55
|
+
ws.broadcast({ kind: 'entity:changed', entityType: 'diagram', slug: diagram.slug });
|
|
56
|
+
res.json({ ...diagram, warnings });
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
next(err);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
router.delete('/:slug', async (req, res, next) => {
|
|
63
|
+
try {
|
|
64
|
+
const slug = req.params.slug;
|
|
65
|
+
const broken = await references.findReferences('diagram', slug);
|
|
66
|
+
const result = service.remove(slug, 'user', broken.map((b) => ({
|
|
67
|
+
pagePath: b.pagePath,
|
|
68
|
+
tagType: b.tagType,
|
|
69
|
+
line: b.line,
|
|
70
|
+
slug,
|
|
71
|
+
type: 'diagram',
|
|
72
|
+
})));
|
|
73
|
+
ws.broadcast({ kind: 'entity:changed', entityType: 'diagram', slug });
|
|
74
|
+
res.json(result);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
next(err);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
router.use(errorHandler);
|
|
81
|
+
return router;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../../src/server/entities/diagram/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RawEntity } from '../../domain/raw-entity-reader.js';
|
|
2
|
+
import type { EntitySerializer } from '../../serialization/types.js';
|
|
3
|
+
import type { DiagramFormat } from '../../../shared/entities.js';
|
|
4
|
+
export interface DiagramSnapshot {
|
|
5
|
+
slug: string;
|
|
6
|
+
format: DiagramFormat;
|
|
7
|
+
/** Literal DSL body, kept verbatim (no trim). May be empty. */
|
|
8
|
+
source: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare const diagramSerializer: EntitySerializer<RawEntity>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
function readFormat(value) {
|
|
2
|
+
return value === 'd2' ? 'd2' : 'mermaid';
|
|
3
|
+
}
|
|
4
|
+
function readSource(value) {
|
|
5
|
+
// `source` is stored verbatim; coerce defensively (a JSON-shaped source could
|
|
6
|
+
// be hydrated into a non-string by the generic reader — mermaid DSL never is).
|
|
7
|
+
return typeof value === 'string' ? value : '';
|
|
8
|
+
}
|
|
9
|
+
// ─── view helpers ────────────────────────────────────────────────────────────
|
|
10
|
+
function baseSingle(entity) {
|
|
11
|
+
return {
|
|
12
|
+
type: 'diagram',
|
|
13
|
+
slug: entity.slug,
|
|
14
|
+
format: readFormat(entity.data.format),
|
|
15
|
+
source: readSource(entity.data.source),
|
|
16
|
+
tags: entity.tags,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function trimItem(entity) {
|
|
20
|
+
const source = readSource(entity.data.source);
|
|
21
|
+
return {
|
|
22
|
+
type: 'diagram',
|
|
23
|
+
slug: entity.slug,
|
|
24
|
+
format: readFormat(entity.data.format),
|
|
25
|
+
sourceLines: source ? source.split('\n').length : 0,
|
|
26
|
+
tags: entity.tags,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// ─── snapshot / restore / diff ──────────────────────────────────────────────
|
|
30
|
+
function buildSnapshot(entity) {
|
|
31
|
+
return {
|
|
32
|
+
slug: entity.slug,
|
|
33
|
+
format: readFormat(entity.data.format),
|
|
34
|
+
source: readSource(entity.data.source),
|
|
35
|
+
tags: [...entity.tags].sort(),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function coerce(raw) {
|
|
39
|
+
const r = (raw ?? {});
|
|
40
|
+
return {
|
|
41
|
+
slug: String(r.slug ?? ''),
|
|
42
|
+
format: readFormat(r.format),
|
|
43
|
+
source: readSource(r.source),
|
|
44
|
+
tags: Array.isArray(r.tags) ? r.tags : [],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function diagramRestore(data, ctx) {
|
|
48
|
+
const snap = coerce(data);
|
|
49
|
+
const result = ctx.writer.upsertDiagram(snap.slug, { slug: snap.slug, format: snap.format, source: snap.source }, ctx.actor);
|
|
50
|
+
ctx.writer.syncTags('diagram', snap.slug, snap.tags);
|
|
51
|
+
return {
|
|
52
|
+
op: result.op,
|
|
53
|
+
entity: result.entity,
|
|
54
|
+
...(result.warnings && result.warnings.length ? { warnings: result.warnings } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function diagramDiff(a, b, slug) {
|
|
58
|
+
if (a == null && b == null)
|
|
59
|
+
return { type: 'diagram', slug, op: 'noop' };
|
|
60
|
+
if (a == null)
|
|
61
|
+
return { type: 'diagram', slug, op: 'created' };
|
|
62
|
+
if (b == null)
|
|
63
|
+
return { type: 'diagram', slug, op: 'deleted' };
|
|
64
|
+
const sa = coerce(a);
|
|
65
|
+
const sb = coerce(b);
|
|
66
|
+
const changes = {};
|
|
67
|
+
if (sa.format !== sb.format)
|
|
68
|
+
changes.format_changed = { from: sa.format, to: sb.format };
|
|
69
|
+
if (sa.source !== sb.source)
|
|
70
|
+
changes.source_changed = true;
|
|
71
|
+
const tagAdded = sb.tags.filter((t) => !sa.tags.includes(t));
|
|
72
|
+
const tagRemoved = sa.tags.filter((t) => !sb.tags.includes(t));
|
|
73
|
+
if (tagAdded.length)
|
|
74
|
+
changes.tag_added = tagAdded;
|
|
75
|
+
if (tagRemoved.length)
|
|
76
|
+
changes.tag_removed = tagRemoved;
|
|
77
|
+
if (Object.keys(changes).length === 0)
|
|
78
|
+
return { type: 'diagram', slug, op: 'noop' };
|
|
79
|
+
return { type: 'diagram', slug, op: 'modified', changes };
|
|
80
|
+
}
|
|
81
|
+
// ─── schemas ─────────────────────────────────────────────────────────────────
|
|
82
|
+
const SINGLE_ELEMENT_SCHEMA = {
|
|
83
|
+
type: 'object',
|
|
84
|
+
required: ['type', 'slug', 'format', 'source', 'tags'],
|
|
85
|
+
properties: {
|
|
86
|
+
type: { const: 'diagram' },
|
|
87
|
+
slug: { type: 'string' },
|
|
88
|
+
format: { type: 'string' },
|
|
89
|
+
source: { type: 'string' },
|
|
90
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const LIST_ITEM_SCHEMA = {
|
|
94
|
+
type: 'object',
|
|
95
|
+
required: ['type', 'slug', 'format', 'sourceLines', 'tags'],
|
|
96
|
+
properties: {
|
|
97
|
+
type: { const: 'diagram' },
|
|
98
|
+
slug: { type: 'string' },
|
|
99
|
+
format: { type: 'string' },
|
|
100
|
+
sourceLines: { type: 'number' },
|
|
101
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
const INLINE_MENTION_SCHEMA = {
|
|
105
|
+
type: 'object',
|
|
106
|
+
required: ['type', 'slug', 'label', 'href'],
|
|
107
|
+
properties: {
|
|
108
|
+
type: { const: 'diagram' },
|
|
109
|
+
slug: { type: 'string' },
|
|
110
|
+
label: { type: 'string' },
|
|
111
|
+
href: { type: 'string' },
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
export const diagramSerializer = {
|
|
115
|
+
type: 'diagram',
|
|
116
|
+
version: '1.0.0',
|
|
117
|
+
inlineMention: (entity) => ({
|
|
118
|
+
type: 'diagram',
|
|
119
|
+
slug: entity.slug,
|
|
120
|
+
label: entity.slug,
|
|
121
|
+
href: `/diagrams/${entity.slug}`,
|
|
122
|
+
}),
|
|
123
|
+
singleElement: (entity) => baseSingle(entity),
|
|
124
|
+
elementListItem: (entity) => trimItem(entity),
|
|
125
|
+
taggedListItem: (entity) => trimItem(entity),
|
|
126
|
+
detail: (entity, ctx) => {
|
|
127
|
+
const base = baseSingle(entity);
|
|
128
|
+
const references = ctx.reader.findSectionReferences('diagram', entity.slug).map((r) => ({
|
|
129
|
+
anchor: r.anchor,
|
|
130
|
+
pagePath: r.pagePath,
|
|
131
|
+
headingText: r.headingText,
|
|
132
|
+
relation: r.relation,
|
|
133
|
+
}));
|
|
134
|
+
return { ...base, _references: references };
|
|
135
|
+
},
|
|
136
|
+
schema: (view) => {
|
|
137
|
+
if (view === 'single_element' || view === 'detail')
|
|
138
|
+
return SINGLE_ELEMENT_SCHEMA;
|
|
139
|
+
if (view === 'inline_mention')
|
|
140
|
+
return INLINE_MENTION_SCHEMA;
|
|
141
|
+
return LIST_ITEM_SCHEMA;
|
|
142
|
+
},
|
|
143
|
+
snapshot: (entity) => buildSnapshot(entity),
|
|
144
|
+
restore: diagramRestore,
|
|
145
|
+
diff: diagramDiff,
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=serializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../../../src/server/entities/diagram/serializer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { BrokenReference, ChangedBy, Diagram, DiagramCreateInput, DiagramDeleteResult, DiagramListQuery, DiagramUpdateInput } from '../../../shared/entities.js';
|
|
3
|
+
import type { TagsService } from '../../services/tags.js';
|
|
4
|
+
import type { VersionService } from '../../services/versions.js';
|
|
5
|
+
import type { EntityStore } from '../../services/entity-store.js';
|
|
6
|
+
/**
|
|
7
|
+
* M29 write options — mirror the other entity services. `capture: false`
|
|
8
|
+
* suppresses the entity_version capture (index-rebuild path); `writeFile: false`
|
|
9
|
+
* skips the JSON file persist (the file is what the rebuild reads).
|
|
10
|
+
*/
|
|
11
|
+
export interface MutateOpts {
|
|
12
|
+
capture?: boolean;
|
|
13
|
+
writeFile?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare class DiagramService {
|
|
16
|
+
private db;
|
|
17
|
+
private tags;
|
|
18
|
+
private versions;
|
|
19
|
+
private store;
|
|
20
|
+
constructor(db: Database.Database, tags: TagsService, versions: VersionService, store: EntityStore);
|
|
21
|
+
/** Resolve a free slug, appending `-2`, `-3`, … on collision. */
|
|
22
|
+
private uniqueSlug;
|
|
23
|
+
private generateSlug;
|
|
24
|
+
create(input: DiagramCreateInput, actor: ChangedBy, opts?: MutateOpts): Diagram;
|
|
25
|
+
list(query?: DiagramListQuery): Diagram[];
|
|
26
|
+
count(query?: DiagramListQuery): number;
|
|
27
|
+
getBySlug(slug: string): Diagram | null;
|
|
28
|
+
update(slug: string, input: DiagramUpdateInput, actor: ChangedBy, opts?: MutateOpts): {
|
|
29
|
+
diagram: Diagram;
|
|
30
|
+
previousSlug: string;
|
|
31
|
+
};
|
|
32
|
+
/** Idempotent UPSERT for M17 restore. CREATE if missing, UPDATE otherwise; preserves slug. */
|
|
33
|
+
upsert(slug: string, input: DiagramCreateInput, actor: ChangedBy, opts?: MutateOpts): {
|
|
34
|
+
diagram: Diagram;
|
|
35
|
+
op: 'created' | 'updated';
|
|
36
|
+
};
|
|
37
|
+
remove(slug: string, actor: ChangedBy, brokenReferences?: BrokenReference[], opts?: MutateOpts): DiagramDeleteResult;
|
|
38
|
+
private getBySlugInternal;
|
|
39
|
+
private hydrate;
|
|
40
|
+
}
|