Files
archify-vscode-ext/scripts/patch-schemas.mjs
T
root-at-skic ebf320a023 Architecture decisions: files, diagram references, views and panels
- *.archify-decision files: id (unique, words), title, status, date,
  elements, diagrams, supersedes, and prose; parsed, merged and link-checked
  in the model index; diagnostics on the file
- diagrams point at decisions with decisions: [...] on the diagram, nodes
  and edges; stripped before Archify, unknown ids reported, completion,
  hover and go-to-definition for the ids and for elements/diagrams/
  supersedes in decision files
- Decisions panel on the main.archify page; Decisions rail panel under a
  diagram (hover lights up the node or connection); decisions on element
  cards and in the element dialog; decision view for the file, with a
  lost-model note outside a model
- Archify | New Decision… command and template; editor schemas; the three
  New Model examples carry decisions; docs, changelog, 0.8.0
2026-10-19 23:13:05 +03:00

118 lines
5.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// Adds the model keys to the editor schemas in schemas/ (the CLI keeps the
// strict originals): `model` on main.archify, `ref` and `diagram` on
// architecture components, and a schema for *.archify-registry files.
// Run after sync-archify.mjs, or on its own after editing this file.
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const schemas = path.join(root, 'schemas');
const read = (file) => JSON.parse(fs.readFileSync(path.join(schemas, file), 'utf8'));
const write = (file, value) => fs.writeFileSync(path.join(schemas, file), `${JSON.stringify(value, null, 2)}\n`);
const MODEL = {
type: 'object',
description: 'Only in main.archify: the entry point of a model (a folder of diagrams that belong together).',
additionalProperties: false,
required: ['id', 'name'],
properties: {
id: { type: 'string', pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$', description: 'Stable id of the model.' },
name: { type: 'string', minLength: 1, description: 'Name shown on the model page.' },
description: { type: 'string', description: 'What the model covers; shown on the model page.' },
},
};
const DIAGRAM_LINK = { type: 'string', description: 'Diagram that explains this element, relative to the model root (main.archify). Double-click the node to open it.' };
const DECISIONS = { type: 'array', items: { type: 'string', minLength: 1 }, description: 'Ids of architecture decisions (*.archify-decision files of the model) this is about. Shown in the Decisions panel under the diagram.' };
const NODE_COLLECTIONS = ['components', 'nodes', 'participants', 'states'];
const EDGE_COLLECTIONS = ['connections', 'edges', 'flows', 'transitions', 'messages'];
for (const file of fs.readdirSync(schemas)) {
if (!/^(architecture|workflow|sequence|dataflow|lifecycle)\.schema\.json$/.test(file)) continue;
const schema = read(file);
schema.properties.model = MODEL;
schema.properties.decisions = DECISIONS;
for (const key of [...NODE_COLLECTIONS, ...EDGE_COLLECTIONS]) {
const items = schema.properties[key]?.items;
if (items?.properties) items.properties.decisions = DECISIONS;
}
if (file === 'architecture.schema.json') {
const item = schema.properties.components.items;
item.properties.ref = { type: 'string', pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$', description: 'A shared element from the model’s registry (*.archify-registry). Its type, label, sublabel, brand and sources come from there; the diagram adds pos/size and may override label, sublabel and tag.' };
item.properties.diagram = DIAGRAM_LINK;
// A ref brings type and label with it; an inline component must state them.
item.anyOf = [{ required: ['ref'] }, { required: ['id', 'type', 'label'] }];
delete item.required;
}
write(file, schema);
}
const common = read('common.schema.json');
const componentType = common.$defs.componentType;
const registry = {
$schema: 'https://json-schema.org/draft/2020-12/schema',
title: 'Archify model registry',
description: 'Shared elements of a model: one name for one thing. Diagrams refer to an element with `ref: <id>`.',
type: 'object',
additionalProperties: false,
required: ['elements'],
properties: {
schema_version: { const: 1 },
elements: {
type: 'object',
description: 'Element id → element. Ids are unique across all registry files of the model.',
propertyNames: { pattern: '^[a-zA-Z][a-zA-Z0-9_-]*$' },
additionalProperties: {
type: 'object',
additionalProperties: false,
required: ['type', 'label'],
properties: {
type: componentType,
label: { type: 'string', minLength: 1 },
sublabel: { type: 'string' },
tag: { type: 'string' },
icon: common.$defs.nodeIcon,
brand: common.$defs.brandMark,
sources: common.$defs.sourceReferences,
description: { type: 'string', description: 'The one description of this thing; shown on hover and on the model page.' },
diagram: DIAGRAM_LINK,
},
},
},
},
};
write('archify-registry.schema.json', registry);
const decision = {
$schema: 'https://json-schema.org/draft/2020-12/schema',
title: 'Archify architecture decision',
description: 'One architecture decision of a model. Diagrams point at it with `decisions: [<id>]`.',
type: 'object',
additionalProperties: false,
required: ['decision'],
properties: {
schema_version: { const: 1 },
decision: {
type: 'object',
additionalProperties: false,
required: ['id', 'title'],
properties: {
id: { type: 'string', minLength: 1, description: 'Unique in the model. Any short string.' },
title: { type: 'string', minLength: 1 },
status: { enum: ['proposed', 'accepted', 'superseded', 'rejected'], description: 'A decision another one supersedes shows as superseded whatever this says.' },
date: { type: 'string', description: 'YYYY-MM-DD.' },
elements: { type: 'array', items: { type: 'string', minLength: 1 }, description: 'Registry element ids the decision is about.' },
diagrams: { type: 'array', items: { type: 'string', minLength: 1 }, description: 'Diagram paths (from the model root) the decision names.' },
supersedes: { type: 'array', items: { type: 'string', minLength: 1 }, description: 'Ids of older decisions this one replaces.' },
},
},
context: { type: 'string', description: 'The situation and what forced a decision.' },
decision: { type: 'string', description: 'What was decided.' },
consequences: { type: 'string', description: 'What becomes easier, harder, or must change.' },
},
};
write('archify-decision.schema.json', decision);
console.log('Patched editor schemas: model, ref, diagram, decisions; wrote archify-registry.schema.json and archify-decision.schema.json');