@meltemi/diagrams-cli 0.0.0-stage → 1.9.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.
- package/LICENSE +21 -0
- package/README.md +58 -2
- package/dist/assets-command.d.ts +16 -0
- package/dist/assets-command.d.ts.map +1 -0
- package/dist/assets-command.js +145 -0
- package/dist/assets-command.js.map +1 -0
- package/dist/assist-command.d.ts +19 -0
- package/dist/assist-command.d.ts.map +1 -0
- package/dist/assist-command.js +268 -0
- package/dist/assist-command.js.map +1 -0
- package/dist/auth-command.d.ts +14 -0
- package/dist/auth-command.d.ts.map +1 -0
- package/dist/auth-command.js +233 -0
- package/dist/auth-command.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +60 -0
- package/dist/bin.js.map +1 -0
- package/dist/build-command.d.ts +23 -0
- package/dist/build-command.d.ts.map +1 -0
- package/dist/build-command.js +123 -0
- package/dist/build-command.js.map +1 -0
- package/dist/cli.d.ts +46 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +823 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud-client.d.ts +246 -0
- package/dist/cloud-client.d.ts.map +1 -0
- package/dist/cloud-client.js +591 -0
- package/dist/cloud-client.js.map +1 -0
- package/dist/cloud-command.d.ts +56 -0
- package/dist/cloud-command.d.ts.map +1 -0
- package/dist/cloud-command.js +81 -0
- package/dist/cloud-command.js.map +1 -0
- package/dist/cloud-context.d.ts +106 -0
- package/dist/cloud-context.d.ts.map +1 -0
- package/dist/cloud-context.js +185 -0
- package/dist/cloud-context.js.map +1 -0
- package/dist/cloud-errors.d.ts +37 -0
- package/dist/cloud-errors.d.ts.map +1 -0
- package/dist/cloud-errors.js +46 -0
- package/dist/cloud-errors.js.map +1 -0
- package/dist/cloud-host.d.ts +72 -0
- package/dist/cloud-host.d.ts.map +1 -0
- package/dist/cloud-host.js +129 -0
- package/dist/cloud-host.js.map +1 -0
- package/dist/cloud-manifest.d.ts +12 -0
- package/dist/cloud-manifest.d.ts.map +1 -0
- package/dist/cloud-manifest.js +21 -0
- package/dist/cloud-manifest.js.map +1 -0
- package/dist/cloud-paths.d.ts +48 -0
- package/dist/cloud-paths.d.ts.map +1 -0
- package/dist/cloud-paths.js +104 -0
- package/dist/cloud-paths.js.map +1 -0
- package/dist/credentials.d.ts +107 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +243 -0
- package/dist/credentials.js.map +1 -0
- package/dist/export-command.d.ts +35 -0
- package/dist/export-command.d.ts.map +1 -0
- package/dist/export-command.js +524 -0
- package/dist/export-command.js.map +1 -0
- package/dist/import-command.d.ts +20 -0
- package/dist/import-command.d.ts.map +1 -0
- package/dist/import-command.js +254 -0
- package/dist/import-command.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/init-command.d.ts +28 -0
- package/dist/init-command.d.ts.map +1 -0
- package/dist/init-command.js +199 -0
- package/dist/init-command.js.map +1 -0
- package/dist/login-listener.d.ts +58 -0
- package/dist/login-listener.d.ts.map +1 -0
- package/dist/login-listener.js +173 -0
- package/dist/login-listener.js.map +1 -0
- package/dist/messages/en.d.ts +533 -0
- package/dist/messages/en.d.ts.map +1 -0
- package/dist/messages/en.js +803 -0
- package/dist/messages/en.js.map +1 -0
- package/dist/messages/es.d.ts +3 -0
- package/dist/messages/es.d.ts.map +1 -0
- package/dist/messages/es.js +764 -0
- package/dist/messages/es.js.map +1 -0
- package/dist/messages/index.d.ts +442 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +42 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/push-pull-en.d.ts +84 -0
- package/dist/messages/push-pull-en.d.ts.map +1 -0
- package/dist/messages/push-pull-en.js +146 -0
- package/dist/messages/push-pull-en.js.map +1 -0
- package/dist/messages/push-pull-es.d.ts +7 -0
- package/dist/messages/push-pull-es.d.ts.map +1 -0
- package/dist/messages/push-pull-es.js +144 -0
- package/dist/messages/push-pull-es.js.map +1 -0
- package/dist/open-url.d.ts +11 -0
- package/dist/open-url.d.ts.map +1 -0
- package/dist/open-url.js +36 -0
- package/dist/open-url.js.map +1 -0
- package/dist/plugins-command.d.ts +15 -0
- package/dist/plugins-command.d.ts.map +1 -0
- package/dist/plugins-command.js +106 -0
- package/dist/plugins-command.js.map +1 -0
- package/dist/preview.d.ts +54 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +249 -0
- package/dist/preview.js.map +1 -0
- package/dist/project-errors.d.ts +17 -0
- package/dist/project-errors.d.ts.map +1 -0
- package/dist/project-errors.js +85 -0
- package/dist/project-errors.js.map +1 -0
- package/dist/projects-command.d.ts +13 -0
- package/dist/projects-command.d.ts.map +1 -0
- package/dist/projects-command.js +85 -0
- package/dist/projects-command.js.map +1 -0
- package/dist/publish-command.d.ts +41 -0
- package/dist/publish-command.d.ts.map +1 -0
- package/dist/publish-command.js +311 -0
- package/dist/publish-command.js.map +1 -0
- package/dist/pull-command.d.ts +21 -0
- package/dist/pull-command.d.ts.map +1 -0
- package/dist/pull-command.js +300 -0
- package/dist/pull-command.js.map +1 -0
- package/dist/push-command.d.ts +31 -0
- package/dist/push-command.d.ts.map +1 -0
- package/dist/push-command.js +391 -0
- package/dist/push-command.js.map +1 -0
- package/dist/push-review.d.ts +16 -0
- package/dist/push-review.d.ts.map +1 -0
- package/dist/push-review.js +72 -0
- package/dist/push-review.js.map +1 -0
- package/dist/push-set.d.ts +126 -0
- package/dist/push-set.d.ts.map +1 -0
- package/dist/push-set.js +289 -0
- package/dist/push-set.js.map +1 -0
- package/dist/push-validation.d.ts +20 -0
- package/dist/push-validation.d.ts.map +1 -0
- package/dist/push-validation.js +70 -0
- package/dist/push-validation.js.map +1 -0
- package/dist/redact.d.ts +9 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +22 -0
- package/dist/redact.js.map +1 -0
- package/dist/review-command.d.ts +44 -0
- package/dist/review-command.d.ts.map +1 -0
- package/dist/review-command.js +348 -0
- package/dist/review-command.js.map +1 -0
- package/package.json +56 -3
- package/templates/c4/diagrams/views.meltemi +16 -0
- package/templates/c4/models/system.meltemi +23 -0
- package/templates/ci/github.yml +96 -0
- package/templates/ci/gitlab.yml +53 -0
- package/templates/flow/diagrams/overview.meltemi +15 -0
- package/templates/free/diagrams/slide.meltemi +39 -0
- package/templates/purchase/diagrams/architecture.meltemi +36 -0
- package/templates/purchase/diagrams/executive.meltemi +52 -0
- package/templates/purchase/diagrams/payment.meltemi +42 -0
- package/templates/purchase/models/commerce.meltemi +30 -0
- package/templates/purchase/stories/purchase.meltemi +38 -0
- package/templates/sequence/diagrams/sign-in.meltemi +36 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { getLocale } from "@meltemi/diagrams-i18n";
|
|
2
|
+
import { mkdirSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
import { ProjectSessions, REVIEW_COLOURS, gitRevisionHost, reviewProjects, } from "@meltemi/diagrams-editor/node";
|
|
6
|
+
import { describeChange } from "@meltemi/diagrams-model";
|
|
7
|
+
import { toProjectPath } from "@meltemi/diagrams-project";
|
|
8
|
+
import { createNodeHost } from "@meltemi/diagrams-project/node";
|
|
9
|
+
import { cloudHost } from "./cloud-host.js";
|
|
10
|
+
import { printablePath } from "./cloud-paths.js";
|
|
11
|
+
import { openCloud, reportCloudError } from "./cloud-context.js";
|
|
12
|
+
import { CloudError } from "./cloud-errors.js";
|
|
13
|
+
import { argumentsError, messages } from "./messages/index.js";
|
|
14
|
+
import { redactSecrets } from "./redact.js";
|
|
15
|
+
/**
|
|
16
|
+
* What `--base` names when it is the cloud: `cloud` (the project's current files) or `cloud:<n>`
|
|
17
|
+
* (version `n`); `invalid` for `cloud:` and `cloud:x`; undefined for a Git revision.
|
|
18
|
+
*/
|
|
19
|
+
export function parseCloudBase(base) {
|
|
20
|
+
if (base === "cloud")
|
|
21
|
+
return { version: undefined };
|
|
22
|
+
if (base === undefined || !base.startsWith("cloud:"))
|
|
23
|
+
return undefined;
|
|
24
|
+
return /^cloud:[0-9]{1,9}$/.test(base) ? { version: Number(base.slice(6)) } : "invalid";
|
|
25
|
+
}
|
|
26
|
+
const EXIT_OK = 0;
|
|
27
|
+
const EXIT_FINDINGS = 1;
|
|
28
|
+
const EXIT_USAGE = 2;
|
|
29
|
+
const SIGNS = {
|
|
30
|
+
added: "+",
|
|
31
|
+
removed: "-",
|
|
32
|
+
renamed: ">",
|
|
33
|
+
changed: "~",
|
|
34
|
+
};
|
|
35
|
+
function exists(path) {
|
|
36
|
+
try {
|
|
37
|
+
return statSync(path).isDirectory() ? "folder" : "file";
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Counts of changes by kind, over every file. */
|
|
44
|
+
export function reviewSummary(review) {
|
|
45
|
+
const counts = { files: review.files.length, added: 0, removed: 0, renamed: 0, changed: 0 };
|
|
46
|
+
for (const file of review.files)
|
|
47
|
+
for (const c of file.changes)
|
|
48
|
+
counts[c.kind]++;
|
|
49
|
+
return counts;
|
|
50
|
+
}
|
|
51
|
+
/** The summary of a review, in the interface language or the one given. */
|
|
52
|
+
function summaryLine(review, locale = getLocale()) {
|
|
53
|
+
const s = reviewSummary(review);
|
|
54
|
+
const t = messages(locale).review;
|
|
55
|
+
if (s.files === 0)
|
|
56
|
+
return t.none;
|
|
57
|
+
return t.summary(s.files, s.added, s.removed, s.renamed, s.changed);
|
|
58
|
+
}
|
|
59
|
+
/** The changes of a file, grouped under the diagram, model or story they are in. */
|
|
60
|
+
function fileLines(file) {
|
|
61
|
+
const head = file.status === "renamed" ? `${file.from} → ${file.path}` : `${file.path}`;
|
|
62
|
+
const lines = [`${SIGNS[file.status]} ${head}`];
|
|
63
|
+
const top = file.changes.filter((c) => c.scope === null);
|
|
64
|
+
for (const c of top) {
|
|
65
|
+
lines.push(` ${describeChange(c)}`);
|
|
66
|
+
const inside = file.changes.filter((x) => x.scope === c.id);
|
|
67
|
+
for (const x of inside)
|
|
68
|
+
lines.push(` ${describeChange(x)}`);
|
|
69
|
+
}
|
|
70
|
+
// Scopes whose block itself did not change.
|
|
71
|
+
const scopes = [...new Set(file.changes.map((c) => c.scope).filter((s) => s !== null))];
|
|
72
|
+
const t = messages().review;
|
|
73
|
+
for (const scope of scopes) {
|
|
74
|
+
if (top.some((c) => c.id === scope))
|
|
75
|
+
continue;
|
|
76
|
+
const kind = file.scopes[scope];
|
|
77
|
+
lines.push(` ${kind === undefined ? t.block : t.scopes[kind]} ${scope}`);
|
|
78
|
+
for (const x of file.changes.filter((c) => c.scope === scope)) {
|
|
79
|
+
lines.push(` ${describeChange(x)}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return lines;
|
|
83
|
+
}
|
|
84
|
+
const escape = (text) => text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
85
|
+
const baseName = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
86
|
+
const url = (path) => path.split("/").map(encodeURIComponent).join("/");
|
|
87
|
+
/**
|
|
88
|
+
* The review page: the changes of every file and the pictures of its changed diagrams, with its
|
|
89
|
+
* words in `locale`, the language of the files the command writes (never the machine's).
|
|
90
|
+
*/
|
|
91
|
+
export function reviewPage(review, title, compared, pictures, locale = "en") {
|
|
92
|
+
const t = messages(locale).review.page;
|
|
93
|
+
const kind = (c) => c.kind;
|
|
94
|
+
const sections = review.files.map((file) => {
|
|
95
|
+
const changes = file.changes
|
|
96
|
+
.map((c) => `<li class="${kind(c)}">${escape(describeChange(c, locale))}${c.scope ? ` <span class="in">${escape(t.in(c.scope))}</span>` : ""}</li>`)
|
|
97
|
+
.join("");
|
|
98
|
+
const diagrams = file.diagrams
|
|
99
|
+
.map((d) => {
|
|
100
|
+
const key = `${file.path}#${d.id}`;
|
|
101
|
+
const files = pictures.get(key);
|
|
102
|
+
const figure = (which, src) => `<figure><figcaption>${which === "before" ? t.before : t.after}</figcaption>${src
|
|
103
|
+
? `<img src="${escape(url(src))}" alt="${escape(t.picture(d.id, which))}">`
|
|
104
|
+
: `<p class="none">${which === "before" ? t.new : t.removed}</p>`}</figure>`;
|
|
105
|
+
return `<h3>${escape(t.diagram(d.from && d.from !== d.id ? `${d.from} → ${d.id}` : d.id))}</h3><div class="pair">${figure("before", files?.before)}${figure("after", files?.after)}</div>`;
|
|
106
|
+
})
|
|
107
|
+
.join("");
|
|
108
|
+
const head = file.status === "renamed" ? `${file.from} → ${file.path}` : file.path;
|
|
109
|
+
return `<section><h2><span class="status ${file.status}">${t.status[file.status]}</span> ${escape(head)}</h2><ul class="changes">${changes}</ul>${diagrams}</section>`;
|
|
110
|
+
});
|
|
111
|
+
const legend = Object.keys(REVIEW_COLOURS)
|
|
112
|
+
.map((k) => `<span><i style="border-color:${REVIEW_COLOURS[k]}"></i>${t.status[k]}</span>`)
|
|
113
|
+
.join("");
|
|
114
|
+
return `<!doctype html>
|
|
115
|
+
<html lang="${locale}">
|
|
116
|
+
<head>
|
|
117
|
+
<meta charset="utf-8">
|
|
118
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
119
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'">
|
|
120
|
+
<title>${escape(`${t.title} · ${title}`)}</title>
|
|
121
|
+
<style>
|
|
122
|
+
:root { color-scheme: light dark; --bg: #f6f7f9; --panel: #fff; --fg: #1b1f24; --muted: #59626e; --line: #d8dde4; }
|
|
123
|
+
@media (prefers-color-scheme: dark) { :root { --bg: #0f1216; --panel: #171b21; --fg: #e6e9ee; --muted: #9ba5b2; --line: #2c323b; } }
|
|
124
|
+
body { margin: 0; background: var(--bg); color: var(--fg); font: 15px/1.5 system-ui, sans-serif; }
|
|
125
|
+
main { max-width: 1400px; margin: 0 auto; padding: 24px 16px 48px; }
|
|
126
|
+
h1 { margin: 0 0 4px; font-size: 1.6rem; }
|
|
127
|
+
h2 { margin: 32px 0 8px; font-size: 1.1rem; }
|
|
128
|
+
h3 { margin: 16px 0 8px; font-size: 1rem; }
|
|
129
|
+
.lead, .in, .none { color: var(--muted); }
|
|
130
|
+
.legend { display: flex; flex-wrap: wrap; gap: 16px; color: var(--muted); }
|
|
131
|
+
.legend i { display: inline-block; width: 12px; height: 12px; margin-right: 6px; border: 3px solid; border-radius: 3px; vertical-align: -2px; }
|
|
132
|
+
.status { display: inline-block; padding: 0 6px; border-radius: 4px; font-size: 0.75rem; text-transform: uppercase; color: #fff; }
|
|
133
|
+
.status.added { background: ${REVIEW_COLOURS.added}; } .status.removed { background: ${REVIEW_COLOURS.removed}; }
|
|
134
|
+
.status.renamed { background: ${REVIEW_COLOURS.renamed}; } .status.changed { background: ${REVIEW_COLOURS.changed}; }
|
|
135
|
+
.changes { padding-left: 1.2em; font: 0.9rem/1.6 ui-monospace, "Cascadia Mono", Consolas, monospace; }
|
|
136
|
+
.changes .added { color: ${REVIEW_COLOURS.added}; } .changes .removed { color: ${REVIEW_COLOURS.removed}; }
|
|
137
|
+
.changes .renamed { color: ${REVIEW_COLOURS.renamed}; }
|
|
138
|
+
.pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
|
|
139
|
+
figure { margin: 0; padding: 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); }
|
|
140
|
+
figcaption { margin-bottom: 6px; color: var(--muted); font-size: 0.85rem; }
|
|
141
|
+
figure img { display: block; max-width: 100%; max-height: 80vh; width: auto; height: auto; margin: 0 auto; }
|
|
142
|
+
</style>
|
|
143
|
+
</head>
|
|
144
|
+
<body>
|
|
145
|
+
<main>
|
|
146
|
+
<h1>${escape(t.title)}</h1>
|
|
147
|
+
<p class="lead">${escape(`${compared}. ${summaryLine(review, locale)}`)}</p>
|
|
148
|
+
<p class="legend">${legend}</p>
|
|
149
|
+
${sections.join("\n")}
|
|
150
|
+
</main>
|
|
151
|
+
</body>
|
|
152
|
+
</html>
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
/** `meltemi-diagrams review`; asynchronous, because `--base cloud` reads the cloud project first. */
|
|
156
|
+
export async function reviewCommand(args, context) {
|
|
157
|
+
/** What the command prints and writes: with a cloud context, without any token in it. */
|
|
158
|
+
const clean = (text) => context.cloud ? redactSecrets(text, context.cloud.env) : text;
|
|
159
|
+
const stdout = (text) => context.stdout(clean(text));
|
|
160
|
+
const stderr = (text) => context.stderr(clean(text));
|
|
161
|
+
const fail = (message) => {
|
|
162
|
+
stderr(`${context.name} review: ${message}\n`);
|
|
163
|
+
return EXIT_USAGE;
|
|
164
|
+
};
|
|
165
|
+
let options;
|
|
166
|
+
let paths;
|
|
167
|
+
try {
|
|
168
|
+
const parsed = parseArgs({
|
|
169
|
+
args: [...args],
|
|
170
|
+
options: {
|
|
171
|
+
base: { type: "string" },
|
|
172
|
+
before: { type: "string" },
|
|
173
|
+
out: { type: "string" },
|
|
174
|
+
project: { type: "string" },
|
|
175
|
+
host: { type: "string" },
|
|
176
|
+
json: { type: "boolean", default: false },
|
|
177
|
+
"exit-code": { type: "boolean", default: false },
|
|
178
|
+
help: { type: "boolean", short: "h", default: false },
|
|
179
|
+
},
|
|
180
|
+
allowPositionals: true,
|
|
181
|
+
strict: true,
|
|
182
|
+
});
|
|
183
|
+
options = parsed.values;
|
|
184
|
+
paths = parsed.positionals;
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return fail(argumentsError(error));
|
|
188
|
+
}
|
|
189
|
+
const t = messages().review;
|
|
190
|
+
if (options.help) {
|
|
191
|
+
stdout(messages().help.review);
|
|
192
|
+
return EXIT_OK;
|
|
193
|
+
}
|
|
194
|
+
if (paths.length > 1)
|
|
195
|
+
return fail(messages().common.oneProjectFolderOrFile);
|
|
196
|
+
if (options.base !== undefined && options.before !== undefined)
|
|
197
|
+
return fail(t.baseOrBefore);
|
|
198
|
+
const cloudBase = parseCloudBase(options.base);
|
|
199
|
+
if (cloudBase === "invalid")
|
|
200
|
+
return fail(t.cloudVersion);
|
|
201
|
+
if (cloudBase === undefined && (options.project !== undefined || options.host !== undefined)) {
|
|
202
|
+
return fail(t.cloudOptions);
|
|
203
|
+
}
|
|
204
|
+
const target = toProjectPath(resolve(context.cwd, paths[0] ?? "."));
|
|
205
|
+
const kind = exists(target);
|
|
206
|
+
if (!kind)
|
|
207
|
+
return fail(messages().common.pathNotFound(paths[0] ?? "."));
|
|
208
|
+
const scopeOf = (path, isFolder, workspace) => isFolder && path === workspace.root ? null : path;
|
|
209
|
+
const afterProjects = new ProjectSessions({
|
|
210
|
+
toolVersion: context.toolVersion,
|
|
211
|
+
...localeOf(context),
|
|
212
|
+
});
|
|
213
|
+
const afterWorkspace = kind === "folder" ? afterProjects.forFolder(target) : afterProjects.forFile(target);
|
|
214
|
+
const after = {
|
|
215
|
+
workspace: afterWorkspace,
|
|
216
|
+
projects: afterProjects,
|
|
217
|
+
scope: scopeOf(target, kind === "folder", afterWorkspace),
|
|
218
|
+
};
|
|
219
|
+
let before;
|
|
220
|
+
/** What was compared, in a language: the terminal's, or the report's. */
|
|
221
|
+
let compared;
|
|
222
|
+
if (options.before !== undefined) {
|
|
223
|
+
const path = toProjectPath(resolve(context.cwd, options.before));
|
|
224
|
+
const beforeKind = exists(path);
|
|
225
|
+
if (!beforeKind)
|
|
226
|
+
return fail(messages().common.pathNotFound(options.before));
|
|
227
|
+
if (beforeKind !== kind)
|
|
228
|
+
return fail(t.sameKinds);
|
|
229
|
+
const projects = new ProjectSessions({
|
|
230
|
+
toolVersion: context.toolVersion,
|
|
231
|
+
...localeOf(context),
|
|
232
|
+
host: createNodeHost(),
|
|
233
|
+
});
|
|
234
|
+
const workspace = kind === "folder" ? projects.forFolder(path) : projects.forFile(path);
|
|
235
|
+
before = { workspace, projects, scope: scopeOf(path, kind === "folder", workspace) };
|
|
236
|
+
// Names, not paths: the page is shared, and paths would tell where the files live.
|
|
237
|
+
compared = (locale) => messages(locale).review.comparedPaths(baseName(path), baseName(target));
|
|
238
|
+
}
|
|
239
|
+
else if (cloudBase !== undefined) {
|
|
240
|
+
const cloud = context.cloud;
|
|
241
|
+
if (cloud === undefined)
|
|
242
|
+
return fail(t.cloudUnavailable);
|
|
243
|
+
let host;
|
|
244
|
+
let project;
|
|
245
|
+
try {
|
|
246
|
+
const manifest = afterWorkspace.manifest().manifest;
|
|
247
|
+
// The manifest never chooses the host (`cloud.host-mismatch`); it names the project.
|
|
248
|
+
const named = options.project ?? manifest?.cloud?.project;
|
|
249
|
+
if (named === undefined) {
|
|
250
|
+
throw new CloudError("cloud.no-project", "The folder names no cloud project.");
|
|
251
|
+
}
|
|
252
|
+
project = named;
|
|
253
|
+
cloud.used.project = project;
|
|
254
|
+
const { client } = openCloud(cloud, {
|
|
255
|
+
host: options.host,
|
|
256
|
+
manifestHost: manifest?.cloud?.host,
|
|
257
|
+
});
|
|
258
|
+
host = await cloudHost(client, {
|
|
259
|
+
project,
|
|
260
|
+
root: afterWorkspace.root,
|
|
261
|
+
...(cloudBase.version === undefined ? {} : { version: cloudBase.version }),
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
if (error instanceof CloudError)
|
|
266
|
+
return reportCloudError(error, cloud);
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
const projects = new ProjectSessions({
|
|
270
|
+
toolVersion: context.toolVersion,
|
|
271
|
+
host,
|
|
272
|
+
...localeOf(context),
|
|
273
|
+
});
|
|
274
|
+
const workspace = kind === "folder" ? projects.forFolder(target) : projects.forFile(target);
|
|
275
|
+
before = { workspace, projects, scope: scopeOf(target, kind === "folder", workspace) };
|
|
276
|
+
compared = (locale) => messages(locale).review.comparedCloud(project, cloudBase.version);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
const revision = options.base ?? "HEAD";
|
|
280
|
+
const host = gitRevisionHost(kind === "folder" ? target : dirname(target), revision);
|
|
281
|
+
if (typeof host === "string")
|
|
282
|
+
return fail(host);
|
|
283
|
+
const projects = new ProjectSessions({
|
|
284
|
+
toolVersion: context.toolVersion,
|
|
285
|
+
host,
|
|
286
|
+
...localeOf(context),
|
|
287
|
+
});
|
|
288
|
+
const workspace = kind === "folder" ? projects.forFolder(target) : projects.forFile(target);
|
|
289
|
+
before = { workspace, projects, scope: scopeOf(target, kind === "folder", workspace) };
|
|
290
|
+
compared = (locale) => messages(locale).review.comparedRevision(revision);
|
|
291
|
+
}
|
|
292
|
+
const review = reviewProjects(before, after, { images: options.out !== undefined });
|
|
293
|
+
const changed = review.files.length > 0;
|
|
294
|
+
if (options.out !== undefined) {
|
|
295
|
+
const out = resolve(context.cwd, options.out);
|
|
296
|
+
const pictures = new Map();
|
|
297
|
+
try {
|
|
298
|
+
for (const file of review.files) {
|
|
299
|
+
for (const diagram of file.diagrams) {
|
|
300
|
+
const stem = file.path.replace(/\.meltemi$/, "");
|
|
301
|
+
const write = (which, svg) => {
|
|
302
|
+
if (svg === null)
|
|
303
|
+
return null;
|
|
304
|
+
const name = `${stem}/${diagram.id}.${which}.svg`;
|
|
305
|
+
mkdirSync(dirname(join(out, name)), { recursive: true });
|
|
306
|
+
writeFileSync(join(out, name), clean(svg));
|
|
307
|
+
return name;
|
|
308
|
+
};
|
|
309
|
+
pictures.set(`${file.path}#${diagram.id}`, {
|
|
310
|
+
before: write("before", diagram.before),
|
|
311
|
+
after: write("after", diagram.after),
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
mkdirSync(out, { recursive: true });
|
|
316
|
+
const title = afterWorkspace.manifest().manifest?.name ?? context.display(target);
|
|
317
|
+
// The report is a written file: `--lang`, else the project's `locale`, else English.
|
|
318
|
+
const locale = afterProjects.contentLocale(afterWorkspace);
|
|
319
|
+
writeFileSync(join(out, "index.html"), clean(reviewPage(review, title, compared(locale), pictures, locale)));
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
return fail(messages().common.cannotWrite(context.display(out), error.message));
|
|
323
|
+
}
|
|
324
|
+
if (!options.json) {
|
|
325
|
+
stdout(`${messages().common.wrote(context.display(join(out, "index.html")))}\n`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (options.json) {
|
|
329
|
+
stdout(`${JSON.stringify({
|
|
330
|
+
compared: compared(getLocale()),
|
|
331
|
+
files: review.files.map(({ diagrams: _d, ...file }) => file),
|
|
332
|
+
summary: reviewSummary(review),
|
|
333
|
+
}, null, 2)}\n`);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
// The labels may come from the cloud's texts, which a collaborator wrote: control characters
|
|
337
|
+
// (an escape sequence could repaint the terminal) are written out.
|
|
338
|
+
for (const file of review.files)
|
|
339
|
+
stdout(`${fileLines(file).map(printablePath).join("\n")}\n`);
|
|
340
|
+
stdout(`${summaryLine(review)}\n`);
|
|
341
|
+
}
|
|
342
|
+
return changed && options["exit-code"] ? EXIT_FINDINGS : EXIT_OK;
|
|
343
|
+
}
|
|
344
|
+
/** The session option for the language of written files, when the command was given one. */
|
|
345
|
+
function localeOf(context) {
|
|
346
|
+
return context.locale ? { locale: context.locale } : {};
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=review-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-command.js","sourceRoot":"","sources":["../src/review-command.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meltemi/diagrams-cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.9.0",
|
|
4
|
+
"description": "Command line interface (meltemi-diagrams, alias mdg) for .meltemi projects.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/askenaz-dev/meltemi-diagrams.git",
|
|
9
|
+
"directory": "packages/cli"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/askenaz-dev/meltemi-diagrams/tree/main/packages/cli#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/askenaz-dev/meltemi-diagrams/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=22.12.0"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"bin": {
|
|
20
|
+
"meltemi-diagrams": "./dist/bin.js",
|
|
21
|
+
"mdg": "./dist/bin.js"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"templates"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@meltemi/diagrams-assets": "1.9.0",
|
|
35
|
+
"@meltemi/diagrams-assist": "1.9.0",
|
|
36
|
+
"@meltemi/diagrams-capture": "1.9.0",
|
|
37
|
+
"@meltemi/diagrams-catalog": "1.9.0",
|
|
38
|
+
"@meltemi/diagrams-edit": "1.9.0",
|
|
39
|
+
"@meltemi/diagrams-fonts": "1.9.0",
|
|
40
|
+
"@meltemi/diagrams-i18n": "1.9.0",
|
|
41
|
+
"@meltemi/diagrams-editor": "1.9.0",
|
|
42
|
+
"@meltemi/diagrams-import": "1.9.0",
|
|
43
|
+
"@meltemi/diagrams-layout": "1.9.0",
|
|
44
|
+
"@meltemi/diagrams-layout-elk": "1.9.0",
|
|
45
|
+
"@meltemi/diagrams-model": "1.9.0",
|
|
46
|
+
"@meltemi/diagrams-language": "1.9.0",
|
|
47
|
+
"@meltemi/diagrams-motion": "1.9.0",
|
|
48
|
+
"@meltemi/diagrams-project": "1.9.0",
|
|
49
|
+
"@meltemi/diagrams-render": "1.9.0",
|
|
50
|
+
"@meltemi/diagrams-player": "1.9.0"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "tsc -p tsconfig.build.json",
|
|
57
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
58
|
+
}
|
|
6
59
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
language "0.2"
|
|
2
|
+
|
|
3
|
+
import system from "../models/system.meltemi"
|
|
4
|
+
|
|
5
|
+
// Two views of the same model: the product in its context, and the containers inside it.
|
|
6
|
+
diagram context: c4 using system {
|
|
7
|
+
title "System context"
|
|
8
|
+
level context
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
diagram containers: c4 using system {
|
|
12
|
+
title "Containers"
|
|
13
|
+
level container
|
|
14
|
+
scope product
|
|
15
|
+
direction LR
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
language "0.2"
|
|
2
|
+
|
|
3
|
+
// The architecture model: people, systems, containers and how they talk. Views choose what to
|
|
4
|
+
// show; renaming an entity here renames it in every view.
|
|
5
|
+
model system {
|
|
6
|
+
person user "User" { description "Uses the product" }
|
|
7
|
+
|
|
8
|
+
system product "Product" {
|
|
9
|
+
description "What the team builds"
|
|
10
|
+
container web "Web app" { technology "TypeScript" }
|
|
11
|
+
container api "API" { technology "Kotlin" }
|
|
12
|
+
datastore db "Database" { technology "PostgreSQL" }
|
|
13
|
+
}
|
|
14
|
+
system email "Email service" {
|
|
15
|
+
description "Sends notifications"
|
|
16
|
+
external
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
user -> product.web: "Uses" as uses
|
|
20
|
+
product.web -> product.api: "Calls" as calls { technology "JSON/HTTPS" }
|
|
21
|
+
product.api -> product.db: "Reads and writes" as stores
|
|
22
|
+
product.api -> email: "Sends emails" as notifies
|
|
23
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Meltemi Diagrams: validate the project, review what changed in pull requests, and build the
|
|
2
|
+
# catalog. Written by `meltemi-diagrams init --ci github`; edit it freely.
|
|
3
|
+
name: Meltemi Diagrams
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
env:
|
|
14
|
+
PROJECT: "{{project}}"
|
|
15
|
+
MELTEMI_DIAGRAMS: "@meltemi/diagrams-cli@{{version}}"
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
diagrams:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
# The review compares with the base branch, so the history is needed.
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: 22
|
|
29
|
+
|
|
30
|
+
- name: Validate
|
|
31
|
+
run: npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams validate "$PROJECT" --strict
|
|
32
|
+
|
|
33
|
+
- name: Review
|
|
34
|
+
if: github.event_name == 'pull_request'
|
|
35
|
+
# The base branch comes from the environment, never written into the script.
|
|
36
|
+
run: |
|
|
37
|
+
{
|
|
38
|
+
echo '### Diagram changes'
|
|
39
|
+
echo '```text'
|
|
40
|
+
npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams review "$PROJECT" --base "origin/$GITHUB_BASE_REF" --out review
|
|
41
|
+
echo '```'
|
|
42
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
43
|
+
|
|
44
|
+
- name: Catalog
|
|
45
|
+
run: npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams build catalog "$PROJECT" --out catalog
|
|
46
|
+
|
|
47
|
+
# PNG, PDF and video profiles use the runner's Chrome; video also needs FFmpeg:
|
|
48
|
+
# - run: sudo apt-get update && sudo apt-get install -y ffmpeg
|
|
49
|
+
# - run: npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams export "$PROJECT" --profiles --out exports
|
|
50
|
+
|
|
51
|
+
- uses: actions/upload-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: diagrams
|
|
54
|
+
path: |
|
|
55
|
+
catalog
|
|
56
|
+
review
|
|
57
|
+
if-no-files-found: ignore
|
|
58
|
+
|
|
59
|
+
# {{cloud-begin}}
|
|
60
|
+
# The job below is written by `meltemi-diagrams init --ci github --cloud` only: it mirrors the
|
|
61
|
+
# project in the Meltemi cloud on every push to the default branch, so that the page, the share
|
|
62
|
+
# links and the published catalog follow the repository.
|
|
63
|
+
#
|
|
64
|
+
# The repository is the truth, so this job pushes with --force: CI cannot answer the question a
|
|
65
|
+
# push asks when the cloud holds something the folder lacks (a diagram somebody drew in the
|
|
66
|
+
# page), and a job that waits for an answer would hang. --strict refuses a project with errors.
|
|
67
|
+
# What differs in the cloud is overwritten; pull it first if it should survive.
|
|
68
|
+
#
|
|
69
|
+
# The job runs on the repository's default branch, and the workflow starts on pushes to main
|
|
70
|
+
# only (`on:` above): edit the branches there if the default branch has another name.
|
|
71
|
+
#
|
|
72
|
+
# MELTEMI_TOKEN is an API token kept in this repository's secrets (Settings, Secrets and
|
|
73
|
+
# variables, Actions); create it in the page, under API tokens in the account menu. It is
|
|
74
|
+
# never written in this file. MELTEMI_HOST is optional: a repository variable that names
|
|
75
|
+
# another service than https://diagrams.meltemi.dev, and it must be a variable, not a secret.
|
|
76
|
+
cloud:
|
|
77
|
+
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
|
78
|
+
# One push to the cloud at a time, and a run still waiting is replaced by a newer one: with
|
|
79
|
+
# --force a slow job for an older commit would otherwise overwrite the newer commit's push.
|
|
80
|
+
concurrency:
|
|
81
|
+
group: meltemi-cloud
|
|
82
|
+
cancel-in-progress: false
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
|
|
87
|
+
- uses: actions/setup-node@v4
|
|
88
|
+
with:
|
|
89
|
+
node-version: 22
|
|
90
|
+
|
|
91
|
+
- name: Push to the cloud
|
|
92
|
+
env:
|
|
93
|
+
MELTEMI_TOKEN: ${{ secrets.MELTEMI_TOKEN }}
|
|
94
|
+
MELTEMI_HOST: ${{ vars.MELTEMI_HOST }}
|
|
95
|
+
run: npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams push "$PROJECT" --force --strict
|
|
96
|
+
# {{cloud-end}}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Meltemi Diagrams: validate the project, review what changed in merge requests, and build the
|
|
2
|
+
# catalog. Written by `meltemi-diagrams init --ci gitlab`; edit it freely.
|
|
3
|
+
meltemi-diagrams:
|
|
4
|
+
image: node:22
|
|
5
|
+
variables:
|
|
6
|
+
PROJECT: "{{project}}"
|
|
7
|
+
MELTEMI_DIAGRAMS: "@meltemi/diagrams-cli@{{version}}"
|
|
8
|
+
# The review compares with the target branch, so the history is needed.
|
|
9
|
+
GIT_DEPTH: "0"
|
|
10
|
+
script:
|
|
11
|
+
- npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams validate "$PROJECT" --strict
|
|
12
|
+
- |
|
|
13
|
+
if [ -n "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
|
14
|
+
git fetch origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
|
|
15
|
+
npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams review "$PROJECT" --base "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --out review
|
|
16
|
+
fi
|
|
17
|
+
- npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams build catalog "$PROJECT" --out catalog
|
|
18
|
+
artifacts:
|
|
19
|
+
paths:
|
|
20
|
+
- catalog
|
|
21
|
+
- review
|
|
22
|
+
expose_as: "Diagrams"
|
|
23
|
+
rules:
|
|
24
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
25
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
26
|
+
|
|
27
|
+
# {{cloud-begin}}
|
|
28
|
+
# The job below is written by `meltemi-diagrams init --ci gitlab --cloud` only: it mirrors the
|
|
29
|
+
# project in the Meltemi cloud on every pipeline of the default branch, so that the page, the share
|
|
30
|
+
# links and the published catalog follow the repository.
|
|
31
|
+
#
|
|
32
|
+
# The repository is the truth, so this job pushes with --force: CI cannot answer the question a push
|
|
33
|
+
# asks when the cloud holds something the folder lacks (a diagram somebody drew in the page), and a
|
|
34
|
+
# job that waits for an answer would hang. --strict refuses a project with errors. What differs in
|
|
35
|
+
# the cloud is overwritten; pull it first if it should survive.
|
|
36
|
+
#
|
|
37
|
+
# MELTEMI_TOKEN is an API token kept as a CI/CD variable of this project (Settings, CI/CD,
|
|
38
|
+
# Variables), masked and protected; create it in the page, under API tokens in the account menu.
|
|
39
|
+
# It is never written in this file. MELTEMI_HOST is optional: a variable that names another service
|
|
40
|
+
# than https://diagrams.meltemi.dev.
|
|
41
|
+
meltemi-diagrams-cloud:
|
|
42
|
+
# One push to the cloud at a time: with --force a slow job for an older commit would otherwise
|
|
43
|
+
# overwrite the newer commit's push.
|
|
44
|
+
resource_group: meltemi-cloud
|
|
45
|
+
image: node:22
|
|
46
|
+
variables:
|
|
47
|
+
PROJECT: "{{project}}"
|
|
48
|
+
MELTEMI_DIAGRAMS: "@meltemi/diagrams-cli@{{version}}"
|
|
49
|
+
script:
|
|
50
|
+
- npx --yes --package "$MELTEMI_DIAGRAMS" meltemi-diagrams push "$PROJECT" --force --strict
|
|
51
|
+
rules:
|
|
52
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
53
|
+
# {{cloud-end}}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
language "0.2"
|
|
2
|
+
|
|
3
|
+
// A first diagram. Change the boxes and arrows, then run `meltemi-diagrams preview` to see it.
|
|
4
|
+
diagram overview: flow {
|
|
5
|
+
title "Overview"
|
|
6
|
+
description "How a request reaches the data"
|
|
7
|
+
direction LR
|
|
8
|
+
|
|
9
|
+
client["Client"]
|
|
10
|
+
api["API"] { description "Handles requests" }
|
|
11
|
+
db[("Database")]
|
|
12
|
+
|
|
13
|
+
client -> api: "HTTPS" as request
|
|
14
|
+
api -> db: "Reads and writes" as store
|
|
15
|
+
}
|