@simplysm/sd-cli 13.0.68 → 13.0.70
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 +10 -957
- package/dist/builders/BaseBuilder.d.ts +23 -23
- package/dist/builders/BaseBuilder.d.ts.map +1 -1
- package/dist/builders/BaseBuilder.js +15 -15
- package/dist/builders/DtsBuilder.d.ts +4 -4
- package/dist/builders/DtsBuilder.js +1 -1
- package/dist/builders/LibraryBuilder.d.ts +3 -3
- package/dist/builders/types.d.ts +10 -10
- package/dist/capacitor/capacitor.d.ts +36 -36
- package/dist/capacitor/capacitor.js +63 -63
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/add-client.d.ts +8 -8
- package/dist/commands/add-client.js +15 -15
- package/dist/commands/add-client.js.map +1 -1
- package/dist/commands/add-server.d.ts +9 -9
- package/dist/commands/add-server.js +13 -13
- package/dist/commands/add-server.js.map +1 -1
- package/dist/commands/build.d.ts +9 -9
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +9 -9
- package/dist/commands/device.d.ts +9 -9
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +17 -17
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/init.d.ts +6 -6
- package/dist/commands/init.js +12 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.d.ts +23 -23
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +25 -25
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/publish.d.ts +13 -13
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +61 -61
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/replace-deps.d.ts +3 -3
- package/dist/commands/replace-deps.d.ts.map +1 -1
- package/dist/commands/replace-deps.js +1 -1
- package/dist/commands/replace-deps.js.map +1 -1
- package/dist/commands/typecheck.d.ts +20 -20
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +20 -20
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/watch.d.ts +7 -7
- package/dist/electron/electron.d.ts +27 -27
- package/dist/electron/electron.js +32 -32
- package/dist/electron/electron.js.map +1 -1
- package/dist/infra/ResultCollector.d.ts +9 -9
- package/dist/infra/ResultCollector.js +5 -5
- package/dist/infra/SignalHandler.d.ts +7 -7
- package/dist/infra/SignalHandler.js +4 -4
- package/dist/infra/WorkerManager.d.ts +14 -14
- package/dist/infra/WorkerManager.js +11 -11
- package/dist/orchestrators/BuildOrchestrator.d.ts +19 -19
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +26 -26
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevOrchestrator.d.ts +25 -25
- package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevOrchestrator.js +30 -30
- package/dist/orchestrators/DevOrchestrator.js.map +1 -1
- package/dist/orchestrators/WatchOrchestrator.d.ts +13 -13
- package/dist/orchestrators/WatchOrchestrator.js +17 -17
- package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +2 -2
- package/dist/sd-cli-entry.js +38 -38
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.d.ts +2 -2
- package/dist/sd-cli.js +1 -1
- package/dist/sd-cli.js.map +1 -1
- package/dist/sd-config.types.d.ts +84 -84
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/build-env.d.ts +1 -1
- package/dist/utils/config-editor.d.ts +5 -5
- package/dist/utils/config-editor.js +2 -2
- package/dist/utils/config-editor.js.map +1 -1
- package/dist/utils/copy-public.d.ts +9 -9
- package/dist/utils/copy-src.d.ts +9 -9
- package/dist/utils/esbuild-config.d.ts +30 -30
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/output-utils.d.ts +6 -6
- package/dist/utils/package-utils.d.ts +6 -6
- package/dist/utils/package-utils.js +1 -1
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/rebuild-manager.js +3 -3
- package/dist/utils/rebuild-manager.js.map +1 -1
- package/dist/utils/replace-deps.d.ts +25 -25
- package/dist/utils/replace-deps.js +3 -3
- package/dist/utils/replace-deps.js.map +1 -1
- package/dist/utils/sd-config.d.ts +3 -3
- package/dist/utils/sd-config.js +3 -3
- package/dist/utils/sd-config.js.map +1 -1
- package/dist/utils/tailwind-config-deps.d.ts +3 -3
- package/dist/utils/template.d.ts +8 -8
- package/dist/utils/tsconfig.d.ts +16 -16
- package/dist/utils/tsconfig.js +2 -2
- package/dist/utils/tsconfig.js.map +1 -1
- package/dist/utils/typecheck-serialization.d.ts +8 -8
- package/dist/utils/vite-config.d.ts +8 -8
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +3 -3
- package/dist/utils/worker-events.d.ts +12 -12
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-utils.d.ts +3 -3
- package/dist/utils/worker-utils.js +2 -2
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/workers/client.worker.d.ts +14 -14
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +1 -1
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/dts.worker.d.ts +13 -13
- package/dist/workers/dts.worker.d.ts.map +1 -1
- package/dist/workers/dts.worker.js +3 -3
- package/dist/workers/dts.worker.js.map +1 -1
- package/dist/workers/library.worker.d.ts +12 -12
- package/dist/workers/library.worker.js +1 -1
- package/dist/workers/library.worker.js.map +1 -1
- package/dist/workers/lint.worker.d.ts +1 -1
- package/dist/workers/server-runtime.worker.d.ts +6 -6
- package/dist/workers/server-runtime.worker.js +6 -6
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/dist/workers/server.worker.d.ts +20 -20
- package/dist/workers/server.worker.d.ts.map +1 -1
- package/dist/workers/server.worker.js +6 -6
- package/dist/workers/server.worker.js.map +1 -1
- package/package.json +8 -7
- package/src/builders/BaseBuilder.ts +33 -33
- package/src/builders/DtsBuilder.ts +5 -5
- package/src/builders/LibraryBuilder.ts +9 -9
- package/src/builders/types.ts +10 -10
- package/src/capacitor/capacitor.ts +119 -119
- package/src/commands/add-client.ts +31 -31
- package/src/commands/add-server.ts +34 -34
- package/src/commands/build.ts +9 -9
- package/src/commands/check.ts +5 -5
- package/src/commands/dev.ts +9 -9
- package/src/commands/device.ts +30 -30
- package/src/commands/init.ts +25 -25
- package/src/commands/lint.ts +64 -64
- package/src/commands/publish.ts +139 -139
- package/src/commands/replace-deps.ts +4 -4
- package/src/commands/typecheck.ts +74 -74
- package/src/commands/watch.ts +7 -7
- package/src/electron/electron.ts +51 -51
- package/src/infra/ResultCollector.ts +9 -9
- package/src/infra/SignalHandler.ts +7 -7
- package/src/infra/WorkerManager.ts +14 -14
- package/src/orchestrators/BuildOrchestrator.ts +76 -76
- package/src/orchestrators/DevOrchestrator.ts +88 -88
- package/src/orchestrators/WatchOrchestrator.ts +39 -39
- package/src/sd-cli-entry.ts +43 -43
- package/src/sd-cli.ts +15 -15
- package/src/sd-config.types.ts +85 -85
- package/src/utils/build-env.ts +1 -1
- package/src/utils/config-editor.ts +19 -19
- package/src/utils/copy-public.ts +17 -17
- package/src/utils/copy-src.ts +11 -11
- package/src/utils/esbuild-config.ts +33 -33
- package/src/utils/output-utils.ts +11 -11
- package/src/utils/package-utils.ts +12 -12
- package/src/utils/rebuild-manager.ts +3 -3
- package/src/utils/replace-deps.ts +361 -361
- package/src/utils/sd-config.ts +44 -44
- package/src/utils/tailwind-config-deps.ts +98 -98
- package/src/utils/template.ts +56 -56
- package/src/utils/tsconfig.ts +127 -127
- package/src/utils/typecheck-serialization.ts +86 -86
- package/src/utils/vite-config.ts +341 -341
- package/src/utils/worker-events.ts +16 -16
- package/src/utils/worker-utils.ts +45 -45
- package/src/workers/client.worker.ts +34 -34
- package/src/workers/dts.worker.ts +467 -467
- package/src/workers/library.worker.ts +314 -314
- package/src/workers/lint.worker.ts +16 -16
- package/src/workers/server-runtime.worker.ts +157 -157
- package/src/workers/server.worker.ts +572 -572
- package/templates/add-client/__CLIENT__/package.json.hbs +1 -1
- package/templates/add-server/__SERVER__/package.json.hbs +2 -2
- package/templates/init/package.json.hbs +3 -3
- package/tests/config-editor.spec.ts +160 -0
- package/tests/copy-src.spec.ts +50 -0
- package/tests/get-compiler-options-for-package.spec.ts +139 -0
- package/tests/get-package-source-files.spec.ts +181 -0
- package/tests/get-types-from-package-json.spec.ts +107 -0
- package/tests/infra/ResultCollector.spec.ts +39 -0
- package/tests/infra/SignalHandler.spec.ts +38 -0
- package/tests/infra/WorkerManager.spec.ts +97 -0
- package/tests/load-ignore-patterns.spec.ts +188 -0
- package/tests/load-sd-config.spec.ts +137 -0
- package/tests/package-utils.spec.ts +188 -0
- package/tests/parse-root-tsconfig.spec.ts +89 -0
- package/tests/replace-deps.spec.ts +308 -0
- package/tests/run-lint.spec.ts +415 -0
- package/tests/run-typecheck.spec.ts +653 -0
- package/tests/run-watch.spec.ts +75 -0
- package/tests/sd-cli.spec.ts +330 -0
- package/tests/tailwind-config-deps.spec.ts +30 -0
- package/tests/template.spec.ts +70 -0
- package/tests/utils/rebuild-manager.spec.ts +43 -0
- package/tests/write-changed-output-files.spec.ts +97 -0
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"vitest": "vitest"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@simplysm/sd-cli": "~13.0.
|
|
19
|
-
"@simplysm/sd-claude": "~13.0.
|
|
20
|
-
"@simplysm/lint": "~13.0.
|
|
18
|
+
"@simplysm/sd-cli": "~13.0.70",
|
|
19
|
+
"@simplysm/sd-claude": "~13.0.70",
|
|
20
|
+
"@simplysm/lint": "~13.0.70",
|
|
21
21
|
"@types/node": "^20.19.33",
|
|
22
22
|
"eslint": "^9.39.2",
|
|
23
23
|
"prettier": "^3.8.1",
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import {
|
|
6
|
+
addPackageToSdConfig,
|
|
7
|
+
setClientServerInSdConfig,
|
|
8
|
+
addTailwindToEslintConfig,
|
|
9
|
+
} from "../src/utils/config-editor";
|
|
10
|
+
|
|
11
|
+
describe("config-editor", () => {
|
|
12
|
+
let tmpDir: string;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sd-cli-test-"));
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("addPackageToSdConfig", () => {
|
|
23
|
+
test("adds client package to empty packages object", () => {
|
|
24
|
+
const configPath = path.join(tmpDir, "sd.config.ts");
|
|
25
|
+
fs.writeFileSync(
|
|
26
|
+
configPath,
|
|
27
|
+
[
|
|
28
|
+
'import type { SdConfigFn } from "@simplysm/sd-cli";',
|
|
29
|
+
"",
|
|
30
|
+
"const config: SdConfigFn = () => ({",
|
|
31
|
+
" packages: {},",
|
|
32
|
+
"});",
|
|
33
|
+
"",
|
|
34
|
+
"export default config;",
|
|
35
|
+
].join("\n"),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
addPackageToSdConfig(configPath, "client-web", { target: "client" });
|
|
39
|
+
|
|
40
|
+
const result = fs.readFileSync(configPath, "utf-8");
|
|
41
|
+
expect(result).toContain('"client-web"');
|
|
42
|
+
expect(result).toContain('"client"');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("adds server package to existing packages", () => {
|
|
46
|
+
const configPath = path.join(tmpDir, "sd.config.ts");
|
|
47
|
+
fs.writeFileSync(
|
|
48
|
+
configPath,
|
|
49
|
+
[
|
|
50
|
+
'import type { SdConfigFn } from "@simplysm/sd-cli";',
|
|
51
|
+
"",
|
|
52
|
+
"const config: SdConfigFn = () => ({",
|
|
53
|
+
" packages: {",
|
|
54
|
+
' "client-web": { target: "client" },',
|
|
55
|
+
" },",
|
|
56
|
+
"});",
|
|
57
|
+
"",
|
|
58
|
+
"export default config;",
|
|
59
|
+
].join("\n"),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
addPackageToSdConfig(configPath, "server", { target: "server" });
|
|
63
|
+
|
|
64
|
+
const result = fs.readFileSync(configPath, "utf-8");
|
|
65
|
+
expect(result).toContain('"client-web"');
|
|
66
|
+
expect(result).toContain('"server"');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("returns false if package already exists", () => {
|
|
70
|
+
const configPath = path.join(tmpDir, "sd.config.ts");
|
|
71
|
+
fs.writeFileSync(
|
|
72
|
+
configPath,
|
|
73
|
+
[
|
|
74
|
+
'import type { SdConfigFn } from "@simplysm/sd-cli";',
|
|
75
|
+
"",
|
|
76
|
+
"const config: SdConfigFn = () => ({",
|
|
77
|
+
" packages: {",
|
|
78
|
+
' "client-web": { target: "client" },',
|
|
79
|
+
" },",
|
|
80
|
+
"});",
|
|
81
|
+
"",
|
|
82
|
+
"export default config;",
|
|
83
|
+
].join("\n"),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const result = addPackageToSdConfig(configPath, "client-web", { target: "client" });
|
|
87
|
+
expect(result).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("setClientServerInSdConfig", () => {
|
|
92
|
+
test("adds server field to client config", () => {
|
|
93
|
+
const configPath = path.join(tmpDir, "sd.config.ts");
|
|
94
|
+
fs.writeFileSync(
|
|
95
|
+
configPath,
|
|
96
|
+
[
|
|
97
|
+
'import type { SdConfigFn } from "@simplysm/sd-cli";',
|
|
98
|
+
"",
|
|
99
|
+
"const config: SdConfigFn = () => ({",
|
|
100
|
+
" packages: {",
|
|
101
|
+
' "client-web": { target: "client" },',
|
|
102
|
+
" },",
|
|
103
|
+
"});",
|
|
104
|
+
"",
|
|
105
|
+
"export default config;",
|
|
106
|
+
].join("\n"),
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
setClientServerInSdConfig(configPath, "client-web", "server");
|
|
110
|
+
|
|
111
|
+
const result = fs.readFileSync(configPath, "utf-8");
|
|
112
|
+
expect(result).toContain('server: "server"');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("addTailwindToEslintConfig", () => {
|
|
117
|
+
test("adds tailwind settings to eslint config without tailwind", () => {
|
|
118
|
+
const configPath = path.join(tmpDir, "eslint.config.ts");
|
|
119
|
+
fs.writeFileSync(
|
|
120
|
+
configPath,
|
|
121
|
+
[
|
|
122
|
+
'import simplysmEslintRecommended from "@simplysm/lint/eslint-recommended";',
|
|
123
|
+
"",
|
|
124
|
+
"export default [",
|
|
125
|
+
" ...simplysmEslintRecommended,",
|
|
126
|
+
"];",
|
|
127
|
+
].join("\n"),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
addTailwindToEslintConfig(configPath, "client-web");
|
|
131
|
+
|
|
132
|
+
const result = fs.readFileSync(configPath, "utf-8");
|
|
133
|
+
expect(result).toContain("tailwindcss");
|
|
134
|
+
expect(result).toContain("packages/client-web/tailwind.config.ts");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("does nothing if tailwind settings already exist", () => {
|
|
138
|
+
const configPath = path.join(tmpDir, "eslint.config.ts");
|
|
139
|
+
const original = [
|
|
140
|
+
'import simplysmEslintRecommended from "@simplysm/lint/eslint-recommended";',
|
|
141
|
+
"",
|
|
142
|
+
"export default [",
|
|
143
|
+
" ...simplysmEslintRecommended,",
|
|
144
|
+
" {",
|
|
145
|
+
' files: ["**/*.{ts,tsx}"],',
|
|
146
|
+
" settings: {",
|
|
147
|
+
" tailwindcss: {",
|
|
148
|
+
' config: "packages/client-old/tailwind.config.ts",',
|
|
149
|
+
" },",
|
|
150
|
+
" },",
|
|
151
|
+
" },",
|
|
152
|
+
"];",
|
|
153
|
+
].join("\n");
|
|
154
|
+
fs.writeFileSync(configPath, original);
|
|
155
|
+
|
|
156
|
+
const result = addTailwindToEslintConfig(configPath, "client-web");
|
|
157
|
+
expect(result).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import fs from "fs/promises";
|
|
5
|
+
import { copySrcFiles } from "../src/utils/copy-src";
|
|
6
|
+
|
|
7
|
+
describe("copySrcFiles", () => {
|
|
8
|
+
let tmpDir: string;
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "copysrc-"));
|
|
12
|
+
// Create src/ structure
|
|
13
|
+
await fs.mkdir(path.join(tmpDir, "src", "components"), { recursive: true });
|
|
14
|
+
await fs.mkdir(path.join(tmpDir, "dist"), { recursive: true });
|
|
15
|
+
await fs.writeFile(path.join(tmpDir, "src", "base.css"), "body {}");
|
|
16
|
+
await fs.writeFile(path.join(tmpDir, "src", "components", "Card.css"), ".card {}");
|
|
17
|
+
await fs.writeFile(path.join(tmpDir, "src", "index.ts"), "export {}");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(async () => {
|
|
21
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("copies files matching glob pattern from src/ to dist/", async () => {
|
|
25
|
+
await copySrcFiles(tmpDir, ["**/*.css"]);
|
|
26
|
+
|
|
27
|
+
const base = await fs.readFile(path.join(tmpDir, "dist", "base.css"), "utf-8");
|
|
28
|
+
expect(base).toBe("body {}");
|
|
29
|
+
|
|
30
|
+
const card = await fs.readFile(path.join(tmpDir, "dist", "components", "Card.css"), "utf-8");
|
|
31
|
+
expect(card).toBe(".card {}");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("does not copy files that don't match pattern", async () => {
|
|
35
|
+
await copySrcFiles(tmpDir, ["**/*.css"]);
|
|
36
|
+
|
|
37
|
+
const exists = await fs.access(path.join(tmpDir, "dist", "index.ts")).then(
|
|
38
|
+
() => true,
|
|
39
|
+
() => false,
|
|
40
|
+
);
|
|
41
|
+
expect(exists).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("copies nothing if pattern is empty array", async () => {
|
|
45
|
+
await copySrcFiles(tmpDir, []);
|
|
46
|
+
|
|
47
|
+
const files = await fs.readdir(path.join(tmpDir, "dist"));
|
|
48
|
+
expect(files).toHaveLength(0);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import type ts from "typescript";
|
|
3
|
+
|
|
4
|
+
// Mock core-node functions
|
|
5
|
+
vi.mock("@simplysm/core-node", () => ({
|
|
6
|
+
fsExists: vi.fn(),
|
|
7
|
+
fsReadJson: vi.fn(),
|
|
8
|
+
pathPosix: vi.fn((p: string) => p.replace(/\\/g, "/")),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
import { fsExists, fsReadJson } from "@simplysm/core-node";
|
|
12
|
+
import { getCompilerOptionsForPackage } from "../src/utils/tsconfig";
|
|
13
|
+
|
|
14
|
+
describe("getCompilerOptionsForPackage", () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
vi.restoreAllMocks();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const baseOptions: ts.CompilerOptions = {
|
|
24
|
+
lib: ["ES2024", "DOM", "DOM.Iterable", "WebWorker"],
|
|
25
|
+
types: [],
|
|
26
|
+
strict: true,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
it("node target: removes DOM lib, includes node in types", async () => {
|
|
30
|
+
const packageDir = "/project/packages/core-node";
|
|
31
|
+
vi.mocked(fsExists).mockResolvedValue(true);
|
|
32
|
+
vi.mocked(fsReadJson).mockResolvedValue({
|
|
33
|
+
devDependencies: {
|
|
34
|
+
"@types/express": "^4.17.0",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const result = await getCompilerOptionsForPackage(baseOptions, "node", packageDir);
|
|
39
|
+
|
|
40
|
+
// DOM, WebWorker lib removed
|
|
41
|
+
expect(result.lib).toEqual(["ES2024"]);
|
|
42
|
+
// types includes node and express
|
|
43
|
+
expect(result.types).toContain("node");
|
|
44
|
+
expect(result.types).toContain("express");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("browser target: keeps lib, removes node from types", async () => {
|
|
48
|
+
const packageDir = "/project/packages/core-browser";
|
|
49
|
+
vi.mocked(fsExists).mockResolvedValue(true);
|
|
50
|
+
vi.mocked(fsReadJson).mockResolvedValue({
|
|
51
|
+
devDependencies: {
|
|
52
|
+
"@types/node": "^20.0.0",
|
|
53
|
+
"@types/react": "^18.0.0",
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const result = await getCompilerOptionsForPackage(baseOptions, "browser", packageDir);
|
|
58
|
+
|
|
59
|
+
// lib is preserved
|
|
60
|
+
expect(result.lib).toEqual(["ES2024", "DOM", "DOM.Iterable", "WebWorker"]);
|
|
61
|
+
// types removes node, includes react only
|
|
62
|
+
expect(result.types).not.toContain("node");
|
|
63
|
+
expect(result.types).toContain("react");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("neutral target: keeps lib, includes node in types", async () => {
|
|
67
|
+
const packageDir = "/project/packages/core-common";
|
|
68
|
+
vi.mocked(fsExists).mockResolvedValue(true);
|
|
69
|
+
vi.mocked(fsReadJson).mockResolvedValue({
|
|
70
|
+
devDependencies: {
|
|
71
|
+
"@types/lodash": "^4.0.0",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const result = await getCompilerOptionsForPackage(baseOptions, "neutral", packageDir);
|
|
76
|
+
|
|
77
|
+
// lib is preserved (includes DOM)
|
|
78
|
+
expect(result.lib).toEqual(["ES2024", "DOM", "DOM.Iterable", "WebWorker"]);
|
|
79
|
+
// types includes node and lodash
|
|
80
|
+
expect(result.types).toContain("node");
|
|
81
|
+
expect(result.types).toContain("lodash");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("node target: removes duplicate node types", async () => {
|
|
85
|
+
const packageDir = "/project/packages/core-node";
|
|
86
|
+
vi.mocked(fsExists).mockResolvedValue(true);
|
|
87
|
+
vi.mocked(fsReadJson).mockResolvedValue({
|
|
88
|
+
devDependencies: {
|
|
89
|
+
"@types/node": "^20.0.0",
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const result = await getCompilerOptionsForPackage(baseOptions, "node", packageDir);
|
|
94
|
+
|
|
95
|
+
// node type is included only once without duplicates
|
|
96
|
+
expect(result.types?.filter((t) => t === "node")).toHaveLength(1);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("handles missing package.json with empty types", async () => {
|
|
100
|
+
const packageDir = "/project/packages/unknown";
|
|
101
|
+
vi.mocked(fsExists).mockResolvedValue(false);
|
|
102
|
+
|
|
103
|
+
const result = await getCompilerOptionsForPackage(baseOptions, "node", packageDir);
|
|
104
|
+
|
|
105
|
+
// includes only node (types from package are empty array)
|
|
106
|
+
expect(result.types).toEqual(["node"]);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("handles undefined lib correctly", async () => {
|
|
110
|
+
const optionsWithoutLib: ts.CompilerOptions = {
|
|
111
|
+
strict: true,
|
|
112
|
+
};
|
|
113
|
+
const packageDir = "/project/packages/core-node";
|
|
114
|
+
vi.mocked(fsExists).mockResolvedValue(false);
|
|
115
|
+
|
|
116
|
+
const result = await getCompilerOptionsForPackage(optionsWithoutLib, "node", packageDir);
|
|
117
|
+
|
|
118
|
+
// handles undefined lib without error
|
|
119
|
+
expect(result.lib).toBeUndefined();
|
|
120
|
+
expect(result.types).toEqual(["node"]);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("does not mutate original baseOptions (immutability)", async () => {
|
|
124
|
+
const originalOptions: ts.CompilerOptions = {
|
|
125
|
+
lib: ["ES2024", "DOM"],
|
|
126
|
+
types: ["original"],
|
|
127
|
+
strict: true,
|
|
128
|
+
};
|
|
129
|
+
const packageDir = "/project/packages/core-node";
|
|
130
|
+
vi.mocked(fsExists).mockResolvedValue(false);
|
|
131
|
+
|
|
132
|
+
await getCompilerOptionsForPackage(originalOptions, "node", packageDir);
|
|
133
|
+
|
|
134
|
+
// original options are not changed
|
|
135
|
+
expect(originalOptions.lib).toEqual(["ES2024", "DOM"]);
|
|
136
|
+
expect(originalOptions.types).toEqual(["original"]);
|
|
137
|
+
expect(originalOptions.noEmit).toBeUndefined();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import type ts from "typescript";
|
|
4
|
+
import { getPackageSourceFiles, getPackageFiles } from "../src/utils/tsconfig";
|
|
5
|
+
|
|
6
|
+
describe("getPackageSourceFiles", () => {
|
|
7
|
+
const sep = path.sep;
|
|
8
|
+
|
|
9
|
+
it("filters files within package src directory only", () => {
|
|
10
|
+
const pkgDir = `/project/packages/core-common`;
|
|
11
|
+
const parsedConfig = {
|
|
12
|
+
fileNames: [
|
|
13
|
+
`/project/packages/core-common/src/index.ts`,
|
|
14
|
+
`/project/packages/core-common/src/utils/string.ts`,
|
|
15
|
+
`/project/packages/core-common/tests/utils.spec.ts`,
|
|
16
|
+
`/project/packages/core-node/src/index.ts`,
|
|
17
|
+
],
|
|
18
|
+
} as ts.ParsedCommandLine;
|
|
19
|
+
|
|
20
|
+
const result = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
21
|
+
|
|
22
|
+
expect(result).toEqual([
|
|
23
|
+
`/project/packages/core-common/src/index.ts`,
|
|
24
|
+
`/project/packages/core-common/src/utils/string.ts`,
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("excludes files from similar package names (core vs core-common)", () => {
|
|
29
|
+
const pkgDir = `/project/packages/core`;
|
|
30
|
+
const parsedConfig = {
|
|
31
|
+
fileNames: [
|
|
32
|
+
`/project/packages/core/src/index.ts`,
|
|
33
|
+
`/project/packages/core-common/src/index.ts`,
|
|
34
|
+
`/project/packages/core-node/src/index.ts`,
|
|
35
|
+
],
|
|
36
|
+
} as ts.ParsedCommandLine;
|
|
37
|
+
|
|
38
|
+
const result = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
39
|
+
|
|
40
|
+
// core-common, core-node are excluded, only core is included
|
|
41
|
+
expect(result).toEqual([`/project/packages/core/src/index.ts`]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("excludes files outside src directory (tests, scripts, etc)", () => {
|
|
45
|
+
const pkgDir = `/project/packages/cli`;
|
|
46
|
+
const parsedConfig = {
|
|
47
|
+
fileNames: [
|
|
48
|
+
`/project/packages/cli/src/index.ts`,
|
|
49
|
+
`/project/packages/cli/src/commands/lint.ts`,
|
|
50
|
+
`/project/packages/cli/tests/lint.spec.ts`,
|
|
51
|
+
`/project/packages/cli/scripts/build.ts`,
|
|
52
|
+
],
|
|
53
|
+
} as ts.ParsedCommandLine;
|
|
54
|
+
|
|
55
|
+
const result = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
56
|
+
|
|
57
|
+
expect(result).toEqual([
|
|
58
|
+
`/project/packages/cli/src/index.ts`,
|
|
59
|
+
`/project/packages/cli/src/commands/lint.ts`,
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns empty array if no files", () => {
|
|
64
|
+
const pkgDir = `/project/packages/empty`;
|
|
65
|
+
const parsedConfig = {
|
|
66
|
+
fileNames: [
|
|
67
|
+
`/project/packages/core/src/index.ts`,
|
|
68
|
+
`/project/packages/core-common/src/index.ts`,
|
|
69
|
+
],
|
|
70
|
+
} as ts.ParsedCommandLine;
|
|
71
|
+
|
|
72
|
+
const result = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
73
|
+
|
|
74
|
+
expect(result).toEqual([]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("handles path separators correctly", () => {
|
|
78
|
+
// use path.sep for platform-independent test
|
|
79
|
+
const pkgDir = `${sep}project${sep}packages${sep}core`;
|
|
80
|
+
const parsedConfig = {
|
|
81
|
+
fileNames: [
|
|
82
|
+
`${sep}project${sep}packages${sep}core${sep}src${sep}index.ts`,
|
|
83
|
+
`${sep}project${sep}packages${sep}core-common${sep}src${sep}index.ts`,
|
|
84
|
+
],
|
|
85
|
+
} as ts.ParsedCommandLine;
|
|
86
|
+
|
|
87
|
+
const result = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
88
|
+
|
|
89
|
+
expect(result).toEqual([`${sep}project${sep}packages${sep}core${sep}src${sep}index.ts`]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("handles forward slash paths from TypeScript API correctly (Windows compatible)", () => {
|
|
93
|
+
// TypeScript API returns forward slash paths even on Windows
|
|
94
|
+
// pkgDir is created with path.join using OS-native separator
|
|
95
|
+
const pkgDir = path.resolve("/project/packages/core-common");
|
|
96
|
+
const parsedConfig = {
|
|
97
|
+
fileNames: [
|
|
98
|
+
"/project/packages/core-common/src/index.ts",
|
|
99
|
+
"/project/packages/core-common/src/utils/string.ts",
|
|
100
|
+
"/project/packages/core-common/tests/utils.spec.ts",
|
|
101
|
+
"/project/packages/core-node/src/index.ts",
|
|
102
|
+
],
|
|
103
|
+
} as ts.ParsedCommandLine;
|
|
104
|
+
|
|
105
|
+
const result = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
106
|
+
|
|
107
|
+
expect(result).toHaveLength(2);
|
|
108
|
+
expect(result.every((f) => f.includes("core-common") && f.includes("src"))).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("getPackageFiles", () => {
|
|
113
|
+
it("filters all files within package directory (src + tests)", () => {
|
|
114
|
+
const pkgDir = `/project/packages/core-common`;
|
|
115
|
+
const parsedConfig = {
|
|
116
|
+
fileNames: [
|
|
117
|
+
`/project/packages/core-common/src/index.ts`,
|
|
118
|
+
`/project/packages/core-common/src/utils/string.ts`,
|
|
119
|
+
`/project/packages/core-common/tests/utils.spec.ts`,
|
|
120
|
+
`/project/packages/core-common/tests/setup/helpers.ts`,
|
|
121
|
+
`/project/packages/core-node/src/index.ts`,
|
|
122
|
+
`/project/packages/core-node/tests/fs.spec.ts`,
|
|
123
|
+
],
|
|
124
|
+
} as ts.ParsedCommandLine;
|
|
125
|
+
|
|
126
|
+
const result = getPackageFiles(pkgDir, parsedConfig);
|
|
127
|
+
|
|
128
|
+
expect(result).toEqual([
|
|
129
|
+
`/project/packages/core-common/src/index.ts`,
|
|
130
|
+
`/project/packages/core-common/src/utils/string.ts`,
|
|
131
|
+
`/project/packages/core-common/tests/utils.spec.ts`,
|
|
132
|
+
`/project/packages/core-common/tests/setup/helpers.ts`,
|
|
133
|
+
]);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("excludes files from similar package names (core vs core-common)", () => {
|
|
137
|
+
const pkgDir = `/project/packages/core`;
|
|
138
|
+
const parsedConfig = {
|
|
139
|
+
fileNames: [
|
|
140
|
+
`/project/packages/core/src/index.ts`,
|
|
141
|
+
`/project/packages/core/tests/utils.spec.ts`,
|
|
142
|
+
`/project/packages/core-common/src/index.ts`,
|
|
143
|
+
`/project/packages/core-common/tests/utils.spec.ts`,
|
|
144
|
+
],
|
|
145
|
+
} as ts.ParsedCommandLine;
|
|
146
|
+
|
|
147
|
+
const result = getPackageFiles(pkgDir, parsedConfig);
|
|
148
|
+
|
|
149
|
+
expect(result).toEqual([
|
|
150
|
+
`/project/packages/core/src/index.ts`,
|
|
151
|
+
`/project/packages/core/tests/utils.spec.ts`,
|
|
152
|
+
]);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("returns empty array if no files", () => {
|
|
156
|
+
const pkgDir = `/project/packages/empty`;
|
|
157
|
+
const parsedConfig = {
|
|
158
|
+
fileNames: [`/project/packages/core/src/index.ts`],
|
|
159
|
+
} as ts.ParsedCommandLine;
|
|
160
|
+
|
|
161
|
+
const result = getPackageFiles(pkgDir, parsedConfig);
|
|
162
|
+
|
|
163
|
+
expect(result).toEqual([]);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("handles forward slash paths from TypeScript API correctly (Windows compatible)", () => {
|
|
167
|
+
const pkgDir = path.resolve("/project/packages/core-common");
|
|
168
|
+
const parsedConfig = {
|
|
169
|
+
fileNames: [
|
|
170
|
+
"/project/packages/core-common/src/index.ts",
|
|
171
|
+
"/project/packages/core-common/tests/utils.spec.ts",
|
|
172
|
+
"/project/packages/core-node/src/index.ts",
|
|
173
|
+
],
|
|
174
|
+
} as ts.ParsedCommandLine;
|
|
175
|
+
|
|
176
|
+
const result = getPackageFiles(pkgDir, parsedConfig);
|
|
177
|
+
|
|
178
|
+
expect(result).toHaveLength(2);
|
|
179
|
+
expect(result.every((f) => f.includes("core-common"))).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
// Mock core-node functions
|
|
5
|
+
vi.mock("@simplysm/core-node", () => ({
|
|
6
|
+
fsExists: vi.fn(),
|
|
7
|
+
fsReadJson: vi.fn(),
|
|
8
|
+
pathPosix: vi.fn((p: string) => p.replace(/\\/g, "/")),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
import { fsExists, fsReadJson } from "@simplysm/core-node";
|
|
12
|
+
import { getTypesFromPackageJson } from "../src/utils/tsconfig";
|
|
13
|
+
|
|
14
|
+
describe("getTypesFromPackageJson", () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
vi.restoreAllMocks();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("converts @types/* devDependencies to types list", async () => {
|
|
24
|
+
const packageDir = "/project/packages/core-common";
|
|
25
|
+
const mockFsExists = vi.mocked(fsExists);
|
|
26
|
+
const mockFsReadJson = vi.mocked(fsReadJson);
|
|
27
|
+
|
|
28
|
+
mockFsExists.mockResolvedValue(true);
|
|
29
|
+
mockFsReadJson.mockResolvedValue({
|
|
30
|
+
devDependencies: {
|
|
31
|
+
"@types/node": "^20.0.0",
|
|
32
|
+
"@types/express": "^4.17.0",
|
|
33
|
+
"typescript": "^5.0.0",
|
|
34
|
+
"vitest": "^1.0.0",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const result = await getTypesFromPackageJson(packageDir);
|
|
39
|
+
|
|
40
|
+
expect(mockFsExists).toHaveBeenCalledWith(path.join(packageDir, "package.json"));
|
|
41
|
+
expect(result).toEqual(["node", "express"]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("returns empty array if package.json does not exist", async () => {
|
|
45
|
+
const packageDir = "/project/packages/unknown";
|
|
46
|
+
const mockFsExists = vi.mocked(fsExists);
|
|
47
|
+
|
|
48
|
+
mockFsExists.mockResolvedValue(false);
|
|
49
|
+
|
|
50
|
+
const result = await getTypesFromPackageJson(packageDir);
|
|
51
|
+
|
|
52
|
+
expect(result).toEqual([]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns empty array if devDependencies does not exist", async () => {
|
|
56
|
+
const packageDir = "/project/packages/core-common";
|
|
57
|
+
const mockFsExists = vi.mocked(fsExists);
|
|
58
|
+
const mockFsReadJson = vi.mocked(fsReadJson);
|
|
59
|
+
|
|
60
|
+
mockFsExists.mockResolvedValue(true);
|
|
61
|
+
mockFsReadJson.mockResolvedValue({
|
|
62
|
+
name: "@simplysm/core-common",
|
|
63
|
+
version: "1.0.0",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const result = await getTypesFromPackageJson(packageDir);
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("filters out dependencies that are not @types/*", async () => {
|
|
72
|
+
const packageDir = "/project/packages/core-common";
|
|
73
|
+
const mockFsExists = vi.mocked(fsExists);
|
|
74
|
+
const mockFsReadJson = vi.mocked(fsReadJson);
|
|
75
|
+
|
|
76
|
+
mockFsExists.mockResolvedValue(true);
|
|
77
|
+
mockFsReadJson.mockResolvedValue({
|
|
78
|
+
devDependencies: {
|
|
79
|
+
typescript: "^5.0.0",
|
|
80
|
+
vitest: "^1.0.0",
|
|
81
|
+
eslint: "^9.0.0",
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const result = await getTypesFromPackageJson(packageDir);
|
|
86
|
+
|
|
87
|
+
expect(result).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("handles scoped @types packages correctly", async () => {
|
|
91
|
+
const packageDir = "/project/packages/core-common";
|
|
92
|
+
const mockFsExists = vi.mocked(fsExists);
|
|
93
|
+
const mockFsReadJson = vi.mocked(fsReadJson);
|
|
94
|
+
|
|
95
|
+
mockFsExists.mockResolvedValue(true);
|
|
96
|
+
mockFsReadJson.mockResolvedValue({
|
|
97
|
+
devDependencies: {
|
|
98
|
+
"@types/node": "^20.0.0",
|
|
99
|
+
"@types/babel__core": "^7.0.0",
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const result = await getTypesFromPackageJson(packageDir);
|
|
104
|
+
|
|
105
|
+
expect(result).toEqual(["node", "babel__core"]);
|
|
106
|
+
});
|
|
107
|
+
});
|