@somewhatabstract/x 0.1.0 → 0.1.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 (39) hide show
  1. package/README.md +9 -37
  2. package/package.json +4 -1
  3. package/.changeset/README.md +0 -8
  4. package/.changeset/config.json +0 -11
  5. package/.github/codeql/codeql-config.yml +0 -5
  6. package/.github/dependabot.yml +0 -28
  7. package/.github/workflows/codeql-analysis.yml +0 -71
  8. package/.github/workflows/dependabot-pr-approval.yml +0 -36
  9. package/.github/workflows/nodejs.yml +0 -129
  10. package/.github/workflows/release.yml +0 -95
  11. package/.vscode/settings.json +0 -19
  12. package/CHANGELOG.md +0 -23
  13. package/CODE_OF_CONDUCT.md +0 -76
  14. package/CONTRIBUTING.md +0 -70
  15. package/biome.json +0 -39
  16. package/src/__tests__/build-environment.test.ts +0 -285
  17. package/src/__tests__/discover-packages.test.ts +0 -196
  18. package/src/__tests__/errors.test.ts +0 -59
  19. package/src/__tests__/execute-script.test.ts +0 -1042
  20. package/src/__tests__/find-matching-bins.test.ts +0 -506
  21. package/src/__tests__/find-workspace-root.test.ts +0 -73
  22. package/src/__tests__/is-node-executable.test.ts +0 -125
  23. package/src/__tests__/resolve-bin-path.test.ts +0 -344
  24. package/src/__tests__/x-impl.test.ts +0 -314
  25. package/src/__tests__/x.test.ts +0 -236
  26. package/src/bin/x.ts +0 -57
  27. package/src/build-environment.ts +0 -98
  28. package/src/discover-packages.ts +0 -35
  29. package/src/errors.ts +0 -10
  30. package/src/execute-script.ts +0 -56
  31. package/src/find-matching-bins.ts +0 -72
  32. package/src/find-workspace-root.ts +0 -24
  33. package/src/is-node-executable.ts +0 -16
  34. package/src/resolve-bin-path.ts +0 -48
  35. package/src/x-impl.ts +0 -96
  36. package/tsconfig-types.json +0 -5
  37. package/tsconfig.json +0 -21
  38. package/tsdown.config.ts +0 -24
  39. package/vitest.config.ts +0 -10
package/biome.json DELETED
@@ -1,39 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/2.4.3/schema.json",
3
- "formatter": {
4
- "enabled": true,
5
- "indentStyle": "space",
6
- "indentWidth": 4,
7
- "bracketSpacing": false,
8
- "includes": ["**", "!dist/**", "!coverage/**"]
9
- },
10
- "linter": {
11
- "enabled": true,
12
- "includes": ["**", "!dist/**", "!coverage/**"]
13
- },
14
- "assist": {
15
- "enabled": true,
16
- "includes": ["**", "!dist/**", "!coverage/**"]
17
- },
18
- "overrides": [
19
- {
20
- "includes": ["**/*.test.*"],
21
- "linter": {
22
- "rules": {
23
- "suspicious": {
24
- "noExplicitAny": "off"
25
- }
26
- }
27
- }
28
- },
29
- {
30
- "includes": ["*.json", "*.jsonc"],
31
- "json": {
32
- "parser": {
33
- "allowComments": true,
34
- "allowTrailingCommas": true
35
- }
36
- }
37
- }
38
- ]
39
- }
@@ -1,285 +0,0 @@
1
- import * as fs from "node:fs/promises";
2
- import * as path from "node:path";
3
- import {beforeEach, describe, expect, it, vi} from "vitest";
4
- import {buildEnvironment} from "../build-environment";
5
-
6
- // Mock the fs module
7
- vi.mock("node:fs/promises", () => ({
8
- readFile: vi.fn(),
9
- }));
10
-
11
- describe("buildEnvironment", () => {
12
- beforeEach(() => {
13
- vi.clearAllMocks();
14
- });
15
-
16
- it("should preserve existing environment variables", async () => {
17
- // Arrange
18
- const workspaceRoot = "/test/workspace";
19
- const currentEnv = {
20
- EXISTING_VAR: "existing-value",
21
- PATH: "/usr/bin:/bin",
22
- };
23
-
24
- vi.mocked(fs.readFile).mockResolvedValue(
25
- JSON.stringify({
26
- name: "test-workspace",
27
- version: "1.0.0",
28
- }),
29
- );
30
-
31
- // Act
32
- const env = await buildEnvironment(workspaceRoot, currentEnv);
33
-
34
- // Assert
35
- expect(env.EXISTING_VAR).toBe("existing-value");
36
- });
37
-
38
- it("should prepend workspace node_modules/.bin to PATH", async () => {
39
- // Arrange
40
- const workspaceRoot = "/test/workspace";
41
- const currentEnv = {
42
- PATH: "/usr/bin:/bin",
43
- };
44
-
45
- vi.mocked(fs.readFile).mockResolvedValue(
46
- JSON.stringify({
47
- name: "test-workspace",
48
- }),
49
- );
50
-
51
- // Act
52
- const env = await buildEnvironment(workspaceRoot, currentEnv);
53
-
54
- // Assert
55
- const expectedPath = path.join(workspaceRoot, "node_modules", ".bin");
56
- expect(env.PATH).toContain(expectedPath);
57
- });
58
-
59
- it("should set npm_command to exec", async () => {
60
- // Arrange
61
- const workspaceRoot = "/test/workspace";
62
- const currentEnv = {PATH: "/usr/bin"};
63
-
64
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
65
-
66
- // Act
67
- const env = await buildEnvironment(workspaceRoot, currentEnv);
68
-
69
- // Assert
70
- expect(env.npm_command).toBe("exec");
71
- });
72
-
73
- it("should set INIT_CWD to current working directory", async () => {
74
- // Arrange
75
- const workspaceRoot = "/test/workspace";
76
- const currentEnv = {PATH: "/usr/bin"};
77
- const expectedCwd = process.cwd();
78
-
79
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
80
-
81
- // Act
82
- const env = await buildEnvironment(workspaceRoot, currentEnv);
83
-
84
- // Assert
85
- expect(env.INIT_CWD).toBe(expectedCwd);
86
- });
87
-
88
- it("should set npm_package_name from workspace package.json", async () => {
89
- // Arrange
90
- const workspaceRoot = "/test/workspace";
91
- const currentEnv = {PATH: "/usr/bin"};
92
-
93
- vi.mocked(fs.readFile).mockResolvedValue(
94
- JSON.stringify({
95
- name: "my-workspace",
96
- version: "2.5.0",
97
- }),
98
- );
99
-
100
- // Act
101
- const env = await buildEnvironment(workspaceRoot, currentEnv);
102
-
103
- // Assert
104
- expect(env.npm_package_name).toBe("my-workspace");
105
- });
106
-
107
- it("should set npm_package_version from workspace package.json", async () => {
108
- // Arrange
109
- const workspaceRoot = "/test/workspace";
110
- const currentEnv = {PATH: "/usr/bin"};
111
-
112
- vi.mocked(fs.readFile).mockResolvedValue(
113
- JSON.stringify({
114
- name: "my-workspace",
115
- version: "2.5.0",
116
- }),
117
- );
118
-
119
- // Act
120
- const env = await buildEnvironment(workspaceRoot, currentEnv);
121
-
122
- // Assert
123
- expect(env.npm_package_version).toBe("2.5.0");
124
- });
125
-
126
- it("should set npm_execpath to node executable path", async () => {
127
- // Arrange
128
- const workspaceRoot = "/test/workspace";
129
- const currentEnv = {PATH: "/usr/bin"};
130
-
131
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
132
-
133
- // Act
134
- const env = await buildEnvironment(workspaceRoot, currentEnv);
135
-
136
- // Assert
137
- expect(env.npm_execpath).toBe(process.execPath);
138
- });
139
-
140
- it("should include package name in npm_config_user_agent", async () => {
141
- // Arrange
142
- const workspaceRoot = "/test/workspace";
143
- const currentEnv = {PATH: "/usr/bin"};
144
-
145
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
146
-
147
- // Act
148
- const env = await buildEnvironment(workspaceRoot, currentEnv);
149
-
150
- // Assert
151
- expect(env.npm_config_user_agent).toContain("x/");
152
- });
153
-
154
- it("should include node version in npm_config_user_agent", async () => {
155
- // Arrange
156
- const workspaceRoot = "/test/workspace";
157
- const currentEnv = {PATH: "/usr/bin"};
158
-
159
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
160
-
161
- // Act
162
- const env = await buildEnvironment(workspaceRoot, currentEnv);
163
-
164
- // Assert
165
- expect(env.npm_config_user_agent).toContain("node/");
166
- });
167
-
168
- it("should set npm_command to exec when package.json is missing", async () => {
169
- // Arrange
170
- const workspaceRoot = "/test/workspace";
171
- const currentEnv = {PATH: "/usr/bin"};
172
-
173
- vi.mocked(fs.readFile).mockRejectedValue(
174
- new Error("ENOENT: no such file"),
175
- );
176
-
177
- // Act
178
- const env = await buildEnvironment(workspaceRoot, currentEnv);
179
-
180
- // Assert
181
- expect(env.npm_command).toBe("exec");
182
- });
183
-
184
- it("should set INIT_CWD when package.json is missing", async () => {
185
- // Arrange
186
- const workspaceRoot = "/test/workspace";
187
- const currentEnv = {PATH: "/usr/bin"};
188
-
189
- vi.mocked(fs.readFile).mockRejectedValue(
190
- new Error("ENOENT: no such file"),
191
- );
192
-
193
- // Act
194
- const env = await buildEnvironment(workspaceRoot, currentEnv);
195
-
196
- // Assert
197
- expect(env.INIT_CWD).toBe(process.cwd());
198
- });
199
-
200
- it("should include npm_package_description if present", async () => {
201
- // Arrange
202
- const workspaceRoot = "/test/workspace";
203
- const currentEnv = {PATH: "/usr/bin"};
204
-
205
- vi.mocked(fs.readFile).mockResolvedValue(
206
- JSON.stringify({
207
- name: "my-workspace",
208
- description: "A test workspace",
209
- }),
210
- );
211
-
212
- // Act
213
- const env = await buildEnvironment(workspaceRoot, currentEnv);
214
-
215
- // Assert
216
- expect(env.npm_package_description).toBe("A test workspace");
217
- });
218
-
219
- it("should convert object fields to JSON strings", async () => {
220
- // Arrange
221
- const workspaceRoot = "/test/workspace";
222
- const currentEnv = {PATH: "/usr/bin"};
223
-
224
- vi.mocked(fs.readFile).mockResolvedValue(
225
- JSON.stringify({
226
- name: "my-workspace",
227
- repository: {
228
- type: "git",
229
- url: "https://github.com/test/repo",
230
- },
231
- }),
232
- );
233
-
234
- // Act
235
- const env = await buildEnvironment(workspaceRoot, currentEnv);
236
-
237
- // Assert
238
- expect(env.npm_package_repository).toBe(
239
- JSON.stringify({
240
- type: "git",
241
- url: "https://github.com/test/repo",
242
- }),
243
- );
244
- });
245
-
246
- it("should set npm_package_license from workspace package.json", async () => {
247
- // Arrange
248
- const workspaceRoot = "/test/workspace";
249
- const currentEnv = {PATH: "/usr/bin"};
250
-
251
- vi.mocked(fs.readFile).mockResolvedValue(
252
- JSON.stringify({
253
- name: "my-workspace",
254
- license: "MIT",
255
- author: "John Doe",
256
- }),
257
- );
258
-
259
- // Act
260
- const env = await buildEnvironment(workspaceRoot, currentEnv);
261
-
262
- // Assert
263
- expect(env.npm_package_license).toBe("MIT");
264
- });
265
-
266
- it("should set npm_package_author from workspace package.json", async () => {
267
- // Arrange
268
- const workspaceRoot = "/test/workspace";
269
- const currentEnv = {PATH: "/usr/bin"};
270
-
271
- vi.mocked(fs.readFile).mockResolvedValue(
272
- JSON.stringify({
273
- name: "my-workspace",
274
- license: "MIT",
275
- author: "John Doe",
276
- }),
277
- );
278
-
279
- // Act
280
- const env = await buildEnvironment(workspaceRoot, currentEnv);
281
-
282
- // Assert
283
- expect(env.npm_package_author).toBe("John Doe");
284
- });
285
- });
@@ -1,196 +0,0 @@
1
- import * as manypkg from "@manypkg/get-packages";
2
- import {beforeEach, describe, expect, it, vi} from "vitest";
3
- import {discoverPackages} from "../discover-packages";
4
- import {HandledError} from "../errors";
5
-
6
- // Mock @manypkg/get-packages
7
- vi.mock("@manypkg/get-packages", () => ({
8
- getPackages: vi.fn(),
9
- }));
10
-
11
- describe("discoverPackages", () => {
12
- beforeEach(() => {
13
- vi.clearAllMocks();
14
- });
15
-
16
- it("should return packages from @manypkg", async () => {
17
- // Arrange
18
- const workspaceRoot = "/test/workspace";
19
- const mockPackages = {
20
- packages: [
21
- {
22
- packageJson: {name: "pkg1", version: "1.0.0"},
23
- dir: "/test/workspace/pkg1",
24
- },
25
- {
26
- packageJson: {name: "pkg2", version: "2.0.0"},
27
- dir: "/test/workspace/pkg2",
28
- },
29
- ],
30
- };
31
-
32
- vi.mocked(manypkg.getPackages).mockResolvedValue(mockPackages as any);
33
-
34
- // Act
35
- const result = await discoverPackages(workspaceRoot);
36
-
37
- // Assert
38
- expect(result).toHaveLength(2);
39
- });
40
-
41
- it("should map package names correctly", async () => {
42
- // Arrange
43
- const workspaceRoot = "/test/workspace";
44
- const mockPackages = {
45
- packages: [
46
- {
47
- packageJson: {name: "test-package", version: "1.0.0"},
48
- dir: "/test/workspace/pkg",
49
- },
50
- ],
51
- };
52
-
53
- vi.mocked(manypkg.getPackages).mockResolvedValue(mockPackages as any);
54
-
55
- // Act
56
- const result = await discoverPackages(workspaceRoot);
57
-
58
- // Assert
59
- expect(result[0].name).toBe("test-package");
60
- });
61
-
62
- it("should map package paths correctly", async () => {
63
- // Arrange
64
- const workspaceRoot = "/test/workspace";
65
- const mockPackages = {
66
- packages: [
67
- {
68
- packageJson: {name: "test-package", version: "1.0.0"},
69
- dir: "/test/workspace/packages/test",
70
- },
71
- ],
72
- };
73
-
74
- vi.mocked(manypkg.getPackages).mockResolvedValue(mockPackages as any);
75
-
76
- // Act
77
- const result = await discoverPackages(workspaceRoot);
78
-
79
- // Assert
80
- expect(result[0].path).toBe("/test/workspace/packages/test");
81
- });
82
-
83
- it("should map package versions correctly", async () => {
84
- // Arrange
85
- const workspaceRoot = "/test/workspace";
86
- const mockPackages = {
87
- packages: [
88
- {
89
- packageJson: {name: "test-package", version: "3.2.1"},
90
- dir: "/test/workspace/pkg",
91
- },
92
- ],
93
- };
94
-
95
- vi.mocked(manypkg.getPackages).mockResolvedValue(mockPackages as any);
96
-
97
- // Act
98
- const result = await discoverPackages(workspaceRoot);
99
-
100
- // Assert
101
- expect(result[0].version).toBe("3.2.1");
102
- });
103
-
104
- it("should use 'unknown' for missing version", async () => {
105
- // Arrange
106
- const workspaceRoot = "/test/workspace";
107
- const mockPackages = {
108
- packages: [
109
- {
110
- packageJson: {name: "test-package"},
111
- dir: "/test/workspace/pkg",
112
- },
113
- ],
114
- };
115
-
116
- vi.mocked(manypkg.getPackages).mockResolvedValue(mockPackages as any);
117
-
118
- // Act
119
- const result = await discoverPackages(workspaceRoot);
120
-
121
- // Assert
122
- expect(result[0].version).toBe("unknown");
123
- });
124
-
125
- it("should call getPackages with workspace root", async () => {
126
- // Arrange
127
- const workspaceRoot = "/test/workspace";
128
- const mockPackages = {
129
- packages: [],
130
- };
131
-
132
- vi.mocked(manypkg.getPackages).mockResolvedValue(mockPackages as any);
133
-
134
- // Act
135
- await discoverPackages(workspaceRoot);
136
-
137
- // Assert
138
- expect(manypkg.getPackages).toHaveBeenCalledWith(workspaceRoot);
139
- });
140
-
141
- it("should rethrow HandledError type as is", async () => {
142
- // Arrange
143
- const workspaceRoot = "/test/workspace";
144
- const handledError = new HandledError("Test handled error");
145
-
146
- vi.mocked(manypkg.getPackages).mockRejectedValue(handledError);
147
-
148
- // Act
149
- const underTest = () => discoverPackages(workspaceRoot);
150
-
151
- // Assert
152
- await expect(underTest).rejects.toThrow(HandledError);
153
- });
154
-
155
- it("should rethrow HandledError message as is", async () => {
156
- // Arrange
157
- const workspaceRoot = "/test/workspace";
158
- const handledError = new HandledError("Test handled error");
159
-
160
- vi.mocked(manypkg.getPackages).mockRejectedValue(handledError);
161
-
162
- // Act
163
- const underTest = () => discoverPackages(workspaceRoot);
164
-
165
- // Assert
166
- await expect(underTest).rejects.toThrow("Test handled error");
167
- });
168
-
169
- it("should wrap non-HandledError in HandledError type", async () => {
170
- // Arrange
171
- const workspaceRoot = "/test/workspace";
172
- const error = new Error("Original error");
173
-
174
- vi.mocked(manypkg.getPackages).mockRejectedValue(error);
175
-
176
- // Act
177
- const underTest = () => discoverPackages(workspaceRoot);
178
-
179
- // Assert
180
- await expect(underTest).rejects.toThrow(HandledError);
181
- });
182
-
183
- it("should use expected message when wrapping non-HandledError", async () => {
184
- // Arrange
185
- const workspaceRoot = "/test/workspace";
186
- const error = new Error("Original error");
187
-
188
- vi.mocked(manypkg.getPackages).mockRejectedValue(error);
189
-
190
- // Act
191
- const underTest = () => discoverPackages(workspaceRoot);
192
-
193
- // Assert
194
- await expect(underTest).rejects.toThrow("Failed to discover packages");
195
- });
196
- });
@@ -1,59 +0,0 @@
1
- import {describe, expect, it} from "vitest";
2
- import {HandledError} from "../errors";
3
-
4
- describe("HandledError", () => {
5
- it("should be an instance of Error", () => {
6
- // Arrange
7
- const error = new HandledError("Test error message");
8
-
9
- // Act
10
- const isError = error instanceof Error;
11
-
12
- // Assert
13
- expect(isError).toBe(true);
14
- });
15
-
16
- it("should have name 'HandledError'", () => {
17
- // Arrange
18
- const error = new HandledError("Test error message");
19
-
20
- // Act
21
- const name = error.name;
22
-
23
- // Assert
24
- expect(name).toBe("HandledError");
25
- });
26
-
27
- it("should preserve the error message", () => {
28
- // Arrange
29
- const message = "Test error message";
30
-
31
- // Act
32
- const error = new HandledError(message);
33
-
34
- // Assert
35
- expect(error.message).toBe(message);
36
- });
37
-
38
- it("should be distinguishable from HandledError type", () => {
39
- // Arrange
40
- const handledError = new HandledError("Handled");
41
-
42
- // Act
43
- const isHandledError = handledError instanceof HandledError;
44
-
45
- // Assert
46
- expect(isHandledError).toBe(true);
47
- });
48
-
49
- it("should distinguish regular errors from HandledError type", () => {
50
- // Arrange
51
- const regularError = new Error("Regular");
52
-
53
- // Act
54
- const isHandledError = regularError instanceof HandledError;
55
-
56
- // Assert
57
- expect(isHandledError).toBe(false);
58
- });
59
- });