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.
Files changed (41) hide show
  1. package/README.md +32 -4
  2. package/bun.lock +576 -0
  3. package/package.json +13 -15
  4. package/src/cli/cli.ts +3 -8
  5. package/src/cli/globalOptions.ts +61 -23
  6. package/src/cli/projectCommands.ts +42 -41
  7. package/src/config/bunWorkspacesConfig.ts +62 -0
  8. package/src/config/configFile.ts +33 -0
  9. package/src/config/index.ts +7 -0
  10. package/src/internal/env.ts +25 -1
  11. package/src/internal/logger.ts +143 -19
  12. package/src/project/project.ts +24 -1
  13. package/src/workspaces/errors.ts +2 -0
  14. package/src/workspaces/findWorkspaces.ts +36 -8
  15. package/src/workspaces/index.ts +0 -1
  16. package/src/workspaces/packageJson.ts +1 -1
  17. package/src/workspaces/workspace.ts +2 -0
  18. package/.vscode/extensions.json +0 -12
  19. package/.vscode/settings.json +0 -23
  20. package/bun-workspaces-0.1.0-alpha-test-publish-2.tgz +0 -0
  21. package/eslint.config.mjs +0 -45
  22. package/ignore-me-CHANGELOG_TEMPLATE.md +0 -264
  23. package/ignore-me-test-projects/no-fail/applications/applicationA/package.json +0 -8
  24. package/ignore-me-test-projects/no-fail/applications/applicationB/package.json +0 -8
  25. package/ignore-me-test-projects/no-fail/libraries/libraryA/package.json +0 -8
  26. package/ignore-me-test-projects/no-fail/libraries/libraryB/package.json +0 -8
  27. package/ignore-me-test-projects/no-fail/libraries/nested/libraryC/package.json +0 -8
  28. package/ignore-me-test-projects/no-fail/package.json +0 -7
  29. package/ignore-me-test-projects/one-fail/applications/applicationA/package.json +0 -8
  30. package/ignore-me-test-projects/one-fail/applications/applicationB/package.json +0 -8
  31. package/ignore-me-test-projects/one-fail/libraries/libraryA/package.json +0 -8
  32. package/ignore-me-test-projects/one-fail/libraries/libraryB/package.json +0 -8
  33. package/ignore-me-test-projects/one-fail/libraries/nested/libraryC/package.json +0 -8
  34. package/ignore-me-test-projects/one-fail/package.json +0 -7
  35. package/ignore-me-test-projects/two-fail/applications/applicationA/package.json +0 -8
  36. package/ignore-me-test-projects/two-fail/applications/applicationB/package.json +0 -8
  37. package/ignore-me-test-projects/two-fail/libraries/libraryA/package.json +0 -8
  38. package/ignore-me-test-projects/two-fail/libraries/libraryB/package.json +0 -8
  39. package/ignore-me-test-projects/two-fail/libraries/nested/libraryC/package.json +0 -8
  40. package/ignore-me-test-projects/two-fail/package.json +0 -7
  41. 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.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.1.38",
11
+ "build": "1.2.22",
12
12
  "libraryConsumer": "^1.1.x"
13
13
  }
14
14
  },
15
15
  "scripts": {
16
- "cli": "NODE_ENV=production bun run bin/cli.js",
17
- "cli:dev": "NODE_ENV=development bun run bin/cli.js",
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.1.14",
25
- "@typescript-eslint/eslint-plugin": "^8.17.0",
26
- "@typescript-eslint/parser": "^8.17.0",
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.16.0",
29
- "eslint-plugin-import": "^2.31.0",
30
- "prettier": "^3.4.2",
31
- "typescript-eslint": "^8.17.0"
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.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.0.0"
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);
@@ -1,22 +1,48 @@
1
1
  import path from "path";
2
2
  import { type Command, Option } from "commander";
3
- import { logger } from "../internal/logger";
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: 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 defineGlobalOptions = (program: Command, defaultCwd: string) => {
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: logger.level as LogLevel,
31
- values: LOG_LEVELS,
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, defaultValue, param, values }]) => {
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(values?.length ? option.choices(values) : option);
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 = (options: CliGlobalOptions) => {
55
- logger.level = options.logLevel;
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
- return applyGlobalOptions(program.opts() as CliGlobalOptions);
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 listWorkspaces = ({
29
- program,
30
- project,
31
- printLines,
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
- lines.push("No workspaces found");
74
+ logger.info("No workspaces found");
76
75
  }
77
76
 
78
- printLines(...lines);
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
- lines.push("No scripts found");
124
+ logger.info("No scripts found");
130
125
  }
131
126
  }
132
127
 
133
- printLines(...lines);
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.findWorkspaceByName(workspaceName);
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
- printLines(
164
- ...(options.json
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
- printLines(
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
- printLines(
203
- ...(options.json
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 silent = logger.level === "silent";
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: silent ? "ignore" : "pipe",
294
- stderr: silent ? "ignore" : "pipe",
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
- commandLogger.info(new TextDecoder().decode(chunk).trim());
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
- commandLogger.error(new TextDecoder().decode(chunk).trim());
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
- logger.info(`${success ? "✅" : "❌"} ${workspaceName}: ${script}`);
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
- logger.info(message);
380
+ commandOutputLogger.info(message);
382
381
  process.exit(1);
383
382
  } else {
384
- logger.info(`${results.length} script${s} ran successfully`);
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
+ };
@@ -0,0 +1,7 @@
1
+ export {
2
+ validateBunWorkspacesConfig,
3
+ type BunWorkspacesConfig,
4
+ type CliConfig,
5
+ type ProjectConfig,
6
+ } from "./bunWorkspacesConfig";
7
+ export { loadConfigFile, DEFAULT_CONFIG_FILE_PATH } from "./configFile";
@@ -1 +1,25 @@
1
- export const IS_TEST = process.env.NODE_ENV === "test";
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";