@ogygie/studio 0.31.0 → 0.32.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/dist/server.js +37 -8
- package/dist-ui/assets/index-Drld2Zf5.js +78 -0
- package/dist-ui/index.html +1 -1
- package/package.json +3 -3
- package/dist-ui/assets/index-DESqTDfB.js +0 -78
package/dist/server.js
CHANGED
|
@@ -1187,7 +1187,7 @@ ${deps.originOf(path)}`
|
|
|
1187
1187
|
}
|
|
1188
1188
|
|
|
1189
1189
|
// src/server/storage/local-adapter.ts
|
|
1190
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
1190
|
+
import { mkdir, stat as stat2, writeFile } from "node:fs/promises";
|
|
1191
1191
|
import { dirname, isAbsolute as isAbsolute2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
1192
1192
|
function resolveInsideRoot2(rootDir, relativePath) {
|
|
1193
1193
|
const root = resolve2(rootDir);
|
|
@@ -1214,6 +1214,14 @@ function createLocalSpecStorage(rootDir) {
|
|
|
1214
1214
|
const absolute = resolveInsideRoot2(rootDir, path);
|
|
1215
1215
|
await mkdir(dirname(absolute), { recursive: true });
|
|
1216
1216
|
await writeFile(absolute, content, "utf8");
|
|
1217
|
+
},
|
|
1218
|
+
async modifiedAt(path) {
|
|
1219
|
+
const absolute = resolveInsideRoot2(rootDir, path);
|
|
1220
|
+
try {
|
|
1221
|
+
return (await stat2(absolute)).mtime.toISOString();
|
|
1222
|
+
} catch {
|
|
1223
|
+
return null;
|
|
1224
|
+
}
|
|
1217
1225
|
}
|
|
1218
1226
|
};
|
|
1219
1227
|
}
|
|
@@ -1345,7 +1353,8 @@ function intentOf(body) {
|
|
|
1345
1353
|
const sentence = /^.*?[.!?](?:\s|$)/u.exec(paragraph)?.[0]?.trim() ?? paragraph;
|
|
1346
1354
|
return sentence.length > 160 ? `${sentence.slice(0, 157).trimEnd()}\u2026` : sentence;
|
|
1347
1355
|
}
|
|
1348
|
-
|
|
1356
|
+
var modifiedAtOf = (deps, filePath) => deps.storage.modifiedAt?.(filePath) ?? Promise.resolve(null);
|
|
1357
|
+
function toReadableSummary(filePath, spec, updatedAt) {
|
|
1349
1358
|
return {
|
|
1350
1359
|
id: spec.frontmatter.id,
|
|
1351
1360
|
status: spec.frontmatter.status,
|
|
@@ -1353,7 +1362,8 @@ function toReadableSummary(filePath, spec) {
|
|
|
1353
1362
|
depends_on: spec.frontmatter.depends_on,
|
|
1354
1363
|
filePath,
|
|
1355
1364
|
presentSections: presentSectionsOf(spec.body),
|
|
1356
|
-
intent: intentOf(spec.body)
|
|
1365
|
+
intent: intentOf(spec.body),
|
|
1366
|
+
updatedAt
|
|
1357
1367
|
};
|
|
1358
1368
|
}
|
|
1359
1369
|
async function listSpecFileNames(deps) {
|
|
@@ -1369,7 +1379,7 @@ async function listSpecSummaries(deps) {
|
|
|
1369
1379
|
const parsed = parseSpec(filePath, fileName, content);
|
|
1370
1380
|
const id = fileName.replace(/\.spec\.md$/, "");
|
|
1371
1381
|
summaries.push(
|
|
1372
|
-
parsed.ok ? toReadableSummary(filePath, parsed.spec) : { id, filePath, error: parsed.error }
|
|
1382
|
+
parsed.ok ? toReadableSummary(filePath, parsed.spec, await modifiedAtOf(deps, filePath)) : { id, filePath, error: parsed.error }
|
|
1373
1383
|
);
|
|
1374
1384
|
}
|
|
1375
1385
|
return summaries;
|
|
@@ -1484,7 +1494,7 @@ ${serialized}
|
|
|
1484
1494
|
---${body}`;
|
|
1485
1495
|
const message = isValidation ? `spec: validate ${specId}` : `spec: save ${specId}`;
|
|
1486
1496
|
await deps.storage.write(filePath, content, message);
|
|
1487
|
-
return toReadableSummary(filePath, { frontmatter: input.frontmatter, body });
|
|
1497
|
+
return toReadableSummary(filePath, { frontmatter: input.frontmatter, body }, await modifiedAtOf(deps, filePath));
|
|
1488
1498
|
}
|
|
1489
1499
|
async function createSpec(deps, specId) {
|
|
1490
1500
|
const fileName = `${specId}.spec.md`;
|
|
@@ -1526,7 +1536,7 @@ async function createSpec(deps, specId) {
|
|
|
1526
1536
|
suggestedFix: "Fix the template's frontmatter to match SpecFrontmatterSchema."
|
|
1527
1537
|
});
|
|
1528
1538
|
}
|
|
1529
|
-
return toReadableSummary(filePath, parsed.spec);
|
|
1539
|
+
return toReadableSummary(filePath, parsed.spec, await modifiedAtOf(deps, filePath));
|
|
1530
1540
|
}
|
|
1531
1541
|
async function getManifest(deps) {
|
|
1532
1542
|
const content = await deps.storage.readFile(MANIFEST_PATH);
|
|
@@ -1920,7 +1930,9 @@ var ReadableSpecSummarySchema = z7.object({
|
|
|
1920
1930
|
filePath: z7.string(),
|
|
1921
1931
|
presentSections: z7.array(z7.string()),
|
|
1922
1932
|
/** The first sentence of `# @intent`, for a list that reads (v1.20: the target-spec suggestions of the brief). */
|
|
1923
|
-
intent: z7.string().default("")
|
|
1933
|
+
intent: z7.string().default(""),
|
|
1934
|
+
/** When the spec last changed (ISO 8601) — the board's order, newest first (v3.4); null when the storage does not know. */
|
|
1935
|
+
updatedAt: z7.string().nullable().default(null)
|
|
1924
1936
|
});
|
|
1925
1937
|
var UnreadableSpecSummarySchema = z7.object({
|
|
1926
1938
|
id: z7.string(),
|
|
@@ -3687,6 +3699,12 @@ function createHostedSpecStorage(deps) {
|
|
|
3687
3699
|
async readFile(path) {
|
|
3688
3700
|
return (await readerOf(path)).readFile(path);
|
|
3689
3701
|
},
|
|
3702
|
+
async modifiedAt(path) {
|
|
3703
|
+
if (deps.lastCommitDateOf === void 0) return null;
|
|
3704
|
+
const specId = specIdOfPath2(path);
|
|
3705
|
+
const ref = specId !== null && (await branches()).has(specBranchOf(specId)) ? specBranchOf(specId) : deps.github.defaultBranch;
|
|
3706
|
+
return deps.lastCommitDateOf(ref, path);
|
|
3707
|
+
},
|
|
3690
3708
|
async exists(path) {
|
|
3691
3709
|
return (await readerOf(path)).exists(path);
|
|
3692
3710
|
},
|
|
@@ -4729,6 +4747,15 @@ function createGithubPullsClient(deps) {
|
|
|
4729
4747
|
);
|
|
4730
4748
|
return (json ?? []).map((entry) => ({ sha: entry.sha, message: entry.commit.message }));
|
|
4731
4749
|
},
|
|
4750
|
+
async lastCommitDateOf(branch, path) {
|
|
4751
|
+
const { json } = await request(
|
|
4752
|
+
"GET",
|
|
4753
|
+
`${repoUrl}/commits?sha=${encodeURIComponent(branch)}&path=${encodeURIComponent(path)}&per_page=1`,
|
|
4754
|
+
void 0
|
|
4755
|
+
);
|
|
4756
|
+
const last = json?.[0];
|
|
4757
|
+
return last?.commit.committer?.date ?? last?.commit.author?.date ?? null;
|
|
4758
|
+
},
|
|
4732
4759
|
async getPullRequest(number) {
|
|
4733
4760
|
const { json } = await request(
|
|
4734
4761
|
"GET",
|
|
@@ -5130,6 +5157,7 @@ async function startHostedStudio(options) {
|
|
|
5130
5157
|
}
|
|
5131
5158
|
}
|
|
5132
5159
|
}
|
|
5160
|
+
const pulls = createGithubPullsClient({ github: config.repo, fetchImpl: githubApp.installationFetch });
|
|
5133
5161
|
const app = await createStudioApp({
|
|
5134
5162
|
uiDistDir,
|
|
5135
5163
|
hosted: {
|
|
@@ -5157,7 +5185,7 @@ async function startHostedStudio(options) {
|
|
|
5157
5185
|
}
|
|
5158
5186
|
}
|
|
5159
5187
|
},
|
|
5160
|
-
pulls
|
|
5188
|
+
pulls,
|
|
5161
5189
|
readerFor,
|
|
5162
5190
|
usage: createGithubUsageClient({ github: config.repo, fetchImpl: githubApp.installationFetch }),
|
|
5163
5191
|
...deploy === void 0 ? {} : { deploy },
|
|
@@ -5167,6 +5195,7 @@ async function startHostedStudio(options) {
|
|
|
5167
5195
|
github: config.repo,
|
|
5168
5196
|
readerFor,
|
|
5169
5197
|
listSpecBranches,
|
|
5198
|
+
lastCommitDateOf: pulls.lastCommitDateOf,
|
|
5170
5199
|
client,
|
|
5171
5200
|
user,
|
|
5172
5201
|
now,
|