@codefast/cli 0.3.13-canary.0 → 0.3.13-canary.1

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 (112) hide show
  1. package/dist/bin.mjs +1 -1
  2. package/dist/commands/arrange.mjs +106 -1
  3. package/dist/commands/mirror.mjs +65 -1
  4. package/dist/commands/tag.mjs +57 -1
  5. package/dist/lib/arrange/application/analyze.mjs +91 -1
  6. package/dist/lib/arrange/application/group-file.mjs +112 -1
  7. package/dist/lib/arrange/application/run-target.mjs +64 -1
  8. package/dist/lib/arrange/domain/ast/ast-helpers.mjs +114 -1
  9. package/dist/lib/arrange/domain/ast/collectors-cn.mjs +60 -1
  10. package/dist/lib/arrange/domain/ast/collectors-jsx.mjs +19 -1
  11. package/dist/lib/arrange/domain/ast/collectors-tv.mjs +169 -1
  12. package/dist/lib/arrange/domain/ast/targets.mjs +105 -1
  13. package/dist/lib/arrange/domain/constants.mjs +168 -1
  14. package/dist/lib/arrange/domain/errors.mjs +18 -1
  15. package/dist/lib/arrange/domain/grouping.mjs +234 -1
  16. package/dist/lib/arrange/domain/imports.mjs +53 -1
  17. package/dist/lib/arrange/domain/tokenizer.mjs +215 -1
  18. package/dist/lib/arrange/index.mjs +14 -15
  19. package/dist/lib/arrange/infra/walk.mjs +32 -1
  20. package/dist/lib/arrange/presentation/formatters.mjs +51 -1
  21. package/dist/lib/arrange/presentation/report.mjs +23 -1
  22. package/dist/lib/config/domain/schema.mjs +24 -1
  23. package/dist/lib/config/index.mjs +2 -3
  24. package/dist/lib/config/infra/loader.mjs +77 -1
  25. package/dist/lib/infra/caught-unknown-message.mjs +19 -1
  26. package/dist/lib/infra/config-reporter.mjs +9 -1
  27. package/dist/lib/infra/node-io.mjs +29 -1
  28. package/dist/lib/infra/workspace/repo-root.mjs +21 -1
  29. package/dist/lib/mirror/application/engine.mjs +247 -1
  30. package/dist/lib/mirror/application/sync.mjs +161 -1
  31. package/dist/lib/mirror/domain/constants.mjs +11 -1
  32. package/dist/lib/mirror/domain/errors.mjs +14 -1
  33. package/dist/lib/mirror/index.mjs +1 -2
  34. package/dist/lib/mirror/infra/dirent-list.mjs +13 -1
  35. package/dist/lib/mirror/infra/package-filter.mjs +25 -1
  36. package/dist/lib/mirror/infra/path-normalizer.mjs +6 -1
  37. package/dist/lib/mirror/infra/update-pkg.mjs +104 -1
  38. package/dist/lib/mirror/infra/workspace-packages.mjs +158 -1
  39. package/dist/lib/mirror/presentation/reporter.mjs +111 -2
  40. package/dist/lib/tag/application/engine.mjs +286 -1
  41. package/dist/lib/tag/index.mjs +3 -4
  42. package/dist/lib/tag/infra/target-resolver.mjs +169 -1
  43. package/dist/lib/tag/presentation/colors.mjs +11 -1
  44. package/dist/lib/tag/presentation/tag-presenter.mjs +62 -1
  45. package/dist/program.mjs +33 -1
  46. package/package.json +2 -2
  47. package/dist/analyze-DvtJ3j9m.mjs +0 -92
  48. package/dist/arrange-Bbh62DrU.mjs +0 -107
  49. package/dist/arrange-BqP2DI3w.mjs +0 -8
  50. package/dist/ast-helpers-MDRYuIAk.mjs +0 -115
  51. package/dist/caught-unknown-message-CRhkDWO7.mjs +0 -20
  52. package/dist/collectors-cn-BS8TTQ8O.mjs +0 -61
  53. package/dist/collectors-jsx-D9tL2ZPM.mjs +0 -20
  54. package/dist/collectors-tv-D2PXZaRt.mjs +0 -170
  55. package/dist/colors-BjdkCfGK.mjs +0 -12
  56. package/dist/commands/mirror.test.mjs +0 -48
  57. package/dist/config-DVia_f9a.mjs +0 -3
  58. package/dist/config-reporter-SCcWDZc1.mjs +0 -10
  59. package/dist/constants-AtPhF-Ct.mjs +0 -169
  60. package/dist/constants-Bq5wdyLC.mjs +0 -8
  61. package/dist/dirent-list-BSDeRG5i.mjs +0 -14
  62. package/dist/engine-CcWEHSCq.mjs +0 -287
  63. package/dist/engine-DRTdkc5u.mjs +0 -236
  64. package/dist/errors-CFH4w6ic.mjs +0 -15
  65. package/dist/errors-CpU1ogfA.mjs +0 -19
  66. package/dist/formatters-DGE8jJ53.mjs +0 -52
  67. package/dist/group-file-ClW7XdD6.mjs +0 -113
  68. package/dist/grouping-c1grpCQT.mjs +0 -235
  69. package/dist/imports-DSVq1xhB.mjs +0 -54
  70. package/dist/lib/arrange/application/analyze.test.mjs +0 -171
  71. package/dist/lib/arrange/application/group-file.test.mjs +0 -273
  72. package/dist/lib/arrange/application/run-target.test.mjs +0 -97
  73. package/dist/lib/arrange/domain/ast/ast-helpers.test.mjs +0 -148
  74. package/dist/lib/arrange/domain/ast/collectors-cn.test.mjs +0 -58
  75. package/dist/lib/arrange/domain/ast/collectors-jsx.test.mjs +0 -20
  76. package/dist/lib/arrange/domain/ast/collectors-tv.test.mjs +0 -145
  77. package/dist/lib/arrange/domain/ast/targets.test.mjs +0 -50
  78. package/dist/lib/arrange/domain/grouping.test.mjs +0 -186
  79. package/dist/lib/arrange/domain/imports.test.mjs +0 -48
  80. package/dist/lib/arrange/domain/tokenizer.test.mjs +0 -165
  81. package/dist/lib/arrange/infra/walk.test.mjs +0 -50
  82. package/dist/lib/arrange/presentation/formatters.test.mjs +0 -73
  83. package/dist/lib/config/infra/loader.test.mjs +0 -116
  84. package/dist/lib/infra/workspace/repo-root.test.mjs +0 -45
  85. package/dist/lib/mirror/application/sync.test.mjs +0 -482
  86. package/dist/lib/mirror/infra/dirent-list.test.mjs +0 -18
  87. package/dist/lib/mirror/infra/package-filter.test.mjs +0 -32
  88. package/dist/lib/mirror/infra/workspace-packages.test.mjs +0 -167
  89. package/dist/lib/tag/application/engine.test.mjs +0 -159
  90. package/dist/lib/tag/presentation/tag-presenter.test.mjs +0 -29
  91. package/dist/loader-DpN-zl5g.mjs +0 -78
  92. package/dist/mirror-CbGiLXKT.mjs +0 -2
  93. package/dist/mirror-DqJE3ejL.mjs +0 -66
  94. package/dist/node-io-DFRbHO6m.mjs +0 -30
  95. package/dist/package-filter-C_8ryqvz.mjs +0 -26
  96. package/dist/path-normalizer-D4ceBO3l.mjs +0 -7
  97. package/dist/program-DR-H4tH3.mjs +0 -34
  98. package/dist/repo-root-HmtIEm6J.mjs +0 -22
  99. package/dist/report-DYxvw34T.mjs +0 -24
  100. package/dist/reporter-CwIe_tAM.mjs +0 -108
  101. package/dist/run-target-CJWrqNT4.mjs +0 -65
  102. package/dist/schema-Or8RAARd.mjs +0 -25
  103. package/dist/sync-e1Sp-shi.mjs +0 -157
  104. package/dist/tag-Cd9JujU5.mjs +0 -2
  105. package/dist/tag-hEKVZ_-7.mjs +0 -58
  106. package/dist/tag-presenter-Cs66UBsH.mjs +0 -63
  107. package/dist/target-resolver-CR3FXMTy.mjs +0 -170
  108. package/dist/targets-pCTslnFh.mjs +0 -106
  109. package/dist/tokenizer-CeZx73Zu.mjs +0 -216
  110. package/dist/update-pkg-CnGfjWBy.mjs +0 -37
  111. package/dist/walk-DjgQn66n.mjs +0 -33
  112. package/dist/workspace-packages-K2NYTHJq.mjs +0 -159
@@ -1,165 +0,0 @@
1
- import { c as selectorKey, d as tokenizeClassString, i as classifyToken, l as stateKey, n as bucketsMergeCompatible, o as indexOfFirstVariantColon, t as bucketsCompatible, u as stripVariants } from "../../../tokenizer-CeZx73Zu.mjs";
2
- import "../../../arrange-BqP2DI3w.mjs";
3
- //#region src/lib/arrange/domain/tokenizer.test.ts
4
- describe("tokenizeClassString", () => {
5
- it("trims and splits on whitespace runs", () => {
6
- expect(tokenizeClassString(" flex gap-2 ")).toEqual(["flex", "gap-2"]);
7
- });
8
- it("returns empty for whitespace-only input", () => {
9
- expect(tokenizeClassString(" \n ")).toEqual([]);
10
- });
11
- });
12
- describe("bucketsMergeCompatible", () => {
13
- it.each([
14
- [
15
- "state",
16
- "state",
17
- false
18
- ],
19
- [
20
- "starting",
21
- "starting",
22
- false
23
- ],
24
- [
25
- "layout",
26
- "sizing",
27
- true
28
- ],
29
- [
30
- "shape",
31
- "shadow",
32
- true
33
- ],
34
- [
35
- "layout",
36
- "state",
37
- false
38
- ],
39
- [
40
- "arbitrary",
41
- "arbitrary",
42
- false
43
- ],
44
- [
45
- "arbitrary",
46
- "state",
47
- false
48
- ],
49
- [
50
- "selector",
51
- "selector",
52
- false
53
- ],
54
- [
55
- "layout",
56
- "selector",
57
- false
58
- ],
59
- [
60
- "selector",
61
- "state",
62
- false
63
- ]
64
- ])("merge compatibility %s + %s -> %s", (a, b, expected) => {
65
- expect(bucketsMergeCompatible(a, b)).toBe(expected);
66
- expect(bucketsMergeCompatible(b, a)).toBe(expected);
67
- });
68
- });
69
- describe("bucketsCompatible", () => {
70
- it.each([
71
- [
72
- "layout",
73
- "layout",
74
- true
75
- ],
76
- [
77
- "layout",
78
- "sizing",
79
- true
80
- ],
81
- [
82
- "shape",
83
- "shadow",
84
- true
85
- ],
86
- [
87
- "layout",
88
- "state",
89
- false
90
- ],
91
- [
92
- "arbitrary",
93
- "state",
94
- false
95
- ],
96
- [
97
- "layout",
98
- "selector",
99
- false
100
- ]
101
- ])("compatibility %s + %s -> %s", (a, b, expected) => {
102
- expect(bucketsCompatible(a, b)).toBe(expected);
103
- expect(bucketsCompatible(b, a)).toBe(expected);
104
- });
105
- });
106
- describe("stateKey", () => {
107
- it("uses the full variant stack for unique keys", () => {
108
- expect(stateKey("@md/field-group:[&>*]:w-auto")).not.toBe(stateKey("@md/field-group:[&>[data-slot=field-label]]:flex-auto"));
109
- });
110
- it("normalizes bracketed data variant stems", () => {
111
- expect(stateKey("data-[state=open]:opacity-100")).toBe("data-[state=open]");
112
- expect(stateKey("in-data-[slot=tooltip-content]:bg-background/20")).toBe("in-data-[slot=tooltip-content]");
113
- });
114
- it("keeps distinct keys for in-data-side-* stems", () => {
115
- expect(stateKey("in-data-side-right:cursor-e-resize")).toBe("in-data-side-right");
116
- expect(stateKey("in-data-side-left:cursor-w-resize")).not.toBe(stateKey("in-data-side-right:cursor-e-resize"));
117
- });
118
- });
119
- describe("indexOfFirstVariantColon + stripVariants", () => {
120
- it("ignores colons inside square brackets", () => {
121
- const tok = "[&_a:hover]:text-red-500";
122
- expect(indexOfFirstVariantColon(tok)).toBe(11);
123
- expect(stripVariants(tok)).toBe("text-red-500");
124
- });
125
- it("strips stacked variant prefixes", () => {
126
- expect(stripVariants("@min-[600px]:@max-[900px]:hidden")).toBe("hidden");
127
- });
128
- });
129
- describe("classifyToken", () => {
130
- it.each([
131
- ["flex", "layout"],
132
- ["w-4", "sizing"],
133
- ["px-3", "spacing"],
134
- ["rounded-md", "shape"],
135
- ["text-sm", "typography"],
136
- ["transition", "motion"],
137
- ["outline-hidden", "shadow"],
138
- ["focus-visible:outline-hidden", "state"],
139
- ["hover:opacity-80", "state"],
140
- ["[&_svg]:size-4", "selector"],
141
- ["*:rounded", "selector"],
142
- ["**:text-sm", "selector"],
143
- ["has-[img]:bg-muted", "selector"],
144
- ["in-[.popover]:opacity-100", "selector"],
145
- ["group-[.is-published]:block", "selector"],
146
- ["peer-[.is-dirty]:peer-required:block", "selector"],
147
- ["not-[.prose]:mt-4", "selector"],
148
- ["starting:opacity-0", "starting"],
149
- ["cursor-default", "behavior"],
150
- ["@container/sidebar", "existence"],
151
- ["@md/sidebar:w-full", "state"]
152
- ])("classifies %s -> %s", (token, bucket) => {
153
- expect(classifyToken(token)).toBe(bucket);
154
- });
155
- });
156
- describe("selectorKey", () => {
157
- it("merges shadcn svg size guard with plain [&_svg] utilities", () => {
158
- expect(selectorKey("[&_svg]:pointer-events-none")).toBe(selectorKey("[&_svg:not([class*='size-'])]:size-6"));
159
- });
160
- it("still splits unrelated arbitrary parent selectors", () => {
161
- expect(selectorKey("[&_svg]:size-4")).not.toBe(selectorKey("[&>*]:block"));
162
- });
163
- });
164
- //#endregion
165
- export {};
@@ -1,50 +0,0 @@
1
- import { n as walkTsxFiles, t as DEFAULT_SKIP_DIRS } from "../../../walk-DjgQn66n.mjs";
2
- import { t as createNodeCliFs } from "../../../node-io-DFRbHO6m.mjs";
3
- import "../../../arrange-BqP2DI3w.mjs";
4
- import fs from "node:fs";
5
- import path from "node:path";
6
- import os from "node:os";
7
- //#region src/lib/arrange/infra/walk.test.ts
8
- const arrangeFs = createNodeCliFs();
9
- describe("DEFAULT_SKIP_DIRS", () => {
10
- it("contains common generated directories", () => {
11
- expect(DEFAULT_SKIP_DIRS.has("node_modules")).toBe(true);
12
- expect(DEFAULT_SKIP_DIRS.has(".git")).toBe(true);
13
- expect(DEFAULT_SKIP_DIRS.has("dist")).toBe(true);
14
- expect(DEFAULT_SKIP_DIRS.has(".turbo")).toBe(true);
15
- });
16
- });
17
- describe("walkTsxFiles", () => {
18
- it("collects .ts/.tsx, skips .d.ts and nested skipped directories", () => {
19
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "arr-walk-"));
20
- try {
21
- fs.mkdirSync(path.join(dir, "a", "node_modules", "x"), { recursive: true });
22
- fs.mkdirSync(path.join(dir, ".git", "hooks"), { recursive: true });
23
- fs.writeFileSync(path.join(dir, "root.ts"), "", "utf8");
24
- fs.writeFileSync(path.join(dir, "root.tsx"), "", "utf8");
25
- fs.writeFileSync(path.join(dir, "types.d.ts"), "", "utf8");
26
- fs.writeFileSync(path.join(dir, "a", "node_modules", "x", "ignored.tsx"), "", "utf8");
27
- fs.writeFileSync(path.join(dir, ".git", "hooks", "ignored.ts"), "", "utf8");
28
- const rel = walkTsxFiles(dir, arrangeFs).map((p) => path.relative(dir, p).split(path.sep).join("/")).sort();
29
- expect(rel).toEqual(["root.ts", "root.tsx"]);
30
- } finally {
31
- fs.rmSync(dir, {
32
- recursive: true,
33
- force: true
34
- });
35
- }
36
- });
37
- it("returns empty array for empty directory", () => {
38
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "arr-walk-empty-"));
39
- try {
40
- expect(walkTsxFiles(dir, arrangeFs)).toEqual([]);
41
- } finally {
42
- fs.rmSync(dir, {
43
- recursive: true,
44
- force: true
45
- });
46
- }
47
- });
48
- });
49
- //#endregion
50
- export {};
@@ -1,73 +0,0 @@
1
- import { a as formatJsxCnAttributeValue, i as formatCnCall, n as formatArray, r as formatCnArguments, t as escapeTsStringLiteralContent } from "../../../formatters-DGE8jJ53.mjs";
2
- import "../../../arrange-BqP2DI3w.mjs";
3
- //#region src/lib/arrange/presentation/formatters.test.ts
4
- describe("escapeTsStringLiteralContent", () => {
5
- it("escapes backslashes and quotes", () => {
6
- expect(escapeTsStringLiteralContent(String.raw`x\"y`)).toBe(String.raw`x\\\"y`);
7
- });
8
- it("keeps plain strings unchanged", () => {
9
- expect(escapeTsStringLiteralContent("plain")).toBe("plain");
10
- });
11
- it("handles empty strings", () => {
12
- expect(escapeTsStringLiteralContent("")).toBe("");
13
- });
14
- });
15
- describe("formatCnArguments", () => {
16
- it("renders indented args without wrapping cn()", () => {
17
- expect(formatCnArguments(["flex gap-2", "text-sm"], { indent: " " })).toBe([" \"flex gap-2\",", " \"text-sm\""].join("\n"));
18
- });
19
- it("adds comma on last group when commaAfterLastGroup=true", () => {
20
- expect(formatCnArguments(["a", "b"], { commaAfterLastGroup: true })).toBe([" \"a\",", " \"b\","].join("\n"));
21
- });
22
- it("appends trailing className line when requested", () => {
23
- expect(formatCnArguments(["a", "b"], { trailingClassName: true })).toBe([
24
- " \"a\",",
25
- " \"b\",",
26
- " className,"
27
- ].join("\n"));
28
- });
29
- it("escapes literals", () => {
30
- expect(formatCnArguments(["x\"y"])).toBe(" \"x\\\"y\"");
31
- });
32
- });
33
- describe("formatCnCall", () => {
34
- it("omits trailing comma for single group", () => {
35
- expect(formatCnCall(["only"])).toBe([
36
- "cn(",
37
- " \"only\"",
38
- ")"
39
- ].join("\n"));
40
- });
41
- it("renders multiline cn() with trailing commas for multi-arg", () => {
42
- expect(formatCnCall(["a", "b"])).toBe([
43
- "cn(",
44
- " \"a\",",
45
- " \"b\",",
46
- ")"
47
- ].join("\n"));
48
- });
49
- it("supports trailing className", () => {
50
- expect(formatCnCall(["a", "b"], { trailingClassName: true })).toContain("className,");
51
- });
52
- });
53
- describe("formatArray", () => {
54
- it("renders multiline string array", () => {
55
- expect(formatArray(["a", "b"])).toBe([
56
- "[",
57
- " \"a\",",
58
- " \"b\",",
59
- "]"
60
- ].join("\n"));
61
- });
62
- });
63
- describe("formatJsxCnAttributeValue", () => {
64
- it("formats className={cn(...)} with source-derived indentation", () => {
65
- const source = `export function F() {\n return <div className="x" />;\n}`;
66
- const out = formatJsxCnAttributeValue(["flex gap-2", "text-sm"], source, source.indexOf("\""));
67
- expect(out.startsWith("{cn(")).toBe(true);
68
- expect(out.endsWith(")}")).toBe(true);
69
- expect(out).toContain("\"flex gap-2\",");
70
- });
71
- });
72
- //#endregion
73
- export {};
@@ -1,116 +0,0 @@
1
- import { n as resetConfigLoaderCacheForTests, t as loadConfig } from "../../../loader-DpN-zl5g.mjs";
2
- import { t as createNodeCliFs } from "../../../node-io-DFRbHO6m.mjs";
3
- import fs from "node:fs";
4
- import path from "node:path";
5
- import os from "node:os";
6
- //#region src/lib/config/infra/loader.test.ts
7
- describe("loadConfig", () => {
8
- const cliFs = createNodeCliFs();
9
- async function withCwd(cwd, fn) {
10
- const prev = process.cwd();
11
- process.chdir(cwd);
12
- resetConfigLoaderCacheForTests();
13
- try {
14
- return await fn();
15
- } finally {
16
- process.chdir(prev);
17
- resetConfigLoaderCacheForTests();
18
- }
19
- }
20
- it("loads mirror + lifecycle hooks from codefast.config.cjs", async () => {
21
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "codefast-config-hooks-"));
22
- try {
23
- fs.writeFileSync(path.join(root, "codefast.config.cjs"), [
24
- "module.exports = {",
25
- " mirror: { skipPackages: [\"@acme/private\"] },",
26
- " tag: { onAfterWrite: async ({ files }) => {",
27
- " if (files.length === 0) return;",
28
- " } },",
29
- " arrange: { onAfterWrite: ({ files }) => files.length },",
30
- "};",
31
- ""
32
- ].join("\n"), "utf8");
33
- await withCwd(root, async () => {
34
- const { config, warnings } = await loadConfig(cliFs);
35
- expect(warnings).toEqual([]);
36
- expect(config.mirror).toEqual({ skipPackages: ["@acme/private"] });
37
- expect(typeof config.tag?.onAfterWrite).toBe("function");
38
- expect(typeof config.arrange?.onAfterWrite).toBe("function");
39
- });
40
- } finally {
41
- fs.rmSync(root, {
42
- recursive: true,
43
- force: true
44
- });
45
- }
46
- });
47
- it("requires mirror config to be nested under the mirror key", async () => {
48
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "codefast-config-mirror-top-"));
49
- try {
50
- fs.writeFileSync(path.join(root, "codefast.config.json"), JSON.stringify({ skipPackages: ["@acme/legacy"] }), "utf8");
51
- await withCwd(root, async () => {
52
- await expect(loadConfig(cliFs)).rejects.toThrow("Invalid config schema");
53
- await expect(loadConfig(cliFs)).rejects.toThrow("Unrecognized key: \"skipPackages\"");
54
- });
55
- } finally {
56
- fs.rmSync(root, {
57
- recursive: true,
58
- force: true
59
- });
60
- }
61
- });
62
- it("throws schema validation errors for invalid hook values", async () => {
63
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "codefast-config-invalid-hook-"));
64
- try {
65
- fs.writeFileSync(path.join(root, "codefast.config.json"), JSON.stringify({
66
- tag: { onAfterWrite: "not-a-function" },
67
- arrange: { onAfterWrite: 123 }
68
- }), "utf8");
69
- await withCwd(root, async () => {
70
- await expect(loadConfig(cliFs)).rejects.toThrow("Invalid config schema");
71
- await expect(loadConfig(cliFs)).rejects.toThrow("tag.onAfterWrite");
72
- });
73
- } finally {
74
- fs.rmSync(root, {
75
- recursive: true,
76
- force: true
77
- });
78
- }
79
- });
80
- it("resolves config with upward search from process.cwd()", async () => {
81
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "codefast-config-upward-"));
82
- const nested = path.join(root, "packages", "ui", "src");
83
- try {
84
- fs.mkdirSync(nested, { recursive: true });
85
- fs.writeFileSync(path.join(root, "codefast.config.json"), JSON.stringify({ mirror: { skipPackages: ["@acme/infra"] } }), "utf8");
86
- await withCwd(nested, async () => {
87
- const { config } = await loadConfig(cliFs);
88
- expect(config.mirror).toEqual({ skipPackages: ["@acme/infra"] });
89
- });
90
- } finally {
91
- fs.rmSync(root, {
92
- recursive: true,
93
- force: true
94
- });
95
- }
96
- });
97
- it("uses singleton cache within one process", async () => {
98
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "codefast-config-cache-"));
99
- try {
100
- fs.writeFileSync(path.join(root, "codefast.config.json"), JSON.stringify({ mirror: { skipPackages: ["@acme/one"] } }), "utf8");
101
- await withCwd(root, async () => {
102
- const first = await loadConfig(cliFs);
103
- fs.writeFileSync(path.join(root, "codefast.config.json"), JSON.stringify({ mirror: { skipPackages: ["@acme/two"] } }), "utf8");
104
- const second = await loadConfig(cliFs);
105
- expect(second.config.mirror).toEqual(first.config.mirror);
106
- });
107
- } finally {
108
- fs.rmSync(root, {
109
- recursive: true,
110
- force: true
111
- });
112
- }
113
- });
114
- });
115
- //#endregion
116
- export {};
@@ -1,45 +0,0 @@
1
- import { t as findRepoRoot } from "../../../repo-root-HmtIEm6J.mjs";
2
- import path from "node:path";
3
- //#region src/lib/infra/workspace/repo-root.test.ts
4
- function makeFs(existsSync) {
5
- return {
6
- existsSync,
7
- statSync: () => ({
8
- isDirectory: () => true,
9
- isFile: () => false
10
- }),
11
- readFileSync: () => "",
12
- writeFileSync: () => void 0,
13
- readdirSync: () => [],
14
- readFile: async () => "",
15
- writeFile: async () => void 0,
16
- readdir: async () => [],
17
- rename: async () => void 0,
18
- unlink: async () => void 0
19
- };
20
- }
21
- describe("findRepoRoot", () => {
22
- it("returns the nearest ancestor containing pnpm-workspace.yaml", () => {
23
- const root = "/tmp/repo";
24
- const marker = path.join(root, "pnpm-workspace.yaml");
25
- const cwdSpy = jest.spyOn(process, "cwd").mockReturnValue("/tmp/repo/packages/cli");
26
- try {
27
- const fs = makeFs((targetPath) => targetPath === marker);
28
- expect(findRepoRoot(fs)).toBe(root);
29
- } finally {
30
- cwdSpy.mockRestore();
31
- }
32
- });
33
- it("includes searched candidate paths when root cannot be resolved", () => {
34
- const cwdSpy = jest.spyOn(process, "cwd").mockReturnValue("/tmp/no-repo");
35
- try {
36
- const fs = makeFs(() => false);
37
- expect(() => findRepoRoot(fs)).toThrow(/Searched from:/);
38
- expect(() => findRepoRoot(fs)).toThrow(/\/tmp\/no-repo/);
39
- } finally {
40
- cwdSpy.mockRestore();
41
- }
42
- });
43
- });
44
- //#endregion
45
- export {};