feat: introduce archify skill for generating architecture diagrams
- Added a new Archify skill, enabling users to create polished architecture, workflow, sequence, data-flow, and lifecycle diagrams. - Implemented comprehensive functionality including rendering, validation, and delivery of diagrams in various formats. - Integrated a user-friendly command-line interface for generating and previewing diagrams. - Developed supporting files including package.json, LICENSE, and SKILL.md for documentation and licensing. - Added unit tests to ensure reliability and functionality of the new skill. These changes enhance the application by providing a structured approach to visualizing system architecture and workflows, improving user experience and data representation.
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import path from 'node:path';
|
||||
|
||||
import { openArtifact, openLoopbackUrl } from '../bin/open-artifact.mjs';
|
||||
|
||||
const target = path.resolve("/tmp/-复杂 path 'quoted'/diagram.html");
|
||||
|
||||
test('open artifact: uses argument arrays without shell interpolation on every supported platform', () => {
|
||||
const cases = [
|
||||
{
|
||||
platform: 'darwin',
|
||||
command: 'open',
|
||||
args: [target],
|
||||
method: 'open',
|
||||
},
|
||||
{
|
||||
platform: 'linux',
|
||||
command: 'xdg-open',
|
||||
args: [target],
|
||||
method: 'xdg-open',
|
||||
},
|
||||
{
|
||||
platform: 'win32',
|
||||
command: 'powershell.exe',
|
||||
args: [
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-Command',
|
||||
'Start-Process -FilePath $args[0]',
|
||||
target,
|
||||
],
|
||||
method: 'powershell',
|
||||
},
|
||||
];
|
||||
|
||||
for (const expected of cases) {
|
||||
let invocation;
|
||||
const result = openArtifact(target, {
|
||||
platform: expected.platform,
|
||||
spawn(command, args, options) {
|
||||
invocation = { command, args, options };
|
||||
return { status: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(result, {
|
||||
requested: true,
|
||||
status: 'opened',
|
||||
target,
|
||||
method: expected.method,
|
||||
});
|
||||
assert.equal(invocation.command, expected.command);
|
||||
assert.deepEqual(invocation.args, expected.args);
|
||||
assert.equal(invocation.options.shell, false);
|
||||
assert.equal(invocation.options.timeout, 5000);
|
||||
}
|
||||
});
|
||||
|
||||
test('open artifact: distinguishes missing support from opener execution failure', () => {
|
||||
const missing = openArtifact(target, {
|
||||
platform: 'linux',
|
||||
spawn() {
|
||||
return { error: Object.assign(new Error('missing'), { code: 'ENOENT' }) };
|
||||
},
|
||||
});
|
||||
assert.equal(missing.status, 'unsupported');
|
||||
assert.equal(missing.method, 'xdg-open');
|
||||
|
||||
const timedOut = openArtifact(target, {
|
||||
platform: 'darwin',
|
||||
spawn() {
|
||||
return { error: Object.assign(new Error('timed out'), { code: 'ETIMEDOUT' }) };
|
||||
},
|
||||
});
|
||||
assert.equal(timedOut.status, 'failed');
|
||||
assert.equal(timedOut.method, 'open');
|
||||
|
||||
const unknown = openArtifact(target, { platform: 'plan9' });
|
||||
assert.deepEqual(unknown, {
|
||||
requested: true,
|
||||
status: 'unsupported',
|
||||
target,
|
||||
method: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('open artifact: live preview opens only an exact loopback HTTP root', () => {
|
||||
const url = 'http://127.0.0.1:43127/';
|
||||
let invocation;
|
||||
const result = openLoopbackUrl(url, {
|
||||
platform: 'darwin',
|
||||
spawn(command, args, options) {
|
||||
invocation = { command, args, options };
|
||||
return { status: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(result, {
|
||||
requested: true,
|
||||
status: 'opened',
|
||||
target: url,
|
||||
method: 'open',
|
||||
});
|
||||
assert.deepEqual(invocation.args, [url]);
|
||||
assert.equal(invocation.options.shell, false);
|
||||
|
||||
for (const rejected of [
|
||||
'https://127.0.0.1:43127/',
|
||||
'http://localhost:43127/',
|
||||
'http://0.0.0.0:43127/',
|
||||
'http://127.0.0.1:43127/path',
|
||||
'http://127.0.0.1:43127/?source=secret',
|
||||
'not a url',
|
||||
]) {
|
||||
assert.throws(() => openLoopbackUrl(rejected), /loopback|valid/i, rejected);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user