Merge pull request '0.8.1: New Registry command, creator order' (#26) from feat/new-registry into main
This commit was merged in pull request #26.
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.8.1 — 2026-10-20
|
||||||
|
|
||||||
|
- **Archify | New Registry…** on a folder (also *File → New File…* and the Command Palette) creates an `.archify-registry` file from the template and opens it.
|
||||||
|
- The Archify entries in the Explorer menu and *File → New File…* come in the order New Model, New Registry, New Diagram, New Decision.
|
||||||
|
|
||||||
## 0.8.0 — 2026-10-19
|
## 0.8.0 — 2026-10-19
|
||||||
|
|
||||||
- **Architecture decisions.** A model can hold decisions: one `*.archify-decision` file each, anywhere under the model root, with an id (unique in the model), title, status, date, the registry `elements` and `diagrams` it is about, `supersedes`, and prose for context, decision and consequences.
|
- **Architecture decisions.** A model can hold decisions: one `*.archify-decision` file each, anywhere under the model root, with an id (unique in the model), title, status, date, the registry `elements` and `diagrams` it is about, `supersedes`, and prose for context, decision and consequences.
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ The Archify CLI and the AI agents that use it write diagrams as JSON, named `nam
|
|||||||
- **Schema help**: completion and hover from Archify's own schemas, through the YAML extension for `.archify` files.
|
- **Schema help**: completion and hover from Archify's own schemas, through the YAML extension for `.archify` files.
|
||||||
- **Source links**: in source-backed diagrams, clicking a source reference opens that file and line range in the editor. If the file is not in the workspace, the web link opens instead.
|
- **Source links**: in source-backed diagrams, clicking a source reference opens that file and line range in the editor. If the file is not in the workspace, the web link opens instead.
|
||||||
- **Export**: the diagram's own Export menu (PNG, SVG, share card, …) saves through a VS Code save dialog.
|
- **Export**: the diagram's own Export menu (PNG, SVG, share card, …) saves through a VS Code save dialog.
|
||||||
- **Commands**: *Archify | New Diagram…*, *Archify | New Model…*, *Archify | New Decision…*, *Archify | Open Model*, *Archify | Render to HTML File…*, *Archify | Open in Browser*, *Archify | Refresh Preview*, *Archify | Show Source*.
|
- **Commands**: *Archify | New Model…*, *Archify | New Registry…*, *Archify | New Diagram…*, *Archify | New Decision…*, *Archify | Open Model*, *Archify | Render to HTML File…*, *Archify | Open in Browser*, *Archify | Refresh Preview*, *Archify | Show Source*.
|
||||||
|
|
||||||
## 3D view
|
## 3D view
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "archify-vscode-ext",
|
"name": "archify-vscode-ext",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "archify-vscode-ext",
|
"name": "archify-vscode-ext",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"three": "^0.186.1",
|
"three": "^0.186.1",
|
||||||
|
|||||||
+36
-22
@@ -2,7 +2,7 @@
|
|||||||
"name": "archify-vscode-ext",
|
"name": "archify-vscode-ext",
|
||||||
"displayName": "Archify Diagram Viewer",
|
"displayName": "Archify Diagram Viewer",
|
||||||
"description": "Archify diagrams in VS Code. Write diagrams as .archify files in YAML: they open as the interactive diagram, with live updates, validation, templates and completion. Also previews Archify's own JSON files (*.architecture.json, …) and opens rendered Archify HTML.",
|
"description": "Archify diagrams in VS Code. Write diagrams as .archify files in YAML: they open as the interactive diagram, with live updates, validation, templates and completion. Also previews Archify's own JSON files (*.architecture.json, …) and opens rendered Archify HTML.",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"publisher": "root-at-skic",
|
"publisher": "root-at-skic",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"sponsor": {
|
"sponsor": {
|
||||||
@@ -49,16 +49,21 @@
|
|||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
|
||||||
"command": "archify.newDiagram",
|
|
||||||
"title": "Archify | New Diagram…",
|
|
||||||
"icon": "$(new-file)"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "archify.newModel",
|
"command": "archify.newModel",
|
||||||
"title": "Archify | New Model…",
|
"title": "Archify | New Model…",
|
||||||
"icon": "$(new-folder)"
|
"icon": "$(new-folder)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "archify.newRegistry",
|
||||||
|
"title": "Archify | New Registry…",
|
||||||
|
"icon": "$(symbol-field)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "archify.newDiagram",
|
||||||
|
"title": "Archify | New Diagram…",
|
||||||
|
"icon": "$(new-file)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.newDecision",
|
"command": "archify.newDecision",
|
||||||
"title": "Archify | New Decision…",
|
"title": "Archify | New Decision…",
|
||||||
@@ -179,39 +184,44 @@
|
|||||||
],
|
],
|
||||||
"explorer/context": [
|
"explorer/context": [
|
||||||
{
|
{
|
||||||
"command": "archify.newDiagram",
|
"command": "archify.newModel",
|
||||||
"when": "explorerResourceIsFolder",
|
"when": "explorerResourceIsFolder",
|
||||||
"group": "zzz_archify@1"
|
"group": "zzz_archify@1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.newModel",
|
"command": "archify.newRegistry",
|
||||||
"when": "explorerResourceIsFolder",
|
"when": "explorerResourceIsFolder",
|
||||||
"group": "zzz_archify@2"
|
"group": "zzz_archify@2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "archify.newDiagram",
|
||||||
|
"when": "explorerResourceIsFolder",
|
||||||
|
"group": "zzz_archify@3"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.newDecision",
|
"command": "archify.newDecision",
|
||||||
"when": "explorerResourceIsFolder",
|
"when": "explorerResourceIsFolder",
|
||||||
"group": "zzz_archify@2"
|
"group": "zzz_archify@4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.showPreview",
|
"command": "archify.showPreview",
|
||||||
"when": "resourceFilename =~ /(\\.archify|\\.archify-registry|\\.archify-decision|\\.(architecture|workflow|sequence|dataflow|lifecycle)\\.json)$/",
|
"when": "resourceFilename =~ /(\\.archify|\\.archify-registry|\\.archify-decision|\\.(architecture|workflow|sequence|dataflow|lifecycle)\\.json)$/",
|
||||||
"group": "zzz_archify@3"
|
"group": "zzz_archify@5"
|
||||||
},
|
|
||||||
{
|
|
||||||
"command": "archify.renderToHtml",
|
|
||||||
"when": "resourceFilename =~ /(\\.archify|\\.(architecture|workflow|sequence|dataflow|lifecycle)\\.json)$/",
|
|
||||||
"group": "zzz_archify@4"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.openHtmlViewer",
|
"command": "archify.openHtmlViewer",
|
||||||
"when": "resourceExtname == .html",
|
"when": "resourceExtname == .html",
|
||||||
"group": "zzz_archify@3"
|
"group": "zzz_archify@6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "archify.renderToHtml",
|
||||||
|
"when": "resourceFilename =~ /(\\.archify|\\.(architecture|workflow|sequence|dataflow|lifecycle)\\.json)$/",
|
||||||
|
"group": "zzz_archify@7"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.openModel",
|
"command": "archify.openModel",
|
||||||
"when": "resourceFilename =~ /\\.archify(-registry|-decision)?$/",
|
"when": "resourceFilename =~ /\\.archify(-registry|-decision)?$/",
|
||||||
"group": "zzz_archify@5"
|
"group": "zzz_archify@8"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"editor/title/context": [
|
"editor/title/context": [
|
||||||
@@ -223,16 +233,20 @@
|
|||||||
],
|
],
|
||||||
"file/newFile": [
|
"file/newFile": [
|
||||||
{
|
{
|
||||||
"command": "archify.newDiagram",
|
"command": "archify.newModel",
|
||||||
"group": "file"
|
"group": "file@1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.newModel",
|
"command": "archify.newRegistry",
|
||||||
"group": "file"
|
"group": "file@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "archify.newDiagram",
|
||||||
|
"group": "file@3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "archify.newDecision",
|
"command": "archify.newDecision",
|
||||||
"group": "file"
|
"group": "file@4"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import * as vscode from 'vscode';
|
|||||||
import { MODEL_EXAMPLES, mainFromExample } from '../language/examples';
|
import { MODEL_EXAMPLES, mainFromExample } from '../language/examples';
|
||||||
import { diagramName, invalidNameReason } from '../language/templates';
|
import { diagramName, invalidNameReason } from '../language/templates';
|
||||||
import { DECISION_EXT, slugify } from '../model/decisions';
|
import { DECISION_EXT, slugify } from '../model/decisions';
|
||||||
import { MAIN_FILE } from '../model/format';
|
import { MAIN_FILE, REGISTRY_EXT } from '../model/format';
|
||||||
|
import { REGISTRY_VIEW_TYPE } from '../views/registryView';
|
||||||
import { DECISION_VIEW_TYPE } from '../views/decisionView';
|
import { DECISION_VIEW_TYPE } from '../views/decisionView';
|
||||||
import { readText } from '../util/files';
|
import { readText } from '../util/files';
|
||||||
import { DIAGRAM_EDITOR_VIEW_TYPE } from '../views/diagramView';
|
import { DIAGRAM_EDITOR_VIEW_TYPE } from '../views/diagramView';
|
||||||
@@ -32,6 +33,25 @@ export function modelCommands(ctx: CommandContext): vscode.Disposable[] {
|
|||||||
await vscode.commands.executeCommand('vscode.openWith', vscode.Uri.joinPath(root, MAIN_FILE), DIAGRAM_EDITOR_VIEW_TYPE, vscode.ViewColumn.Active);
|
await vscode.commands.executeCommand('vscode.openWith', vscode.Uri.joinPath(root, MAIN_FILE), DIAGRAM_EDITOR_VIEW_TYPE, vscode.ViewColumn.Active);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// Creates a registry file in the clicked folder and opens it.
|
||||||
|
vscode.commands.registerCommand('archify.newRegistry', async (arg?: unknown) => {
|
||||||
|
const folder = await parentFolder(arg);
|
||||||
|
if (!folder) return;
|
||||||
|
const root = await ctx.models.rootOf(vscode.Uri.joinPath(folder, 'x'));
|
||||||
|
const name = await vscode.window.showInputBox({
|
||||||
|
title: 'Archify | New Registry',
|
||||||
|
prompt: `File name in ${vscode.workspace.asRelativePath(folder, true)}${root ? '' : ' (not inside a model: add a main.archify above it so diagrams can refer to its elements)'}`,
|
||||||
|
value: 'elements',
|
||||||
|
validateInput: async (value) =>
|
||||||
|
invalidNameReason(value) ?? ((await exists(vscode.Uri.joinPath(folder, `${diagramName(value).replace(/\.archify-registry$/i, '')}${REGISTRY_EXT}`))) ? `${diagramName(value)}${REGISTRY_EXT} already exists.` : undefined),
|
||||||
|
});
|
||||||
|
if (name === undefined) return;
|
||||||
|
const target = vscode.Uri.joinPath(folder, `${diagramName(name).replace(/\.archify-registry$/i, '')}${REGISTRY_EXT}`);
|
||||||
|
const template = await readText(vscode.Uri.joinPath(ctx.extension.extensionUri, 'templates', 'registry.archify-registry'));
|
||||||
|
await vscode.workspace.fs.writeFile(target, Buffer.from(template, 'utf8'));
|
||||||
|
await vscode.commands.executeCommand('vscode.openWith', target, REGISTRY_VIEW_TYPE);
|
||||||
|
}),
|
||||||
|
|
||||||
// Creates a decision file in the clicked folder of a model and opens it.
|
// Creates a decision file in the clicked folder of a model and opens it.
|
||||||
vscode.commands.registerCommand('archify.newDecision', async (arg?: unknown) => {
|
vscode.commands.registerCommand('archify.newDecision', async (arg?: unknown) => {
|
||||||
const folder = await parentFolder(arg);
|
const folder = await parentFolder(arg);
|
||||||
|
|||||||
@@ -349,6 +349,30 @@ export async function run(): Promise<void> {
|
|||||||
await vscode.workspace.fs.delete(bad);
|
await vscode.workspace.fs.delete(bad);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await check('Archify | New Registry… creates a registry file and opens the registry view; creators are ordered', async () => {
|
||||||
|
const commands = vscode.extensions.getExtension(EXTENSION_ID)?.packageJSON.contributes as { commands: { command: string }[]; menus: Record<string, { command: string; group: string }[]> };
|
||||||
|
const creators = commands.menus['explorer/context'].filter((m) => /^archify\.new/.test(m.command));
|
||||||
|
assert.deepEqual(creators.map((m) => m.command), ['archify.newModel', 'archify.newRegistry', 'archify.newDiagram', 'archify.newDecision']);
|
||||||
|
assert.deepEqual(creators.map((m) => m.group), ['zzz_archify@1', 'zzz_archify@2', 'zzz_archify@3', 'zzz_archify@4']);
|
||||||
|
const folder = workspaceFile('model/registry');
|
||||||
|
const window = vscode.window as unknown as Record<string, unknown>;
|
||||||
|
const originalInput = window.showInputBox;
|
||||||
|
window.showInputBox = async () => 'partners';
|
||||||
|
try {
|
||||||
|
await vscode.commands.executeCommand('archify.newRegistry', folder);
|
||||||
|
} finally {
|
||||||
|
window.showInputBox = originalInput;
|
||||||
|
}
|
||||||
|
const file = vscode.Uri.joinPath(folder, 'partners.archify-registry');
|
||||||
|
const text = new TextDecoder().decode(await vscode.workspace.fs.readFile(file));
|
||||||
|
assert.match(text, /^elements:/m);
|
||||||
|
const tab = await waitFor('registry view tab', () =>
|
||||||
|
vscode.window.tabGroups.all.flatMap((g) => g.tabs).find((t) => t.isActive && t.input instanceof vscode.TabInputCustom && t.input.viewType === 'archify.registry' && t.input.uri.toString() === file.toString()),
|
||||||
|
);
|
||||||
|
assert.ok(tab);
|
||||||
|
await vscode.workspace.fs.delete(file);
|
||||||
|
});
|
||||||
|
|
||||||
await check('Archify | New Diagram… → Model creates main.archify from the folder name', async () => {
|
await check('Archify | New Diagram… → Model creates main.archify from the folder name', async () => {
|
||||||
const folder = workspaceFile('new-shop');
|
const folder = workspaceFile('new-shop');
|
||||||
await vscode.workspace.fs.createDirectory(folder);
|
await vscode.workspace.fs.createDirectory(folder);
|
||||||
|
|||||||
Reference in New Issue
Block a user