@intentius/chant 0.1.4 → 0.1.6

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 (131) hide show
  1. package/bin/chant +1 -10
  2. package/package.json +4 -5
  3. package/src/attrref.test.ts +1 -1
  4. package/src/bench.test.ts +1 -1
  5. package/src/build.test.ts +3 -5
  6. package/src/builder.test.ts +1 -1
  7. package/src/cli/commands/__fixtures__/init-lexicon-output/justfile +8 -8
  8. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +4 -4
  9. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate-cli.ts +1 -1
  10. package/src/cli/commands/__fixtures__/init-lexicon-output/src/plugin.ts +3 -3
  11. package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate-cli.ts +1 -1
  12. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +7 -7
  13. package/src/cli/commands/build.test.ts +1 -1
  14. package/src/cli/commands/diff.test.ts +1 -1
  15. package/src/cli/commands/doctor.test.ts +1 -1
  16. package/src/cli/commands/doctor.ts +7 -7
  17. package/src/cli/commands/import.test.ts +1 -1
  18. package/src/cli/commands/init-lexicon/templates/codegen.ts +1 -1
  19. package/src/cli/commands/init-lexicon/templates/plugin.ts +3 -3
  20. package/src/cli/commands/init-lexicon/templates/project.ts +13 -13
  21. package/src/cli/commands/init-lexicon/templates/tests.ts +4 -4
  22. package/src/cli/commands/init-lexicon.test.ts +2 -2
  23. package/src/cli/commands/init-lexicon.ts +1 -1
  24. package/src/cli/commands/init.test.ts +1 -1
  25. package/src/cli/commands/init.ts +1 -2
  26. package/src/cli/commands/lint.test.ts +3 -3
  27. package/src/cli/commands/list.test.ts +2 -2
  28. package/src/cli/commands/onboard.test.ts +33 -33
  29. package/src/cli/commands/onboard.ts +13 -13
  30. package/src/cli/commands/update.test.ts +1 -1
  31. package/src/cli/conflict-check.test.ts +7 -2
  32. package/src/cli/format.test.ts +1 -1
  33. package/src/cli/lsp/server.test.ts +8 -4
  34. package/src/cli/main.test.ts +1 -1
  35. package/src/cli/main.ts +6 -5
  36. package/src/cli/mcp/server.test.ts +1 -1
  37. package/src/cli/plugins.test.ts +1 -1
  38. package/src/cli/reporters/stylish.test.ts +1 -1
  39. package/src/cli/watch.test.ts +1 -1
  40. package/src/codegen/docs-interpolation.test.ts +3 -3
  41. package/src/codegen/docs-rules.test.ts +1 -1
  42. package/src/codegen/docs.ts +1 -1
  43. package/src/codegen/fetch.test.ts +1 -1
  44. package/src/codegen/generate-registry.test.ts +1 -1
  45. package/src/codegen/generate-runtime-index.test.ts +1 -1
  46. package/src/codegen/generate-typescript.test.ts +1 -1
  47. package/src/codegen/generate.test.ts +1 -1
  48. package/src/codegen/json-patch.test.ts +1 -1
  49. package/src/codegen/json-schema.test.ts +1 -1
  50. package/src/codegen/topo-sort.test.ts +1 -1
  51. package/src/codegen/typecheck.test.ts +1 -1
  52. package/src/codegen/typecheck.ts +18 -5
  53. package/src/codegen/validate.test.ts +1 -1
  54. package/src/composite.test.ts +17 -16
  55. package/src/composite.ts +5 -4
  56. package/src/config.test.ts +3 -3
  57. package/src/config.ts +0 -4
  58. package/src/declarable.test.ts +1 -1
  59. package/src/detectLexicon.test.ts +1 -1
  60. package/src/discovery/cache.test.ts +1 -1
  61. package/src/discovery/collect.test.ts +1 -1
  62. package/src/discovery/cycles.test.ts +1 -1
  63. package/src/discovery/files.test.ts +1 -1
  64. package/src/discovery/graph.test.ts +1 -1
  65. package/src/discovery/import.test.ts +4 -3
  66. package/src/discovery/index.test.ts +1 -1
  67. package/src/discovery/resolve.test.ts +1 -1
  68. package/src/errors.test.ts +1 -1
  69. package/src/import/base-parser.test.ts +1 -1
  70. package/src/import/ir-utils.test.ts +1 -1
  71. package/src/index.ts +4 -0
  72. package/src/intrinsic-interpolation.test.ts +1 -1
  73. package/src/intrinsic.test.ts +1 -1
  74. package/src/lexicon-integrity.test.ts +2 -2
  75. package/src/lexicon-manifest.test.ts +1 -1
  76. package/src/lexicon-output.test.ts +1 -1
  77. package/src/lexicon-schema.test.ts +1 -1
  78. package/src/lint/config-overrides.test.ts +2 -2
  79. package/src/lint/config.test.ts +2 -2
  80. package/src/lint/config.ts +1 -1
  81. package/src/lint/declarative.test.ts +1 -1
  82. package/src/lint/discover.test.ts +1 -1
  83. package/src/lint/discover.ts +10 -0
  84. package/src/lint/engine.test.ts +1 -1
  85. package/src/lint/named-checks.test.ts +1 -1
  86. package/src/lint/parser.test.ts +2 -2
  87. package/src/lint/post-synth.test.ts +1 -1
  88. package/src/lint/rule-loader.test.ts +2 -2
  89. package/src/lint/rule-options.test.ts +2 -2
  90. package/src/lint/rule-registry.test.ts +1 -1
  91. package/src/lint/rule.test.ts +1 -1
  92. package/src/lint/rules/cor017-composite-name-match.test.ts +1 -1
  93. package/src/lint/rules/cor018-composite-prefer-lexicon-type.test.ts +1 -1
  94. package/src/lint/rules/declarable-naming-convention.test.ts +1 -1
  95. package/src/lint/rules/evl001-non-literal-expression.test.ts +1 -1
  96. package/src/lint/rules/evl002-control-flow-resource.test.ts +1 -1
  97. package/src/lint/rules/evl003-dynamic-property-access.test.ts +1 -1
  98. package/src/lint/rules/evl004-spread-non-const.test.ts +1 -1
  99. package/src/lint/rules/evl005-resource-block-body.test.ts +1 -1
  100. package/src/lint/rules/evl007-invalid-siblings.test.ts +1 -1
  101. package/src/lint/rules/evl009-composite-no-constant.test.ts +1 -1
  102. package/src/lint/rules/evl010-composite-no-transform.test.ts +1 -1
  103. package/src/lint/rules/export-required.test.ts +1 -1
  104. package/src/lint/rules/file-declarable-limit.test.ts +1 -1
  105. package/src/lint/rules/flat-declarations.test.ts +1 -1
  106. package/src/lint/rules/no-cyclic-declarable-ref.test.ts +1 -1
  107. package/src/lint/rules/no-redundant-type-import.test.ts +1 -1
  108. package/src/lint/rules/no-redundant-value-cast.test.ts +1 -1
  109. package/src/lint/rules/no-string-ref.test.ts +1 -1
  110. package/src/lint/rules/no-unused-declarable-import.test.ts +1 -1
  111. package/src/lint/rules/no-unused-declarable.test.ts +1 -1
  112. package/src/lint/rules/single-concern-file.test.ts +1 -1
  113. package/src/lint/selectors.test.ts +1 -1
  114. package/src/op/builders.ts +96 -0
  115. package/src/op/index.ts +4 -0
  116. package/src/op/op.test.ts +199 -0
  117. package/src/op/resource.ts +8 -0
  118. package/src/op/types.ts +66 -0
  119. package/src/project-validation.test.ts +2 -2
  120. package/src/pseudo-parameter.test.ts +1 -1
  121. package/src/resource-attributes.test.ts +2 -2
  122. package/src/runtime-adapter.ts +13 -68
  123. package/src/serializer-walker.test.ts +2 -1
  124. package/src/sort.test.ts +1 -1
  125. package/src/stack-output.ts +2 -2
  126. package/src/toml.test.ts +2 -2
  127. package/src/types.test.ts +1 -1
  128. package/src/utils.test.ts +1 -1
  129. package/src/utils.ts +2 -2
  130. package/src/validation.test.ts +1 -1
  131. package/src/yaml.test.ts +1 -1
@@ -1,4 +1,4 @@
1
- import { describe, test, expect, beforeEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach } from "vitest";
2
2
  import {
3
3
  Composite,
4
4
  isCompositeInstance,
@@ -13,6 +13,7 @@ import {
13
13
  } from "./composite";
14
14
  import { DECLARABLE_MARKER, type Declarable } from "./declarable";
15
15
  import { AttrRef } from "./attrref";
16
+ import { createResource } from "./runtime";
16
17
 
17
18
  function mockDeclarable(type = "TestEntity", lexicon = "test"): Declarable {
18
19
  return {
@@ -234,18 +235,18 @@ describe("resource() helper", () => {
234
235
 
235
236
  test("forwards attributes as second constructor argument", () => {
236
237
  // MockResource doesn't store attributes, so use createResource which does
237
- const { createResource } = require("./runtime");
238
238
  const TestRes = createResource("Test::Resource", "test", { arn: "Arn" });
239
239
  const attrs = { DependsOn: ["Other"], Condition: "IsProd" };
240
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
240
241
  const instance = resource(TestRes as any, { name: "test" }, attrs);
241
- expect((instance as any).attributes).toEqual(attrs);
242
+ expect((instance as unknown as Record<string, unknown>).attributes).toEqual(attrs);
242
243
  });
243
244
 
244
245
  test("without attributes, resource() creates instance with empty attributes", () => {
245
- const { createResource } = require("./runtime");
246
246
  const TestRes = createResource("Test::Resource", "test", { arn: "Arn" });
247
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
247
248
  const instance = resource(TestRes as any, { name: "test" });
248
- expect((instance as any).attributes).toEqual({});
249
+ expect((instance as unknown as Record<string, unknown>).attributes).toEqual({});
249
250
  });
250
251
  });
251
252
 
@@ -410,8 +411,8 @@ describe("propagate", () => {
410
411
  const instance = propagate(MyComp({}), { env: "prod" });
411
412
  const expanded = expandComposite("s", instance);
412
413
 
413
- const bucketProps = (expanded.get("sBucket") as any).props;
414
- const roleProps = (expanded.get("sRole") as any).props;
414
+ const bucketProps = (expanded.get("sBucket") as unknown as Record<string, unknown>).props as Record<string, unknown>;
415
+ const roleProps = (expanded.get("sRole") as unknown as Record<string, unknown>).props as Record<string, unknown>;
415
416
  expect(bucketProps.env).toBe("prod");
416
417
  expect(roleProps.env).toBe("prod");
417
418
  });
@@ -427,7 +428,7 @@ describe("propagate", () => {
427
428
  tags: [{ key: "env", value: "prod" }],
428
429
  });
429
430
  const expanded = expandComposite("s", instance);
430
- const tags = (expanded.get("sBucket") as any).props.tags;
431
+ const tags = ((expanded.get("sBucket") as unknown as Record<string, unknown>).props as Record<string, unknown>).tags;
431
432
 
432
433
  expect(tags).toEqual([
433
434
  { key: "env", value: "prod" },
@@ -442,7 +443,7 @@ describe("propagate", () => {
442
443
 
443
444
  const instance = propagate(MyComp({}), { region: "eu-west-1" });
444
445
  const expanded = expandComposite("s", instance);
445
- expect((expanded.get("sBucket") as any).props.region).toBe("us-west-2");
446
+ expect(((expanded.get("sBucket") as unknown as Record<string, unknown>).props as Record<string, unknown>).region).toBe("us-west-2");
446
447
  });
447
448
 
448
449
  test("undefined values in shared props are stripped", () => {
@@ -452,7 +453,7 @@ describe("propagate", () => {
452
453
 
453
454
  const instance = propagate(MyComp({}), { name: undefined, extra: "yes" });
454
455
  const expanded = expandComposite("s", instance);
455
- const props = (expanded.get("sBucket") as any).props;
456
+ const props = (expanded.get("sBucket") as unknown as Record<string, unknown>).props as Record<string, unknown>;
456
457
  expect(props.name).toBe("data");
457
458
  expect(props.extra).toBe("yes");
458
459
  });
@@ -470,8 +471,8 @@ describe("propagate", () => {
470
471
  const instance = propagate(Outer({}), { env: "prod" });
471
472
  const expanded = expandComposite("app", instance);
472
473
 
473
- expect((expanded.get("appBucket") as any).props.env).toBe("prod");
474
- expect((expanded.get("appNestedTable") as any).props.env).toBe("prod");
474
+ expect(((expanded.get("appBucket") as unknown as Record<string, unknown>).props as Record<string, unknown>).env).toBe("prod");
475
+ expect(((expanded.get("appNestedTable") as unknown as Record<string, unknown>).props as Record<string, unknown>).env).toBe("prod");
475
476
  });
476
477
 
477
478
  test("expanded declarables are same object references", () => {
@@ -489,7 +490,7 @@ describe("propagate", () => {
489
490
  }));
490
491
 
491
492
  const expanded = expandComposite("s", MyComp({}));
492
- expect((expanded.get("sBucket") as any).props.name).toBe("data");
493
+ expect(((expanded.get("sBucket") as unknown as Record<string, unknown>).props as Record<string, unknown>).name).toBe("data");
493
494
  });
494
495
  });
495
496
 
@@ -523,10 +524,10 @@ describe("mergeDefaults", () => {
523
524
 
524
525
  test("object override deep merges nested objects", () => {
525
526
  const result = mergeDefaults(
526
- { config: { a: 1, b: 2 } },
527
- { config: { a: 10 } as any },
527
+ { config: { a: 1, b: 2 } } as Record<string, unknown>,
528
+ { config: { a: 10 } },
528
529
  );
529
- expect(result.config).toEqual({ a: 10, b: 2 } as any);
530
+ expect(result["config"]).toEqual({ a: 10, b: 2 });
530
531
  });
531
532
 
532
533
  test("new keys from overrides are added", () => {
package/src/composite.ts CHANGED
@@ -16,6 +16,7 @@ export type CompositeMembers = Record<string, Declarable>;
16
16
  export interface CompositeInstance<M extends CompositeMembers = CompositeMembers> {
17
17
  readonly [COMPOSITE_MARKER]: true;
18
18
  readonly members: M;
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
20
  readonly _definition: CompositeDefinition<any, M>;
20
21
  }
21
22
 
@@ -120,7 +121,7 @@ export function expandComposite(
120
121
  instance: CompositeInstance,
121
122
  ): Map<string, Declarable> {
122
123
  const result = new Map<string, Declarable>();
123
- const shared = (instance as any)[SHARED_PROPS] as Record<string, unknown> | undefined;
124
+ const shared = (instance as unknown as Record<symbol, unknown>)[SHARED_PROPS] as Record<string, unknown> | undefined;
124
125
 
125
126
  for (const [memberName, member] of Object.entries(instance.members)) {
126
127
  const fullName = `${prefix}${memberName[0].toUpperCase()}${memberName.slice(1)}`;
@@ -265,17 +266,17 @@ export function mergeDefaults<T extends Record<string, unknown>>(
265
266
  if (value === undefined) continue;
266
267
  const existing = result[key as keyof T];
267
268
  if (Array.isArray(existing) && Array.isArray(value)) {
268
- (result as any)[key] = [...existing, ...value];
269
+ (result as Record<string, unknown>)[key] =[...existing, ...value];
269
270
  } else if (
270
271
  existing != null && typeof existing === "object" && !Array.isArray(existing) &&
271
272
  value != null && typeof value === "object" && !Array.isArray(value)
272
273
  ) {
273
- (result as any)[key] = mergeDefaults(
274
+ (result as Record<string, unknown>)[key] =mergeDefaults(
274
275
  existing as Record<string, unknown>,
275
276
  value as Record<string, unknown>,
276
277
  );
277
278
  } else {
278
- (result as any)[key] = value;
279
+ (result as Record<string, unknown>)[key] =value;
279
280
  }
280
281
  }
281
282
  return result;
@@ -1,9 +1,9 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
2
  import { loadChantConfig, DEFAULT_CHANT_CONFIG } from "./config";
3
3
  import { writeFileSync, mkdirSync, rmSync } from "fs";
4
4
  import { join } from "path";
5
5
 
6
- const TEST_DIR = join(import.meta.dir, "__test_chant_config__");
6
+ const TEST_DIR = join(import.meta.dirname, "__test_chant_config__");
7
7
 
8
8
  beforeEach(() => {
9
9
  mkdirSync(TEST_DIR, { recursive: true });
@@ -68,7 +68,7 @@ describe("loadChantConfig", () => {
68
68
  );
69
69
 
70
70
  const result = await loadChantConfig(TEST_DIR);
71
- expect(result.configPath).toEndWith("chant.config.ts");
71
+ expect(result.configPath?.endsWith("chant.config.ts")).toBe(true);
72
72
  });
73
73
 
74
74
  test("handles empty config", async () => {
package/src/config.ts CHANGED
@@ -7,7 +7,6 @@ import type { LintConfig } from "./lint/config";
7
7
  * Zod schema for ChantConfig validation.
8
8
  */
9
9
  export const ChantConfigSchema = z.object({
10
- runtime: z.enum(["bun", "node"]).optional(),
11
10
  lexicons: z.array(z.string().min(1)).optional(),
12
11
  environments: z.array(z.string().min(1)).optional(),
13
12
  lint: z.record(z.string(), z.unknown()).optional(),
@@ -19,9 +18,6 @@ export const ChantConfigSchema = z.object({
19
18
  * Loaded from `chant.config.ts` (preferred) or `chant.config.json`.
20
19
  */
21
20
  export interface ChantConfig {
22
- /** JS runtime to use for spawned commands: "bun" (default) or "node" */
23
- runtime?: "bun" | "node";
24
-
25
21
  /** Lexicon package names to load (e.g. ["aws"]) */
26
22
  lexicons?: string[];
27
23
 
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import {
3
3
  DECLARABLE_MARKER,
4
4
  type Declarable,
@@ -1,4 +1,4 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
2
  import { detectLexicons } from "./detectLexicon";
3
3
  import { mkdir, writeFile, rm } from "node:fs/promises";
4
4
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { DiscoveryCache } from "./cache";
3
3
  import { writeFileSync, mkdirSync, rmSync } from "fs";
4
4
  import { join } from "path";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect, beforeEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach } from "vitest";
2
2
  import { collectEntities } from "./collect";
3
3
  import { DECLARABLE_MARKER } from "../declarable";
4
4
  import { DiscoveryError } from "../errors";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { detectCycles, normalizeCycleKey } from "./cycles";
3
3
 
4
4
  describe("detectCycles", () => {
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { findInfraFiles } from "./files";
3
3
  import { withTestDir } from "@intentius/chant-test-utils";
4
4
  import { mkdir, writeFile } from "node:fs/promises";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { buildDependencyGraph } from "./graph";
3
3
  import { DECLARABLE_MARKER, type Declarable } from "../declarable";
4
4
  import { AttrRef } from "../attrref";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { importModule } from "./import";
3
3
  import { DiscoveryError } from "../errors";
4
4
  import { withTestDir, expectToThrow } from "@intentius/chant-test-utils";
@@ -28,8 +28,8 @@ describe("importModule", () => {
28
28
 
29
29
  const module = await importModule(filePath);
30
30
  expect(module.default).toBeDefined();
31
- expect((module.default as any).name).toBe("test");
32
- expect((module.default as any).value).toBe(123);
31
+ expect((module.default as Record<string, unknown>).name).toBe("test");
32
+ expect((module.default as Record<string, unknown>).value).toBe(123);
33
33
  });
34
34
  });
35
35
 
@@ -125,6 +125,7 @@ describe("importModule", () => {
125
125
 
126
126
  const module = await importModule(filePath);
127
127
  expect(module.MyClass).toBeDefined();
128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
129
  const instance = new (module.MyClass as any)(100);
129
130
  expect(instance.getValue()).toBe(100);
130
131
  });
@@ -1,4 +1,4 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
2
  import { discover } from "./index";
3
3
  import { mkdir, writeFile, rm } from "node:fs/promises";
4
4
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { resolveAttrRefs } from "./resolve";
3
3
  import { AttrRef } from "../attrref";
4
4
  import type { Declarable } from "../declarable";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { DiscoveryError, BuildError, LintError } from "./errors";
3
3
 
4
4
  describe("DiscoveryError", () => {
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, test } from "vitest";
2
2
  import { BaseValueParser } from "./base-parser";
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, test } from "vitest";
2
2
  import { hasIntrinsicInValue, irUsesIntrinsic, collectDependencies } from "./ir-utils";
3
3
  import type { TemplateIR } from "./parser";
4
4
 
package/src/index.ts CHANGED
@@ -61,3 +61,7 @@ export * from "./lsp/lexicon-providers";
61
61
  export * from "./mcp/types";
62
62
  export * from "./state/index";
63
63
  export * from "./spell/index";
64
+ // Op builders — use explicit exports to avoid collision with the core `build` function
65
+ export { Op, phase, activity, gate, kubectlApply, helmInstall, waitForStack,
66
+ gitlabPipeline, stateSnapshot, shell, teardown, OpResource } from "./op/index";
67
+ export type { OpConfig, PhaseDefinition, StepDefinition, ActivityStep, GateStep, RetryPolicy } from "./op/index";
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, test } from "vitest";
2
2
  import { buildInterpolatedString, defaultInterpolationSerializer } from "./intrinsic-interpolation";
3
3
  import { AttrRef } from "./attrref";
4
4
  import { INTRINSIC_MARKER } from "./intrinsic";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { INTRINSIC_MARKER, resolveIntrinsicValue, isIntrinsic } from "./intrinsic";
3
3
 
4
4
  describe("resolveIntrinsicValue", () => {
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { hashArtifact, computeIntegrity, verifyIntegrity, type ArtifactIntegrity } from "./lexicon-integrity";
3
3
  import type { BundleSpec } from "./lexicon";
4
4
 
@@ -35,7 +35,7 @@ function makeSpec(overrides?: Partial<BundleSpec>): BundleSpec {
35
35
  describe("computeIntegrity", () => {
36
36
  test("returns xxhash64 algorithm", () => {
37
37
  const integrity = computeIntegrity(makeSpec());
38
- expect(integrity.algorithm).toBe("xxhash64");
38
+ expect(integrity.algorithm).toBe("sha256");
39
39
  });
40
40
 
41
41
  test("hashes all artifacts", () => {
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { validateManifest } from "./lexicon-schema";
3
3
  import { checkVersionCompatibility } from "./lexicon-manifest";
4
4
 
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { LexiconOutput, output, isLexiconOutput } from "./lexicon-output";
3
3
  import { AttrRef } from "./attrref";
4
4
  import { INTRINSIC_MARKER } from "./intrinsic";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import {
3
3
  validateManifest,
4
4
  validateRegistry,
@@ -1,9 +1,9 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
2
  import { loadConfig, resolveRulesForFile, type LintConfig } from "./config";
3
3
  import { writeFileSync, mkdirSync, rmSync } from "fs";
4
4
  import { join } from "path";
5
5
 
6
- const TEST_DIR = join(import.meta.dir, "__test_config_overrides__");
6
+ const TEST_DIR = join(import.meta.dirname, "__test_config_overrides__");
7
7
 
8
8
  beforeEach(() => {
9
9
  mkdirSync(TEST_DIR, { recursive: true });
@@ -1,9 +1,9 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
2
  import { loadConfig, DEFAULT_CONFIG } from "./config";
3
3
  import { writeFileSync, mkdirSync, rmSync } from "fs";
4
4
  import { join } from "path";
5
5
 
6
- const TEST_DIR = join(import.meta.dir, "__test_config__");
6
+ const TEST_DIR = join(import.meta.dirname, "__test_config__");
7
7
 
8
8
  beforeEach(() => {
9
9
  // Create test directory
@@ -42,7 +42,7 @@ function isBadSeverityError(issue: z.ZodIssue, config: unknown, path: readonly (
42
42
  let value: unknown = config;
43
43
  for (const key of path) {
44
44
  if (value == null || typeof value !== "object") return null;
45
- value = (value as any)[key];
45
+ value = (value as Record<string, unknown>)[key];
46
46
  }
47
47
 
48
48
  // If the value is a string, the user meant it as a severity — show the specific severity error
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { rule } from "./declarative";
4
4
  import type { RuleSpec } from "./declarative";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { join, dirname } from "path";
3
3
  import { fileURLToPath } from "url";
4
4
  import { discoverLintRules, discoverPostSynthChecks } from "./discover";
@@ -11,6 +11,16 @@ import { createRequire } from "module";
11
11
  import type { LintRule } from "./rule";
12
12
  import type { PostSynthCheck } from "./post-synth";
13
13
 
14
+ // Register tsx so createRequire can load TypeScript files in Node.js ESM context.
15
+ // This is a no-op if tsx is not available or already registered.
16
+ try {
17
+ const _req = createRequire(import.meta.url);
18
+ const { register } = _req("tsx/cjs/api") as { register: () => void };
19
+ register();
20
+ } catch {
21
+ // tsx not available; only pre-compiled .js files can be require()'d
22
+ }
23
+
14
24
  /**
15
25
  * Discover lint rules from a directory.
16
26
  *
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { runLint } from "./engine";
3
3
  import type { LintRule, LintContext, LintDiagnostic } from "./rule";
4
4
  import { withTestDir } from "@intentius/chant-test-utils";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { registerCheck, getNamedCheck, listChecks } from "./named-checks";
4
4
  import type { LintContext } from "./rule";
@@ -1,10 +1,10 @@
1
- import { describe, test, expect, beforeAll, afterAll } from "bun:test";
1
+ import { describe, test, expect, beforeAll, afterAll } from "vitest";
2
2
  import { parseFile } from "./parser";
3
3
  import { writeFileSync, unlinkSync, mkdirSync } from "fs";
4
4
  import { join } from "path";
5
5
  import * as ts from "typescript";
6
6
 
7
- const TEST_DIR = join(import.meta.dir, "__test_parser__");
7
+ const TEST_DIR = join(import.meta.dirname, "__test_parser__");
8
8
  const VALID_FILE = join(TEST_DIR, "valid.ts");
9
9
  const INVALID_FILE = join(TEST_DIR, "invalid.ts");
10
10
  const NONEXISTENT_FILE = join(TEST_DIR, "nonexistent.ts");
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { runPostSynthChecks } from "./post-synth";
3
3
  import type { PostSynthCheck, PostSynthContext } from "./post-synth";
4
4
 
@@ -1,9 +1,9 @@
1
- import { describe, test, expect, beforeAll, afterAll } from "bun:test";
1
+ import { describe, test, expect, beforeAll, afterAll } from "vitest";
2
2
  import { mkdirSync, writeFileSync, rmSync, existsSync } from "fs";
3
3
  import { join } from "path";
4
4
  import { loadLocalRules } from "./rule-loader";
5
5
 
6
- const TEST_DIR = join(import.meta.dir, "__test_rules_fixture__");
6
+ const TEST_DIR = join(import.meta.dirname, "__test_rules_fixture__");
7
7
  const RULES_DIR = join(TEST_DIR, ".chant", "rules");
8
8
 
9
9
  beforeAll(() => {
@@ -1,4 +1,4 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
2
  import { parseRuleConfig, loadConfig } from "./config";
3
3
  import { fileDeclarableLimitRule } from "./rules/file-declarable-limit";
4
4
  import * as ts from "typescript";
@@ -15,7 +15,7 @@ function makeNewExprs(names: string[]): string {
15
15
  return names.map((n) => `const x = new ${n}({ name: "a" });`).join("\n");
16
16
  }
17
17
 
18
- const TEST_DIR = join(import.meta.dir, "__test_rule_options__");
18
+ const TEST_DIR = join(import.meta.dirname, "__test_rule_options__");
19
19
 
20
20
  beforeEach(() => {
21
21
  mkdirSync(TEST_DIR, { recursive: true });
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import { buildRuleRegistry } from "./rule-registry";
3
3
  import type { LintRule, LintContext, LintDiagnostic } from "./rule";
4
4
  import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "./post-synth";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import type {
3
3
  LintRule,
4
4
  LintContext,
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { cor017CompositeNameMatchRule } from "./cor017-composite-name-match";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { cor018CompositePreferLexiconTypeRule } from "./cor018-composite-prefer-lexicon-type";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { declarableNamingConventionRule } from "./declarable-naming-convention";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl001NonLiteralExpressionRule } from "./evl001-non-literal-expression";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl002ControlFlowResourceRule } from "./evl002-control-flow-resource";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl003DynamicPropertyAccessRule } from "./evl003-dynamic-property-access";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl004SpreadNonConstRule } from "./evl004-spread-non-const";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl005ResourceBlockBodyRule } from "./evl005-resource-block-body";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl007InvalidSiblingsRule } from "./evl007-invalid-siblings";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl009CompositeNoConstantRule } from "./evl009-composite-no-constant";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { evl010CompositeNoTransformRule } from "./evl010-composite-no-transform";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { exportRequiredRule } from "./export-required";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { fileDeclarableLimitRule } from "./file-declarable-limit";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { flatDeclarationsRule } from "./flat-declarations";
4
4
  import type { LintContext } from "../rule";
@@ -1,4 +1,4 @@
1
- import { describe, test, expect } from "bun:test";
1
+ import { describe, test, expect } from "vitest";
2
2
  import * as ts from "typescript";
3
3
  import { noCyclicDeclarableRefRule } from "./no-cyclic-declarable-ref";
4
4
  import type { LintContext } from "../rule";