@askrjs/cli 0.0.3 → 0.0.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/README.md +37 -0
- package/dist/add.d.ts +16 -0
- package/dist/add.js +33 -29
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +0 -2
- package/dist/create.d.ts +5 -0
- package/dist/create.js +104 -26
- package/dist/directory-swap-DWoHtx7C.js +35 -0
- package/dist/discovery-Difb7Y4G.js +0 -2
- package/dist/generate.d.ts +5 -0
- package/dist/generate.js +77 -12
- package/dist/is-direct-execution-Cdlr-ZUl.js +0 -2
- package/dist/openapi.d.ts +25 -0
- package/dist/openapi.js +44 -12
- package/dist/planner-VAj7qlxr.js +0 -2
- package/dist/range-YUs9eimn.js +0 -2
- package/dist/registry-CyrRHRG5.js +0 -2
- package/dist/skills/askr-ssr-ssg/SKILL.md +3 -1
- package/dist/{skills-Bh0mEhIx.js → skills-B7CbWur9.js} +89 -26
- package/dist/skills.d.ts +18 -0
- package/dist/skills.js +1 -1
- package/dist/specification-DXnDOC-0.js +0 -2
- package/dist/ssg-config.d.ts +41 -0
- package/dist/ssg-config.js +1 -0
- package/dist/ssg.d.ts +61 -0
- package/dist/ssg.js +360 -24
- package/dist/templates/full-stack/package.json +1 -1
- package/dist/templates/full-stack/src/server/action-registry.ts +0 -1
- package/dist/templates/full-stack/tsconfig.json +1 -1
- package/dist/templates/spa/package.json +2 -3
- package/dist/templates/spa/src/pages/app/_routes.tsx +2 -0
- package/dist/templates/spa/src/pages/public/_routes.tsx +2 -0
- package/dist/templates/spa/tsconfig.json +2 -1
- package/dist/templates/spa/vitest.config.ts +0 -4
- package/dist/templates/ssg/README.md +1 -1
- package/dist/templates/ssg/package.json +1 -1
- package/dist/templates/ssg/ssg.config.ts +7 -0
- package/dist/templates/ssg/tests/ssg-config.test.ts +2 -0
- package/dist/templates/ssg/tsconfig.json +2 -1
- package/dist/templates/ssg/vitest.config.ts +0 -4
- package/dist/templates/ssr/package.json +2 -2
- package/dist/templates/startkit/package.json +2 -2
- package/dist/templates/startkit/src/lib/mock-data.ts +17 -39
- package/dist/templates/startkit/tsconfig.json +2 -1
- package/dist/update.d.ts +41 -0
- package/dist/update.js +0 -2
- package/dist/writer-D8qe_7ud.js +0 -2
- package/package.json +13 -8
- package/dist/add.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/create.js.map +0 -1
- package/dist/discovery-Difb7Y4G.js.map +0 -1
- package/dist/generate.js.map +0 -1
- package/dist/is-direct-execution-Cdlr-ZUl.js.map +0 -1
- package/dist/openapi.js.map +0 -1
- package/dist/planner-VAj7qlxr.js.map +0 -1
- package/dist/range-YUs9eimn.js.map +0 -1
- package/dist/registry-CyrRHRG5.js.map +0 -1
- package/dist/skills-Bh0mEhIx.js.map +0 -1
- package/dist/specification-DXnDOC-0.js.map +0 -1
- package/dist/ssg.js.map +0 -1
- package/dist/templates/full-stack/src/vite-server.d.ts +0 -5
- package/dist/templates/spa/src/styles.d.ts +0 -1
- package/dist/templates/ssg/src/vite-env.d.ts +0 -5
- package/dist/templates/ssr/src/vite-server.d.ts +0 -7
- package/dist/templates/startkit/src/vite-env.d.ts +0 -5
- package/dist/update.js.map +0 -1
- package/dist/writer-D8qe_7ud.js.map +0 -1
- package/skills/askr-accessibility/SKILL.md +0 -68
- package/skills/askr-accessibility/agents/openai.yaml +0 -4
- package/skills/askr-agent-execution/SKILL.md +0 -85
- package/skills/askr-agent-execution/agents/openai.yaml +0 -4
- package/skills/askr-agent-workflows/SKILL.md +0 -57
- package/skills/askr-agent-workflows/agents/openai.yaml +0 -4
- package/skills/askr-api-integration/SKILL.md +0 -79
- package/skills/askr-api-integration/agents/openai.yaml +0 -4
- package/skills/askr-app-builder/SKILL.md +0 -99
- package/skills/askr-app-builder/agents/openai.yaml +0 -4
- package/skills/askr-auth-access/SKILL.md +0 -74
- package/skills/askr-auth-access/agents/openai.yaml +0 -4
- package/skills/askr-cli-vite/SKILL.md +0 -76
- package/skills/askr-cli-vite/agents/openai.yaml +0 -4
- package/skills/askr-dashboard-charts/SKILL.md +0 -99
- package/skills/askr-dashboard-charts/agents/openai.yaml +0 -4
- package/skills/askr-design-system/SKILL.md +0 -86
- package/skills/askr-design-system/agents/openai.yaml +0 -4
- package/skills/askr-env-config/SKILL.md +0 -74
- package/skills/askr-env-config/agents/openai.yaml +0 -4
- package/skills/askr-error-loading-empty/SKILL.md +0 -89
- package/skills/askr-error-loading-empty/agents/openai.yaml +0 -4
- package/skills/askr-file-upload-artifacts/SKILL.md +0 -77
- package/skills/askr-file-upload-artifacts/agents/openai.yaml +0 -4
- package/skills/askr-forms-tables-crud/SKILL.md +0 -98
- package/skills/askr-forms-tables-crud/agents/openai.yaml +0 -4
- package/skills/askr-mental-model/SKILL.md +0 -109
- package/skills/askr-mental-model/agents/openai.yaml +0 -4
- package/skills/askr-migration-react/SKILL.md +0 -81
- package/skills/askr-migration-react/agents/openai.yaml +0 -4
- package/skills/askr-observability-debugging/SKILL.md +0 -83
- package/skills/askr-observability-debugging/agents/openai.yaml +0 -4
- package/skills/askr-project-structure/SKILL.md +0 -79
- package/skills/askr-project-structure/agents/openai.yaml +0 -4
- package/skills/askr-query-mutation/SKILL.md +0 -115
- package/skills/askr-query-mutation/agents/openai.yaml +0 -4
- package/skills/askr-realtime-streaming/SKILL.md +0 -76
- package/skills/askr-realtime-streaming/agents/openai.yaml +0 -4
- package/skills/askr-resources-data/SKILL.md +0 -100
- package/skills/askr-resources-data/agents/openai.yaml +0 -4
- package/skills/askr-routing-layouts/SKILL.md +0 -107
- package/skills/askr-routing-layouts/agents/openai.yaml +0 -4
- package/skills/askr-runtime-reactivity/SKILL.md +0 -92
- package/skills/askr-runtime-reactivity/agents/openai.yaml +0 -4
- package/skills/askr-ssr-ssg/SKILL.md +0 -76
- package/skills/askr-ssr-ssg/agents/openai.yaml +0 -4
- package/skills/askr-testing-determinism/SKILL.md +0 -75
- package/skills/askr-testing-determinism/agents/openai.yaml +0 -4
- package/skills/askr-theming/SKILL.md +0 -86
- package/skills/askr-theming/agents/openai.yaml +0 -4
- package/skills/askr-ui-composition/SKILL.md +0 -92
- package/skills/askr-ui-composition/agents/openai.yaml +0 -4
- package/templates/full-stack/AGENTS.md +0 -11
- package/templates/full-stack/README.md +0 -17
- package/templates/full-stack/gitignore.template +0 -4
- package/templates/full-stack/index.html +0 -13
- package/templates/full-stack/package.json +0 -39
- package/templates/full-stack/server.ts +0 -9
- package/templates/full-stack/src/action-authorizations.ts +0 -10
- package/templates/full-stack/src/actions/create-message.ts +0 -10
- package/templates/full-stack/src/i18n.ts +0 -8
- package/templates/full-stack/src/main.tsx +0 -11
- package/templates/full-stack/src/pages/home.tsx +0 -25
- package/templates/full-stack/src/pages/layout.tsx +0 -43
- package/templates/full-stack/src/pages/not-found.tsx +0 -7
- package/templates/full-stack/src/routes.tsx +0 -19
- package/templates/full-stack/src/schemas.ts +0 -10
- package/templates/full-stack/src/server/action-registry.ts +0 -8
- package/templates/full-stack/src/server/actions/create-message.ts +0 -14
- package/templates/full-stack/src/server/app.ts +0 -76
- package/templates/full-stack/src/server/dependencies.ts +0 -55
- package/templates/full-stack/src/server/entry-server.ts +0 -8
- package/templates/full-stack/src/telemetry.ts +0 -3
- package/templates/full-stack/src/vite-server.d.ts +0 -5
- package/templates/full-stack/tests/actions/create-message.test.ts +0 -12
- package/templates/full-stack/tsconfig.json +0 -15
- package/templates/full-stack/vite.config.ts +0 -10
- package/templates/spa/AGENTS.md +0 -60
- package/templates/spa/README.md +0 -96
- package/templates/spa/gitignore.template +0 -16
- package/templates/spa/index.html +0 -13
- package/templates/spa/package.json +0 -35
- package/templates/spa/src/adapters/operations-client.ts +0 -95
- package/templates/spa/src/components/shared/metric-card.tsx +0 -27
- package/templates/spa/src/components/shared/status-badge.tsx +0 -24
- package/templates/spa/src/features/operations/operations.query.ts +0 -9
- package/templates/spa/src/main.tsx +0 -10
- package/templates/spa/src/pages/_layout.tsx +0 -9
- package/templates/spa/src/pages/_routes.tsx +0 -27
- package/templates/spa/src/pages/app/_layout.tsx +0 -94
- package/templates/spa/src/pages/app/_routes.tsx +0 -10
- package/templates/spa/src/pages/app/admin-home.tsx +0 -170
- package/templates/spa/src/pages/app/agent-runs.tsx +0 -93
- package/templates/spa/src/pages/app/settings.tsx +0 -91
- package/templates/spa/src/pages/auth/_layout.tsx +0 -38
- package/templates/spa/src/pages/auth/_routes.tsx +0 -6
- package/templates/spa/src/pages/auth/login.tsx +0 -63
- package/templates/spa/src/pages/not-found.tsx +0 -22
- package/templates/spa/src/pages/public/_layout.tsx +0 -47
- package/templates/spa/src/pages/public/_routes.tsx +0 -6
- package/templates/spa/src/pages/public/home.tsx +0 -143
- package/templates/spa/src/shared/format.ts +0 -12
- package/templates/spa/src/shared/navigation.ts +0 -15
- package/templates/spa/src/styles/components.css +0 -49
- package/templates/spa/src/styles/layout.css +0 -192
- package/templates/spa/src/styles/reset.css +0 -44
- package/templates/spa/src/styles/theme.css +0 -57
- package/templates/spa/src/styles/tokens.css +0 -20
- package/templates/spa/src/styles.css +0 -7
- package/templates/spa/src/styles.d.ts +0 -1
- package/templates/spa/tests/app.test.tsx +0 -37
- package/templates/spa/tests/components/shared.test.tsx +0 -12
- package/templates/spa/tests/resources.test.ts +0 -22
- package/templates/spa/tsconfig.json +0 -20
- package/templates/spa/tsconfig.node.json +0 -10
- package/templates/spa/vite.config.ts +0 -24
- package/templates/spa/vitest.config.ts +0 -17
- package/templates/ssg/AGENTS.md +0 -55
- package/templates/ssg/README.md +0 -39
- package/templates/ssg/gitignore.template +0 -17
- package/templates/ssg/index.html +0 -13
- package/templates/ssg/package.json +0 -35
- package/templates/ssg/src/app.tsx +0 -14
- package/templates/ssg/src/components/badge.tsx +0 -3
- package/templates/ssg/src/components/counter.tsx +0 -30
- package/templates/ssg/src/components/site-shell.tsx +0 -111
- package/templates/ssg/src/jsx.d.ts +0 -23
- package/templates/ssg/src/main.tsx +0 -8
- package/templates/ssg/src/pages/about.tsx +0 -82
- package/templates/ssg/src/pages/content.tsx +0 -63
- package/templates/ssg/src/pages/example.tsx +0 -97
- package/templates/ssg/src/pages/home.tsx +0 -51
- package/templates/ssg/src/resources/user.ts +0 -15
- package/templates/ssg/src/routes.tsx +0 -15
- package/templates/ssg/src/styles.css +0 -89
- package/templates/ssg/src/vite-env.d.ts +0 -5
- package/templates/ssg/ssg.config.ts +0 -34
- package/templates/ssg/tests/app.test.tsx +0 -19
- package/templates/ssg/tests/components/counter.test.tsx +0 -18
- package/templates/ssg/tests/resources.test.ts +0 -11
- package/templates/ssg/tests/ssg-config.test.ts +0 -11
- package/templates/ssg/tsconfig.json +0 -20
- package/templates/ssg/tsconfig.node.json +0 -10
- package/templates/ssg/vite.config.ts +0 -24
- package/templates/ssg/vitest.config.ts +0 -17
- package/templates/ssr/AGENTS.md +0 -28
- package/templates/ssr/README.md +0 -38
- package/templates/ssr/gitignore.template +0 -16
- package/templates/ssr/index.html +0 -13
- package/templates/ssr/package.json +0 -34
- package/templates/ssr/server.ts +0 -10
- package/templates/ssr/src/app.tsx +0 -21
- package/templates/ssr/src/components/counter.tsx +0 -26
- package/templates/ssr/src/entry-server.tsx +0 -12
- package/templates/ssr/src/main.tsx +0 -11
- package/templates/ssr/src/pages/about.tsx +0 -75
- package/templates/ssr/src/pages/example.tsx +0 -113
- package/templates/ssr/src/pages/home.tsx +0 -56
- package/templates/ssr/src/resources/user.ts +0 -15
- package/templates/ssr/src/routes.tsx +0 -13
- package/templates/ssr/src/styles.css +0 -148
- package/templates/ssr/src/vite-server.d.ts +0 -7
- package/templates/ssr/tests/app.test.tsx +0 -24
- package/templates/ssr/tests/components/counter.test.tsx +0 -13
- package/templates/ssr/tests/resources.test.ts +0 -11
- package/templates/ssr/tsconfig.json +0 -22
- package/templates/ssr/tsconfig.node.json +0 -10
- package/templates/ssr/tsconfig.server.json +0 -15
- package/templates/ssr/vite.config.ts +0 -25
- package/templates/ssr/vitest.config.ts +0 -13
- package/templates/startkit/AGENTS.md +0 -77
- package/templates/startkit/README.md +0 -192
- package/templates/startkit/gitignore.template +0 -16
- package/templates/startkit/index.html +0 -13
- package/templates/startkit/package.json +0 -35
- package/templates/startkit/src/components/app-header.tsx +0 -93
- package/templates/startkit/src/components/app-sidebar.tsx +0 -95
- package/templates/startkit/src/components/data-table.tsx +0 -80
- package/templates/startkit/src/components/empty-state.tsx +0 -13
- package/templates/startkit/src/components/page-header.tsx +0 -23
- package/templates/startkit/src/components/stat-card.tsx +0 -24
- package/templates/startkit/src/features/accounts/account-filters.tsx +0 -61
- package/templates/startkit/src/features/accounts/account-table.tsx +0 -79
- package/templates/startkit/src/lib/format.ts +0 -31
- package/templates/startkit/src/lib/mock-data.ts +0 -441
- package/templates/startkit/src/lib/routes.ts +0 -116
- package/templates/startkit/src/main.tsx +0 -12
- package/templates/startkit/src/pages/_layout.tsx +0 -56
- package/templates/startkit/src/pages/auth/_layout.tsx +0 -7
- package/templates/startkit/src/pages/auth/login.tsx +0 -129
- package/templates/startkit/src/pages/home.tsx +0 -83
- package/templates/startkit/src/pages/not-found.tsx +0 -24
- package/templates/startkit/src/pages/workspace/_layout.tsx +0 -17
- package/templates/startkit/src/pages/workspace/accounts/index.tsx +0 -217
- package/templates/startkit/src/pages/workspace/dashboard.tsx +0 -118
- package/templates/startkit/src/pages/workspace/settings.tsx +0 -218
- package/templates/startkit/src/router.tsx +0 -7
- package/templates/startkit/src/routes/auth-config.ts +0 -38
- package/templates/startkit/src/routes/auth.ts +0 -8
- package/templates/startkit/src/routes/index.ts +0 -28
- package/templates/startkit/src/routes/public.ts +0 -8
- package/templates/startkit/src/routes/workspace/accounts.ts +0 -8
- package/templates/startkit/src/routes/workspace/index.ts +0 -14
- package/templates/startkit/src/styles/components.css +0 -396
- package/templates/startkit/src/styles/layout.css +0 -192
- package/templates/startkit/src/styles/reset.css +0 -38
- package/templates/startkit/src/styles/theme.css +0 -76
- package/templates/startkit/src/styles/tokens.css +0 -67
- package/templates/startkit/src/styles.css +0 -7
- package/templates/startkit/src/toast.ts +0 -55
- package/templates/startkit/src/utils/join-classes.ts +0 -4
- package/templates/startkit/src/vite-env.d.ts +0 -5
- package/templates/startkit/tests/app.test.tsx +0 -32
- package/templates/startkit/tests/preferences.test.ts +0 -43
- package/templates/startkit/tests/resources.test.ts +0 -82
- package/templates/startkit/tsconfig.json +0 -20
- package/templates/startkit/tsconfig.node.json +0 -10
- package/templates/startkit/vite.config.ts +0 -32
- package/templates/startkit/vitest.config.ts +0 -13
package/dist/generate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
1
|
+
import { mkdir, mkdtemp, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
4
|
import { load } from "js-yaml";
|
|
5
5
|
//#region src/generate/generator.ts
|
|
@@ -34,6 +34,17 @@ function schemaType(schema, at, direction = "response") {
|
|
|
34
34
|
const name = decodeURIComponent(String(schema.$ref).split("/").at(-1));
|
|
35
35
|
return pascal(name);
|
|
36
36
|
}
|
|
37
|
+
if (Array.isArray(schema.type)) {
|
|
38
|
+
const includesNull = schema.type.includes("null");
|
|
39
|
+
const rendered = [...new Set(schema.type.filter((value) => value !== "null"))].map((variant) => schemaType({
|
|
40
|
+
...schema,
|
|
41
|
+
type: variant,
|
|
42
|
+
nullable: false
|
|
43
|
+
}, at, direction));
|
|
44
|
+
if (includesNull) rendered.push("null");
|
|
45
|
+
if (rendered.length === 0) fail("Schema type array must not be empty", at);
|
|
46
|
+
return [...new Set(rendered)].join(" | ");
|
|
47
|
+
}
|
|
37
48
|
if (schema.const !== void 0) return JSON.stringify(schema.const);
|
|
38
49
|
if (schema.enum) return schema.enum.map((value) => JSON.stringify(value)).join(" | ") || "never";
|
|
39
50
|
if (schema.oneOf || schema.anyOf) return (schema.oneOf ?? schema.anyOf).map((item, i) => schemaType(item, `${at}/${schema.oneOf ? "oneOf" : "anyOf"}/${i}`, direction)).join(" | ");
|
|
@@ -230,18 +241,31 @@ function generateFiles(document) {
|
|
|
230
241
|
if (seen.has(id)) fail("Duplicate operationId", `${at}/operationId`, id);
|
|
231
242
|
seen.add(id);
|
|
232
243
|
if (operation.callbacks) fail("Callbacks are unsupported", `${at}/callbacks`, id);
|
|
233
|
-
const
|
|
244
|
+
const parametersByIdentity = /* @__PURE__ */ new Map();
|
|
245
|
+
for (const parameter of [...document.paths[path].parameters ?? [], ...operation.parameters ?? []]) {
|
|
246
|
+
if (parameter.$ref) fail("Parameter references must be bundled", `${at}/parameters`, id);
|
|
247
|
+
if (typeof parameter.name !== "string" || typeof parameter.in !== "string") fail("Parameters require string name and in fields", `${at}/parameters`, id);
|
|
248
|
+
parametersByIdentity.set(`${parameter.in}\0${parameter.name}`, parameter);
|
|
249
|
+
}
|
|
250
|
+
const parameters = [...parametersByIdentity.values()];
|
|
234
251
|
const byLocation = {
|
|
235
252
|
path: [],
|
|
236
253
|
query: [],
|
|
237
254
|
header: []
|
|
238
255
|
};
|
|
239
256
|
for (const parameter of parameters) {
|
|
240
|
-
if (parameter.$ref) fail("Parameter references must be bundled", `${at}/parameters`, id);
|
|
241
257
|
if (parameter.in === "cookie") fail("Cookie parameters are unsupported", `${at}/parameters`, id);
|
|
242
258
|
if (!byLocation[parameter.in]) fail(`Unsupported parameter location ${parameter.in}`, `${at}/parameters`, id);
|
|
243
259
|
byLocation[parameter.in].push(parameter);
|
|
244
260
|
}
|
|
261
|
+
const templateParameters = new Set([...path.matchAll(/\{([^{}]+)\}/g)].map((match) => match[1]));
|
|
262
|
+
const declaredPathParameters = new Set(byLocation.path.map((parameter) => parameter.name));
|
|
263
|
+
for (const name of templateParameters) {
|
|
264
|
+
const parameter = byLocation.path.find((candidate) => candidate.name === name);
|
|
265
|
+
if (!parameter) fail(`Path template parameter ${name} is not declared`, `${at}/parameters`, id);
|
|
266
|
+
if (!parameter || parameter.required !== true) fail(`Path parameter ${name} must be required`, `${at}/parameters`, id);
|
|
267
|
+
}
|
|
268
|
+
for (const name of declaredPathParameters) if (!templateParameters.has(name)) fail(`Path parameter ${name} is not present in the path template`, `${at}/parameters`, id);
|
|
245
269
|
const prefix = pascal(id);
|
|
246
270
|
const renderParameters = (location) => {
|
|
247
271
|
const list = byLocation[location].sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -319,6 +343,8 @@ async function existingFiles(directory) {
|
|
|
319
343
|
}
|
|
320
344
|
async function writeGenerated(directory, files, check) {
|
|
321
345
|
const output = resolve(directory);
|
|
346
|
+
const outputStat = await stat(output).catch(() => null);
|
|
347
|
+
if (outputStat && !outputStat.isDirectory()) throw new GenerationError(`Generated output must be a directory: ${output}`);
|
|
322
348
|
const entries = await existingFiles(output);
|
|
323
349
|
if (check) {
|
|
324
350
|
if (!entries.length) throw new GenerationError(`Generated directory is missing: ${output}`);
|
|
@@ -357,6 +383,11 @@ async function writeGenerated(directory, files, check) {
|
|
|
357
383
|
}
|
|
358
384
|
}
|
|
359
385
|
async function generate(input, output, check = false) {
|
|
386
|
+
if (!/^https?:\/\//.test(input)) {
|
|
387
|
+
const resolvedInput = resolve(input);
|
|
388
|
+
const inputWithinOutput = relative(resolve(output), resolvedInput);
|
|
389
|
+
if (!inputWithinOutput.startsWith("..") && !isAbsolute(inputWithinOutput)) throw new GenerationError("Generated output must not contain its OpenAPI input document");
|
|
390
|
+
}
|
|
360
391
|
const files = generateFiles(await loadOpenApi(input));
|
|
361
392
|
await mkdir(dirname(resolve(output)), { recursive: true });
|
|
362
393
|
await writeGenerated(output, files, check);
|
|
@@ -364,33 +395,67 @@ async function generate(input, output, check = false) {
|
|
|
364
395
|
//#endregion
|
|
365
396
|
//#region src/bin/generate.ts
|
|
366
397
|
async function runGenerateCli(args, io = console) {
|
|
398
|
+
const wantsJson = args.includes("--json");
|
|
367
399
|
let output;
|
|
368
400
|
let check = false;
|
|
401
|
+
let json = false;
|
|
402
|
+
let help = false;
|
|
369
403
|
const inputs = [];
|
|
370
404
|
for (let i = 0; i < args.length; i++) {
|
|
371
405
|
const arg = args[i];
|
|
372
406
|
if (arg === "--check") check = true;
|
|
373
|
-
else if (arg === "
|
|
374
|
-
else if (arg
|
|
407
|
+
else if (arg === "--json") json = true;
|
|
408
|
+
else if (arg === "--help" || arg === "-h") help = true;
|
|
409
|
+
else if (arg === "-o" || arg === "--output") {
|
|
410
|
+
const value = args[i + 1];
|
|
411
|
+
if (!value || value.startsWith("-")) {
|
|
412
|
+
const message = `${arg} requires a path`;
|
|
413
|
+
io.error(wantsJson ? JSON.stringify({
|
|
414
|
+
status: "error",
|
|
415
|
+
error: message
|
|
416
|
+
}) : message);
|
|
417
|
+
return 1;
|
|
418
|
+
}
|
|
419
|
+
output = value;
|
|
420
|
+
i += 1;
|
|
421
|
+
} else if (arg.startsWith("--output=")) output = arg.slice(9);
|
|
375
422
|
else if (arg.startsWith("-")) {
|
|
376
|
-
|
|
423
|
+
const message = `Unknown option: ${arg}`;
|
|
424
|
+
io.error(wantsJson ? JSON.stringify({
|
|
425
|
+
status: "error",
|
|
426
|
+
error: message
|
|
427
|
+
}) : message);
|
|
377
428
|
return 1;
|
|
378
429
|
} else inputs.push(arg);
|
|
379
430
|
}
|
|
431
|
+
const usage = "Usage: askr generate <input> -o <output-directory> [--check] [--json]";
|
|
432
|
+
if (help) {
|
|
433
|
+
io.log(usage);
|
|
434
|
+
return 0;
|
|
435
|
+
}
|
|
380
436
|
if (inputs.length !== 1 || !output) {
|
|
381
|
-
io.error(
|
|
437
|
+
io.error(json ? JSON.stringify({
|
|
438
|
+
status: "error",
|
|
439
|
+
error: usage
|
|
440
|
+
}) : usage);
|
|
382
441
|
return 1;
|
|
383
442
|
}
|
|
384
443
|
try {
|
|
385
444
|
await generate(inputs[0], output, check);
|
|
386
|
-
io.log(
|
|
445
|
+
io.log(json ? JSON.stringify({
|
|
446
|
+
status: "ok",
|
|
447
|
+
action: check ? "checked" : "generated",
|
|
448
|
+
output
|
|
449
|
+
}) : check ? "Generated client is current." : `Generated client in ${output}.`);
|
|
387
450
|
return 0;
|
|
388
451
|
} catch (error) {
|
|
389
|
-
|
|
452
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
453
|
+
io.error(json ? JSON.stringify({
|
|
454
|
+
status: "error",
|
|
455
|
+
error: message
|
|
456
|
+
}) : message);
|
|
390
457
|
return 1;
|
|
391
458
|
}
|
|
392
459
|
}
|
|
393
460
|
//#endregion
|
|
394
461
|
export { runGenerateCli };
|
|
395
|
-
|
|
396
|
-
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/bin/openapi.d.ts
|
|
2
|
+
type CliIo = Pick<Console, "error" | "log">;
|
|
3
|
+
interface ParsedArgs {
|
|
4
|
+
entry: string;
|
|
5
|
+
output: string;
|
|
6
|
+
check: boolean;
|
|
7
|
+
help: boolean;
|
|
8
|
+
json: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface OpenApiDeps {
|
|
11
|
+
cwd(): string;
|
|
12
|
+
importModule(filePath: string): Promise<unknown>;
|
|
13
|
+
readFile(filePath: string): Promise<string>;
|
|
14
|
+
mkdir(directory: string): Promise<void>;
|
|
15
|
+
writeFile(filePath: string, contents: string): Promise<void>;
|
|
16
|
+
rename(from: string, to: string): Promise<void>;
|
|
17
|
+
rm(filePath: string): Promise<void>;
|
|
18
|
+
temporarySuffix(): string;
|
|
19
|
+
}
|
|
20
|
+
declare function parseOpenApiArgs(args: readonly string[]): ParsedArgs;
|
|
21
|
+
declare function serializeOpenApi(document: unknown): string;
|
|
22
|
+
declare function validateOpenApiDocument(document: unknown): asserts document is Record<string, unknown>;
|
|
23
|
+
declare function runOpenApiCli(args?: string[], io?: CliIo, overrides?: Partial<OpenApiDeps>): Promise<number>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { parseOpenApiArgs, runOpenApiCli, serializeOpenApi, validateOpenApiDocument };
|
package/dist/openapi.js
CHANGED
|
@@ -15,6 +15,7 @@ Options:
|
|
|
15
15
|
--entry <path> TypeScript API module (default: ./src/api.ts)
|
|
16
16
|
--output <path> YAML artifact (default: ./openapi.yml)
|
|
17
17
|
--check Fail when the artifact is missing or byte-stale; never write
|
|
18
|
+
--json Print machine-readable command results
|
|
18
19
|
--help, -h Show help
|
|
19
20
|
`;
|
|
20
21
|
const defaultDeps = {
|
|
@@ -32,17 +33,19 @@ function parseOpenApiArgs(args) {
|
|
|
32
33
|
entry: "./src/api.ts",
|
|
33
34
|
output: "./openapi.yml",
|
|
34
35
|
check: false,
|
|
35
|
-
help: false
|
|
36
|
+
help: false,
|
|
37
|
+
json: false
|
|
36
38
|
};
|
|
37
39
|
for (let index = 0; index < args.length; index += 1) {
|
|
38
40
|
const value = args[index];
|
|
39
41
|
if (value === "--entry" || value === "--output") {
|
|
40
42
|
const next = args[index + 1];
|
|
41
|
-
if (!next) throw new Error(`${value} requires a path`);
|
|
43
|
+
if (!next || next.startsWith("-")) throw new Error(`${value} requires a path`);
|
|
42
44
|
if (value === "--entry") parsed.entry = next;
|
|
43
45
|
else parsed.output = next;
|
|
44
46
|
index += 1;
|
|
45
47
|
} else if (value === "--check") parsed.check = true;
|
|
48
|
+
else if (value === "--json") parsed.json = true;
|
|
46
49
|
else if (value === "--help" || value === "-h") parsed.help = true;
|
|
47
50
|
else throw new Error(`Unknown option: ${value}`);
|
|
48
51
|
}
|
|
@@ -62,9 +65,18 @@ function serializeOpenApi(document) {
|
|
|
62
65
|
noRefs: true
|
|
63
66
|
}).replace(/\n+$/, "")}\n`;
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
const document = exporterFrom(await deps.importModule(entry)).toOpenApiDocument();
|
|
68
|
+
function validateOpenApiDocument(document) {
|
|
67
69
|
if (!document || typeof document !== "object" || Array.isArray(document)) throw new Error("toOpenApiDocument() must return an OpenAPI document object");
|
|
70
|
+
const candidate = document;
|
|
71
|
+
if (typeof candidate.openapi !== "string" || !/^3\.(?:0|1)\.\d+(?:[-+].+)?$/.test(candidate.openapi)) throw new Error("OpenAPI document must declare a supported openapi 3.0.x or 3.1.x version");
|
|
72
|
+
if (!candidate.info || typeof candidate.info !== "object" || Array.isArray(candidate.info)) throw new Error("OpenAPI document must contain an info object");
|
|
73
|
+
const info = candidate.info;
|
|
74
|
+
if (typeof info.title !== "string" || !info.title.trim() || typeof info.version !== "string" || !info.version.trim()) throw new Error("OpenAPI info must contain non-empty title and version strings");
|
|
75
|
+
if (!candidate.paths || typeof candidate.paths !== "object" || Array.isArray(candidate.paths)) throw new Error("OpenAPI document must contain a paths object");
|
|
76
|
+
}
|
|
77
|
+
async function generate(entry, deps) {
|
|
78
|
+
const document = await exporterFrom(await deps.importModule(entry)).toOpenApiDocument();
|
|
79
|
+
validateOpenApiDocument(document);
|
|
68
80
|
return serializeOpenApi(document);
|
|
69
81
|
}
|
|
70
82
|
async function atomicWrite(output, contents, deps) {
|
|
@@ -83,6 +95,7 @@ async function runOpenApiCli(args = process.argv.slice(2), io = console, overrid
|
|
|
83
95
|
...defaultDeps,
|
|
84
96
|
...overrides
|
|
85
97
|
};
|
|
98
|
+
const wantsJson = args.includes("--json");
|
|
86
99
|
try {
|
|
87
100
|
const parsed = parseOpenApiArgs(args);
|
|
88
101
|
if (parsed.help) {
|
|
@@ -91,6 +104,7 @@ async function runOpenApiCli(args = process.argv.slice(2), io = console, overrid
|
|
|
91
104
|
}
|
|
92
105
|
const entry = path.resolve(deps.cwd(), parsed.entry);
|
|
93
106
|
const output = path.resolve(deps.cwd(), parsed.output);
|
|
107
|
+
if (entry === output) throw new Error("OpenAPI output must not overwrite its source entry");
|
|
94
108
|
const expected = await generate(entry, deps);
|
|
95
109
|
if (parsed.check) {
|
|
96
110
|
let actual;
|
|
@@ -98,23 +112,43 @@ async function runOpenApiCli(args = process.argv.slice(2), io = console, overrid
|
|
|
98
112
|
actual = await deps.readFile(output);
|
|
99
113
|
} catch (error) {
|
|
100
114
|
if (error.code === "ENOENT") {
|
|
101
|
-
io.error(
|
|
115
|
+
io.error(parsed.json ? JSON.stringify({
|
|
116
|
+
status: "error",
|
|
117
|
+
reason: "missing",
|
|
118
|
+
output
|
|
119
|
+
}) : `OpenAPI artifact is missing: ${output}`);
|
|
102
120
|
return 1;
|
|
103
121
|
}
|
|
104
122
|
throw error;
|
|
105
123
|
}
|
|
106
124
|
if (actual !== expected) {
|
|
107
|
-
io.error(
|
|
125
|
+
io.error(parsed.json ? JSON.stringify({
|
|
126
|
+
status: "error",
|
|
127
|
+
reason: "stale",
|
|
128
|
+
output
|
|
129
|
+
}) : `OpenAPI artifact is stale: ${output}`);
|
|
108
130
|
return 1;
|
|
109
131
|
}
|
|
110
|
-
io.log(
|
|
132
|
+
io.log(parsed.json ? JSON.stringify({
|
|
133
|
+
status: "ok",
|
|
134
|
+
action: "checked",
|
|
135
|
+
output
|
|
136
|
+
}) : `OpenAPI artifact is current: ${output}`);
|
|
111
137
|
return 0;
|
|
112
138
|
}
|
|
113
139
|
await atomicWrite(output, expected, deps);
|
|
114
|
-
io.log(
|
|
140
|
+
io.log(parsed.json ? JSON.stringify({
|
|
141
|
+
status: "ok",
|
|
142
|
+
action: "generated",
|
|
143
|
+
output
|
|
144
|
+
}) : `Generated OpenAPI artifact: ${output}`);
|
|
115
145
|
return 0;
|
|
116
146
|
} catch (error) {
|
|
117
|
-
|
|
147
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
148
|
+
io.error(wantsJson ? JSON.stringify({
|
|
149
|
+
status: "error",
|
|
150
|
+
error: message
|
|
151
|
+
}) : message);
|
|
118
152
|
return 1;
|
|
119
153
|
}
|
|
120
154
|
}
|
|
@@ -123,6 +157,4 @@ async function main() {
|
|
|
123
157
|
}
|
|
124
158
|
if (isDirectExecution(import.meta.url)) main();
|
|
125
159
|
//#endregion
|
|
126
|
-
export { parseOpenApiArgs, runOpenApiCli, serializeOpenApi };
|
|
127
|
-
|
|
128
|
-
//# sourceMappingURL=openapi.js.map
|
|
160
|
+
export { parseOpenApiArgs, runOpenApiCli, serializeOpenApi, validateOpenApiDocument };
|
package/dist/planner-VAj7qlxr.js
CHANGED
package/dist/range-YUs9eimn.js
CHANGED
|
@@ -28,7 +28,8 @@ Use this when the app renders outside the browser or produces static output. The
|
|
|
28
28
|
2. Register routes at module load before boot or render.
|
|
29
29
|
3. Keep render paths deterministic and environment-safe.
|
|
30
30
|
4. Use route `entries` or the template's static config for parameterized SSG paths.
|
|
31
|
-
5.
|
|
31
|
+
5. Set the canonical `siteUrl` and explicitly exclude non-indexable routes in `sitemap.routes`.
|
|
32
|
+
6. Build and preview after changes that cross the render boundary.
|
|
32
33
|
|
|
33
34
|
## Copy This Shape
|
|
34
35
|
|
|
@@ -61,6 +62,7 @@ npx @askrjs/cli ssg --config ./ssg.config.ts --output ./dist/static
|
|
|
61
62
|
- SSR or SSG build output is deterministic for the same inputs.
|
|
62
63
|
- Hydration has no structural mismatch warnings.
|
|
63
64
|
- Generated static routes cover expected params.
|
|
65
|
+
- `sitemap.xml` contains every intended canonical route and excludes runtime-only or non-indexable routes.
|
|
64
66
|
- Browser preview still navigates correctly after hydration.
|
|
65
67
|
|
|
66
68
|
## Done When
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { t as isDirectExecution } from "./is-direct-execution-Cdlr-ZUl.js";
|
|
2
|
+
import { n as publishStagedDirectory, t as createSiblingStage } from "./directory-swap-DWoHtx7C.js";
|
|
2
3
|
import fs from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
5
|
+
import { constants } from "node:fs";
|
|
4
6
|
import { fileURLToPath } from "node:url";
|
|
5
7
|
//#region src/bin/skill-review.ts
|
|
6
8
|
const TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
@@ -312,29 +314,41 @@ const REVIEW_PROMPTS = [
|
|
|
312
314
|
async function pathExists$1(filePath) {
|
|
313
315
|
return Boolean(await fs.stat(filePath).catch(() => null));
|
|
314
316
|
}
|
|
317
|
+
const MAX_REVIEW_FILES = 1e4;
|
|
318
|
+
const MAX_REVIEW_FILE_BYTES = 2 * 1024 * 1024;
|
|
319
|
+
const MAX_REVIEW_TOTAL_BYTES = 20 * 1024 * 1024;
|
|
315
320
|
function shouldReadFile(filePath) {
|
|
316
321
|
return TEXT_FILE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
|
|
317
322
|
}
|
|
318
|
-
async function collectReviewFiles(targetPath,
|
|
323
|
+
async function collectReviewFiles(targetPath, state) {
|
|
319
324
|
const stat = await fs.lstat(targetPath);
|
|
320
325
|
if (stat.isSymbolicLink()) return;
|
|
321
326
|
if (stat.isDirectory()) {
|
|
322
327
|
const entries = await fs.readdir(targetPath, { withFileTypes: true });
|
|
323
328
|
for (const entry of entries) {
|
|
324
329
|
if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) continue;
|
|
325
|
-
await collectReviewFiles(path.join(targetPath, entry.name),
|
|
330
|
+
await collectReviewFiles(path.join(targetPath, entry.name), state);
|
|
326
331
|
}
|
|
327
332
|
return;
|
|
328
333
|
}
|
|
329
|
-
if (stat.isFile() && shouldReadFile(targetPath))
|
|
334
|
+
if (stat.isFile() && shouldReadFile(targetPath)) {
|
|
335
|
+
if (stat.size > MAX_REVIEW_FILE_BYTES) throw new Error(`Review file exceeds ${MAX_REVIEW_FILE_BYTES} bytes: ${targetPath}`);
|
|
336
|
+
if (state.files.length >= MAX_REVIEW_FILES) throw new Error(`Review target exceeds ${MAX_REVIEW_FILES} text files`);
|
|
337
|
+
state.totalBytes += stat.size;
|
|
338
|
+
if (state.totalBytes > MAX_REVIEW_TOTAL_BYTES) throw new Error(`Review target exceeds ${MAX_REVIEW_TOTAL_BYTES} text bytes`);
|
|
339
|
+
state.files.push(targetPath);
|
|
340
|
+
}
|
|
330
341
|
}
|
|
331
342
|
async function loadReviewFiles(targetPath) {
|
|
332
343
|
const resolvedTarget = path.resolve(targetPath);
|
|
333
344
|
if (!await pathExists$1(resolvedTarget)) throw new Error(`Review target not found: ${resolvedTarget}`);
|
|
334
345
|
const baseDirectory = (await fs.stat(resolvedTarget)).isDirectory() ? resolvedTarget : path.dirname(resolvedTarget);
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
346
|
+
const collection = {
|
|
347
|
+
files: [],
|
|
348
|
+
totalBytes: 0
|
|
349
|
+
};
|
|
350
|
+
await collectReviewFiles(resolvedTarget, collection);
|
|
351
|
+
const files = await Promise.all(collection.files.map(async (filePath) => ({
|
|
338
352
|
path: path.relative(baseDirectory, filePath) || path.basename(filePath),
|
|
339
353
|
content: await fs.readFile(filePath, "utf8")
|
|
340
354
|
})));
|
|
@@ -496,17 +510,23 @@ function parseArgs(args) {
|
|
|
496
510
|
cwd: process.cwd(),
|
|
497
511
|
force: false,
|
|
498
512
|
help: false,
|
|
499
|
-
json: false
|
|
513
|
+
json: false,
|
|
514
|
+
errors: []
|
|
500
515
|
};
|
|
501
516
|
for (let i = 0; i < args.length; i += 1) {
|
|
502
517
|
const arg = args[i];
|
|
503
518
|
if (arg === "--help" || arg === "-h") parsed.help = true;
|
|
504
519
|
else if (arg === "--json") parsed.json = true;
|
|
505
520
|
else if (arg === "--force") parsed.force = true;
|
|
506
|
-
else if (arg === "--cwd"
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
521
|
+
else if (arg === "--cwd") {
|
|
522
|
+
const value = args[i + 1];
|
|
523
|
+
if (!value || value.startsWith("-")) parsed.errors.push("Missing value for --cwd");
|
|
524
|
+
else {
|
|
525
|
+
parsed.cwd = value;
|
|
526
|
+
i += 1;
|
|
527
|
+
}
|
|
528
|
+
} else if (arg.startsWith("-")) parsed.errors.push(`Unknown option: ${arg}`);
|
|
529
|
+
else positional.push(arg);
|
|
510
530
|
}
|
|
511
531
|
return {
|
|
512
532
|
...parsed,
|
|
@@ -572,16 +592,36 @@ async function copyBundledSkills(targetSkillsDir, bundledNames) {
|
|
|
572
592
|
await copyDir(src, dest);
|
|
573
593
|
}
|
|
574
594
|
}
|
|
595
|
+
async function stageSkillsDirectory(targetSkillsDir) {
|
|
596
|
+
const stage = await createSiblingStage(targetSkillsDir, "askr-skills");
|
|
597
|
+
if (await pathExists(targetSkillsDir)) await fs.cp(targetSkillsDir, stage, {
|
|
598
|
+
recursive: true,
|
|
599
|
+
mode: constants.COPYFILE_FICLONE
|
|
600
|
+
});
|
|
601
|
+
return stage;
|
|
602
|
+
}
|
|
603
|
+
async function replaceBundledSkills(targetSkillsDir, bundledNames) {
|
|
604
|
+
const stage = await stageSkillsDirectory(targetSkillsDir);
|
|
605
|
+
try {
|
|
606
|
+
await removeManagedSkillArtifacts(stage, bundledNames);
|
|
607
|
+
await copyBundledSkills(stage, bundledNames);
|
|
608
|
+
await publishStagedDirectory(stage, targetSkillsDir);
|
|
609
|
+
} catch (error) {
|
|
610
|
+
await fs.rm(stage, {
|
|
611
|
+
recursive: true,
|
|
612
|
+
force: true
|
|
613
|
+
});
|
|
614
|
+
throw error;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
575
617
|
async function installBundledSkills(options = {}) {
|
|
576
618
|
const targetRoot = path.resolve(options.cwd ?? process.cwd());
|
|
577
619
|
const targetSkillsDir = path.join(targetRoot, PROJECT_SKILLS_DIR);
|
|
578
620
|
const bundledNames = await listBundledSkills();
|
|
621
|
+
const targetStat = await fs.stat(targetSkillsDir).catch(() => null);
|
|
622
|
+
if (targetStat && !targetStat.isDirectory()) throw new Error(`Skills target exists and is not a directory: ${targetSkillsDir}`);
|
|
579
623
|
if ((await fs.readdir(targetSkillsDir).catch(() => [])).length > 0 && !options.force) throw new Error(`Refusing to install into non-empty ${targetSkillsDir}.`);
|
|
580
|
-
|
|
581
|
-
await fs.mkdir(targetSkillsDir, { recursive: true });
|
|
582
|
-
await removeManagedSkillArtifacts(targetSkillsDir, bundledNames);
|
|
583
|
-
}
|
|
584
|
-
await copyBundledSkills(targetSkillsDir, bundledNames);
|
|
624
|
+
await replaceBundledSkills(targetSkillsDir, bundledNames);
|
|
585
625
|
return {
|
|
586
626
|
bundledNames,
|
|
587
627
|
targetSkillsDir
|
|
@@ -591,9 +631,9 @@ async function syncBundledSkills(options = {}) {
|
|
|
591
631
|
const targetRoot = path.resolve(options.cwd ?? process.cwd());
|
|
592
632
|
const targetSkillsDir = path.join(targetRoot, PROJECT_SKILLS_DIR);
|
|
593
633
|
const bundledNames = await listBundledSkills();
|
|
594
|
-
await fs.
|
|
595
|
-
|
|
596
|
-
await
|
|
634
|
+
const targetStat = await fs.stat(targetSkillsDir).catch(() => null);
|
|
635
|
+
if (targetStat && !targetStat.isDirectory()) throw new Error(`Skills target exists and is not a directory: ${targetSkillsDir}`);
|
|
636
|
+
await replaceBundledSkills(targetSkillsDir, bundledNames);
|
|
597
637
|
return {
|
|
598
638
|
bundledNames,
|
|
599
639
|
targetSkillsDir
|
|
@@ -615,9 +655,14 @@ async function installSkills(parsed, io) {
|
|
|
615
655
|
}
|
|
616
656
|
}
|
|
617
657
|
async function syncSkills(parsed, io) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
658
|
+
try {
|
|
659
|
+
const { bundledNames, targetSkillsDir } = await syncBundledSkills({ cwd: parsed.cwd });
|
|
660
|
+
io.log(`Synced ${bundledNames.length} Askr skills to ${targetSkillsDir}`);
|
|
661
|
+
return 0;
|
|
662
|
+
} catch (error) {
|
|
663
|
+
io.error(error instanceof Error ? error.message : String(error));
|
|
664
|
+
return 1;
|
|
665
|
+
}
|
|
621
666
|
}
|
|
622
667
|
async function reviewSkills(parsed, io) {
|
|
623
668
|
if (parsed.help && parsed.command === "review") {
|
|
@@ -646,6 +691,10 @@ async function reviewSkills(parsed, io) {
|
|
|
646
691
|
}
|
|
647
692
|
async function runSkillsCli(args = process.argv.slice(2), io = console) {
|
|
648
693
|
const parsed = parseArgs(args);
|
|
694
|
+
if (parsed.errors.length > 0) {
|
|
695
|
+
for (const error of parsed.errors) io.error(error);
|
|
696
|
+
return 1;
|
|
697
|
+
}
|
|
649
698
|
if (parsed.command === "review" && parsed.help) {
|
|
650
699
|
io.log(reviewHelpText());
|
|
651
700
|
return 0;
|
|
@@ -660,12 +709,28 @@ async function runSkillsCli(args = process.argv.slice(2), io = console) {
|
|
|
660
709
|
return 1;
|
|
661
710
|
}
|
|
662
711
|
if (parsed.command === "list") {
|
|
712
|
+
if (parsed.positionals.length !== 1) {
|
|
713
|
+
io.error("Usage: askr skills list");
|
|
714
|
+
return 1;
|
|
715
|
+
}
|
|
663
716
|
const names = await listBundledSkills();
|
|
664
717
|
for (const name of names) io.log(name);
|
|
665
718
|
return 0;
|
|
666
719
|
}
|
|
667
|
-
if (parsed.command === "install")
|
|
668
|
-
|
|
720
|
+
if (parsed.command === "install") {
|
|
721
|
+
if (parsed.positionals.length !== 1) {
|
|
722
|
+
io.error("Usage: askr skills install [--cwd <dir>] [--force]");
|
|
723
|
+
return 1;
|
|
724
|
+
}
|
|
725
|
+
return installSkills(parsed, io);
|
|
726
|
+
}
|
|
727
|
+
if (parsed.command === "sync") {
|
|
728
|
+
if (parsed.positionals.length !== 1) {
|
|
729
|
+
io.error("Usage: askr skills sync [--cwd <dir>]");
|
|
730
|
+
return 1;
|
|
731
|
+
}
|
|
732
|
+
return syncSkills(parsed, io);
|
|
733
|
+
}
|
|
669
734
|
if (parsed.command === "review") return reviewSkills(parsed, io);
|
|
670
735
|
io.error(`Unknown skills command: ${parsed.command}`);
|
|
671
736
|
io.error("Run `askr skills --help` to see available commands.");
|
|
@@ -678,5 +743,3 @@ async function main() {
|
|
|
678
743
|
if (isDirectExecution(import.meta.url)) main();
|
|
679
744
|
//#endregion
|
|
680
745
|
export { runSkillsCli as n, syncBundledSkills as r, installBundledSkills as t };
|
|
681
|
-
|
|
682
|
-
//# sourceMappingURL=skills-Bh0mEhIx.js.map
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/bin/skills.d.ts
|
|
2
|
+
type CliIo = Pick<Console, "error" | "log">;
|
|
3
|
+
declare function installBundledSkills(options?: {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
force?: boolean;
|
|
6
|
+
}): Promise<{
|
|
7
|
+
bundledNames: string[];
|
|
8
|
+
targetSkillsDir: string;
|
|
9
|
+
}>;
|
|
10
|
+
declare function syncBundledSkills(options?: {
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
bundledNames: string[];
|
|
14
|
+
targetSkillsDir: string;
|
|
15
|
+
}>;
|
|
16
|
+
declare function runSkillsCli(args?: string[], io?: CliIo): Promise<number>;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { installBundledSkills, runSkillsCli, syncBundledSkills };
|
package/dist/skills.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as runSkillsCli, r as syncBundledSkills, t as installBundledSkills } from "./skills-
|
|
2
|
+
import { n as runSkillsCli, r as syncBundledSkills, t as installBundledSkills } from "./skills-B7CbWur9.js";
|
|
3
3
|
export { installBundledSkills, runSkillsCli, syncBundledSkills };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/ssg/sitemap.d.ts
|
|
2
|
+
type SitemapChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
3
|
+
interface SitemapRouteConfig {
|
|
4
|
+
/** Canonical URL. Relative values resolve against siteUrl. */
|
|
5
|
+
url?: string;
|
|
6
|
+
/** W3C date/datetime or Date describing the last meaningful page update. */
|
|
7
|
+
lastModified?: string | Date;
|
|
8
|
+
changeFrequency?: SitemapChangeFrequency;
|
|
9
|
+
/** Relative crawl priority from 0 through 1. */
|
|
10
|
+
priority?: number;
|
|
11
|
+
/** hreflang to canonical URL mapping, including optional x-default. */
|
|
12
|
+
alternates?: Readonly<Record<string, string>>;
|
|
13
|
+
}
|
|
14
|
+
interface SitemapRouteContext {
|
|
15
|
+
path: string;
|
|
16
|
+
filePath: string;
|
|
17
|
+
status: string;
|
|
18
|
+
}
|
|
19
|
+
interface SitemapConfig {
|
|
20
|
+
/** Site-wide values inherited by included routes. */
|
|
21
|
+
defaults?: Omit<SitemapRouteConfig, "url" | "alternates">;
|
|
22
|
+
/** Exact concrete route overrides. Set a route to false to exclude it. */
|
|
23
|
+
routes?: Readonly<Record<string, SitemapRouteConfig | false>>;
|
|
24
|
+
/** Compute or override sitemap data. Returning false excludes the route. */
|
|
25
|
+
resolve?: (route: SitemapRouteContext) => SitemapRouteConfig | false | null | undefined | Promise<SitemapRouteConfig | false | null | undefined>;
|
|
26
|
+
/** Output path relative to the SSG output directory. */
|
|
27
|
+
output?: string;
|
|
28
|
+
/** Maintain a Sitemap directive in robots.txt. Defaults to true. */
|
|
29
|
+
robots?: boolean | {
|
|
30
|
+
output?: string;
|
|
31
|
+
};
|
|
32
|
+
/** Optional lower limits for deterministic partitioning and tests. */
|
|
33
|
+
limits?: {
|
|
34
|
+
urlsPerFile?: number;
|
|
35
|
+
bytesPerFile?: number;
|
|
36
|
+
};
|
|
37
|
+
/** Maximum concurrent async route metadata resolvers. Defaults to 16. */
|
|
38
|
+
resolverConcurrency?: number;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export type { SitemapChangeFrequency, SitemapConfig, SitemapRouteConfig, SitemapRouteContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|