bun-workspaces 1.0.0-alpha.8 → 1.0.0

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 (233) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +212 -19
  3. package/bin/cli.js +1 -1
  4. package/package.json +25 -9
  5. package/src/cli/commands/commandHandlerUtils.d.ts +45 -0
  6. package/src/cli/commands/commandHandlerUtils.mjs +81 -0
  7. package/src/cli/commands/commands.d.ts +10 -0
  8. package/src/cli/commands/commands.mjs +23 -0
  9. package/src/cli/commands/commandsConfig.d.ts +351 -0
  10. package/src/cli/commands/commandsConfig.mjs +183 -0
  11. package/src/cli/commands/handleSimpleCommands.d.ts +15 -0
  12. package/src/cli/commands/handleSimpleCommands.mjs +174 -0
  13. package/src/cli/commands/index.d.ts +3 -0
  14. package/src/cli/commands/index.mjs +3 -0
  15. package/src/cli/commands/runScript/handleRunScript.d.ts +3 -0
  16. package/src/cli/commands/runScript/handleRunScript.mjs +250 -0
  17. package/src/cli/commands/runScript/index.d.ts +2 -0
  18. package/src/cli/commands/runScript/index.mjs +2 -0
  19. package/src/cli/commands/runScript/output/index.d.ts +1 -0
  20. package/src/cli/commands/runScript/output/index.mjs +1 -0
  21. package/src/cli/commands/runScript/output/outputStyle.d.ts +8 -0
  22. package/src/cli/commands/runScript/output/outputStyle.mjs +17 -0
  23. package/src/cli/commands/runScript/output/renderGroupedOutput.d.ts +71 -0
  24. package/src/cli/commands/runScript/output/renderGroupedOutput.mjs +307 -0
  25. package/src/cli/commands/runScript/output/renderPlainOutput.d.ts +22 -0
  26. package/src/cli/commands/runScript/output/renderPlainOutput.mjs +43 -0
  27. package/src/cli/commands/runScript/output/sanitizeChunk.d.ts +4 -0
  28. package/src/cli/commands/runScript/output/sanitizeChunk.mjs +101 -0
  29. package/src/cli/createCli.d.ts +14 -8
  30. package/src/cli/createCli.mjs +94 -39
  31. package/src/cli/fatalErrorLogger.d.ts +1 -0
  32. package/src/cli/fatalErrorLogger.mjs +7 -0
  33. package/src/cli/globalOptions/globalOptions.d.ts +38 -2
  34. package/src/cli/globalOptions/globalOptions.mjs +96 -47
  35. package/src/cli/globalOptions/globalOptionsConfig.d.ts +37 -31
  36. package/src/cli/globalOptions/globalOptionsConfig.mjs +32 -30
  37. package/src/cli/globalOptions/index.mjs +1 -1
  38. package/src/cli/index.d.ts +3 -1
  39. package/src/cli/index.mjs +3 -2
  40. package/src/config/index.d.ts +3 -2
  41. package/src/config/index.mjs +3 -3
  42. package/src/config/rootConfig/errors.d.ts +1 -0
  43. package/src/config/rootConfig/errors.mjs +6 -0
  44. package/src/config/rootConfig/index.d.ts +5 -0
  45. package/src/config/rootConfig/index.mjs +5 -0
  46. package/src/config/rootConfig/loadRootConfig.d.ts +3 -0
  47. package/src/config/rootConfig/loadRootConfig.mjs +22 -0
  48. package/src/config/rootConfig/rootConfig.d.ts +17 -0
  49. package/src/config/rootConfig/rootConfig.mjs +43 -0
  50. package/src/config/rootConfig/rootConfigLocation.d.ts +2 -0
  51. package/src/config/rootConfig/rootConfigLocation.mjs +5 -0
  52. package/src/config/rootConfig/rootConfigSchema.d.ts +21 -0
  53. package/src/config/rootConfig/rootConfigSchema.mjs +24 -0
  54. package/src/config/userEnvVars/index.d.ts +1 -0
  55. package/src/config/userEnvVars/index.mjs +1 -0
  56. package/src/config/userEnvVars/userEnvVars.d.ts +13 -0
  57. package/src/config/userEnvVars/userEnvVars.mjs +10 -0
  58. package/src/config/util/ajvTypes.d.ts +10 -0
  59. package/src/config/util/ajvTypes.mjs +2 -0
  60. package/src/config/util/configLocation.d.ts +12 -0
  61. package/src/config/util/configLocation.mjs +11 -0
  62. package/src/config/util/index.d.ts +4 -0
  63. package/src/config/util/index.mjs +3 -0
  64. package/src/config/util/loadConfig.d.ts +16 -0
  65. package/src/config/util/loadConfig.mjs +118 -0
  66. package/src/config/util/validateConfig.d.ts +8 -0
  67. package/src/config/util/validateConfig.mjs +17 -0
  68. package/src/config/workspaceConfig/errors.d.ts +1 -0
  69. package/src/config/workspaceConfig/errors.mjs +6 -0
  70. package/src/config/workspaceConfig/index.d.ts +5 -0
  71. package/src/config/workspaceConfig/index.mjs +5 -0
  72. package/src/config/workspaceConfig/loadWorkspaceConfig.d.ts +3 -0
  73. package/src/config/workspaceConfig/loadWorkspaceConfig.mjs +25 -0
  74. package/src/config/workspaceConfig/workspaceConfig.d.ts +22 -0
  75. package/src/config/workspaceConfig/workspaceConfig.mjs +31 -0
  76. package/src/config/workspaceConfig/workspaceConfigLocation.d.ts +2 -0
  77. package/src/config/workspaceConfig/workspaceConfigLocation.mjs +5 -0
  78. package/src/config/workspaceConfig/workspaceConfigSchema.d.ts +25 -0
  79. package/src/config/workspaceConfig/workspaceConfigSchema.mjs +28 -0
  80. package/src/doctor/doctor.d.ts +35 -0
  81. package/src/doctor/doctor.mjs +52 -0
  82. package/src/doctor/index.d.ts +1 -0
  83. package/src/doctor/index.mjs +1 -0
  84. package/src/index.d.ts +37 -3
  85. package/src/index.mjs +16 -3
  86. package/src/internal/bun/bunLock.d.ts +20 -0
  87. package/src/internal/bun/bunLock.mjs +70 -0
  88. package/src/internal/bun/bunVersion.d.ts +21 -0
  89. package/src/internal/bun/bunVersion.mjs +43 -0
  90. package/src/internal/bun/index.d.ts +2 -0
  91. package/src/internal/bun/index.mjs +2 -0
  92. package/src/internal/core/error/error.d.ts +13 -0
  93. package/src/internal/core/error/error.mjs +36 -0
  94. package/src/internal/core/error/index.d.ts +1 -0
  95. package/src/internal/core/error/index.mjs +1 -0
  96. package/src/internal/core/index.d.ts +4 -0
  97. package/src/internal/core/index.mjs +4 -0
  98. package/src/internal/core/json/index.d.ts +2 -0
  99. package/src/internal/core/json/index.mjs +2 -0
  100. package/src/internal/core/json/json.d.ts +49 -0
  101. package/src/internal/core/json/json.mjs +12 -0
  102. package/src/internal/core/json/jsonc.d.ts +9 -0
  103. package/src/internal/core/json/jsonc.mjs +117 -0
  104. package/src/internal/core/language/array/index.d.ts +1 -0
  105. package/src/internal/core/language/array/index.mjs +1 -0
  106. package/src/internal/core/language/array/optionalArray.d.ts +15 -0
  107. package/src/internal/core/language/array/optionalArray.mjs +8 -0
  108. package/src/internal/core/language/asyncIterable/asyncIterableQueue.d.ts +16 -0
  109. package/src/internal/core/language/asyncIterable/asyncIterableQueue.mjs +81 -0
  110. package/src/internal/core/language/asyncIterable/index.d.ts +2 -0
  111. package/src/internal/core/language/asyncIterable/index.mjs +2 -0
  112. package/src/internal/core/language/asyncIterable/mergeAsyncIterables.d.ts +5 -0
  113. package/src/internal/core/language/asyncIterable/mergeAsyncIterables.mjs +27 -0
  114. package/src/internal/core/language/events/typedEventTarget.d.ts +50 -0
  115. package/src/internal/core/language/events/typedEventTarget.mjs +14 -0
  116. package/src/internal/core/language/index.d.ts +5 -0
  117. package/src/internal/core/language/index.mjs +5 -0
  118. package/src/internal/core/language/regex/index.d.ts +1 -0
  119. package/src/internal/core/language/regex/index.mjs +1 -0
  120. package/src/internal/{regex.d.ts → core/language/regex/regex.d.ts} +1 -0
  121. package/src/internal/core/language/regex/regex.mjs +10 -0
  122. package/src/internal/core/language/string/id.d.ts +1 -0
  123. package/src/internal/core/language/string/id.mjs +10 -0
  124. package/src/internal/core/language/string/index.d.ts +1 -0
  125. package/src/internal/core/language/string/index.mjs +1 -0
  126. package/src/internal/core/language/string/utf/eastAsianWidth.d.ts +16 -0
  127. package/src/internal/core/language/string/utf/eastAsianWidth.mjs +326 -0
  128. package/src/internal/core/language/string/utf/visibleLength.d.ts +5 -0
  129. package/src/internal/core/language/string/utf/visibleLength.mjs +29 -0
  130. package/src/internal/core/language/types/index.d.ts +2 -0
  131. package/src/internal/core/language/types/index.mjs +1 -0
  132. package/src/internal/core/language/types/typeof.d.ts +102 -0
  133. package/src/internal/core/language/types/typeof.mjs +123 -0
  134. package/src/internal/core/language/types/types.d.ts +14 -0
  135. package/src/internal/core/language/types/types.mjs +2 -0
  136. package/src/internal/{env.d.ts → core/runtime/env.d.ts} +1 -0
  137. package/src/internal/core/runtime/env.mjs +36 -0
  138. package/src/internal/core/runtime/index.d.ts +5 -0
  139. package/src/internal/core/runtime/index.mjs +5 -0
  140. package/src/internal/core/runtime/onExit.d.ts +4 -0
  141. package/src/internal/core/runtime/onExit.mjs +54 -0
  142. package/src/internal/core/runtime/os.d.ts +4 -0
  143. package/src/internal/core/runtime/os.mjs +7 -0
  144. package/src/internal/core/runtime/tempFile.d.ts +20 -0
  145. package/src/internal/core/runtime/tempFile.mjs +87 -0
  146. package/src/internal/core/runtime/terminal.d.ts +1 -0
  147. package/src/internal/core/runtime/terminal.mjs +4 -0
  148. package/src/internal/generated/ajv/validateRootConfig.mjs +1 -0
  149. package/src/internal/generated/ajv/validateWorkspaceConfig.mjs +1 -0
  150. package/src/internal/logger/index.d.ts +1 -0
  151. package/src/internal/logger/index.mjs +1 -0
  152. package/src/internal/logger/logger.d.ts +39 -0
  153. package/src/internal/logger/logger.mjs +116 -0
  154. package/src/internal/version.d.ts +1 -0
  155. package/src/internal/version.mjs +6 -0
  156. package/src/project/errors.d.ts +5 -1
  157. package/src/project/errors.mjs +10 -3
  158. package/src/project/implementations/fileSystemProject.d.ts +148 -0
  159. package/src/project/implementations/fileSystemProject.mjs +455 -0
  160. package/src/project/implementations/memoryProject.d.ts +41 -0
  161. package/src/project/implementations/memoryProject.mjs +148 -0
  162. package/src/project/implementations/projectBase.d.ts +35 -0
  163. package/src/project/implementations/projectBase.mjs +197 -0
  164. package/src/project/index.d.ts +5 -1
  165. package/src/project/index.mjs +4 -2
  166. package/src/project/project.d.ts +72 -28
  167. package/src/project/project.mjs +6 -72
  168. package/src/runScript/index.d.ts +7 -0
  169. package/src/runScript/index.mjs +7 -0
  170. package/src/runScript/output/index.d.ts +3 -0
  171. package/src/runScript/output/index.mjs +2 -0
  172. package/src/runScript/output/multiProcessOutput.d.ts +14 -0
  173. package/src/runScript/output/multiProcessOutput.mjs +21 -0
  174. package/src/runScript/output/outputStream.d.ts +1 -0
  175. package/src/runScript/output/outputStream.mjs +1 -0
  176. package/src/runScript/output/processOutput.d.ts +33 -0
  177. package/src/runScript/output/processOutput.mjs +124 -0
  178. package/src/runScript/parallel.d.ts +15 -0
  179. package/src/runScript/parallel.mjs +56 -0
  180. package/src/runScript/recursion.d.ts +4 -0
  181. package/src/runScript/recursion.mjs +17 -0
  182. package/src/runScript/runScript.d.ts +45 -0
  183. package/src/runScript/runScript.mjs +89 -0
  184. package/src/runScript/runScripts.d.ts +65 -0
  185. package/src/runScript/runScripts.mjs +263 -0
  186. package/src/runScript/scriptCommand.d.ts +33 -0
  187. package/src/runScript/scriptCommand.mjs +19 -0
  188. package/src/runScript/scriptExecution.d.ts +9 -0
  189. package/src/runScript/scriptExecution.mjs +50 -0
  190. package/src/runScript/scriptRuntimeMetadata.d.ts +73 -0
  191. package/src/runScript/scriptRuntimeMetadata.mjs +61 -0
  192. package/src/runScript/scriptShellOption.d.ts +8 -0
  193. package/src/runScript/scriptShellOption.mjs +39 -0
  194. package/src/runScript/subprocesses.d.ts +11 -0
  195. package/src/runScript/subprocesses.mjs +34 -0
  196. package/src/workspaces/dependencyGraph/cycles.d.ts +9 -0
  197. package/src/workspaces/dependencyGraph/cycles.mjs +91 -0
  198. package/src/workspaces/dependencyGraph/index.d.ts +2 -0
  199. package/src/workspaces/dependencyGraph/index.mjs +2 -0
  200. package/src/workspaces/dependencyGraph/resolveDependencies.d.ts +18 -0
  201. package/src/workspaces/dependencyGraph/resolveDependencies.mjs +52 -0
  202. package/src/workspaces/errors.d.ts +13 -1
  203. package/src/workspaces/errors.mjs +18 -3
  204. package/src/workspaces/findWorkspaces.d.ts +20 -13
  205. package/src/workspaces/findWorkspaces.mjs +208 -57
  206. package/src/workspaces/index.d.ts +4 -3
  207. package/src/workspaces/index.mjs +3 -2
  208. package/src/workspaces/packageJson.d.ts +28 -5
  209. package/src/workspaces/packageJson.mjs +177 -54
  210. package/src/workspaces/workspace.d.ts +19 -13
  211. package/src/workspaces/workspace.mjs +2 -0
  212. package/src/workspaces/workspacePattern.d.ts +21 -0
  213. package/src/workspaces/workspacePattern.mjs +104 -0
  214. package/src/cli/projectCommands/index.d.ts +0 -2
  215. package/src/cli/projectCommands/index.mjs +0 -2
  216. package/src/cli/projectCommands/projectCommandHandlers.d.ts +0 -8
  217. package/src/cli/projectCommands/projectCommandHandlers.mjs +0 -180
  218. package/src/cli/projectCommands/projectCommandsConfig.d.ts +0 -191
  219. package/src/cli/projectCommands/projectCommandsConfig.mjs +0 -100
  220. package/src/config/bunWorkspacesConfig.d.ts +0 -13
  221. package/src/config/bunWorkspacesConfig.mjs +0 -18
  222. package/src/config/configFile.d.ts +0 -3
  223. package/src/config/configFile.mjs +0 -21
  224. package/src/internal/bunVersion.d.ts +0 -14
  225. package/src/internal/bunVersion.mjs +0 -8
  226. package/src/internal/env.mjs +0 -15
  227. package/src/internal/error.d.ts +0 -7
  228. package/src/internal/error.mjs +0 -26
  229. package/src/internal/logger.d.ts +0 -21
  230. package/src/internal/logger.mjs +0 -85
  231. package/src/internal/regex.mjs +0 -3
  232. package/src/project/scriptCommand.d.ts +0 -15
  233. package/src/project/scriptCommand.mjs +0 -18
@@ -1,66 +1,217 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { logger } from "../internal/logger.mjs";
4
- import { ERRORS } from "./errors.mjs";
5
- import { resolvePackageJsonContent, resolvePackageJsonPath, scanWorkspaceGlob } from "./packageJson.mjs";
6
- const validatePattern = (pattern)=>{
7
- if (pattern.startsWith("!")) {
8
- logger.warn(`Negation patterns are not supported by Bun workspaces: ${JSON.stringify(pattern)}`);
9
- return false;
10
- }
11
- return true;
3
+ import bun from "bun";
4
+ import {
5
+ createDefaultWorkspaceConfig,
6
+ loadWorkspaceConfig,
7
+ } from "../config/index.mjs";
8
+ import { BUN_LOCK_ERRORS, readBunLockfile } from "../internal/bun/index.mjs";
9
+ import { BunWorkspacesError } from "../internal/core/index.mjs";
10
+ import { logger } from "../internal/logger/logger.mjs";
11
+ import { resolveWorkspaceDependencies } from "./dependencyGraph/resolveDependencies.mjs";
12
+ import { WORKSPACE_ERRORS } from "./errors.mjs";
13
+ import {
14
+ resolvePackageJsonContent,
15
+ resolvePackageJsonPath,
16
+ } from "./packageJson.mjs"; // CONCATENATED MODULE: external "fs"
17
+ // CONCATENATED MODULE: external "path"
18
+ // CONCATENATED MODULE: external "bun"
19
+ // CONCATENATED MODULE: external "../config/index.mjs"
20
+ // CONCATENATED MODULE: external "../internal/bun/index.mjs"
21
+ // CONCATENATED MODULE: external "../internal/core/index.mjs"
22
+ // CONCATENATED MODULE: external "../internal/logger/logger.mjs"
23
+ // CONCATENATED MODULE: external "./dependencyGraph/resolveDependencies.mjs"
24
+ // CONCATENATED MODULE: external "./errors.mjs"
25
+ // CONCATENATED MODULE: external "./packageJson.mjs"
26
+ // CONCATENATED MODULE: ./src/workspaces/findWorkspaces.ts
27
+
28
+ const sortWorkspaces = (workspaces) =>
29
+ [...workspaces]
30
+ .sort((a, b) =>
31
+ a.isRoot
32
+ ? -1
33
+ : a.path.localeCompare(b.path) || a.name.localeCompare(b.name),
34
+ )
35
+ .reduce((acc, workspace, i, arr) => {
36
+ const previousWorkspace = arr[i - 1];
37
+ if (previousWorkspace && previousWorkspace.path === workspace.path) {
38
+ return acc;
39
+ }
40
+ return [...acc, workspace];
41
+ }, []);
42
+ const getRootPackageJsonWorkspaceData = ({ rootDirectory }) => {
43
+ const packageJsonPath = path.join(rootDirectory, "package.json");
44
+ if (!fs.existsSync(packageJsonPath)) {
45
+ throw new WORKSPACE_ERRORS.PackageNotFound(
46
+ `No package.json found for project root at ${packageJsonPath}`,
47
+ );
48
+ }
49
+ const { workspaces, catalog, catalogs } = resolvePackageJsonContent(
50
+ packageJsonPath,
51
+ rootDirectory,
52
+ ["workspaces"],
53
+ );
54
+ return {
55
+ workspaceGlobs: workspaces ?? [],
56
+ catalog,
57
+ catalogs,
58
+ };
12
59
  };
13
- const validateWorkspace = (workspace, workspaces)=>{
14
- if (workspaces.find((ws)=>ws.path === workspace.path)) return false;
15
- if (workspaces.find((ws)=>ws.name === workspace.name)) throw new ERRORS.DuplicateWorkspaceName(`Duplicate workspace name found: ${JSON.stringify(workspace.name)}`);
16
- return true;
60
+ const validateWorkspace = (workspace, workspaces) => {
61
+ if (workspaces.find((ws) => ws.path === workspace.path)) {
62
+ return false;
63
+ }
64
+ if (workspaces.find((ws) => ws.name === workspace.name)) {
65
+ throw new WORKSPACE_ERRORS.DuplicateWorkspaceName(
66
+ `Duplicate workspace name found: ${JSON.stringify(workspace.name)}`,
67
+ );
68
+ }
69
+ return true;
17
70
  };
18
- const findWorkspaces = ({ rootDir, workspaceGlobs, workspaceAliases })=>{
19
- rootDir = path.resolve(rootDir);
20
- const workspaces = [];
21
- for (const pattern of workspaceGlobs)if (validatePattern(pattern)) for (const item of scanWorkspaceGlob(pattern, rootDir)){
22
- const packageJsonPath = resolvePackageJsonPath(item);
23
- if (packageJsonPath) {
24
- const packageJsonContent = resolvePackageJsonContent(packageJsonPath, rootDir, [
25
- "name",
26
- "scripts"
27
- ]);
28
- const workspace = {
29
- name: packageJsonContent.name ?? "",
30
- matchPattern: pattern,
31
- path: path.relative(rootDir, path.dirname(packageJsonPath)),
32
- packageJson: packageJsonContent,
33
- aliases: Object.entries(workspaceAliases ?? {}).filter(([_, value])=>value === packageJsonContent.name).map(([key])=>key)
34
- };
35
- if (validateWorkspace(workspace, workspaces)) workspaces.push(workspace);
71
+ const findWorkspaces = ({
72
+ rootDirectory,
73
+ workspaceGlobs: _workspaceGlobs,
74
+ includeRootWorkspace = false,
75
+ }) => {
76
+ rootDirectory = path.resolve(rootDirectory);
77
+ logger.debug(`Finding workspaces in ${rootDirectory}`);
78
+ let workspaces = [];
79
+ const workspaceMap = {};
80
+ logger.debug(`Reading bun.lock`);
81
+ const bunLock = readBunLockfile(rootDirectory);
82
+ if (bunLock instanceof BunWorkspacesError) {
83
+ if (bunLock instanceof BUN_LOCK_ERRORS.BunLockNotFound) {
84
+ bunLock.message =
85
+ `No bun.lock found at ${rootDirectory}. Check that this is the directory of your project and that you've ran 'bun install'.` +
86
+ " If you have ran 'bun install', you may simply have no workspaces or dependencies in your project.";
87
+ }
88
+ throw bunLock;
89
+ }
90
+ const { workspaceGlobs, catalog, catalogs } = _workspaceGlobs
91
+ ? {
92
+ workspaceGlobs: _workspaceGlobs,
93
+ catalog: {},
94
+ catalogs: {},
95
+ }
96
+ : getRootPackageJsonWorkspaceData({
97
+ rootDirectory,
98
+ });
99
+ const bunCatalogs = {
100
+ defaultCatalog: catalog,
101
+ namedCatalogs: catalogs,
102
+ };
103
+ let rootWorkspace;
104
+ const workspaceAliases = {};
105
+ for (const workspacePath of Object.keys(bunLock.workspaces).map((p) =>
106
+ path.join(rootDirectory, p),
107
+ )) {
108
+ const packageJsonPath = resolvePackageJsonPath(workspacePath);
109
+ if (packageJsonPath) {
110
+ const packageJsonContent = resolvePackageJsonContent(
111
+ packageJsonPath,
112
+ rootDirectory,
113
+ ["name", "scripts"],
114
+ );
115
+ const workspaceConfig = loadWorkspaceConfig(
116
+ path.dirname(packageJsonPath),
117
+ );
118
+ if (workspaceConfig) {
119
+ for (const alias of workspaceConfig.aliases) {
120
+ workspaceAliases[alias] = packageJsonContent.name;
121
+ }
122
+ }
123
+ const relativePath = path.relative(
124
+ rootDirectory,
125
+ path.dirname(packageJsonPath),
126
+ );
127
+ const matchPattern =
128
+ workspaceGlobs.find((glob) => new bun.Glob(glob).match(relativePath)) ??
129
+ "";
130
+ const isRootWorkspace = workspacePath === rootDirectory;
131
+ if (!matchPattern && !isRootWorkspace) {
132
+ logger.debug(`No match pattern found for ${relativePath}`);
133
+ }
134
+ const workspace = {
135
+ name: packageJsonContent.name ?? "",
136
+ isRoot: isRootWorkspace,
137
+ matchPattern: workspacePath === rootDirectory ? "" : matchPattern,
138
+ path: path.relative(rootDirectory, path.dirname(packageJsonPath)),
139
+ scripts: Object.keys(packageJsonContent.scripts ?? {}).sort(),
140
+ aliases: [
141
+ ...new Set(
142
+ Object.entries(workspaceAliases ?? {})
143
+ .filter(([_, value]) => value === packageJsonContent.name)
144
+ .map(([key]) => key)
145
+ .concat(workspaceConfig?.aliases ?? []),
146
+ ),
147
+ ],
148
+ dependencies: [],
149
+ dependents: [],
150
+ };
151
+ if (workspace.isRoot) {
152
+ logger.debug(`Found root workspace: ${workspace.name}`);
153
+ rootWorkspace = workspace;
154
+ }
155
+ if (validateWorkspace(workspace, workspaces)) {
156
+ if (!workspace.isRoot || includeRootWorkspace) {
157
+ workspaces.push(workspace);
36
158
  }
159
+ workspaceMap[workspace.name] = {
160
+ workspace,
161
+ config: workspaceConfig ?? createDefaultWorkspaceConfig(),
162
+ packageJson: packageJsonContent,
163
+ };
164
+ }
37
165
  }
38
- workspaces.sort((a, b)=>a.name.localeCompare(b.name) || a.path.localeCompare(b.path));
39
- return {
40
- workspaces
41
- };
166
+ }
167
+ if (!rootWorkspace) {
168
+ throw new WORKSPACE_ERRORS.RootWorkspaceNotFound("No root workspace found");
169
+ }
170
+ workspaces = sortWorkspaces(
171
+ resolveWorkspaceDependencies(
172
+ workspaceMap,
173
+ includeRootWorkspace,
174
+ bunCatalogs,
175
+ ),
176
+ );
177
+ validateWorkspaceAliases(workspaces, workspaceAliases, rootWorkspace.name);
178
+ logger.debug(
179
+ `Found ${workspaces.length} workspaces: ${workspaces.map((ws) => ws.name).join(", ")}`,
180
+ );
181
+ return {
182
+ workspaces,
183
+ workspaceMap,
184
+ rootWorkspace,
185
+ };
42
186
  };
43
- const validateWorkspaceAliases = (workspaces, workspaceAliases)=>{
44
- for (const [alias, name] of Object.entries(workspaceAliases ?? {})){
45
- if (workspaces.find((ws)=>ws.name === alias)) throw new ERRORS.AliasConflict(`Alias ${JSON.stringify(alias)} conflicts with workspace name ${JSON.stringify(name)}`);
46
- if (!workspaces.find((ws)=>ws.name === name)) throw new ERRORS.AliasedWorkspaceNotFound(`Workspace ${JSON.stringify(name)} was aliased by ${JSON.stringify(alias)} but was not found`);
187
+ const validateWorkspaceAliases = (
188
+ workspaces,
189
+ workspaceAliases,
190
+ rootWorkspaceName,
191
+ ) => {
192
+ for (const [alias, name] of Object.entries(workspaceAliases ?? {})) {
193
+ if (workspaces.find((ws) => ws.name === alias)) {
194
+ throw new WORKSPACE_ERRORS.AliasConflict(
195
+ `Alias ${JSON.stringify(alias)} conflicts with workspace name ${JSON.stringify(name)}`,
196
+ );
47
197
  }
198
+ const workspaceWithDuplicateAlias = workspaces.find(
199
+ (ws) => ws.name !== name && ws.aliases.includes(alias),
200
+ );
201
+ if (workspaceWithDuplicateAlias) {
202
+ throw new WORKSPACE_ERRORS.AliasConflict(
203
+ `Workspaces ${JSON.stringify(name)} and ${JSON.stringify(workspaceWithDuplicateAlias.name)} have the same alias ${JSON.stringify(alias)}`,
204
+ );
205
+ }
206
+ if (
207
+ !workspaces.find((ws) => ws.name === name) &&
208
+ name !== rootWorkspaceName
209
+ ) {
210
+ throw new WORKSPACE_ERRORS.AliasedWorkspaceNotFound(
211
+ `Workspace ${JSON.stringify(name)} was aliased by ${JSON.stringify(alias)} but was not found`,
212
+ );
213
+ }
214
+ }
48
215
  };
49
- const findWorkspacesFromPackage = ({ rootDir, workspaceAliases })=>{
50
- const packageJsonPath = path.join(rootDir, "package.json");
51
- if (!fs.existsSync(packageJsonPath)) throw new ERRORS.PackageNotFound(`No package.json found at ${packageJsonPath}`);
52
- const packageJson = resolvePackageJsonContent(packageJsonPath, rootDir, [
53
- "workspaces"
54
- ]);
55
- const result = findWorkspaces({
56
- rootDir,
57
- workspaceGlobs: packageJson.workspaces ?? [],
58
- workspaceAliases
59
- });
60
- validateWorkspaceAliases(result.workspaces, workspaceAliases);
61
- return {
62
- ...result,
63
- name: packageJson.name ?? ""
64
- };
65
- };
66
- export { findWorkspaces, findWorkspacesFromPackage, validateWorkspaceAliases };
216
+
217
+ export { findWorkspaces, sortWorkspaces, validateWorkspaceAliases };
@@ -1,3 +1,4 @@
1
- export { findWorkspaces, findWorkspacesFromPackage, type FindWorkspacesOptions, } from "./findWorkspaces";
2
- export { type Workspace } from "./workspace";
3
- export type { ResolvedPackageJsonContent } from "./packageJson";
1
+ export * from "./findWorkspaces";
2
+ export * from "./packageJson";
3
+ export * from "./errors";
4
+ export type * from "./workspace";
@@ -1,2 +1,3 @@
1
- import { findWorkspaces, findWorkspacesFromPackage } from "./findWorkspaces.mjs";
2
- export { findWorkspaces, findWorkspacesFromPackage };
1
+ export * from "./findWorkspaces.mjs";
2
+ export * from "./packageJson.mjs";
3
+ export * from "./errors.mjs"; // CONCATENATED MODULE: ./src/workspaces/index.ts
@@ -1,8 +1,31 @@
1
1
  export declare const resolvePackageJsonPath: (directoryItem: string) => string;
2
+ export type BunCatalog = Record<string, string>;
3
+ export type BunCatalogSet = {
4
+ defaultCatalog: BunCatalog;
5
+ namedCatalogs: Record<string, BunCatalog>;
6
+ };
2
7
  export type ResolvedPackageJsonContent = {
3
- name: string;
4
- workspaces: string[];
5
- scripts: Record<string, string>;
8
+ name: string;
9
+ workspaces: string[];
10
+ catalog: BunCatalog;
11
+ catalogs: Record<string, BunCatalog>;
12
+ scripts: Record<string, string>;
13
+ dependencies: Record<string, string>;
14
+ devDependencies: Record<string, string>;
15
+ peerDependencies: Record<string, string>;
16
+ optionalDependencies: Record<string, string>;
6
17
  } & Record<string, unknown>;
7
- export declare const scanWorkspaceGlob: (pattern: string, rootDir: string) => Generator<string, void, void>;
8
- export declare const resolvePackageJsonContent: (packageJsonPath: string, rootDir: string, validations: ("workspaces" | "name" | "scripts")[]) => ResolvedPackageJsonContent;
18
+ /**
19
+ * Resolve a `catalog:` or `catalog:name` version reference for a given package name.
20
+ * Returns the resolved version string, or null if the catalog or package is not found.
21
+ */
22
+ export declare const resolveCatalogDependencyVersion: (
23
+ packageName: string,
24
+ catalogRef: string,
25
+ catalogs: BunCatalogSet,
26
+ ) => string | null;
27
+ export declare const resolvePackageJsonContent: (
28
+ packageJsonPath: string,
29
+ rootDirectory: string,
30
+ validations: ("workspaces" | "name" | "scripts")[],
31
+ ) => ResolvedPackageJsonContent;
@@ -1,65 +1,188 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { Glob } from "glob";
4
- import { logger } from "../internal/logger.mjs";
5
- import { ERRORS } from "./errors.mjs";
6
- const resolvePackageJsonPath = (directoryItem)=>{
7
- if ("package.json" === path.basename(directoryItem)) return directoryItem;
8
- if (fs.existsSync(path.join(directoryItem, "package.json"))) return path.join(directoryItem, "package.json");
9
- return "";
3
+ import { isJSONObject } from "../internal/core/index.mjs";
4
+ import { logger } from "../internal/logger/index.mjs";
5
+ import { WORKSPACE_ERRORS } from "./errors.mjs"; // CONCATENATED MODULE: external "fs"
6
+ // CONCATENATED MODULE: external "path"
7
+ // CONCATENATED MODULE: external "../internal/core/index.mjs"
8
+ // CONCATENATED MODULE: external "../internal/logger/index.mjs"
9
+ // CONCATENATED MODULE: external "./errors.mjs"
10
+ // CONCATENATED MODULE: ./src/workspaces/packageJson.ts
11
+
12
+ const resolvePackageJsonPath = (directoryItem) => {
13
+ if (path.basename(directoryItem) === "package.json") {
14
+ return directoryItem;
15
+ }
16
+ if (fs.existsSync(path.join(directoryItem, "package.json"))) {
17
+ return path.join(directoryItem, "package.json");
18
+ }
19
+ return "";
10
20
  };
11
- const scanWorkspaceGlob = (pattern, rootDir)=>new Glob(pattern, {
12
- absolute: true,
13
- cwd: rootDir
14
- }).iterateSync();
15
- const validateJsonRoot = (json)=>{
16
- if (!json || "object" != typeof json || Array.isArray(json)) throw new ERRORS.InvalidPackageJson(`Expected package.json to be an object, got ${typeof json}`);
21
+ const validateJsonRoot = (json) => {
22
+ if (!json || typeof json !== "object" || Array.isArray(json)) {
23
+ throw new WORKSPACE_ERRORS.InvalidPackageJson(
24
+ `Expected package.json to be an object, got ${typeof json}`,
25
+ );
26
+ }
17
27
  };
18
- const validateName = (json)=>{
19
- if ("string" != typeof json.name) throw new ERRORS.NoWorkspaceName(`Expected package.json to have a string "name" field${void 0 !== json.name ? ` (Received ${json.name})` : ""}`);
20
- if (!json.name.trim()) throw new ERRORS.NoWorkspaceName('Expected package.json to have a non-empty "name" field');
21
- if (json.name.includes("*")) throw new ERRORS.InvalidWorkspaceName(`Package name cannot contain the character '*' (workspace: "${json.name}")`);
22
- return json.name;
28
+ const validateName = (json) => {
29
+ if (typeof json.name !== "string") {
30
+ throw new WORKSPACE_ERRORS.NoWorkspaceName(
31
+ `Expected package.json to have a string "name" field${json.name !== undefined ? ` (Received ${json.name})` : ""}`,
32
+ );
33
+ }
34
+ if (!json.name.trim()) {
35
+ throw new WORKSPACE_ERRORS.NoWorkspaceName(
36
+ `Expected package.json to have a non-empty "name" field`,
37
+ );
38
+ }
39
+ if (json.name.includes("*")) {
40
+ throw new WORKSPACE_ERRORS.InvalidWorkspaceName(
41
+ `Package name cannot contain the character '*' (workspace: "${json.name}")`,
42
+ );
43
+ }
44
+ return json.name;
23
45
  };
24
- const validateWorkspacePattern = (workspacePattern, rootDir)=>{
25
- if ("string" != typeof workspacePattern) throw new ERRORS.InvalidWorkspacePattern(`Expected workspace pattern to be a string, got ${typeof workspacePattern}`);
26
- if (!workspacePattern.trim()) return false;
27
- const absolutePattern = path.resolve(rootDir, workspacePattern);
28
- if (!absolutePattern.startsWith(rootDir)) throw new ERRORS.InvalidWorkspacePattern(`Cannot resolve workspace pattern outside of root directory ${rootDir}: ${absolutePattern}`);
29
- return true;
46
+ const validateWorkspacePattern = (workspacePattern, rootDirectory) => {
47
+ if (typeof workspacePattern !== "string") {
48
+ throw new WORKSPACE_ERRORS.InvalidWorkspacePattern(
49
+ `Expected workspace pattern to be a string, got ${typeof workspacePattern}`,
50
+ );
51
+ }
52
+ if (!workspacePattern.trim()) {
53
+ return false;
54
+ }
55
+ const absolutePattern = path.resolve(rootDirectory, workspacePattern);
56
+ if (!absolutePattern.startsWith(rootDirectory)) {
57
+ throw new WORKSPACE_ERRORS.InvalidWorkspacePattern(
58
+ `Cannot resolve workspace pattern outside of root directory ${rootDirectory}: ${absolutePattern}`,
59
+ );
60
+ }
61
+ return true;
30
62
  };
31
- const validateWorkspacePatterns = (json, rootDir)=>{
32
- const workspaces = [];
33
- if (json.workspaces) {
34
- if (!Array.isArray(json.workspaces)) throw new ERRORS.InvalidWorkspaces('Expected package.json to have an array "workspaces" field');
35
- for (const workspacePattern of json.workspaces)if (validateWorkspacePattern(workspacePattern, rootDir)) workspaces.push(workspacePattern);
36
- }
37
- return workspaces;
63
+ const parseCatalogMap = (raw) => {
64
+ if (!isJSONObject(raw)) return {};
65
+ return Object.fromEntries(
66
+ Object.entries(raw).filter(([, value]) => typeof value === "string"),
67
+ );
38
68
  };
39
- const validateScripts = (json)=>{
40
- if (json.scripts && ("object" != typeof json.scripts || Array.isArray(json.scripts))) throw new ERRORS.InvalidScripts('Expected package.json to have an object "scripts" field');
41
- if (json.scripts) {
42
- for (const value of Object.values(json.scripts))if ("string" != typeof value) throw new ERRORS.InvalidScripts(`Expected workspace "${json.name}" script "${json.scripts}" to be a string, got ${typeof value}`);
69
+ const validateWorkspacePatterns = (json, rootDirectory) => {
70
+ const workspaces = [];
71
+ let catalog = {};
72
+ const catalogs = {};
73
+ if (json.workspaces) {
74
+ let source = "array";
75
+ let rawWorkspaces = [];
76
+ if (isJSONObject(json.workspaces)) {
77
+ source = "catalogObject";
78
+ rawWorkspaces = json.workspaces?.packages;
79
+ catalog = parseCatalogMap(json.workspaces.catalog);
80
+ if (isJSONObject(json.workspaces.catalogs)) {
81
+ for (const [name, value] of Object.entries(json.workspaces.catalogs)) {
82
+ catalogs[name] = parseCatalogMap(value);
83
+ }
84
+ }
85
+ } else {
86
+ source = "array";
87
+ rawWorkspaces = json.workspaces;
88
+ }
89
+ if (!Array.isArray(rawWorkspaces)) {
90
+ throw new WORKSPACE_ERRORS.InvalidWorkspaces(
91
+ `Expected package.json "workspaces${source === "catalogObject" ? ".packages" : ""}" to be an array`,
92
+ );
93
+ }
94
+ for (const workspacePattern of rawWorkspaces) {
95
+ if (validateWorkspacePattern(workspacePattern, rootDirectory)) {
96
+ workspaces.push(workspacePattern);
97
+ }
43
98
  }
44
- return {
45
- ...json.scripts
46
- };
99
+ }
100
+ return {
101
+ workspaces,
102
+ catalog,
103
+ catalogs,
104
+ };
47
105
  };
48
- const resolvePackageJsonContent = (packageJsonPath, rootDir, validations)=>{
49
- rootDir = path.resolve(rootDir);
50
- let json = {};
51
- try {
52
- json = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
53
- } catch (error) {
54
- logger.error(error);
55
- throw new ERRORS.InvalidPackageJson(`Failed to read and parse package.json at ${packageJsonPath}: ${error.message}`);
106
+ const validateScripts = (json) => {
107
+ if (
108
+ json.scripts &&
109
+ (typeof json.scripts !== "object" || Array.isArray(json.scripts))
110
+ ) {
111
+ throw new WORKSPACE_ERRORS.InvalidScripts(
112
+ `Expected package.json to have an object "scripts" field`,
113
+ );
114
+ }
115
+ if (json.scripts) {
116
+ for (const value of Object.values(json.scripts)) {
117
+ if (typeof value !== "string") {
118
+ throw new WORKSPACE_ERRORS.InvalidScripts(
119
+ `Expected workspace "${json.name}" script "${json.scripts}" to be a string, got ${typeof value}`,
120
+ );
121
+ }
56
122
  }
57
- validateJsonRoot(json);
58
- return {
59
- ...json,
60
- name: validations.includes("name") ? validateName(json) : json.name ?? "",
61
- workspaces: validations.includes("workspaces") ? validateWorkspacePatterns(json, rootDir) : json?.workspaces ?? [],
62
- scripts: validations.includes("scripts") ? validateScripts(json) : json.scripts ?? {}
63
- };
123
+ }
124
+ return {
125
+ ...json.scripts,
126
+ };
127
+ };
128
+ /**
129
+ * Resolve a `catalog:` or `catalog:name` version reference for a given package name.
130
+ * Returns the resolved version string, or null if the catalog or package is not found.
131
+ */ const resolveCatalogDependencyVersion = (
132
+ packageName,
133
+ catalogRef,
134
+ catalogs,
135
+ ) => {
136
+ if (!catalogRef.startsWith("catalog:")) return null;
137
+ const catalogName = catalogRef.slice("catalog:".length);
138
+ if (!catalogName) {
139
+ return catalogs.defaultCatalog[packageName] ?? null;
140
+ }
141
+ return catalogs.namedCatalogs[catalogName]?.[packageName] ?? null;
142
+ };
143
+ const resolvePackageJsonContent = (
144
+ packageJsonPath,
145
+ rootDirectory,
146
+ validations,
147
+ ) => {
148
+ rootDirectory = path.resolve(rootDirectory);
149
+ let json = {};
150
+ try {
151
+ json = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
152
+ } catch (error) {
153
+ logger.error(error);
154
+ throw new WORKSPACE_ERRORS.InvalidPackageJson(
155
+ `Failed to read and parse package.json at ${packageJsonPath}: ${error.message}`,
156
+ );
157
+ }
158
+ validateJsonRoot(json);
159
+ const { workspaces, catalog, catalogs } = validations.includes("workspaces")
160
+ ? validateWorkspacePatterns(json, rootDirectory)
161
+ : {
162
+ workspaces: json?.workspaces ?? [],
163
+ catalog: {},
164
+ catalogs: {},
165
+ };
166
+ return {
167
+ ...json,
168
+ // Dependency data types are validated by bun install
169
+ // TODO investigate whether we need to validate any of these fields in the first place
170
+ dependencies: json.dependencies ?? {},
171
+ devDependencies: json.devDependencies ?? {},
172
+ peerDependencies: json.peerDependencies ?? {},
173
+ optionalDependencies: json.optionalDependencies ?? {},
174
+ name: validations.includes("name") ? validateName(json) : (json.name ?? ""),
175
+ workspaces,
176
+ catalog,
177
+ catalogs,
178
+ scripts: validations.includes("scripts")
179
+ ? validateScripts(json)
180
+ : (json.scripts ?? {}),
181
+ };
182
+ };
183
+
184
+ export {
185
+ resolveCatalogDependencyVersion,
186
+ resolvePackageJsonContent,
187
+ resolvePackageJsonPath,
64
188
  };
65
- export { resolvePackageJsonContent, resolvePackageJsonPath, scanWorkspaceGlob };
@@ -1,13 +1,19 @@
1
- import type { ResolvedPackageJsonContent } from "./packageJson";
2
- export interface Workspace {
3
- /** The name of the workspace from its `package.json` */
4
- name: string;
5
- /** The relative path to the workspace from the root `package.json` */
6
- path: string;
7
- /** The pattern from `"workspaces"` in the root `package.json`that this workspace was matched from*/
8
- matchPattern: string;
9
- /** The contents of the workspace's package.json, with `"workspaces"` and `"scripts"` resolved */
10
- packageJson: ResolvedPackageJsonContent;
11
- /** Aliases assigned to the workspace via the `"workspaceAliases"` field in the config */
12
- aliases: string[];
13
- }
1
+ /** Metadata about a nested package within a Bun monorepo */
2
+ export type Workspace = {
3
+ /** The name of the workspace from its `package.json` */
4
+ name: string;
5
+ /** Whether the workspace is the root workspace */
6
+ isRoot: boolean;
7
+ /** The relative path to the workspace from the root `package.json` */
8
+ path: string;
9
+ /** The pattern from `"workspaces"` in the root `package.json`that this workspace was matched from*/
10
+ matchPattern: string;
11
+ /** The scripts available in package.json */
12
+ scripts: string[];
13
+ /** Aliases assigned to the workspace via the `"workspaceAliases"` field in the config */
14
+ aliases: string[];
15
+ /** Names of workspaces that this workspace depends on */
16
+ dependencies: string[];
17
+ /** Names of workspaces that depend on this workspace */
18
+ dependents: string[];
19
+ };
@@ -0,0 +1,2 @@
1
+ // CONCATENATED MODULE: ./src/workspaces/workspace.ts
2
+ /** Metadata about a nested package within a Bun monorepo */
@@ -0,0 +1,21 @@
1
+ import type { Workspace } from "./workspace";
2
+ declare const TARGETS: readonly ["path", "alias", "name"];
3
+ export declare const WORKSPACE_PATTERN_ERRORS: import("../internal/core").DefinedErrors<"InvalidWorkspacePattern">;
4
+ export type WorkspacePatternTarget = (typeof TARGETS)[number];
5
+ export type WorkspacePattern = {
6
+ target: WorkspacePatternTarget | "default";
7
+ value: string;
8
+ isNegated: boolean;
9
+ };
10
+ export declare const WORKSPACE_PATTERN_SEPARATOR = ":";
11
+ export declare const parseWorkspacePattern: (
12
+ pattern: string,
13
+ ) => WorkspacePattern;
14
+ export declare const stringifyWorkspacePattern: (
15
+ pattern: WorkspacePattern,
16
+ ) => string;
17
+ export declare const matchWorkspacesByPatterns: (
18
+ patterns: string[],
19
+ workspaces: Workspace[],
20
+ ) => Workspace[];
21
+ export {};