@specatlas/core 0.1.1 → 0.1.3
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/dist/index.d.ts +2 -1
- package/dist/index.js +23 -16
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -215,6 +215,7 @@ interface Workspace {
|
|
|
215
215
|
sddDir: string;
|
|
216
216
|
specs: SpecRef[];
|
|
217
217
|
changes: Change[];
|
|
218
|
+
archived?: Change[];
|
|
218
219
|
diagnostics: Diagnostic[];
|
|
219
220
|
}
|
|
220
221
|
|
|
@@ -1047,7 +1048,7 @@ interface ApprovalsIndex {
|
|
|
1047
1048
|
}
|
|
1048
1049
|
declare function loadApprovals(sddDir: string): Promise<ApprovalsIndex>;
|
|
1049
1050
|
declare function loadSpecs(sddDir: string): Promise<SpecRef[]>;
|
|
1050
|
-
declare function loadChange(root: string, slug: string): Promise<Change>;
|
|
1051
|
+
declare function loadChange(root: string, slug: string, relDir?: string): Promise<Change>;
|
|
1051
1052
|
declare function listChangeSlugs(root: string, opts?: {
|
|
1052
1053
|
includeArchived?: boolean;
|
|
1053
1054
|
}): Promise<string[]>;
|
package/dist/index.js
CHANGED
|
@@ -1255,8 +1255,8 @@ async function loadSpecs(sddDir) {
|
|
|
1255
1255
|
}
|
|
1256
1256
|
return out;
|
|
1257
1257
|
}
|
|
1258
|
-
async function loadChange(root, slug) {
|
|
1259
|
-
const dir = path4.join(root, SDD_DIR, "changes", slug);
|
|
1258
|
+
async function loadChange(root, slug, relDir) {
|
|
1259
|
+
const dir = path4.join(root, SDD_DIR, "changes", relDir ?? slug);
|
|
1260
1260
|
const diagnostics = [];
|
|
1261
1261
|
const change = { slug, dir, diagnostics };
|
|
1262
1262
|
const metaFile = path4.join(dir, "meta.yaml");
|
|
@@ -1318,7 +1318,14 @@ async function loadWorkspace(root) {
|
|
|
1318
1318
|
changes.push(change);
|
|
1319
1319
|
diagnostics.push(...change.diagnostics);
|
|
1320
1320
|
}
|
|
1321
|
-
|
|
1321
|
+
const archived = [];
|
|
1322
|
+
const archivedDir = path4.join(sddDir, "changes", "archive");
|
|
1323
|
+
if (await isDirectory(archivedDir)) {
|
|
1324
|
+
for (const entry of await listDirs(archivedDir)) {
|
|
1325
|
+
archived.push(await loadChange(root, entry.replace(/^\d{4}-\d{2}-/, ""), path4.join("archive", entry)));
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
return { workspace: { root, sddDir, specs, changes, archived, diagnostics }, config };
|
|
1322
1329
|
}
|
|
1323
1330
|
async function ensureSddDirs(sddDir) {
|
|
1324
1331
|
const created = [];
|
|
@@ -3073,7 +3080,7 @@ async function generatePresentation(opts) {
|
|
|
3073
3080
|
language,
|
|
3074
3081
|
labels,
|
|
3075
3082
|
title: change.meta?.title ?? change.slug,
|
|
3076
|
-
domain: change.meta?.domain ?? "\
|
|
3083
|
+
domain: change.meta?.domain ?? "\u2014",
|
|
3077
3084
|
lane: change.meta?.lane ?? config.lanes.default,
|
|
3078
3085
|
project: config.project.name,
|
|
3079
3086
|
version: change.delta.sectionsFound.length,
|
|
@@ -3100,7 +3107,7 @@ async function copyMockups(root, change, destDir) {
|
|
|
3100
3107
|
for (const screen of manifest.screens) {
|
|
3101
3108
|
const src = path12.join(dir, screen.file);
|
|
3102
3109
|
if (!await exists(src)) {
|
|
3103
|
-
diagnostics.push(diag("ATLAS-PRESENT-002", "warning", `El mockup ${screen.file} no existe y no se incluir\
|
|
3110
|
+
diagnostics.push(diag("ATLAS-PRESENT-002", "warning", `El mockup ${screen.file} no existe y no se incluir\xE1`, { path: src }));
|
|
3104
3111
|
continue;
|
|
3105
3112
|
}
|
|
3106
3113
|
await copyFile(src, path12.join(destDir, screen.file));
|
|
@@ -3151,15 +3158,15 @@ function labelsFor(language) {
|
|
|
3151
3158
|
return {
|
|
3152
3159
|
kicker: "Propuesta",
|
|
3153
3160
|
summary: "Resumen de negocio",
|
|
3154
|
-
criteria: "Criterios de aceptaci\
|
|
3161
|
+
criteria: "Criterios de aceptaci\xF3n",
|
|
3155
3162
|
requirements: "Requisitos y escenarios",
|
|
3156
3163
|
mockups: "Mockups",
|
|
3157
|
-
approve: "Aprobaci\
|
|
3164
|
+
approve: "Aprobaci\xF3n",
|
|
3158
3165
|
approveText: "Esta propuesta se aprueba firmando la spec (hash + autor). Cualquier cambio posterior invalida la firma.",
|
|
3159
3166
|
command: "Comando",
|
|
3160
3167
|
hash: "Hash",
|
|
3161
3168
|
generated: "Generado",
|
|
3162
|
-
noProposal: "La propuesta est\
|
|
3169
|
+
noProposal: "La propuesta est\xE1 vac\xEDa.",
|
|
3163
3170
|
added: "agregado",
|
|
3164
3171
|
modified: "modificado",
|
|
3165
3172
|
scenario: "Escenario",
|
|
@@ -3214,13 +3221,13 @@ footer { color: var(--muted); font-size: 13px; text-align:center; }
|
|
|
3214
3221
|
function page(input) {
|
|
3215
3222
|
const l = input.labels;
|
|
3216
3223
|
const reqHtml = input.requirements.map(({ req, kind }) => {
|
|
3217
|
-
const rules = req.rules.map((r) => `<li><code>${esc(r.id)}</code> \
|
|
3224
|
+
const rules = req.rules.map((r) => `<li><code>${esc(r.id)}</code> \u2014 ${inline(r.text)}</li>`).join("");
|
|
3218
3225
|
const scenarios = req.scenarios.map((s) => {
|
|
3219
3226
|
const when = s.when.map((w) => `<div class="when">CUANDO ${inline(w)}</div>`).join("");
|
|
3220
3227
|
const then = s.then.map((t) => `<div class="then">ENTONCES ${inline(t)}</div>`).join("");
|
|
3221
|
-
return `<div class="scenario"><h4>${esc(s.id)} \
|
|
3228
|
+
return `<div class="scenario"><h4>${esc(s.id)} \u2014 ${esc(s.title)}</h4>${when}${then}</div>`;
|
|
3222
3229
|
}).join("");
|
|
3223
|
-
return `<div class="req"><h3>${esc(req.id)} \
|
|
3230
|
+
return `<div class="req"><h3>${esc(req.id)} \u2014 ${esc(req.title)}<span class="badge">${kind === "added" ? l.added : l.modified}</span></h3><p>${inline(req.prose)}</p>${rules ? `<ul class="rules">${rules}</ul>` : ""}${scenarios}</div>`;
|
|
3224
3231
|
}).join("");
|
|
3225
3232
|
const criteriaRows = input.requirements.flatMap(({ req }) => req.scenarios).map((s) => {
|
|
3226
3233
|
const status = input.evidence.get(s.id);
|
|
@@ -3229,7 +3236,7 @@ function page(input) {
|
|
|
3229
3236
|
return `<tr><td><code>${esc(s.id)}</code></td><td>${esc(s.title)}</td><td><span class="pill ${cls}">${esc(label)}</span></td></tr>`;
|
|
3230
3237
|
}).join("");
|
|
3231
3238
|
const mockupHtml = input.mockups.length === 0 ? `<p><em>${l.noMockups}</em></p>` : `<div class="mockups">${input.mockups.map(
|
|
3232
|
-
(m) => `<div class="mockup ${m.platform === "mobile" ? "phone" : ""}"><header>${esc(m.title)} \
|
|
3239
|
+
(m) => `<div class="mockup ${m.platform === "mobile" ? "phone" : ""}"><header>${esc(m.title)} \u2014 ${esc(m.file)}</header><iframe src="${esc(m.file)}" loading="lazy" title="${esc(m.title)}"></iframe></div>`
|
|
3233
3240
|
).join("")}</div>`;
|
|
3234
3241
|
const shotsHtml = input.screenshots.length === 0 ? "" : `<h3>${l.screenshots}</h3><div class="grid-shots">${input.screenshots.map((s) => `<img src="${esc(s)}" alt="${esc(s)}" loading="lazy">`).join("")}</div>`;
|
|
3235
3242
|
return `<!doctype html>
|
|
@@ -3237,15 +3244,15 @@ function page(input) {
|
|
|
3237
3244
|
<head>
|
|
3238
3245
|
<meta charset="utf-8">
|
|
3239
3246
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
3240
|
-
<title>${esc(l.kicker)} \
|
|
3247
|
+
<title>${esc(l.kicker)} \u2014 ${esc(input.title)}</title>
|
|
3241
3248
|
<style>${CSS}</style>
|
|
3242
3249
|
</head>
|
|
3243
3250
|
<body>
|
|
3244
3251
|
<div class="wrap">
|
|
3245
3252
|
<header class="hero">
|
|
3246
|
-
<p class="kicker">${esc(l.kicker)} \
|
|
3253
|
+
<p class="kicker">${esc(l.kicker)} \xB7 ${esc(input.domain)} \xB7 ${esc(input.lane)}</p>
|
|
3247
3254
|
<h1>${esc(input.title)}</h1>
|
|
3248
|
-
<p class="meta">${esc(input.project)} \
|
|
3255
|
+
<p class="meta">${esc(input.project)} \xB7 ${esc(l.hash)} ${esc(shortHash(input.hash))} \xB7 ${esc(l.generated)} ${esc(input.generatedAt)}</p>
|
|
3249
3256
|
</header>
|
|
3250
3257
|
|
|
3251
3258
|
<section>
|
|
@@ -3275,7 +3282,7 @@ function page(input) {
|
|
|
3275
3282
|
<p>${esc(l.command)}: <code>${esc(input.approveHint)}</code></p>
|
|
3276
3283
|
</section>
|
|
3277
3284
|
|
|
3278
|
-
<footer>SpecAtlas \
|
|
3285
|
+
<footer>SpecAtlas \xB7 ${esc(input.project)} \xB7 ${esc(input.generatedAt)}</footer>
|
|
3279
3286
|
</div>
|
|
3280
3287
|
</body>
|
|
3281
3288
|
</html>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@specatlas/core",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Kernel determinista de SpecAtlas: parsing,
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Kernel determinista de SpecAtlas: parsing, validación, trazabilidad, olas y ciclo de vida",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|