@askrjs/cli 0.0.20 → 0.0.22

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.
Files changed (30) hide show
  1. package/dist/analyze.js +1 -1
  2. package/dist/cli.js +1 -1
  3. package/dist/create.js +1 -1
  4. package/dist/generate.js +3 -2
  5. package/dist/{guardrails-L60OAzIp.js → guardrails-BVxzrcBX.js} +1 -1
  6. package/dist/openapi.js +2 -1
  7. package/dist/{registry-BVliEbUv.js → registry-BmGIkoO0.js} +2 -1
  8. package/dist/{runner-CYvonJ0C.js → runner-D2iNzz9g.js} +72 -6
  9. package/dist/{runner-DzWc9R4G.js → runner-N2qHCBar.js} +3 -3
  10. package/dist/{skills-CSGdAZHN.js → skills-C72Z3-Cr.js} +2 -2
  11. package/dist/skills.js +1 -1
  12. package/dist/ssg.js +18 -2
  13. package/dist/templates/full-stack/package.json +4 -3
  14. package/dist/templates/spa/package.json +4 -3
  15. package/dist/templates/spa/tests/app.test.tsx +1 -1
  16. package/dist/templates/spa/tests/components/shared.test.tsx +1 -1
  17. package/dist/templates/spa/tests/resources.test.ts +2 -2
  18. package/dist/templates/ssg/package.json +4 -3
  19. package/dist/templates/ssg/tests/app.test.tsx +1 -1
  20. package/dist/templates/ssg/tests/components/counter.test.tsx +1 -1
  21. package/dist/templates/ssg/tests/resources.test.ts +1 -1
  22. package/dist/templates/ssg/tests/ssg-config.test.ts +1 -1
  23. package/dist/templates/ssr/package.json +4 -3
  24. package/dist/templates/ssr/tests/app.test.tsx +1 -1
  25. package/dist/templates/ssr/tests/components/counter.test.tsx +1 -1
  26. package/dist/templates/ssr/tests/resources.test.ts +1 -1
  27. package/dist/templates/startkit/package.json +4 -3
  28. package/dist/templates/startkit/tests/app.test.tsx +3 -3
  29. package/dist/update.js +1 -1
  30. package/package.json +23 -21
package/dist/analyze.js CHANGED
@@ -71,7 +71,7 @@ async function runAnalyzeCli(args = process.argv.slice(2), io = console, runtime
71
71
  io.log(helpText.trimEnd());
72
72
  return 0;
73
73
  }
74
- const report = await (runtime.analyze ?? (await import("./runner-CYvonJ0C.js")).runAnalysis)({
74
+ const report = await (runtime.analyze ?? (await import("./runner-D2iNzz9g.js")).runAnalysis)({
75
75
  cwd: parsed.cwd,
76
76
  workspacePatterns: parsed.workspacePatterns,
77
77
  check: parsed.check
package/dist/cli.js CHANGED
@@ -96,7 +96,7 @@ async function runCli(args = process.argv.slice(2), io = console) {
96
96
  return runAnalyzeCli(args.slice(1), io);
97
97
  }
98
98
  if (command === "check" || command === "doctor" || command === "repair") {
99
- const { runGuardrailCli } = await import("./guardrails-L60OAzIp.js");
99
+ const { runGuardrailCli } = await import("./guardrails-BVxzrcBX.js");
100
100
  return runGuardrailCli(command, args.slice(1), io);
101
101
  }
102
102
  if (command === "generate") {
package/dist/create.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as isDirectExecution } from "./is-direct-execution-Cdlr-ZUl.js";
3
- import { n as installBundledSkills } from "./skills-CSGdAZHN.js";
3
+ import { n as installBundledSkills } from "./skills-C72Z3-Cr.js";
4
4
  import { n as publishStagedDirectory, t as createSiblingStage } from "./directory-swap-DWoHtx7C.js";
5
5
  import fs from "node:fs/promises";
6
6
  import path from "node:path";
package/dist/generate.js CHANGED
@@ -419,7 +419,7 @@ async function loadOpenApi(input, options = {}) {
419
419
  return parsed.origin;
420
420
  })),
421
421
  allowPrivateHosts: options.allowPrivateHosts ?? false,
422
- maxBytes: positiveOption("maxBytes", options.maxBytes ?? 5 * 1024 * 1024),
422
+ maxBytes: positiveOption("maxBytes", options.maxBytes ?? 5242880),
423
423
  maxDepth: positiveOption("maxDepth", options.maxDepth ?? 32),
424
424
  maxRedirects: positiveOption("maxRedirects", options.maxRedirects ?? 5),
425
425
  timeoutMs: positiveOption("timeoutMs", options.timeoutMs ?? 1e4),
@@ -604,7 +604,8 @@ async function writeGenerated(directory, files, check) {
604
604
  async function generate(input, output, check = false, loadOptions = {}) {
605
605
  if (!/^https?:\/\//.test(input)) {
606
606
  const resolvedInput = resolve(input);
607
- const inputWithinOutput = relative(resolve(output), resolvedInput);
607
+ const resolvedOutput = resolve(output);
608
+ const inputWithinOutput = relative(resolvedOutput, resolvedInput);
608
609
  if (!inputWithinOutput.startsWith("..") && !isAbsolute(inputWithinOutput)) throw new GenerationError("Generated output must not contain its OpenAPI input document");
609
610
  }
610
611
  const files = generateFiles(await loadOpenApi(input, loadOptions));
@@ -98,7 +98,7 @@ async function runGuardrailCli(command, args = process.argv.slice(2), io = conso
98
98
  cwd: parsed.cwd,
99
99
  workspacePatterns: parsed.workspacePatterns
100
100
  };
101
- const { runCheck, runDoctor, runRepair } = await import("./runner-DzWc9R4G.js");
101
+ const { runCheck, runDoctor, runRepair } = await import("./runner-N2qHCBar.js");
102
102
  const report = command === "doctor" ? await runDoctor(options, runtime) : command === "repair" ? await runRepair(options) : await runCheck(options, runtime);
103
103
  if (parsed.json) io.log(JSON.stringify(report));
104
104
  else if (report.command === "doctor") printDoctor(report, io);
package/dist/openapi.js CHANGED
@@ -61,7 +61,8 @@ function exporterFrom(moduleValue) {
61
61
  function serializeOpenApi(document) {
62
62
  return `${dump(document, {
63
63
  lineWidth: -1,
64
- noRefs: true
64
+ noRefs: true,
65
+ quoteStyle: "double"
65
66
  }).replace(/\n+$/, "")}\n`;
66
67
  }
67
68
  function validateOpenApiDocument(document) {
@@ -16,8 +16,9 @@ function executionEnvironment(env) {
16
16
  async function loadNpmConfiguration(root, env = process.env) {
17
17
  const effectiveEnvironment = executionEnvironment(env);
18
18
  const { definitions, flatten, shorthands } = npmDefinitions;
19
+ const npmPath = path.dirname(fileURLToPath(import.meta.resolve("@npmcli/config/package.json")));
19
20
  const configuration = new Config({
20
- npmPath: path.dirname(fileURLToPath(import.meta.resolve("@npmcli/config/package.json"))),
21
+ npmPath,
21
22
  definitions,
22
23
  flatten,
23
24
  shorthands,
@@ -413,15 +413,47 @@ function collectStateBindings(sourceFile, bindings) {
413
413
  owners
414
414
  };
415
415
  }
416
- function identifierIsReadAsValue(node) {
416
+ function isCallableJsxProp(node, checker) {
417
+ const expression = node.parent;
418
+ if (!ts.isJsxExpression(expression) || !expression.expression) return false;
419
+ const attribute = expression.parent;
420
+ if (!ts.isJsxAttribute(attribute)) return false;
421
+ const opening = attribute.parent.parent;
422
+ if (!ts.isJsxOpeningLikeElement(opening)) return false;
423
+ const attributeName = ts.isIdentifier(attribute.name) ? attribute.name.text : ts.isJsxNamespacedName(attribute.name) && ts.isIdentifier(attribute.name.name) ? attribute.name.name.text : null;
424
+ if (!attributeName) return false;
425
+ let expected = checker.getContextualType(expression.expression);
426
+ if (!expected || expected.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) {
427
+ const tagType = checker.getTypeAtLocation(opening.tagName);
428
+ for (const signature of tagType.getCallSignatures()) {
429
+ const propsParameter = signature.parameters[0];
430
+ if (!propsParameter) continue;
431
+ const prop = checker.getTypeOfSymbolAtLocation(propsParameter, opening.tagName).getProperty(attributeName);
432
+ if (!prop) continue;
433
+ expected = checker.getTypeOfSymbolAtLocation(prop, attribute);
434
+ if (expected.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) continue;
435
+ if (expected.getCallSignatures().length > 0 || expected.isUnion()) break;
436
+ }
437
+ }
438
+ if (!expected || expected.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) return false;
439
+ const hasCallableSignature = (type) => type.isUnion() ? type.types.some((member) => hasCallableSignature(member)) : type.getCallSignatures().length > 0;
440
+ return hasCallableSignature(expected);
441
+ }
442
+ function identifierIsReadAsValue(node, checker) {
417
443
  const parent = node.parent;
418
444
  if (ts.isCallExpression(parent) && parent.expression === node) return false;
419
- if (ts.isPropertyAccessExpression(parent) && parent.expression === node) return false;
445
+ if (ts.isPropertyAccessExpression(parent)) {
446
+ if (parent.expression === node || parent.name === node) return false;
447
+ }
448
+ if (ts.isElementAccessExpression(parent) && parent.expression === node) return false;
420
449
  if (ts.isVariableDeclaration(parent) && parent.name === node) return false;
421
450
  if (ts.isBindingElement(parent) && parent.name === node) return false;
422
- if (ts.isImportSpecifier(parent) || ts.isImportClause(parent) || ts.isNamespaceImport(parent)) return false;
423
- if (ts.isJsxExpression(parent)) return !ts.isJsxAttribute(parent.parent);
424
- return ts.isReturnStatement(parent);
451
+ if (ts.isImportSpecifier(parent) || ts.isImportClause(parent) || ts.isNamespaceImport(parent) || ts.isParameter(parent) && parent.name === node || ts.isPropertyDeclaration(parent) && parent.name === node || ts.isPropertySignature(parent) && parent.name === node || ts.isMethodDeclaration(parent) && parent.name === node || ts.isMethodSignature(parent) && parent.name === node || ts.isExportSpecifier(parent) && (parent.name === node || parent.propertyName === node) || ts.isTypeQueryNode(parent) && parent.exprName === node) return false;
452
+ if (ts.isJsxAttribute(parent) && parent.name === node) return false;
453
+ if (isCallableJsxProp(node, checker)) return false;
454
+ if (ts.isPropertyAssignment(parent) && parent.name === node) return false;
455
+ if (ts.isShorthandPropertyAssignment(parent)) return true;
456
+ return true;
425
457
  }
426
458
  const stateAccessRule = {
427
459
  id: "askr/state-access",
@@ -434,7 +466,7 @@ const stateAccessRule = {
434
466
  const state = collectStateBindings(sourceFile, sourceBindings(sourceFile));
435
467
  visit(sourceFile, (node) => {
436
468
  if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && state.setters.has(node.expression.text) && node.arguments.length === 0) diagnostics.push(diagnostic(context, node.expression, this, `State setter '${node.expression.text}' is called without a value or updater.`, "Pass the next value or a functional updater."));
437
- else if (ts.isIdentifier(node) && state.getters.has(node.text) && identifierIsReadAsValue(node)) diagnostics.push(diagnostic(context, node, this, `State getter '${node.text}' is used as a value instead of being called.`, `Read it with ${node.text}().`));
469
+ else if (ts.isIdentifier(node) && state.getters.has(node.text) && identifierIsReadAsValue(node, context.checker)) diagnostics.push(diagnostic(context, node, this, `State getter '${node.text}' is used as a value instead of being called.`, `Read it with ${node.text}().`));
438
470
  });
439
471
  }
440
472
  return diagnostics;
@@ -525,6 +557,32 @@ const stableDependenciesRule = {
525
557
  function jsxAttributes(node) {
526
558
  return new Map(node.attributes.properties.flatMap((attribute) => ts.isJsxAttribute(attribute) && ts.isIdentifier(attribute.name) ? [[attribute.name.text, attribute]] : []));
527
559
  }
560
+ function staticallyNonFunction(expression, checker) {
561
+ if (ts.isArrowFunction(expression) || ts.isFunctionExpression(expression) || ts.isClassExpression(expression)) return false;
562
+ if (ts.isStringLiteral(expression) || ts.isNumericLiteral(expression) || expression.kind === ts.SyntaxKind.TrueKeyword || expression.kind === ts.SyntaxKind.FalseKeyword || expression.kind === ts.SyntaxKind.NullKeyword || ts.isObjectLiteralExpression(expression) || ts.isArrayLiteralExpression(expression)) return true;
563
+ const type = checker.getTypeAtLocation(expression);
564
+ if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) return false;
565
+ if (type.isUnion()) return type.types.every((member) => staticallyNonFunctionType(member));
566
+ return staticallyNonFunctionType(type);
567
+ }
568
+ function staticallyNonFunctionType(type) {
569
+ if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) return false;
570
+ if (type.isUnion()) return type.types.some((member) => !(member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike)) && staticallyNonFunctionType(member));
571
+ return type.getCallSignatures().length === 0;
572
+ }
573
+ function staticallyNotTrue(expression, checker) {
574
+ if (expression.kind === ts.SyntaxKind.TrueKeyword) return false;
575
+ if (ts.isStringLiteral(expression) || ts.isNumericLiteral(expression) || expression.kind === ts.SyntaxKind.FalseKeyword || expression.kind === ts.SyntaxKind.NullKeyword || ts.isObjectLiteralExpression(expression) || ts.isArrayLiteralExpression(expression)) return true;
576
+ const type = checker.getTypeAtLocation(expression);
577
+ if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) return false;
578
+ return staticallyNotTrueType(type, checker);
579
+ }
580
+ function staticallyNotTrueType(type, checker) {
581
+ if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) return false;
582
+ if (type.isUnion()) return type.types.every((member) => staticallyNotTrueType(member, checker));
583
+ if (type.flags & ts.TypeFlags.BooleanLike) return (type.flags & ts.TypeFlags.BooleanLiteral) !== 0 && type === checker.getFalseType();
584
+ return true;
585
+ }
528
586
  const forContractRule = {
529
587
  id: "askr/for-contract",
530
588
  category: "correctness",
@@ -543,6 +601,14 @@ const forContractRule = {
543
601
  const byIndex = attributes.get("byIndex");
544
602
  if (!by && !byIndex) diagnostics.push(diagnostic(context, node.tagName, this, "<For> requires a stable by function or explicit byIndex.", "Prefer by={(item) => item.id}; use byIndex only for positional lists."));
545
603
  else if (by && byIndex) diagnostics.push(diagnostic(context, byIndex, this, "<For> accepts either by or byIndex, not both.", "Remove one key strategy."));
604
+ if (by) {
605
+ const expression = by.initializer && ts.isJsxExpression(by.initializer) ? by.initializer.expression : void 0;
606
+ if (!expression || staticallyNonFunction(expression, context.checker)) diagnostics.push(diagnostic(context, by, this, "<For> by must be a function.", "Pass by={(item) => item.id} or use byIndex for positional lists."));
607
+ }
608
+ if (byIndex?.initializer) {
609
+ const expression = ts.isJsxExpression(byIndex.initializer) ? byIndex.initializer.expression : void 0;
610
+ if (!expression || staticallyNotTrue(expression, context.checker)) diagnostics.push(diagnostic(context, byIndex, this, "<For> byIndex must be true.", "Use bare byIndex or byIndex={true} for positional lists."));
611
+ }
546
612
  const element = ts.isJsxOpeningElement(node) && ts.isJsxElement(node.parent) ? node.parent : null;
547
613
  if (ts.isJsxSelfClosingElement(node) || element && element.children.every((child) => ts.isJsxText(child) && child.text.trim().length === 0)) diagnostics.push(diagnostic(context, node.tagName, this, "<For> is missing its item renderer child.", "Provide a function child such as {(item) => <Row item={item} />}."));
548
614
  });
@@ -1,12 +1,12 @@
1
- import { t as inspectBundledSkills } from "./skills-CSGdAZHN.js";
1
+ import { t as inspectBundledSkills } from "./skills-C72Z3-Cr.js";
2
2
  import { discoverWorkspaceProject } from "./discovery-DUDrZCIC.js";
3
- import { analysisHasBlockingFindings, runAnalysis } from "./runner-CYvonJ0C.js";
3
+ import { analysisHasBlockingFindings, runAnalysis } from "./runner-D2iNzz9g.js";
4
4
  import fs from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  import { spawn } from "node:child_process";
7
7
  import semver from "semver";
8
8
  //#region src/guardrails/runner.ts
9
- const SUPPORTED_NODE_RANGE = "^20.19.0 || >=22.12.0";
9
+ const SUPPORTED_NODE_RANGE = ">=24.0.0";
10
10
  const VALIDATION_SCRIPTS = [
11
11
  "lint",
12
12
  "typecheck",
@@ -316,8 +316,8 @@ async function pathExists$1(filePath) {
316
316
  return Boolean(await fs.stat(filePath).catch(() => null));
317
317
  }
318
318
  const MAX_REVIEW_FILES = 1e4;
319
- const MAX_REVIEW_FILE_BYTES = 2 * 1024 * 1024;
320
- const MAX_REVIEW_TOTAL_BYTES = 20 * 1024 * 1024;
319
+ const MAX_REVIEW_FILE_BYTES = 2097152;
320
+ const MAX_REVIEW_TOTAL_BYTES = 20971520;
321
321
  function shouldReadFile(filePath) {
322
322
  return TEXT_FILE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
323
323
  }
package/dist/skills.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { i as syncBundledSkills, n as installBundledSkills, r as runSkillsCli, t as inspectBundledSkills } from "./skills-CSGdAZHN.js";
2
+ import { i as syncBundledSkills, n as installBundledSkills, r as runSkillsCli, t as inspectBundledSkills } from "./skills-C72Z3-Cr.js";
3
3
  export { inspectBundledSkills, installBundledSkills, runSkillsCli, syncBundledSkills };
package/dist/ssg.js CHANGED
@@ -23,7 +23,7 @@ const changeFrequencies = /* @__PURE__ */ new Set([
23
23
  "never"
24
24
  ]);
25
25
  const MAX_URLS_PER_SITEMAP = 5e4;
26
- const MAX_SITEMAP_BYTES = 50 * 1024 * 1024;
26
+ const MAX_SITEMAP_BYTES = 52428800;
27
27
  const MANIFEST_PATH = ".askr/sitemap-manifest.json";
28
28
  function escapeXml(value) {
29
29
  return value.replace(/[&<>"']/g, (character) => {
@@ -486,12 +486,27 @@ async function writeSsgOutputReport(outputDir, routes, inspections, config = {})
486
486
  }
487
487
  assets.sort((left, right) => left.path.localeCompare(right.path));
488
488
  const assetMap = new Map(assets.map((asset) => [asset.path, asset]));
489
+ const missingReferences = /* @__PURE__ */ new Set();
489
490
  const outputRoutes = [];
490
491
  for (const route of [...routes].sort((left, right) => left.path.localeCompare(right.path))) {
491
492
  const inspection = inspections.get(route.path);
492
493
  if (!inspection) continue;
493
494
  const html = inspection.html;
494
- const referenced = (references, type) => references.map((reference) => localReference(reference, inspection.filePath)).filter((reference) => Boolean(reference)).map((reference) => assetMap.get(reference)).filter((asset) => asset?.type === type).sort((left, right) => left.path.localeCompare(right.path));
495
+ const referenced = (references, type) => {
496
+ const resolved = [];
497
+ for (const reference of references) {
498
+ const localPath = localReference(reference, inspection.filePath);
499
+ if (!localPath) continue;
500
+ const asset = assetMap.get(localPath);
501
+ if (!asset) {
502
+ missingReferences.add(`route ${route.path} references missing ${type} asset ${localPath}`);
503
+ continue;
504
+ }
505
+ if (asset.type !== type) continue;
506
+ resolved.push(asset);
507
+ }
508
+ return resolved.sort((left, right) => left.path.localeCompare(right.path));
509
+ };
495
510
  outputRoutes.push({
496
511
  route: route.path,
497
512
  filePath: inspection.filePath,
@@ -506,6 +521,7 @@ async function writeSsgOutputReport(outputDir, routes, inspections, config = {})
506
521
  }
507
522
  });
508
523
  }
524
+ if (missingReferences.size > 0) throw new Error(`SSG output contains missing local assets:\n${[...missingReferences].sort().map((item) => `- ${item}`).join("\n")}`);
509
525
  const total = (type) => assets.filter((asset) => asset.type === type).reduce((sum, asset) => ({
510
526
  raw: sum.raw + asset.raw,
511
527
  gzip: sum.gzip + asset.gzip
@@ -30,11 +30,12 @@
30
30
  "@askrjs/vite": ">=0.0.6 <0.1.0",
31
31
  "@types/node": "^20.19.0",
32
32
  "jsdom": "^29.1.1",
33
- "typescript": "^6.0.3",
33
+ "typescript": "^7.0.2",
34
34
  "vite-plus": "^0.2.4",
35
35
  "vitest": "^4.1.10"
36
36
  },
37
37
  "engines": {
38
- "node": "^20.19.0 || >=22.12.0"
39
- }
38
+ "node": ">=24.0.0"
39
+ },
40
+ "packageManager": "npm@12.0.1"
40
41
  }
@@ -26,10 +26,11 @@
26
26
  "@askrjs/vite": ">=0.0.6 <0.1.0",
27
27
  "@types/node": "^20.19.0",
28
28
  "jsdom": "^29.1.1",
29
- "typescript": "^6.0.3",
29
+ "typescript": "^7.0.2",
30
30
  "vite-plus": "^0.2.4"
31
31
  },
32
32
  "engines": {
33
- "node": "^20.19.0 || >=22.12.0"
34
- }
33
+ "node": ">=24.0.0"
34
+ },
35
+ "packageManager": "npm@12.0.1"
35
36
  }
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, it } from 'vite-plus/test';
2
2
 
3
3
  describe('SPA template structure', () => {
4
- it('documents the route-first shell and theme layers the app should keep', () => {
4
+ it('should document the route-first shell and theme layers the app should keep', () => {
5
5
  const structure = [
6
6
  'src/main.tsx',
7
7
  'src/pages/_routes.tsx',
@@ -3,7 +3,7 @@ import MetricCard from '../../src/components/shared/metric-card';
3
3
  import StatusBadge from '../../src/components/shared/status-badge';
4
4
 
5
5
  describe('shared app components', () => {
6
- it('exports small app-local wrappers around theme primitives', () => {
6
+ it('should export small app-local wrappers around theme primitives', () => {
7
7
  expect(MetricCard).toBeDefined();
8
8
  expect(StatusBadge).toBeDefined();
9
9
  expect(typeof MetricCard).toBe('function');
@@ -3,7 +3,7 @@ import { getOperationsSnapshot } from '../src/adapters/operations-client';
3
3
  import { loadOperations } from '../src/features/operations/operations.query';
4
4
 
5
5
  describe('operations data flow', () => {
6
- it('loads the dashboard snapshot through the feature query boundary', async () => {
6
+ it('should load the dashboard snapshot through the feature query boundary', async () => {
7
7
  const snapshot = await loadOperations({});
8
8
 
9
9
  expect(snapshot.metrics.length).toBeGreaterThan(0);
@@ -11,7 +11,7 @@ describe('operations data flow', () => {
11
11
  expect(snapshot.lastEventId).toMatch(/^evt_/);
12
12
  });
13
13
 
14
- it('keeps cancellation owned by the adapter', async () => {
14
+ it('should keep cancellation owned by the adapter', async () => {
15
15
  const controller = new AbortController();
16
16
  const request = getOperationsSnapshot({ signal: controller.signal });
17
17
 
@@ -27,10 +27,11 @@
27
27
  "@askrjs/vite": ">=0.0.6 <0.1.0",
28
28
  "@types/node": "^20.19.0",
29
29
  "jsdom": "^29.1.1",
30
- "typescript": "^6.0.3",
30
+ "typescript": "^7.0.2",
31
31
  "vite-plus": "^0.2.4"
32
32
  },
33
33
  "engines": {
34
- "node": "^20.19.0 || >=22.12.0"
35
- }
34
+ "node": ">=24.0.0"
35
+ },
36
+ "packageManager": "npm@12.0.1"
36
37
  }
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vite-plus/test';
2
2
  import { navItems } from '../src/app';
3
3
 
4
4
  describe('App shell', () => {
5
- it('exposes the workflow-focused navigation order', () => {
5
+ it('should expose the workflow-focused navigation order', () => {
6
6
  expect(navItems.map((item) => item.label)).toEqual([
7
7
  'Home',
8
8
  'Workflow',
@@ -3,7 +3,7 @@ import { renderToString } from '@askrjs/askr/ssr';
3
3
  import Counter from '../../src/components/counter';
4
4
 
5
5
  describe('Counter', () => {
6
- it('renders the initial hydration check view', () => {
6
+ it('should render the initial hydration check view', () => {
7
7
  const html = renderToString(() => <Counter />);
8
8
 
9
9
  expect(html).toContain('Hydration check');
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vite-plus/test';
2
2
  import { fetchUser } from '../src/resources/user';
3
3
 
4
4
  describe('Resources', () => {
5
- it('creates a resource for fetching user data', () => {
5
+ it('should create a resource for fetching user data', () => {
6
6
  // Resources are called during component render
7
7
  // Here we just verify the function is defined
8
8
  expect(fetchUser).toBeDefined();
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vite-plus/test';
2
2
  import { staticConfig } from '../ssg.config';
3
3
 
4
4
  describe('SSG config', () => {
5
- it('keeps the sample route tree explicit', () => {
5
+ it('should keep the sample route tree explicit', () => {
6
6
  expect(
7
7
  staticConfig.registry.manifest.records.map((route) => route.path).sort()
8
8
  ).toEqual(['/', '/content', '/preview', '/workflow'].sort());
@@ -26,10 +26,11 @@
26
26
  "@types/node": "^20.19.0",
27
27
  "jsdom": "^29.1.1",
28
28
  "tsx": "^4.23.1",
29
- "typescript": "^6.0.3",
29
+ "typescript": "^7.0.2",
30
30
  "vite-plus": "^0.2.4"
31
31
  },
32
32
  "engines": {
33
- "node": "^20.19.0 || >=22.12.0"
34
- }
33
+ "node": ">=24.0.0"
34
+ },
35
+ "packageManager": "npm@12.0.1"
35
36
  }
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect } from 'vite-plus/test';
2
2
 
3
3
  describe('App Component', () => {
4
- it('renders layout with navigation', () => {
4
+ it('should render layout with navigation', () => {
5
5
  const app = (
6
6
  <div>
7
7
  <header>
@@ -3,7 +3,7 @@ import { renderToString } from '@askrjs/askr/ssr';
3
3
  import Counter from '../../src/components/counter';
4
4
 
5
5
  describe('Counter', () => {
6
- it('renders its initial state during SSR', () => {
6
+ it('should render its initial state during SSR', () => {
7
7
  const html = renderToString(() => <Counter />);
8
8
 
9
9
  expect(html).toContain('counter-value');
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vite-plus/test';
2
2
  import { fetchUser } from '../src/resources/user';
3
3
 
4
4
  describe('SSR Resources', () => {
5
- it('creates a resource for fetching user data', () => {
5
+ it('should create a resource for fetching user data', () => {
6
6
  // Resources are called during component render
7
7
  // Here we just verify the function is defined
8
8
  expect(fetchUser).toBeDefined();
@@ -27,10 +27,11 @@
27
27
  "@askrjs/vite": ">=0.0.6 <0.1.0",
28
28
  "@types/node": "^20.19.0",
29
29
  "jsdom": "^29.1.1",
30
- "typescript": "^6.0.3",
30
+ "typescript": "^7.0.2",
31
31
  "vite-plus": "^0.2.4"
32
32
  },
33
33
  "engines": {
34
- "node": "^20.19.0 || >=22.12.0"
35
- }
34
+ "node": ">=24.0.0"
35
+ },
36
+ "packageManager": "npm@12.0.1"
36
37
  }
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect } from 'vite-plus/test';
2
2
 
3
3
  describe('App Component', () => {
4
- it('exposes the current starter route set', () => {
4
+ it('should expose the current starter route set', () => {
5
5
  const routes = [
6
6
  '/',
7
7
  '/login',
@@ -16,14 +16,14 @@ describe('App Component', () => {
16
16
  expect(routes).toContain('/login');
17
17
  });
18
18
 
19
- it('uses the updated primary nav labels', () => {
19
+ it('should use the updated primary nav labels', () => {
20
20
  const navLabels = ['Dashboard', 'Accounts', 'Settings'];
21
21
 
22
22
  expect(navLabels).toContain('Accounts');
23
23
  expect(navLabels).toContain('Settings');
24
24
  });
25
25
 
26
- it('documents the starter appearance presets', () => {
26
+ it('should document the starter appearance presets', () => {
27
27
  const appearanceModes = ['Default', 'Harbor', 'Ink'];
28
28
 
29
29
  expect(appearanceModes).toContain('Harbor');
package/dist/update.js CHANGED
@@ -193,7 +193,7 @@ function collectEdits(decisions) {
193
193
  }] : []));
194
194
  }
195
195
  async function defaultRegistry(root, packageNames, requirements) {
196
- const { fetchPackuments, loadNpmConfiguration } = await import("./registry-BVliEbUv.js");
196
+ const { fetchPackuments, loadNpmConfiguration } = await import("./registry-BmGIkoO0.js");
197
197
  return fetchPackuments(packageNames, await loadNpmConfiguration(root), { requirements });
198
198
  }
199
199
  async function runDependencyCli(command, args, io = console, runtime = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askrjs/cli",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "description": "Unified CLI for the Askr platform",
5
5
  "homepage": "https://github.com/askrjs/askr-cli#readme",
6
6
  "bugs": {
@@ -41,11 +41,11 @@
41
41
  "fmt": "vp fmt .",
42
42
  "lint": "vp lint src tests benchmarks vite.config.ts vitest.config.ts vitest.bench.config.ts",
43
43
  "typecheck": "tsc -p tsconfig.json --noEmit",
44
- "test:changelog": "node scripts/verify-changelog.mjs",
45
- "test:peer-floor": "node scripts/verify-peer-floor.mjs",
44
+ "test:changelog": "vp test run -c vitest.config.ts tests/changelog.test.ts",
45
+ "test:peer-floor": "vp test run -c vitest.integration.config.ts tests/integration/peer-floor.test.ts",
46
46
  "test:publint": "publint",
47
47
  "pack:check": "npm pack --ignore-scripts --dry-run --json",
48
- "test:templates": "node scripts/verify-packed-templates.mjs",
48
+ "test:templates": "vp test run -c vitest.integration.config.ts tests/integration/packed-templates.test.ts",
49
49
  "bench": "npm run build --silent && npm run bench:analyze && node --import tsx benchmarks/cli.mjs --gate",
50
50
  "bench:analyze": "vp test bench --run -c vitest.bench.config.ts",
51
51
  "bench:json": "npm run build --silent && node --import tsx benchmarks/cli.mjs --gate --json",
@@ -55,32 +55,33 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "@npmcli/config": "^11.0.1",
58
- "js-yaml": "^5.2.2",
58
+ "js-yaml": "^5.2.3",
59
59
  "minimatch": "^10.2.6",
60
60
  "npm-registry-fetch": "^20.0.1",
61
61
  "parse5": "^8.0.1",
62
62
  "semver": "^7.8.5",
63
- "tsx": "^4.23.1",
64
- "typescript": "^6.0.3"
63
+ "tsx": "^4.23.11",
64
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
65
65
  },
66
66
  "devDependencies": {
67
- "@askrjs/askr": ">=0.0.53 <0.1.0",
68
- "@askrjs/charts": ">=0.1.0 <0.2.0",
69
- "@askrjs/logos": ">=0.0.3 <0.1.0",
70
- "@askrjs/lucide": ">=0.0.3 <0.1.0",
71
- "@askrjs/themes": ">=0.0.12 <0.1.0",
72
- "@askrjs/ui": ">=0.0.13 <0.1.0",
73
- "@askrjs/vite": ">=0.0.6 <0.1.0",
67
+ "@askrjs/askr": ">=0.0.89 <0.1.0",
68
+ "@askrjs/charts": ">=0.1.6 <0.2.0",
69
+ "@askrjs/logos": ">=0.0.7 <0.1.0",
70
+ "@askrjs/lucide": ">=0.0.9 <0.1.0",
71
+ "@askrjs/themes": ">=0.0.24 <0.1.0",
72
+ "@askrjs/ui": ">=0.0.27 <0.1.0",
73
+ "@askrjs/vite": ">=0.0.13 <0.1.0",
74
74
  "@types/js-yaml": "^4.0.9",
75
- "@types/node": "^26.1.1",
76
- "@types/semver": "^7.7.1",
75
+ "@types/node": "^26.2.0",
76
+ "@types/semver": "^7.8.0",
77
+ "@typescript/native": "npm:typescript@^7.0.2",
77
78
  "@vitest/coverage-v8": "^4.1.10",
78
- "publint": "^0.3.21",
79
- "vite-plus": "0.2.6",
79
+ "publint": "^0.3.23",
80
+ "vite-plus": "0.2.8",
80
81
  "vitest": "^4.1.10"
81
82
  },
82
83
  "peerDependencies": {
83
- "@askrjs/askr": ">=0.0.53 <0.1.0"
84
+ "@askrjs/askr": ">=0.0.89 <0.1.0"
84
85
  },
85
86
  "peerDependenciesMeta": {
86
87
  "@askrjs/askr": {
@@ -88,6 +89,7 @@
88
89
  }
89
90
  },
90
91
  "engines": {
91
- "node": "^20.19.0 || >=22.12.0"
92
- }
92
+ "node": ">=24.0.0"
93
+ },
94
+ "packageManager": "npm@12.0.1"
93
95
  }