@memoarchitect/tools 0.4.6 → 0.6.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.
Files changed (111) hide show
  1. package/README.md +5 -5
  2. package/package.json +3 -3
  3. package/packages/tools/lib/bin/memo.js +1 -1
  4. package/packages/tools/lib/browser/index.d.ts +2 -0
  5. package/packages/tools/lib/browser/index.d.ts.map +1 -1
  6. package/packages/tools/lib/browser/index.js +2 -0
  7. package/packages/tools/lib/browser/index.js.map +1 -1
  8. package/packages/tools/lib/commands/create-package.js +1 -1
  9. package/packages/tools/lib/commands/dev.d.ts.map +1 -1
  10. package/packages/tools/lib/commands/dev.js +40 -5
  11. package/packages/tools/lib/commands/dev.js.map +1 -1
  12. package/packages/tools/lib/commands/install.js +1 -1
  13. package/packages/tools/lib/commands/ontology.js +1 -1
  14. package/packages/tools/lib/commands/ontology.js.map +1 -1
  15. package/packages/tools/lib/dhf/document-registry.js +5 -5
  16. package/packages/tools/lib/dhf/document-registry.js.map +1 -1
  17. package/packages/tools/lib/dhf/template-engine.js +3 -3
  18. package/packages/tools/lib/dhf/template-engine.js.map +1 -1
  19. package/packages/tools/lib/importer/cameo-importer.d.ts.map +1 -1
  20. package/packages/tools/lib/importer/cameo-importer.js +5 -2
  21. package/packages/tools/lib/importer/cameo-importer.js.map +1 -1
  22. package/packages/tools/lib/importer/ea-importer.d.ts +1 -1
  23. package/packages/tools/lib/importer/ea-importer.d.ts.map +1 -1
  24. package/packages/tools/lib/importer/ea-importer.js +6 -4
  25. package/packages/tools/lib/importer/ea-importer.js.map +1 -1
  26. package/packages/tools/lib/index.d.ts +2 -0
  27. package/packages/tools/lib/index.d.ts.map +1 -1
  28. package/packages/tools/lib/index.js +2 -0
  29. package/packages/tools/lib/index.js.map +1 -1
  30. package/packages/tools/lib/language/generated/ast.d.ts +409 -42
  31. package/packages/tools/lib/language/generated/ast.d.ts.map +1 -1
  32. package/packages/tools/lib/language/generated/ast.js +318 -12
  33. package/packages/tools/lib/language/generated/ast.js.map +1 -1
  34. package/packages/tools/lib/language/generated/grammar.d.ts.map +1 -1
  35. package/packages/tools/lib/language/generated/grammar.js +1732 -513
  36. package/packages/tools/lib/language/generated/grammar.js.map +1 -1
  37. package/packages/tools/lib/model/builder.d.ts.map +1 -1
  38. package/packages/tools/lib/model/builder.js +38 -14
  39. package/packages/tools/lib/model/builder.js.map +1 -1
  40. package/packages/tools/lib/model/config.d.ts +11 -1
  41. package/packages/tools/lib/model/config.d.ts.map +1 -1
  42. package/packages/tools/lib/model/kind-registry.d.ts +9 -0
  43. package/packages/tools/lib/model/kind-registry.d.ts.map +1 -1
  44. package/packages/tools/lib/model/kind-registry.js +26 -3
  45. package/packages/tools/lib/model/kind-registry.js.map +1 -1
  46. package/packages/tools/lib/model/layer-resolver.d.ts.map +1 -1
  47. package/packages/tools/lib/model/layer-resolver.js +15 -0
  48. package/packages/tools/lib/model/layer-resolver.js.map +1 -1
  49. package/packages/tools/lib/model/ontology-loader.d.ts +2 -0
  50. package/packages/tools/lib/model/ontology-loader.d.ts.map +1 -1
  51. package/packages/tools/lib/model/ontology-loader.js +92 -28
  52. package/packages/tools/lib/model/ontology-loader.js.map +1 -1
  53. package/packages/tools/lib/model/parser-utils.d.ts +9 -0
  54. package/packages/tools/lib/model/parser-utils.d.ts.map +1 -1
  55. package/packages/tools/lib/model/parser-utils.js +24 -0
  56. package/packages/tools/lib/model/parser-utils.js.map +1 -1
  57. package/packages/tools/lib/model/paths.d.ts +0 -2
  58. package/packages/tools/lib/model/paths.d.ts.map +1 -1
  59. package/packages/tools/lib/model/paths.js +0 -2
  60. package/packages/tools/lib/model/paths.js.map +1 -1
  61. package/packages/tools/lib/model/relationship-legality.d.ts +261 -0
  62. package/packages/tools/lib/model/relationship-legality.d.ts.map +1 -0
  63. package/packages/tools/lib/model/relationship-legality.js +391 -0
  64. package/packages/tools/lib/model/relationship-legality.js.map +1 -0
  65. package/packages/tools/lib/model/relationship-registry.d.ts +38 -4
  66. package/packages/tools/lib/model/relationship-registry.d.ts.map +1 -1
  67. package/packages/tools/lib/model/relationship-registry.js +109 -1
  68. package/packages/tools/lib/model/relationship-registry.js.map +1 -1
  69. package/packages/tools/lib/model/semantic.d.ts +42 -0
  70. package/packages/tools/lib/model/semantic.d.ts.map +1 -1
  71. package/packages/tools/lib/model/semantic.js +3 -0
  72. package/packages/tools/lib/model/semantic.js.map +1 -1
  73. package/packages/tools/lib/model/short-id.js +1 -1
  74. package/packages/tools/lib/model/short-id.js.map +1 -1
  75. package/packages/tools/lib/model/source-affinity.d.ts +21 -0
  76. package/packages/tools/lib/model/source-affinity.d.ts.map +1 -0
  77. package/packages/tools/lib/model/source-affinity.js +42 -0
  78. package/packages/tools/lib/model/source-affinity.js.map +1 -0
  79. package/packages/tools/lib/model/source-graph.d.ts +30 -0
  80. package/packages/tools/lib/model/source-graph.d.ts.map +1 -0
  81. package/packages/tools/lib/model/source-graph.js +154 -0
  82. package/packages/tools/lib/model/source-graph.js.map +1 -0
  83. package/packages/tools/lib/model/view-kinds.d.ts.map +1 -1
  84. package/packages/tools/lib/model/view-kinds.js +1 -0
  85. package/packages/tools/lib/model/view-kinds.js.map +1 -1
  86. package/packages/tools/lib/operations/project-snapshot.d.ts.map +1 -1
  87. package/packages/tools/lib/operations/project-snapshot.js +2 -15
  88. package/packages/tools/lib/operations/project-snapshot.js.map +1 -1
  89. package/packages/tools/lib/protocol/messages.d.ts +92 -8
  90. package/packages/tools/lib/protocol/messages.d.ts.map +1 -1
  91. package/packages/tools/lib/server/dev-server.d.ts +16 -0
  92. package/packages/tools/lib/server/dev-server.d.ts.map +1 -1
  93. package/packages/tools/lib/server/dev-server.js +190 -16
  94. package/packages/tools/lib/server/dev-server.js.map +1 -1
  95. package/packages/tools/lib/server/file-watcher.d.ts +21 -2
  96. package/packages/tools/lib/server/file-watcher.d.ts.map +1 -1
  97. package/packages/tools/lib/server/file-watcher.js +55 -23
  98. package/packages/tools/lib/server/file-watcher.js.map +1 -1
  99. package/packages/tools/lib/server/persistor.d.ts +0 -13
  100. package/packages/tools/lib/server/persistor.d.ts.map +1 -1
  101. package/packages/tools/lib/server/persistor.js +3 -31
  102. package/packages/tools/lib/server/persistor.js.map +1 -1
  103. package/packages/tools/lib/server/relationship-writer.d.ts +104 -0
  104. package/packages/tools/lib/server/relationship-writer.d.ts.map +1 -0
  105. package/packages/tools/lib/server/relationship-writer.js +402 -0
  106. package/packages/tools/lib/server/relationship-writer.js.map +1 -0
  107. package/packages/tools/lib/server/view-layout-store.d.ts +14 -1
  108. package/packages/tools/lib/server/view-layout-store.d.ts.map +1 -1
  109. package/packages/tools/lib/server/view-layout-store.js +63 -11
  110. package/packages/tools/lib/server/view-layout-store.js.map +1 -1
  111. package/packages/tools/src/grammar/memo-sysml.langium +102 -18
@@ -0,0 +1,402 @@
1
+ // ─── Relationship Writer ──────────────────────────────────────────────────────
2
+ //
3
+ // Persists model relationships as typed SysML connection usages, and removes
4
+ // them again. A relationship is a semantic model fact, so it is always written
5
+ // into project SysML — never into a diagram, layout sidecar, or UI state.
6
+ //
7
+ // Editing is CST-aware: the file is parsed, the edit is applied by source
8
+ // offset so comments and unrelated declarations survive untouched, the result
9
+ // is reparsed and validated, and only then does it atomically replace the file.
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
12
+ import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
13
+ import { parseText } from '../model/parser-utils.js';
14
+ import { isConnectionUsage, isPackageDeclaration, } from '../language/generated/ast.js';
15
+ // Project-layout conventions, not ontology semantics — these describe where a
16
+ // MEMO project keeps its files, so they are overridable per project rather than
17
+ // fixed in the engine.
18
+ /** Default file used when the project has no better home for a relationship. */
19
+ export const CANONICAL_RELATIONSHIP_FILE = 'model/relationships.sysml';
20
+ /** Directory segments holding view/presentation SysML — never a relationship home. */
21
+ export const DEFAULT_PRESENTATION_DIRS = ['views'];
22
+ /** Filenames a package uses to collect its relationships. */
23
+ export const DEFAULT_RELATIONSHIP_FILE_PATTERN = /relationships?\.sysml$/i;
24
+ // ─── Path guards ────────────────────────────────────────────────────────────
25
+ /**
26
+ * Whether a project-relative path is a legal home for a model relationship.
27
+ *
28
+ * Rejects anything outside the project, non-.sysml files, installed ontology
29
+ * content, and the diagram presentation section. Symlinks are resolved before
30
+ * the containment check so an in-tree link cannot escape the project.
31
+ */
32
+ export function isWritableRelationshipFile(relativePath, options) {
33
+ if (!relativePath || !relativePath.endsWith('.sysml'))
34
+ return false;
35
+ const projectRoot = realpathSync(resolve(options.projectRoot));
36
+ const requested = resolve(projectRoot, relativePath);
37
+ // Resolve symlinks for files that already exist; a new file is judged by
38
+ // the real path of the closest existing ancestor directory.
39
+ let real = requested;
40
+ if (existsSync(requested)) {
41
+ real = realpathSync(requested);
42
+ }
43
+ else {
44
+ let dir = dirname(requested);
45
+ while (!existsSync(dir) && dirname(dir) !== dir)
46
+ dir = dirname(dir);
47
+ real = join(realpathSync(dir), relative(dir, requested));
48
+ }
49
+ const rel = relative(projectRoot, real);
50
+ if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))
51
+ return false;
52
+ // Installed ontology and library content is read-only.
53
+ const segments = rel.split(sep);
54
+ if (segments.includes('node_modules'))
55
+ return false;
56
+ for (const root of options.ontologyRoots ?? []) {
57
+ const ontologyReal = existsSync(root) ? realpathSync(root) : resolve(root);
58
+ const fromOntology = relative(ontologyReal, real);
59
+ if (fromOntology && !fromOntology.startsWith('..') && !isAbsolute(fromOntology))
60
+ return false;
61
+ }
62
+ // A relationship is a model fact, not presentation — keep it out of views/.
63
+ const presentationDirs = options.presentationDirs ?? DEFAULT_PRESENTATION_DIRS;
64
+ if (segments.some(segment => presentationDirs.includes(segment)))
65
+ return false;
66
+ return true;
67
+ }
68
+ // ─── Ownership policy ───────────────────────────────────────────────────────
69
+ /**
70
+ * Choose the file that will own a new relationship, deterministically:
71
+ *
72
+ * 1. the file the request explicitly asked for
73
+ * 2. the designated relationship file of the active model package
74
+ * 3. an existing relationships file in the nearest common package of both
75
+ * endpoints, else the source element's own file within that package
76
+ * 4. the configured canonical relationship file, when it already exists
77
+ * 5. the canonical file, created only because nothing above was suitable
78
+ *
79
+ * Every candidate passes isWritableRelationshipFile before it is considered.
80
+ */
81
+ export function resolveRelationshipPlacement(request, model, options) {
82
+ const accept = (file) => isWritableRelationshipFile(file, options);
83
+ const exists = (file) => existsSync(resolve(options.projectRoot, file));
84
+ // 1 — explicit request.
85
+ if (request.owningFile && accept(request.owningFile)) {
86
+ return { file: request.owningFile, reason: 'requested', willCreate: !exists(request.owningFile) };
87
+ }
88
+ const source = model.elements[request.sourceId];
89
+ const target = model.elements[request.targetId];
90
+ // 2 — the active package's designated relationship file.
91
+ const designated = options.designatedFiles ?? {};
92
+ for (const pkg of [source?.package, target?.package]) {
93
+ const file = pkg ? designated[pkg] : undefined;
94
+ if (file && accept(file)) {
95
+ return { file, reason: 'designated-package-file', willCreate: !exists(file) };
96
+ }
97
+ }
98
+ // 3 — nearest writable common project package for both endpoints.
99
+ if (source?.file && target?.file) {
100
+ const commonDir = commonDirectory(source.file, target.file);
101
+ const existingRelFile = findRelationshipFileIn(commonDir, options);
102
+ if (existingRelFile && accept(existingRelFile)) {
103
+ return { file: existingRelFile, reason: 'common-package-file', willCreate: false };
104
+ }
105
+ // The source element's own file, when it sits in that common package.
106
+ if (withinDirectory(source.file, commonDir) && accept(source.file) && exists(source.file)) {
107
+ return { file: source.file, reason: 'source-element-file', willCreate: false };
108
+ }
109
+ }
110
+ // 4/5 — the canonical file, created only as a last resort.
111
+ const canonical = options.canonicalFile ?? CANONICAL_RELATIONSHIP_FILE;
112
+ return {
113
+ file: canonical,
114
+ reason: exists(canonical) ? 'canonical-file' : 'canonical-file-created',
115
+ willCreate: !exists(canonical),
116
+ };
117
+ }
118
+ /** Deepest directory containing both project-relative files. */
119
+ function commonDirectory(fileA, fileB) {
120
+ const a = dirname(fileA).split(/[\\/]/);
121
+ const b = dirname(fileB).split(/[\\/]/);
122
+ const common = [];
123
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
124
+ if (a[i] !== b[i])
125
+ break;
126
+ common.push(a[i]);
127
+ }
128
+ return common.join(sep);
129
+ }
130
+ /** True when a project-relative file sits in or under a directory. */
131
+ function withinDirectory(file, dir) {
132
+ if (!dir)
133
+ return true;
134
+ const normalized = dirname(file).split(/[\\/]/).join(sep);
135
+ return normalized === dir || normalized.startsWith(dir + sep);
136
+ }
137
+ /**
138
+ * An existing relationships-named .sysml directly in a directory. Convention
139
+ * over configuration: a package that already collects its links in one file
140
+ * keeps collecting them there.
141
+ */
142
+ function findRelationshipFileIn(dir, options) {
143
+ const absoluteDir = resolve(options.projectRoot, dir);
144
+ if (!existsSync(absoluteDir))
145
+ return undefined;
146
+ let entries;
147
+ try {
148
+ const pattern = options.relationshipFilePattern ?? DEFAULT_RELATIONSHIP_FILE_PATTERN;
149
+ entries = readdirSync(absoluteDir, { withFileTypes: true })
150
+ .filter(e => e.isFile() && pattern.test(e.name))
151
+ .map(e => e.name)
152
+ .sort();
153
+ }
154
+ catch {
155
+ return undefined;
156
+ }
157
+ if (entries.length === 0)
158
+ return undefined;
159
+ return dir ? `${dir}${sep}${entries[0]}` : entries[0];
160
+ }
161
+ // ─── ID generation ──────────────────────────────────────────────────────────
162
+ /**
163
+ * A stable, explicit relationship ID. Named connection usages are what make a
164
+ * relationship addressable for inspection, deletion, and deep links, so every
165
+ * authored relationship gets one.
166
+ */
167
+ export function generateRelationshipId(type, sourceId, targetId, taken) {
168
+ const sanitize = (value) => value.replace(/[^A-Za-z0-9_]/g, '_');
169
+ const base = `rel_${sanitize(type)}_${sanitize(sourceId)}_${sanitize(targetId)}`;
170
+ const used = new Set(taken);
171
+ if (!used.has(base))
172
+ return base;
173
+ let n = 2;
174
+ while (used.has(`${base}_${n}`))
175
+ n++;
176
+ return `${base}_${n}`;
177
+ }
178
+ /** Render the typed connection usage for a relationship. */
179
+ export function generateRelationshipDeclaration(id, definition, sourceId, targetId) {
180
+ return `connection ${id} : ${definition.sysmlName} connect ` +
181
+ `${definition.sourceEnd.name} ::> ${sourceId} to ` +
182
+ `${definition.targetEnd.name} ::> ${targetId};`;
183
+ }
184
+ // ─── Create ─────────────────────────────────────────────────────────────────
185
+ /**
186
+ * Write a relationship into project SysML.
187
+ *
188
+ * The declaration is inserted inside the target package by source offset, the
189
+ * whole updated file is reparsed, and the write is abandoned if the result does
190
+ * not parse or does not contain the new connection.
191
+ */
192
+ export async function writeRelationship(request, definition, model, options) {
193
+ const placement = resolveRelationshipPlacement(request, model, options);
194
+ if (!isWritableRelationshipFile(placement.file, options)) {
195
+ return { success: false, error: `No writable project file can own this relationship (${placement.file})` };
196
+ }
197
+ const absolutePath = resolve(options.projectRoot, placement.file);
198
+ const relationshipId = generateRelationshipId(definition.name, request.sourceId, request.targetId, model.relationships.map(rel => rel.id));
199
+ const declaration = generateRelationshipDeclaration(relationshipId, definition, request.sourceId, request.targetId);
200
+ let updated;
201
+ if (!existsSync(absolutePath)) {
202
+ updated = newRelationshipFile(placement.file, declaration);
203
+ }
204
+ else {
205
+ const original = readFileSync(absolutePath, 'utf8');
206
+ const inserted = await insertIntoPackage(original, declaration);
207
+ if (!inserted.ok)
208
+ return { success: false, error: inserted.error };
209
+ updated = inserted.text;
210
+ }
211
+ // Parse-before-commit: a file that does not parse never reaches disk.
212
+ const { document, errors } = await parseText(updated);
213
+ if (errors.length > 0) {
214
+ return {
215
+ success: false,
216
+ error: `The updated source did not parse (${errors[0].message}); the file was left unchanged`,
217
+ };
218
+ }
219
+ const written = findConnectionUsage(document.parseResult.value, relationshipId);
220
+ if (!written) {
221
+ return {
222
+ success: false,
223
+ error: 'The relationship was not present after reparsing; the file was left unchanged',
224
+ };
225
+ }
226
+ try {
227
+ atomicWrite(absolutePath, updated);
228
+ }
229
+ catch (e) {
230
+ return { success: false, error: `Could not write ${placement.file}: ${String(e)}` };
231
+ }
232
+ return {
233
+ success: true,
234
+ sourceFile: placement.file,
235
+ relationshipId,
236
+ declaration,
237
+ placementReason: placement.reason,
238
+ };
239
+ }
240
+ /** Body of a freshly created relationship file. */
241
+ function newRelationshipFile(relativePath, declaration) {
242
+ const packageName = relativePath
243
+ .replace(/\.sysml$/, '')
244
+ .replace(/[^A-Za-z0-9]+/g, '_')
245
+ .replace(/^_+|_+$/g, '') || 'relationships';
246
+ return `package ${packageName} {\n ${declaration}\n}\n`;
247
+ }
248
+ /**
249
+ * Insert a declaration as the last member of the file's final top-level
250
+ * package, matching the indentation of the members already there. Everything
251
+ * else in the file — comments, imports, unrelated declarations — is untouched
252
+ * because only this one offset is edited.
253
+ */
254
+ async function insertIntoPackage(source, declaration) {
255
+ const { document, errors } = await parseText(source);
256
+ if (errors.length > 0) {
257
+ return { ok: false, error: `The target file does not parse (${errors[0].message})` };
258
+ }
259
+ const model = document.parseResult.value;
260
+ const packages = (model.members ?? []).filter(isPackageDeclaration);
261
+ if (packages.length === 0) {
262
+ return { ok: false, error: 'The target file declares no package to own the relationship' };
263
+ }
264
+ const target = packages[packages.length - 1];
265
+ const cst = target.$cstNode;
266
+ if (!cst)
267
+ return { ok: false, error: 'The target package has no source range' };
268
+ // The package's own closing brace is the last '}' in its source range.
269
+ const packageEnd = cst.offset + cst.length;
270
+ const closingBrace = source.lastIndexOf('}', packageEnd - 1);
271
+ if (closingBrace < 0)
272
+ return { ok: false, error: 'The target package is not brace-delimited' };
273
+ const indent = memberIndent(source, target, closingBrace);
274
+ // Keep the existing content up to the closing brace exactly as written, then
275
+ // add the declaration on its own line just before it.
276
+ const before = source.slice(0, closingBrace);
277
+ const after = source.slice(closingBrace);
278
+ const separator = before.endsWith('\n') ? '' : '\n';
279
+ return { ok: true, text: `${before}${separator}${indent}${declaration}\n${after}` };
280
+ }
281
+ /** Indentation used by the package's existing members, defaulting to 4 spaces. */
282
+ function memberIndent(source, pkg, closingBrace) {
283
+ const firstMember = (pkg.members ?? [])[0];
284
+ const offset = firstMember?.$cstNode?.offset;
285
+ if (typeof offset === 'number') {
286
+ const lineStart = source.lastIndexOf('\n', offset - 1) + 1;
287
+ const lead = source.slice(lineStart, offset);
288
+ if (/^[ \t]*$/.test(lead))
289
+ return lead;
290
+ }
291
+ // Fall back to one level in from the closing brace's own indentation.
292
+ const braceLineStart = source.lastIndexOf('\n', closingBrace - 1) + 1;
293
+ const braceIndent = source.slice(braceLineStart, closingBrace);
294
+ return /^[ \t]*$/.test(braceIndent) ? braceIndent + ' ' : ' ';
295
+ }
296
+ // ─── Delete ─────────────────────────────────────────────────────────────────
297
+ /**
298
+ * Remove exactly one connection usage from its owning file.
299
+ *
300
+ * Only the declaration's own source range is cut — together with the whitespace
301
+ * on its line — so neighbouring comments and declarations are preserved. Both
302
+ * endpoint elements are left completely untouched.
303
+ */
304
+ export async function removeRelationship(relationship, options) {
305
+ if (!relationship.named) {
306
+ return {
307
+ success: false,
308
+ error: `Relationship "${relationship.id}" is an anonymous connection and cannot be addressed for deletion. ` +
309
+ 'Give it a name in SysML first.',
310
+ };
311
+ }
312
+ if (!relationship.file || !isWritableRelationshipFile(relationship.file, options)) {
313
+ return { success: false, error: `${relationship.file || 'The source file'} is not a writable project file` };
314
+ }
315
+ const absolutePath = resolve(options.projectRoot, relationship.file);
316
+ if (!existsSync(absolutePath)) {
317
+ return { success: false, error: `${relationship.file} no longer exists` };
318
+ }
319
+ const source = readFileSync(absolutePath, 'utf8');
320
+ const { document, errors } = await parseText(source);
321
+ if (errors.length > 0) {
322
+ return { success: false, error: `${relationship.file} does not parse (${errors[0].message})` };
323
+ }
324
+ const usage = findConnectionUsage(document.parseResult.value, relationship.id);
325
+ const cst = usage?.$cstNode;
326
+ if (!usage || !cst) {
327
+ return { success: false, error: `Relationship "${relationship.id}" was not found in ${relationship.file}` };
328
+ }
329
+ // Widen the cut to the whole line when the declaration is alone on it, so
330
+ // deletion leaves no blank indented remnant.
331
+ let start = cst.offset;
332
+ let end = cst.offset + cst.length;
333
+ const lineStart = source.lastIndexOf('\n', start - 1) + 1;
334
+ if (/^[ \t]*$/.test(source.slice(lineStart, start)))
335
+ start = lineStart;
336
+ const lineEnd = source.indexOf('\n', end);
337
+ if (lineEnd >= 0 && /^[ \t]*$/.test(source.slice(end, lineEnd)))
338
+ end = lineEnd + 1;
339
+ const removedDeclaration = source.slice(cst.offset, cst.offset + cst.length);
340
+ const updated = source.slice(0, start) + source.slice(end);
341
+ // Parse-before-commit, exactly as on the create path.
342
+ const reparsed = await parseText(updated);
343
+ if (reparsed.errors.length > 0) {
344
+ return {
345
+ success: false,
346
+ error: `Removing the relationship left invalid source (${reparsed.errors[0].message}); ` +
347
+ 'the file was left unchanged',
348
+ };
349
+ }
350
+ if (findConnectionUsage(reparsed.document.parseResult.value, relationship.id)) {
351
+ return { success: false, error: 'The relationship was still present after removal; the file was left unchanged' };
352
+ }
353
+ try {
354
+ atomicWrite(absolutePath, updated);
355
+ }
356
+ catch (e) {
357
+ return { success: false, error: `Could not write ${relationship.file}: ${String(e)}` };
358
+ }
359
+ return { success: true, sourceFile: relationship.file, removedDeclaration };
360
+ }
361
+ // ─── Shared helpers ─────────────────────────────────────────────────────────
362
+ /** Depth-first search for a named connection usage anywhere in the document. */
363
+ function findConnectionUsage(model, name) {
364
+ const stack = [...(model.members ?? [])];
365
+ while (stack.length > 0) {
366
+ const node = stack.pop();
367
+ if (!node || typeof node !== 'object')
368
+ continue;
369
+ if (isConnectionUsage(node) && node.name === name)
370
+ return node;
371
+ if (Array.isArray(node.members))
372
+ stack.push(...node.members);
373
+ if (Array.isArray(node.body))
374
+ stack.push(...node.body);
375
+ }
376
+ return undefined;
377
+ }
378
+ /**
379
+ * Replace a file's contents atomically: write a sibling temp file, then rename
380
+ * over the target. A crash mid-write leaves the original intact rather than a
381
+ * half-written model file.
382
+ */
383
+ function atomicWrite(absolutePath, contents) {
384
+ const dir = dirname(absolutePath);
385
+ if (!existsSync(dir))
386
+ mkdirSync(dir, { recursive: true });
387
+ const tempPath = `${absolutePath}.${process.pid}.tmp`;
388
+ try {
389
+ writeFileSync(tempPath, contents, 'utf8');
390
+ renameSync(tempPath, absolutePath);
391
+ }
392
+ catch (e) {
393
+ if (existsSync(tempPath)) {
394
+ try {
395
+ unlinkSync(tempPath);
396
+ }
397
+ catch { /* best effort cleanup */ }
398
+ }
399
+ throw e;
400
+ }
401
+ }
402
+ //# sourceMappingURL=relationship-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationship-writer.js","sourceRoot":"","sources":["../../src/server/relationship-writer.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,19 @@ export declare const VIEW_LAYOUT_EXTENSION = ".viewlayout";
3
3
  /** Companion location beside the SysML file that defines the view. */
4
4
  export declare function viewLayoutPath(projectRoot: string, diagram: DiagramDTO): string;
5
5
  export declare function loadViewLayout(projectRoot: string, diagram: DiagramDTO): DiagramLayout | null;
6
- export declare function saveViewLayout(projectRoot: string, diagram: DiagramDTO, layout: DiagramLayout): string;
6
+ /**
7
+ * Whether a layout says anything the model does not already say: a moved node,
8
+ * a routed connector, or a canvas setting the user changed. A companion exists
9
+ * to record overrides, so a layout that holds none is not worth a file — the
10
+ * view renders identically without it.
11
+ */
12
+ export declare function isDefaultViewLayout(layout: DiagramLayout): boolean;
13
+ /**
14
+ * Persist a diagram's overrides beside its SysML source. Returns the companion
15
+ * path, or null when there was nothing to persist — a layout that carries no
16
+ * override drops its entry instead, and the companion is removed once it holds
17
+ * no entries at all, so a purely visual toggle never dirties the project.
18
+ */
19
+ export declare function saveViewLayout(projectRoot: string, diagram: DiagramDTO, layout: DiagramLayout): string | null;
7
20
  export declare function loadViewLayouts(projectRoot: string, diagrams: DiagramDTO[]): Record<string, DiagramLayout>;
8
21
  //# sourceMappingURL=view-layout-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"view-layout-store.d.ts","sourceRoot":"","sources":["../../src/server/view-layout-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEtE,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AAUnD,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAO/E;AAMD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI,CAgB7F;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAoBtG;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAO1G"}
1
+ {"version":3,"file":"view-layout-store.d.ts","sourceRoot":"","sources":["../../src/server/view-layout-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEtE,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AAUnD,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAO/E;AAMD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI,CAgB7F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAalE;AAeD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CA+B7G;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAO1G"}
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
2
  import { basename, dirname, resolve } from 'node:path';
3
3
  import { parse, stringify } from 'yaml';
4
4
  export const VIEW_LAYOUT_EXTENSION = '.viewlayout';
@@ -39,20 +39,72 @@ export function loadViewLayout(projectRoot, diagram) {
39
39
  return null;
40
40
  }
41
41
  }
42
+ /**
43
+ * Whether a layout says anything the model does not already say: a moved node,
44
+ * a routed connector, or a canvas setting the user changed. A companion exists
45
+ * to record overrides, so a layout that holds none is not worth a file — the
46
+ * view renders identically without it.
47
+ */
48
+ export function isDefaultViewLayout(layout) {
49
+ if (Object.keys(layout.nodes ?? {}).length > 0)
50
+ return false;
51
+ if (Object.keys(layout.edges ?? {}).length > 0)
52
+ return false;
53
+ const canvas = layout.canvas;
54
+ if (!canvas)
55
+ return true;
56
+ // Automatic layout and still connectors are the defaults; every other
57
+ // canvas field is unset until the user sets it.
58
+ return canvas.autoLayout !== false
59
+ && canvas.flowAnimation !== true
60
+ && canvas.zoom === undefined
61
+ && canvas.pan === undefined
62
+ && canvas.grid === undefined
63
+ && canvas.snap === undefined;
64
+ }
65
+ /** Existing companion entries, keyed by diagram id; empty for a new file. */
66
+ function readViewLayouts(path) {
67
+ if (!existsSync(path))
68
+ return {};
69
+ try {
70
+ const existing = parse(readFileSync(path, 'utf8'));
71
+ if (existing.format === 'memo.viewlayout/v1' || existing.format === 'memo.sysmlview/v2')
72
+ return existing.layouts ?? {};
73
+ if (existing.diagramId && existing.layout)
74
+ return { [existing.diagramId]: existing.layout };
75
+ }
76
+ catch { /* replace malformed companion */ }
77
+ return {};
78
+ }
79
+ /**
80
+ * Persist a diagram's overrides beside its SysML source. Returns the companion
81
+ * path, or null when there was nothing to persist — a layout that carries no
82
+ * override drops its entry instead, and the companion is removed once it holds
83
+ * no entries at all, so a purely visual toggle never dirties the project.
84
+ */
42
85
  export function saveViewLayout(projectRoot, diagram, layout) {
43
86
  const path = viewLayoutPath(projectRoot, diagram);
44
- mkdirSync(dirname(path), { recursive: true });
45
- let existingLayouts = {};
46
- if (existsSync(path)) {
47
- try {
48
- const existing = parse(readFileSync(path, 'utf8'));
49
- if (existing.format === 'memo.viewlayout/v1' || existing.format === 'memo.sysmlview/v2')
50
- existingLayouts = existing.layouts ?? {};
51
- else if (existing.diagramId && existing.layout)
52
- existingLayouts = { [existing.diagramId]: existing.layout };
87
+ const existingLayouts = readViewLayouts(path);
88
+ if (isDefaultViewLayout(layout)) {
89
+ if (!(diagram.id in existingLayouts)) {
90
+ if (existsSync(path) && Object.keys(existingLayouts).length === 0)
91
+ rmSync(path, { force: true });
92
+ return null;
53
93
  }
54
- catch { /* replace malformed companion */ }
94
+ const remaining = { ...existingLayouts };
95
+ delete remaining[diagram.id];
96
+ if (Object.keys(remaining).length === 0) {
97
+ rmSync(path, { force: true });
98
+ return null;
99
+ }
100
+ writeFileSync(path, stringify({
101
+ format: 'memo.viewlayout/v1',
102
+ ...(diagram.sourceFile ? { viewSource: diagram.sourceFile } : {}),
103
+ layouts: remaining,
104
+ }), 'utf8');
105
+ return path;
55
106
  }
107
+ mkdirSync(dirname(path), { recursive: true });
56
108
  const artifact = {
57
109
  format: 'memo.viewlayout/v1',
58
110
  ...(diagram.sourceFile ? { viewSource: diagram.sourceFile } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"view-layout-store.js","sourceRoot":"","sources":["../../src/server/view-layout-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-layout-store.js","sourceRoot":"","sources":["../../src/server/view-layout-store.ts"],"names":[],"mappings":"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"}