#!/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.' }; 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; 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: `.', 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); console.log('Patched editor schemas: model, ref, diagram; wrote archify-registry.schema.json');