@sleepy-hollow/framework 0.3.2 → 0.3.4
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/CHANGELOG.md +25 -0
- package/README.md +1 -1
- package/dist/{chunk-BJONRVDG.js → chunk-2GNHTFCZ.js} +4 -4
- package/dist/{chunk-DGTHFZPZ.js → chunk-AADQFGT4.js} +3 -3
- package/dist/chunk-EHBEUJIZ.js +139 -0
- package/dist/chunk-EHBEUJIZ.js.map +1 -0
- package/dist/{chunk-53TZY5YP.js → chunk-LPPASMRR.js} +2 -2
- package/dist/chunk-LPPASMRR.js.map +1 -0
- package/dist/{chunk-CAPFDC25.js → chunk-QY3TSXM6.js} +2 -2
- package/dist/{chunk-D4U3ZY4O.js → chunk-RYKRRAPD.js} +2 -2
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +115 -25
- package/dist/cli.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/routing.d.ts +1 -1
- package/dist/routing.js +2 -2
- package/dist/security.js +4 -4
- package/dist/server.d.ts +15 -6
- package/dist/server.js +1 -1
- package/dist/testing.js +5 -5
- package/dist/validation.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-53TZY5YP.js.map +0 -1
- package/dist/chunk-LNJDFJGT.js +0 -47
- package/dist/chunk-LNJDFJGT.js.map +0 -1
- /package/dist/{chunk-BJONRVDG.js.map → chunk-2GNHTFCZ.js.map} +0 -0
- /package/dist/{chunk-DGTHFZPZ.js.map → chunk-AADQFGT4.js.map} +0 -0
- /package/dist/{chunk-CAPFDC25.js.map → chunk-QY3TSXM6.js.map} +0 -0
- /package/dist/{chunk-D4U3ZY4O.js.map → chunk-RYKRRAPD.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveConfiguration
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2GNHTFCZ.js";
|
|
5
5
|
import {
|
|
6
6
|
createTraceabilityReport,
|
|
7
7
|
selectAffectedTests
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RYKRRAPD.js";
|
|
9
9
|
import "./chunk-BAKXP7IR.js";
|
|
10
10
|
import {
|
|
11
11
|
composeProjectSecurity
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-AADQFGT4.js";
|
|
13
13
|
import {
|
|
14
14
|
normalizeRoutes
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-QY3TSXM6.js";
|
|
16
16
|
import {
|
|
17
17
|
discoverRoutes,
|
|
18
18
|
platform
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-LPPASMRR.js";
|
|
20
|
+
import "./chunk-EHBEUJIZ.js";
|
|
21
21
|
import "./chunk-5WRI5ZAA.js";
|
|
22
22
|
|
|
23
23
|
// cli/main.ts
|
|
@@ -1006,7 +1006,7 @@ var CreationError = class extends Error {
|
|
|
1006
1006
|
};
|
|
1007
1007
|
|
|
1008
1008
|
// cli/create/create.ts
|
|
1009
|
-
var VERSION = "0.3.
|
|
1009
|
+
var VERSION = "0.3.4";
|
|
1010
1010
|
var NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
1011
1011
|
function files(name) {
|
|
1012
1012
|
return {
|
|
@@ -1090,7 +1090,33 @@ test("capture artifact is persisted", async () => { await persist(); });
|
|
|
1090
1090
|
engines: { node: ">=24" },
|
|
1091
1091
|
scripts: { check: "tsc --noEmit", test: "vitest run", verify: "npm run check && npm run test && node .sleepyhollow/verify.ts" },
|
|
1092
1092
|
dependencies: { "@sleepy-hollow/framework": `^${FRAMEWORK_VERSION}` },
|
|
1093
|
-
devDependencies: { typescript: "5.9.3", vitest: "4.1.11" }
|
|
1093
|
+
devDependencies: { "@types/node": "26.2.0", typescript: "5.9.3", vitest: "4.1.11" }
|
|
1094
|
+
},
|
|
1095
|
+
null,
|
|
1096
|
+
2
|
|
1097
|
+
) + "\n",
|
|
1098
|
+
"tsconfig.json": JSON.stringify(
|
|
1099
|
+
{
|
|
1100
|
+
compilerOptions: {
|
|
1101
|
+
target: "ES2024",
|
|
1102
|
+
module: "NodeNext",
|
|
1103
|
+
moduleResolution: "NodeNext",
|
|
1104
|
+
strict: true,
|
|
1105
|
+
noEmit: true,
|
|
1106
|
+
allowImportingTsExtensions: true,
|
|
1107
|
+
verbatimModuleSyntax: true,
|
|
1108
|
+
skipLibCheck: true,
|
|
1109
|
+
types: ["node", "vitest/globals"]
|
|
1110
|
+
},
|
|
1111
|
+
include: [
|
|
1112
|
+
".sleepyhollow/**/*.ts",
|
|
1113
|
+
"api/**/*.ts",
|
|
1114
|
+
"models/**/*.ts",
|
|
1115
|
+
"tests/**/*.ts",
|
|
1116
|
+
"sleepyhollow.config.ts",
|
|
1117
|
+
"vitest.config.ts"
|
|
1118
|
+
],
|
|
1119
|
+
exclude: ["generated", "node_modules"]
|
|
1094
1120
|
},
|
|
1095
1121
|
null,
|
|
1096
1122
|
2
|
|
@@ -1102,15 +1128,20 @@ export default defineConfig({ test: { globals: true, include: ["**/*_test.ts", "
|
|
|
1102
1128
|
"generated/.gitkeep": "",
|
|
1103
1129
|
"models/.gitkeep": "",
|
|
1104
1130
|
"requirements/application.req.md": `---
|
|
1105
|
-
schema:
|
|
1131
|
+
schema: sgad-application/v0.2
|
|
1132
|
+
id: ${name}-application
|
|
1106
1133
|
title: ${name}
|
|
1107
1134
|
status: draft
|
|
1135
|
+
risk: standard
|
|
1136
|
+
depends_on: []
|
|
1137
|
+
owners:
|
|
1138
|
+
- application owner
|
|
1108
1139
|
---
|
|
1109
1140
|
|
|
1110
1141
|
# Application requirements
|
|
1111
1142
|
|
|
1112
|
-
Use the official Sleepy Hollow skill to
|
|
1113
|
-
|
|
1143
|
+
Use the official Sleepy Hollow skill to replace this planning placeholder with
|
|
1144
|
+
the complete application requirements before generating endpoints.
|
|
1114
1145
|
`,
|
|
1115
1146
|
"sleepyhollow.config.ts": `import { defineProject } from "./.sleepyhollow/project.ts";
|
|
1116
1147
|
|
|
@@ -1142,7 +1173,7 @@ async function pathExists(path) {
|
|
|
1142
1173
|
throw error;
|
|
1143
1174
|
}
|
|
1144
1175
|
}
|
|
1145
|
-
var FRAMEWORK_VERSION = "0.3.
|
|
1176
|
+
var FRAMEWORK_VERSION = "0.3.4";
|
|
1146
1177
|
async function createProject(options) {
|
|
1147
1178
|
if (!NAME.test(options.name) || options.name.length > 64) {
|
|
1148
1179
|
throw creationError(
|
|
@@ -1328,6 +1359,7 @@ async function startWorker(options, expectedRoutes) {
|
|
|
1328
1359
|
const child = workerCommand(options, "serve").spawn();
|
|
1329
1360
|
const stdout = readFirstLine(child.stdout);
|
|
1330
1361
|
const stderr = readBounded(child.stderr);
|
|
1362
|
+
const status = child.status;
|
|
1331
1363
|
let timeout;
|
|
1332
1364
|
const timer = new Promise((_, reject) => {
|
|
1333
1365
|
timeout = setTimeout(
|
|
@@ -1356,9 +1388,34 @@ async function startWorker(options, expectedRoutes) {
|
|
|
1356
1388
|
);
|
|
1357
1389
|
}
|
|
1358
1390
|
let stopped = false;
|
|
1391
|
+
const failure3 = new Promise((_, reject) => {
|
|
1392
|
+
void status.then(async (result) => {
|
|
1393
|
+
if (stopped) return;
|
|
1394
|
+
if (result.success) {
|
|
1395
|
+
reject(new DevCommandError([{
|
|
1396
|
+
code: "SH_DEV_WORKER_EXITED",
|
|
1397
|
+
severity: "error",
|
|
1398
|
+
summary: "The development worker exited after becoming active",
|
|
1399
|
+
correction: "Inspect the worker diagnostics and retry."
|
|
1400
|
+
}]));
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
reject(await workerFailure(
|
|
1404
|
+
await stderr,
|
|
1405
|
+
"The development worker failed after becoming active"
|
|
1406
|
+
));
|
|
1407
|
+
}, async () => {
|
|
1408
|
+
if (stopped) return;
|
|
1409
|
+
reject(await workerFailure(
|
|
1410
|
+
await stderr,
|
|
1411
|
+
"The development worker failed after becoming active"
|
|
1412
|
+
));
|
|
1413
|
+
});
|
|
1414
|
+
});
|
|
1359
1415
|
return {
|
|
1360
1416
|
url: `http://${options.hostname}:${options.port}/`,
|
|
1361
1417
|
routeCount: expectedRoutes,
|
|
1418
|
+
failure: failure3,
|
|
1362
1419
|
async stop() {
|
|
1363
1420
|
if (stopped) return;
|
|
1364
1421
|
stopped = true;
|
|
@@ -1589,6 +1646,7 @@ function failure2(error, fallback) {
|
|
|
1589
1646
|
}
|
|
1590
1647
|
function changedPaths(projectRoot, paths) {
|
|
1591
1648
|
const normalized = [];
|
|
1649
|
+
const runtimeDatabaseArtifact = /^\.sleepyhollow\/[^/]+\.(?:sqlite|db)(?:-(?:wal|shm))?$/;
|
|
1592
1650
|
for (const path of paths) {
|
|
1593
1651
|
const absolute = isAbsolute(path) ? resolve2(path) : resolve2(projectRoot, path);
|
|
1594
1652
|
const local = relative(projectRoot, absolute).split(sep).join("/");
|
|
@@ -1599,7 +1657,7 @@ function changedPaths(projectRoot, paths) {
|
|
|
1599
1657
|
"Watch only project-contained application inputs."
|
|
1600
1658
|
);
|
|
1601
1659
|
}
|
|
1602
|
-
if (local === ".git" || local.startsWith(".git/") || local === "generated" || local.startsWith("generated/") || local.includes("/node_modules/") || /(?:^|\/)(?:\.DS_Store|.*(?:\.swp|~))$/.test(local)) continue;
|
|
1660
|
+
if (local === ".git" || local.startsWith(".git/") || local === "generated" || local.startsWith("generated/") || local.includes("/node_modules/") || runtimeDatabaseArtifact.test(local) || /(?:^|\/)(?:\.DS_Store|.*(?:\.swp|~))$/.test(local)) continue;
|
|
1603
1661
|
normalized.push(local);
|
|
1604
1662
|
}
|
|
1605
1663
|
return Object.freeze([...new Set(normalized)].sort());
|
|
@@ -1614,6 +1672,21 @@ function abortReason(signal) {
|
|
|
1614
1672
|
}
|
|
1615
1673
|
return "cancelled";
|
|
1616
1674
|
}
|
|
1675
|
+
async function nextChange(iterator, active) {
|
|
1676
|
+
const change = iterator.next();
|
|
1677
|
+
if (!active?.failure) return change;
|
|
1678
|
+
return Promise.race([
|
|
1679
|
+
change,
|
|
1680
|
+
active.failure.then(() => {
|
|
1681
|
+
throw new DevCommandError([{
|
|
1682
|
+
code: "SH_DEV_WORKER_EXITED",
|
|
1683
|
+
severity: "error",
|
|
1684
|
+
summary: "The active development worker exited unexpectedly",
|
|
1685
|
+
correction: "Inspect the worker diagnostics and retry."
|
|
1686
|
+
}]);
|
|
1687
|
+
})
|
|
1688
|
+
]);
|
|
1689
|
+
}
|
|
1617
1690
|
async function runDevCommand(args, io, suppliedDependencies) {
|
|
1618
1691
|
const parsed = parse2(args);
|
|
1619
1692
|
if ("code" in parsed) {
|
|
@@ -1735,7 +1808,11 @@ ${parsed.correction}`
|
|
|
1735
1808
|
return 1;
|
|
1736
1809
|
}
|
|
1737
1810
|
if (signal.aborted) await closeWatcher();
|
|
1738
|
-
|
|
1811
|
+
const iterator = watcher[Symbol.asyncIterator]();
|
|
1812
|
+
while (true) {
|
|
1813
|
+
const next = await nextChange(iterator, active);
|
|
1814
|
+
if (next.done) break;
|
|
1815
|
+
const paths = next.value;
|
|
1739
1816
|
if (signal.aborted) break;
|
|
1740
1817
|
const changes = changedPaths(projectRoot, paths);
|
|
1741
1818
|
if (!Array.isArray(changes)) {
|
|
@@ -1888,14 +1965,26 @@ function safeDiagnostic(error, intent) {
|
|
|
1888
1965
|
...typeof item.key === "string" ? { configuration: [item.key] } : {}
|
|
1889
1966
|
}));
|
|
1890
1967
|
}
|
|
1891
|
-
|
|
1968
|
+
const nodeError = error;
|
|
1969
|
+
const nodeCode = typeof nodeError?.code === "string" ? nodeError.code : void 0;
|
|
1970
|
+
const isListenFailure = error instanceof platform.errors.AddrInUse || error instanceof platform.errors.PermissionDenied || nodeError?.syscall === "listen" || nodeCode === "EADDRINUSE" || nodeCode === "EACCES" || nodeCode === "EPERM";
|
|
1971
|
+
if (intent === "serve" && isListenFailure) {
|
|
1892
1972
|
return [{
|
|
1893
1973
|
code: "SH_DEV_BIND_FAILED",
|
|
1894
1974
|
severity: "error",
|
|
1895
|
-
summary: "The loopback listener could not bind",
|
|
1975
|
+
summary: nodeCode ? `The loopback listener failed with ${nodeCode}` : "The loopback listener could not bind",
|
|
1896
1976
|
correction: "Choose an available port and confirm local network access."
|
|
1897
1977
|
}];
|
|
1898
1978
|
}
|
|
1979
|
+
if (intent === "serve") {
|
|
1980
|
+
const cause = error instanceof Error ? `${error.name}: ${error.message}`.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "").replace(/(?:Bearer|token|password|secret|authorization)[=: ]+\S+/gi, "$1=[redacted]").replace(/(?:[A-Za-z]:)?\/[^\s]+/g, "[path]").slice(0, 180) : void 0;
|
|
1981
|
+
return [{
|
|
1982
|
+
code: "SH_DEV_SERVE_FAILED",
|
|
1983
|
+
severity: "error",
|
|
1984
|
+
summary: cause ? `The development server failed: ${cause}` : "The development server failed",
|
|
1985
|
+
correction: "Inspect the bounded server diagnostic and retry after repairing the host boundary."
|
|
1986
|
+
}];
|
|
1987
|
+
}
|
|
1899
1988
|
return [{
|
|
1900
1989
|
code: "SH_DEV_PROJECT_INVALID",
|
|
1901
1990
|
severity: "error",
|
|
@@ -1967,20 +2056,20 @@ async function runDevWorker(args) {
|
|
|
1967
2056
|
const [intent, projectRoot, hostname, rawPort] = args;
|
|
1968
2057
|
const port = Number(rawPort);
|
|
1969
2058
|
if (hostname !== "127.0.0.1" || !Number.isInteger(port) || port < 1 || port > 65535) return 2;
|
|
2059
|
+
let server;
|
|
1970
2060
|
try {
|
|
1971
2061
|
const { runtime: runtime2, routeCount } = await loadRuntime(projectRoot);
|
|
1972
2062
|
if (intent === "validate") {
|
|
1973
2063
|
console.log(JSON.stringify({ ready: true, routeCount }));
|
|
1974
2064
|
return 0;
|
|
1975
2065
|
}
|
|
1976
|
-
|
|
2066
|
+
server = platform.serve({ hostname, port }, (request) => runtime2.fetch(request));
|
|
2067
|
+
await server.ready;
|
|
1977
2068
|
console.log(JSON.stringify({ ready: true, routeCount }));
|
|
1978
|
-
await
|
|
1979
|
-
server.once("close", resolve5);
|
|
1980
|
-
server.once("error", reject);
|
|
1981
|
-
});
|
|
2069
|
+
await server.finished;
|
|
1982
2070
|
return 0;
|
|
1983
2071
|
} catch (error) {
|
|
2072
|
+
await server?.shutdown().catch(() => void 0);
|
|
1984
2073
|
console.error(
|
|
1985
2074
|
JSON.stringify({
|
|
1986
2075
|
ready: false,
|
|
@@ -2880,7 +2969,7 @@ function renderArtifacts(inventory2) {
|
|
|
2880
2969
|
];
|
|
2881
2970
|
const manifestContent = canonicalJson({
|
|
2882
2971
|
schema: "sleepy-hollow-generated-manifest/v1",
|
|
2883
|
-
generatorVersion: "0.3.
|
|
2972
|
+
generatorVersion: "0.3.4",
|
|
2884
2973
|
serviceId: normalized.serviceId,
|
|
2885
2974
|
inputDigest: digest2(input),
|
|
2886
2975
|
artifacts: Object.fromEntries(
|
|
@@ -3154,7 +3243,7 @@ function inventoryFromRoutes(routes2, options) {
|
|
|
3154
3243
|
return {
|
|
3155
3244
|
serviceId: options.serviceId,
|
|
3156
3245
|
title: options.title ?? options.serviceId,
|
|
3157
|
-
version: options.version ?? "0.3.
|
|
3246
|
+
version: options.version ?? "0.3.4",
|
|
3158
3247
|
...options.description ? { description: options.description } : {},
|
|
3159
3248
|
operations,
|
|
3160
3249
|
securitySchemes: options.securitySchemes ?? {}
|
|
@@ -4008,7 +4097,7 @@ var CLI_COMMANDS = [
|
|
|
4008
4097
|
"generate",
|
|
4009
4098
|
"deploy"
|
|
4010
4099
|
];
|
|
4011
|
-
var CLI_VERSION = "0.3.
|
|
4100
|
+
var CLI_VERSION = "0.3.4";
|
|
4012
4101
|
var commandMetadata = {
|
|
4013
4102
|
create: {
|
|
4014
4103
|
description: "Create one deterministic Sleepy Hollow project.",
|
|
@@ -5578,7 +5667,8 @@ function declaredStatuses(schemas) {
|
|
|
5578
5667
|
function authenticationOf(security2) {
|
|
5579
5668
|
if (typeof security2 !== "object" || security2 === null) return "none";
|
|
5580
5669
|
const declared = security2.authentication;
|
|
5581
|
-
|
|
5670
|
+
if (typeof declared !== "object" || declared === null) return "none";
|
|
5671
|
+
return declared.mode === "required" ? "required" : "none";
|
|
5582
5672
|
}
|
|
5583
5673
|
async function routes(project, artifact2) {
|
|
5584
5674
|
const roots = project.services.length > 0 ? project.services.map((service) => ({
|