bun-workspaces 0.3.0 → 1.0.1-alpha
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 +32 -4
- package/bun.lock +576 -0
- package/package.json +13 -15
- package/src/cli/cli.ts +3 -8
- package/src/cli/globalOptions.ts +61 -23
- package/src/cli/projectCommands.ts +42 -41
- package/src/config/bunWorkspacesConfig.ts +62 -0
- package/src/config/configFile.ts +33 -0
- package/src/config/index.ts +7 -0
- package/src/internal/env.ts +25 -1
- package/src/internal/logger.ts +143 -19
- package/src/project/project.ts +24 -1
- package/src/workspaces/errors.ts +2 -0
- package/src/workspaces/findWorkspaces.ts +36 -8
- package/src/workspaces/index.ts +0 -1
- package/src/workspaces/packageJson.ts +1 -1
- package/src/workspaces/workspace.ts +2 -0
- package/.vscode/extensions.json +0 -12
- package/.vscode/settings.json +0 -23
- package/bun-workspaces-0.1.0-alpha-test-publish-2.tgz +0 -0
- package/eslint.config.mjs +0 -45
- package/ignore-me-CHANGELOG_TEMPLATE.md +0 -264
- package/ignore-me-test-projects/no-fail/applications/applicationA/package.json +0 -8
- package/ignore-me-test-projects/no-fail/applications/applicationB/package.json +0 -8
- package/ignore-me-test-projects/no-fail/libraries/libraryA/package.json +0 -8
- package/ignore-me-test-projects/no-fail/libraries/libraryB/package.json +0 -8
- package/ignore-me-test-projects/no-fail/libraries/nested/libraryC/package.json +0 -8
- package/ignore-me-test-projects/no-fail/package.json +0 -7
- package/ignore-me-test-projects/one-fail/applications/applicationA/package.json +0 -8
- package/ignore-me-test-projects/one-fail/applications/applicationB/package.json +0 -8
- package/ignore-me-test-projects/one-fail/libraries/libraryA/package.json +0 -8
- package/ignore-me-test-projects/one-fail/libraries/libraryB/package.json +0 -8
- package/ignore-me-test-projects/one-fail/libraries/nested/libraryC/package.json +0 -8
- package/ignore-me-test-projects/one-fail/package.json +0 -7
- package/ignore-me-test-projects/two-fail/applications/applicationA/package.json +0 -8
- package/ignore-me-test-projects/two-fail/applications/applicationB/package.json +0 -8
- package/ignore-me-test-projects/two-fail/libraries/libraryA/package.json +0 -8
- package/ignore-me-test-projects/two-fail/libraries/libraryB/package.json +0 -8
- package/ignore-me-test-projects/two-fail/libraries/nested/libraryC/package.json +0 -8
- package/ignore-me-test-projects/two-fail/package.json +0 -7
- package/src/cli/output.ts +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-workspaces",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1-alpha",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"homepage": "https://github.com/ScottMorse/bun-workspaces#readme",
|
|
6
6
|
"bin": {
|
|
@@ -8,35 +8,33 @@
|
|
|
8
8
|
},
|
|
9
9
|
"custom": {
|
|
10
10
|
"bunVersion": {
|
|
11
|
-
"build": "1.
|
|
11
|
+
"build": "1.2.22",
|
|
12
12
|
"libraryConsumer": "^1.1.x"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"cli": "
|
|
17
|
-
"cli:dev": "
|
|
16
|
+
"cli": "bun run bin/cli.js",
|
|
17
|
+
"cli:dev": "_BW_RUNTIME_MODE=development bun run bin/cli.js",
|
|
18
18
|
"type-check": "tsc --noEmit",
|
|
19
19
|
"lint": "eslint .",
|
|
20
20
|
"format": "prettier --write .",
|
|
21
21
|
"format-check": "prettier --check ."
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/bun": "^1.
|
|
25
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
26
|
-
"@typescript-eslint/parser": "^8.
|
|
24
|
+
"@types/bun": "^1.2.22",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
|
26
|
+
"@typescript-eslint/parser": "^8.44.1",
|
|
27
27
|
"bun-workspaces": "file:.",
|
|
28
|
-
"eslint": "^9.
|
|
29
|
-
"eslint-plugin-import": "^2.
|
|
30
|
-
"prettier": "^3.
|
|
31
|
-
"typescript-eslint": "^8.
|
|
28
|
+
"eslint": "^9.36.0",
|
|
29
|
+
"eslint-plugin-import": "^2.32.0",
|
|
30
|
+
"prettier": "^3.6.2",
|
|
31
|
+
"typescript-eslint": "^8.44.1"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"commander": "^12.1.0",
|
|
35
|
-
"glob": "^11.0.
|
|
36
|
-
"pino": "^9.5.0",
|
|
37
|
-
"pino-pretty": "^13.0.0"
|
|
35
|
+
"glob": "^11.0.3"
|
|
38
36
|
},
|
|
39
37
|
"peerDependencies": {
|
|
40
|
-
"typescript": "^5.
|
|
38
|
+
"typescript": "^5.9.2"
|
|
41
39
|
}
|
|
42
40
|
}
|
package/src/cli/cli.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
} from "../internal/bunVersion";
|
|
7
7
|
import { logger } from "../internal/logger";
|
|
8
8
|
import { initializeWithGlobalOptions } from "./globalOptions";
|
|
9
|
-
import { OUTPUT_CONFIG } from "./output";
|
|
10
9
|
import { defineProjectCommands } from "./projectCommands";
|
|
11
10
|
|
|
12
11
|
export interface RunCliOptions {
|
|
@@ -18,16 +17,12 @@ export interface CliProgram {
|
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
export interface CreateCliProgramOptions {
|
|
21
|
-
writeOut?: (s: string) => void;
|
|
22
|
-
writeErr?: (s: string) => void;
|
|
23
20
|
handleError?: (error: Error) => void;
|
|
24
21
|
postInit?: (program: Command) => unknown;
|
|
25
22
|
defaultCwd?: string;
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
export const createCliProgram = ({
|
|
29
|
-
writeOut = OUTPUT_CONFIG.writeOut,
|
|
30
|
-
writeErr = OUTPUT_CONFIG.writeErr,
|
|
31
26
|
handleError,
|
|
32
27
|
postInit,
|
|
33
28
|
defaultCwd = process.cwd(),
|
|
@@ -48,8 +43,9 @@ export const createCliProgram = ({
|
|
|
48
43
|
.description("CLI for utilities for Bun workspaces")
|
|
49
44
|
.version(packageJson.version)
|
|
50
45
|
.configureOutput({
|
|
51
|
-
writeOut,
|
|
52
|
-
writeErr
|
|
46
|
+
writeOut: (s) => logger.info(s),
|
|
47
|
+
writeErr: (s) =>
|
|
48
|
+
s.startsWith("Usage") ? logger.info(s) : logger.error(s),
|
|
53
49
|
});
|
|
54
50
|
|
|
55
51
|
postInit?.(program);
|
|
@@ -75,7 +71,6 @@ export const createCliProgram = ({
|
|
|
75
71
|
defineProjectCommands({
|
|
76
72
|
program,
|
|
77
73
|
project,
|
|
78
|
-
printLines: (...lines: string[]) => writeOut(lines.join("\n") + "\n"),
|
|
79
74
|
});
|
|
80
75
|
|
|
81
76
|
await program.parseAsync(args);
|
package/src/cli/globalOptions.ts
CHANGED
|
@@ -1,22 +1,48 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { type Command, Option } from "commander";
|
|
3
|
-
import {
|
|
3
|
+
import { loadConfigFile, type BunWorkspacesConfig } from "../config";
|
|
4
|
+
import { LOG_LEVELS, logger, type LogLevelSetting } from "../internal/logger";
|
|
4
5
|
import { createProject } from "../project";
|
|
5
6
|
|
|
6
|
-
const LOG_LEVELS = ["silent", "error", "warn", "info", "debug"] as const;
|
|
7
|
-
|
|
8
|
-
export type LogLevel = (typeof LOG_LEVELS)[number];
|
|
9
|
-
|
|
10
7
|
export interface CliGlobalOptions {
|
|
11
|
-
logLevel:
|
|
8
|
+
logLevel: LogLevelSetting;
|
|
12
9
|
cwd: string;
|
|
10
|
+
configFile?: string;
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
export type CliGlobalOptionName = keyof CliGlobalOptions;
|
|
16
14
|
|
|
17
|
-
const
|
|
15
|
+
const getWorkingDirectory = (
|
|
16
|
+
program: Command,
|
|
17
|
+
args: string[],
|
|
18
|
+
defaultCwd: string,
|
|
19
|
+
) => {
|
|
20
|
+
program.addOption(
|
|
21
|
+
new Option("-d --cwd <path>", "Working directory").default(defaultCwd),
|
|
22
|
+
);
|
|
23
|
+
program.parseOptions(args);
|
|
24
|
+
return program.opts().cwd;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const getConfig = (program: Command, args: string[]) => {
|
|
28
|
+
program.addOption(new Option("-c --configFile <path>", "Config file"));
|
|
29
|
+
program.parseOptions(args);
|
|
30
|
+
return program.opts().configFile;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const defineGlobalOptions = (
|
|
34
|
+
program: Command,
|
|
35
|
+
args: string[],
|
|
36
|
+
defaultCwd: string,
|
|
37
|
+
) => {
|
|
38
|
+
const cwd = getWorkingDirectory(program, args, defaultCwd);
|
|
39
|
+
|
|
40
|
+
const configFilePath = getConfig(program, args);
|
|
41
|
+
|
|
42
|
+
const config = loadConfigFile(configFilePath, cwd);
|
|
43
|
+
|
|
18
44
|
const globalOptions: {
|
|
19
|
-
[K in CliGlobalOptionName]: {
|
|
45
|
+
[K in Exclude<CliGlobalOptionName, "configFile" | "cwd">]: {
|
|
20
46
|
shortName: string;
|
|
21
47
|
description: string;
|
|
22
48
|
defaultValue: CliGlobalOptions[K];
|
|
@@ -27,36 +53,39 @@ const defineGlobalOptions = (program: Command, defaultCwd: string) => {
|
|
|
27
53
|
logLevel: {
|
|
28
54
|
shortName: "l",
|
|
29
55
|
description: "Log levels",
|
|
30
|
-
defaultValue:
|
|
31
|
-
|
|
56
|
+
defaultValue:
|
|
57
|
+
config?.cli?.logLevel ?? (logger.printLevel as LogLevelSetting),
|
|
58
|
+
values: [...LOG_LEVELS, "silent"],
|
|
32
59
|
param: "level",
|
|
33
60
|
},
|
|
34
|
-
cwd: {
|
|
35
|
-
shortName: "d",
|
|
36
|
-
description: "Working directory",
|
|
37
|
-
defaultValue: defaultCwd ?? process.cwd(),
|
|
38
|
-
param: "dir",
|
|
39
|
-
},
|
|
40
61
|
};
|
|
41
62
|
|
|
42
63
|
Object.entries(globalOptions).forEach(
|
|
43
|
-
([name, { shortName, description,
|
|
64
|
+
([name, { shortName, description, param, values, defaultValue }]) => {
|
|
44
65
|
const option = new Option(
|
|
45
66
|
`-${shortName} --${name}${param ? ` <${param}>` : ""}`,
|
|
46
67
|
description,
|
|
47
68
|
).default(defaultValue);
|
|
48
69
|
|
|
49
|
-
program.addOption(
|
|
70
|
+
program.addOption(
|
|
71
|
+
values?.length ? option.choices(values as string[]) : option,
|
|
72
|
+
);
|
|
50
73
|
},
|
|
51
74
|
);
|
|
75
|
+
|
|
76
|
+
return { cwd, config };
|
|
52
77
|
};
|
|
53
78
|
|
|
54
|
-
const applyGlobalOptions = (
|
|
55
|
-
|
|
79
|
+
const applyGlobalOptions = (
|
|
80
|
+
options: CliGlobalOptions,
|
|
81
|
+
config: BunWorkspacesConfig | null,
|
|
82
|
+
) => {
|
|
83
|
+
logger.printLevel = options.logLevel;
|
|
56
84
|
logger.debug("Log level: " + options.logLevel);
|
|
57
85
|
|
|
58
86
|
const project = createProject({
|
|
59
87
|
rootDir: options.cwd,
|
|
88
|
+
workspaceAliases: config?.project?.workspaceAliases ?? {},
|
|
60
89
|
});
|
|
61
90
|
|
|
62
91
|
logger.debug(
|
|
@@ -74,11 +103,20 @@ export const initializeWithGlobalOptions = (
|
|
|
74
103
|
args: string[],
|
|
75
104
|
defaultCwd: string,
|
|
76
105
|
) => {
|
|
77
|
-
defineGlobalOptions(program, defaultCwd);
|
|
78
|
-
|
|
79
106
|
program.allowUnknownOption(true);
|
|
107
|
+
|
|
108
|
+
const { cwd, config } = defineGlobalOptions(program, args, defaultCwd);
|
|
109
|
+
|
|
80
110
|
program.parseOptions(args);
|
|
81
111
|
program.allowUnknownOption(false);
|
|
82
112
|
|
|
83
|
-
|
|
113
|
+
const options = program.opts() as CliGlobalOptions;
|
|
114
|
+
|
|
115
|
+
return applyGlobalOptions(
|
|
116
|
+
{
|
|
117
|
+
...options,
|
|
118
|
+
cwd,
|
|
119
|
+
},
|
|
120
|
+
config,
|
|
121
|
+
);
|
|
84
122
|
};
|
|
@@ -7,11 +7,11 @@ import type { Workspace } from "../workspaces";
|
|
|
7
7
|
export interface ProjectCommandsContext {
|
|
8
8
|
project: Project;
|
|
9
9
|
program: Command;
|
|
10
|
-
printLines: (...lines: string[]) => void;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
const createWorkspaceInfoLines = (workspace: Workspace) => [
|
|
14
13
|
`Workspace: ${workspace.name}`,
|
|
14
|
+
` - Aliases: ${workspace.aliases.join(", ")}`,
|
|
15
15
|
` - Path: ${workspace.path}`,
|
|
16
16
|
` - Glob Match: ${workspace.matchPattern}`,
|
|
17
17
|
` - Scripts: ${Object.keys(workspace.packageJson.scripts).sort().join(", ")}`,
|
|
@@ -25,11 +25,10 @@ const createScriptInfoLines = (script: string, workspaces: Workspace[]) => [
|
|
|
25
25
|
const createJsonLines = (data: unknown, options: { pretty: boolean }) =>
|
|
26
26
|
JSON.stringify(data, null, options.pretty ? 2 : undefined).split("\n");
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}: ProjectCommandsContext) => {
|
|
28
|
+
export const commandOutputLogger = createLogger("");
|
|
29
|
+
commandOutputLogger.printLevel = "info";
|
|
30
|
+
|
|
31
|
+
const listWorkspaces = ({ program, project }: ProjectCommandsContext) => {
|
|
33
32
|
program
|
|
34
33
|
.command("list-workspaces [pattern]")
|
|
35
34
|
.aliases(["ls", "list"])
|
|
@@ -72,19 +71,15 @@ const listWorkspaces = ({
|
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
if (!lines.length) {
|
|
75
|
-
|
|
74
|
+
logger.info("No workspaces found");
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
if (lines.length) commandOutputLogger.info(lines.join("\n"));
|
|
79
78
|
},
|
|
80
79
|
);
|
|
81
80
|
};
|
|
82
81
|
|
|
83
|
-
const listScripts = ({
|
|
84
|
-
program,
|
|
85
|
-
project,
|
|
86
|
-
printLines,
|
|
87
|
-
}: ProjectCommandsContext) => {
|
|
82
|
+
const listScripts = ({ program, project }: ProjectCommandsContext) => {
|
|
88
83
|
program
|
|
89
84
|
.command("list-scripts")
|
|
90
85
|
.description("List all scripts available with their workspaces")
|
|
@@ -126,20 +121,16 @@ const listScripts = ({
|
|
|
126
121
|
});
|
|
127
122
|
|
|
128
123
|
if (!lines.length) {
|
|
129
|
-
|
|
124
|
+
logger.info("No scripts found");
|
|
130
125
|
}
|
|
131
126
|
}
|
|
132
127
|
|
|
133
|
-
|
|
128
|
+
if (lines.length) commandOutputLogger.info(lines.join("\n"));
|
|
134
129
|
},
|
|
135
130
|
);
|
|
136
131
|
};
|
|
137
132
|
|
|
138
|
-
const workspaceInfo = ({
|
|
139
|
-
program,
|
|
140
|
-
project,
|
|
141
|
-
printLines,
|
|
142
|
-
}: ProjectCommandsContext) => {
|
|
133
|
+
const workspaceInfo = ({ program, project }: ProjectCommandsContext) => {
|
|
143
134
|
program
|
|
144
135
|
.command("workspace-info <workspace>")
|
|
145
136
|
.aliases(["info"])
|
|
@@ -152,7 +143,7 @@ const workspaceInfo = ({
|
|
|
152
143
|
`Command: Workspace info for ${workspaceName} (options: ${JSON.stringify(options)})`,
|
|
153
144
|
);
|
|
154
145
|
|
|
155
|
-
const workspace = project.
|
|
146
|
+
const workspace = project.findWorkspaceByNameOrAlias(workspaceName);
|
|
156
147
|
if (!workspace) {
|
|
157
148
|
logger.error(
|
|
158
149
|
`Workspace not found: (options: ${JSON.stringify(workspaceName)})`,
|
|
@@ -160,20 +151,17 @@ const workspaceInfo = ({
|
|
|
160
151
|
return;
|
|
161
152
|
}
|
|
162
153
|
|
|
163
|
-
|
|
164
|
-
|
|
154
|
+
commandOutputLogger.info(
|
|
155
|
+
(options.json
|
|
165
156
|
? createJsonLines(workspace, options)
|
|
166
|
-
: createWorkspaceInfoLines(workspace)
|
|
157
|
+
: createWorkspaceInfoLines(workspace)
|
|
158
|
+
).join("\n"),
|
|
167
159
|
);
|
|
168
160
|
},
|
|
169
161
|
);
|
|
170
162
|
};
|
|
171
163
|
|
|
172
|
-
const scriptInfo = ({
|
|
173
|
-
program,
|
|
174
|
-
project,
|
|
175
|
-
printLines,
|
|
176
|
-
}: ProjectCommandsContext) => {
|
|
164
|
+
const scriptInfo = ({ program, project }: ProjectCommandsContext) => {
|
|
177
165
|
program
|
|
178
166
|
.command("script-info <script>")
|
|
179
167
|
.description("Show information about a script")
|
|
@@ -192,15 +180,15 @@ const scriptInfo = ({
|
|
|
192
180
|
const scripts = project.listScriptsWithWorkspaces();
|
|
193
181
|
const scriptMetadata = scripts[script];
|
|
194
182
|
if (!scriptMetadata) {
|
|
195
|
-
|
|
183
|
+
logger.error(
|
|
196
184
|
`Script not found: ${JSON.stringify(
|
|
197
185
|
script,
|
|
198
186
|
)} (available: ${Object.keys(scripts).join(", ")})`,
|
|
199
187
|
);
|
|
200
188
|
return;
|
|
201
189
|
}
|
|
202
|
-
|
|
203
|
-
|
|
190
|
+
commandOutputLogger.info(
|
|
191
|
+
(options.json
|
|
204
192
|
? createJsonLines(
|
|
205
193
|
options.workspacesOnly
|
|
206
194
|
? scriptMetadata.workspaces.map(({ name }) => name)
|
|
@@ -214,7 +202,8 @@ const scriptInfo = ({
|
|
|
214
202
|
)
|
|
215
203
|
: options.workspacesOnly
|
|
216
204
|
? scriptMetadata.workspaces.map(({ name }) => name)
|
|
217
|
-
: createScriptInfoLines(script, scriptMetadata.workspaces)
|
|
205
|
+
: createScriptInfoLines(script, scriptMetadata.workspaces)
|
|
206
|
+
).join("\n"),
|
|
218
207
|
);
|
|
219
208
|
},
|
|
220
209
|
);
|
|
@@ -285,24 +274,32 @@ const runScript = ({ program, project }: ProjectCommandsContext) => {
|
|
|
285
274
|
}): ${splitCommand.join(" ")}`,
|
|
286
275
|
);
|
|
287
276
|
|
|
288
|
-
const
|
|
277
|
+
const isSilent = logger.printLevel === "silent";
|
|
289
278
|
|
|
290
279
|
const proc = Bun.spawn(command.command.split(/\s+/g), {
|
|
291
280
|
cwd: command.cwd,
|
|
292
281
|
env: process.env,
|
|
293
|
-
stdout:
|
|
294
|
-
stderr:
|
|
282
|
+
stdout: isSilent ? "ignore" : "pipe",
|
|
283
|
+
stderr: isSilent ? "ignore" : "pipe",
|
|
295
284
|
});
|
|
296
285
|
|
|
286
|
+
const linePrefix = `[${workspace.name}:${scriptName}] `;
|
|
287
|
+
|
|
297
288
|
if (proc.stdout) {
|
|
298
289
|
for await (const chunk of proc.stdout) {
|
|
299
|
-
|
|
290
|
+
const line = new TextDecoder().decode(chunk).trim();
|
|
291
|
+
line.split("\n").forEach((line) => {
|
|
292
|
+
commandLogger.info(linePrefix + line);
|
|
293
|
+
});
|
|
300
294
|
}
|
|
301
295
|
}
|
|
302
296
|
|
|
303
297
|
if (proc.stderr) {
|
|
304
298
|
for await (const chunk of proc.stderr) {
|
|
305
|
-
|
|
299
|
+
const line = new TextDecoder().decode(chunk).trim();
|
|
300
|
+
line.split("\n").forEach((line) => {
|
|
301
|
+
commandLogger.error(linePrefix + line);
|
|
302
|
+
});
|
|
306
303
|
}
|
|
307
304
|
}
|
|
308
305
|
|
|
@@ -372,16 +369,20 @@ const runScript = ({ program, project }: ProjectCommandsContext) => {
|
|
|
372
369
|
let failCount = 0;
|
|
373
370
|
results.forEach(({ success, workspaceName }) => {
|
|
374
371
|
if (!success) failCount++;
|
|
375
|
-
|
|
372
|
+
commandOutputLogger.info(
|
|
373
|
+
`${success ? "✅" : "❌"} ${workspaceName}: ${script}`,
|
|
374
|
+
);
|
|
376
375
|
});
|
|
377
376
|
|
|
378
377
|
const s = results.length === 1 ? "" : "s";
|
|
379
378
|
if (failCount) {
|
|
380
379
|
const message = `${failCount} of ${results.length} script${s} failed`;
|
|
381
|
-
|
|
380
|
+
commandOutputLogger.info(message);
|
|
382
381
|
process.exit(1);
|
|
383
382
|
} else {
|
|
384
|
-
|
|
383
|
+
commandOutputLogger.info(
|
|
384
|
+
`${results.length} script${s} ran successfully`,
|
|
385
|
+
);
|
|
385
386
|
}
|
|
386
387
|
});
|
|
387
388
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { validateLogLevel, type LogLevelSetting } from "../internal/logger";
|
|
2
|
+
|
|
3
|
+
export interface CliConfig {
|
|
4
|
+
logLevel?: LogLevelSetting;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ProjectConfig {
|
|
8
|
+
/** A map of aliases to a workspace name */
|
|
9
|
+
workspaceAliases?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface BunWorkspacesConfig {
|
|
13
|
+
cli?: CliConfig;
|
|
14
|
+
project?: ProjectConfig;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const validateCliConfig = (cliConfig: CliConfig) => {
|
|
18
|
+
if (typeof cliConfig !== "object" || Array.isArray(cliConfig)) {
|
|
19
|
+
throw new Error(`Config file: "cli" must be an object`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (cliConfig?.logLevel) {
|
|
23
|
+
validateLogLevel(cliConfig.logLevel);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const validateProjectConfig = (projectConfig: ProjectConfig) => {
|
|
28
|
+
if (typeof projectConfig !== "object" || Array.isArray(projectConfig)) {
|
|
29
|
+
throw new Error(`Config file: "project" must be an object`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (projectConfig?.workspaceAliases) {
|
|
33
|
+
if (
|
|
34
|
+
typeof projectConfig.workspaceAliases !== "object" ||
|
|
35
|
+
Array.isArray(projectConfig.workspaceAliases)
|
|
36
|
+
) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Config file: project.workspaceAliases must be an object`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
for (const alias of Object.values(projectConfig.workspaceAliases)) {
|
|
42
|
+
if (typeof alias !== "string") {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Config file: project.workspaceAliases must be an object with string keys and values`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const validateBunWorkspacesConfig = (config: BunWorkspacesConfig) => {
|
|
52
|
+
if (typeof config !== "object" || Array.isArray(config)) {
|
|
53
|
+
throw new Error(`Config file: must be an object`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (typeof config.cli !== "undefined") {
|
|
57
|
+
validateCliConfig(config.cli);
|
|
58
|
+
}
|
|
59
|
+
if (typeof config.project !== "undefined") {
|
|
60
|
+
validateProjectConfig(config.project);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import {
|
|
4
|
+
validateBunWorkspacesConfig,
|
|
5
|
+
type BunWorkspacesConfig,
|
|
6
|
+
} from "./bunWorkspacesConfig";
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_CONFIG_FILE_PATH = "bw.json";
|
|
9
|
+
|
|
10
|
+
export const loadConfigFile = (filePath?: string, rootDir = ".") => {
|
|
11
|
+
if (!filePath) {
|
|
12
|
+
const defaultFilePath = path.resolve(rootDir, DEFAULT_CONFIG_FILE_PATH);
|
|
13
|
+
if (fs.existsSync(defaultFilePath)) {
|
|
14
|
+
filePath = defaultFilePath;
|
|
15
|
+
} else {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
filePath = path.resolve(rootDir, filePath);
|
|
21
|
+
|
|
22
|
+
const configFile = fs.readFileSync(filePath, "utf8");
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const json = JSON.parse(configFile);
|
|
26
|
+
validateBunWorkspacesConfig(json);
|
|
27
|
+
return json as BunWorkspacesConfig;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Config file: "${filePath}" is not a valid JSON file: ${error}`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
};
|
package/src/internal/env.ts
CHANGED
|
@@ -1 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
const RUNTIME_MODE_VALUES = ["development", "production", "test"] as const;
|
|
2
|
+
|
|
3
|
+
export type RuntimeMode = "development" | "production" | "test";
|
|
4
|
+
|
|
5
|
+
const _RUNTIME_MODE: RuntimeMode = ((process.env
|
|
6
|
+
._BW_RUNTIME_MODE as RuntimeMode) ||
|
|
7
|
+
(process.env.NODE_ENV?.match(/test(ing)?/)
|
|
8
|
+
? "test"
|
|
9
|
+
: process.env.NODE_ENV === "development"
|
|
10
|
+
? "development"
|
|
11
|
+
: "production")) as RuntimeMode;
|
|
12
|
+
|
|
13
|
+
export const RUNTIME_MODE = RUNTIME_MODE_VALUES.includes(_RUNTIME_MODE)
|
|
14
|
+
? _RUNTIME_MODE
|
|
15
|
+
: "production";
|
|
16
|
+
|
|
17
|
+
if (RUNTIME_MODE !== _RUNTIME_MODE) {
|
|
18
|
+
console.error(
|
|
19
|
+
`Env var RUNTIME_MODE has an invalid value: "${_RUNTIME_MODE}". Defaulting to "${RUNTIME_MODE}". Accepted values: ${RUNTIME_MODE_VALUES.join(", ")}.`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const IS_TEST = RUNTIME_MODE === "test";
|
|
24
|
+
export const IS_PRODUCTION = RUNTIME_MODE === "production";
|
|
25
|
+
export const IS_DEVELOPMENT = RUNTIME_MODE === "development";
|