bun-workspaces 1.8.2 → 1.10.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 (47) hide show
  1. package/AGENTS.md +537 -0
  2. package/README.md +51 -13
  3. package/package.json +1 -1
  4. package/src/2392.mjs +184 -3
  5. package/src/5166.mjs +1 -0
  6. package/src/8529.mjs +10 -0
  7. package/src/affected/affectedBaseRef.mjs +12 -0
  8. package/src/affected/externalDependencyChanges.mjs +47 -0
  9. package/src/affected/fileAffectedWorkspaces.mjs +152 -54
  10. package/src/affected/gitAffectedFiles.mjs +44 -1
  11. package/src/affected/gitAffectedWorkspaces.mjs +73 -3
  12. package/src/affected/index.mjs +2 -0
  13. package/src/ai/mcp/serverState.mjs +1 -1
  14. package/src/cli/commands/commandHandlerUtils.mjs +12 -7
  15. package/src/cli/commands/commands.mjs +4 -1
  16. package/src/cli/commands/handleSimpleCommands.mjs +2 -2
  17. package/src/cli/commands/listAffected.mjs +184 -0
  18. package/src/cli/commands/runScript/handleRunAffected.mjs +99 -0
  19. package/src/cli/commands/runScript/handleRunScript.mjs +19 -202
  20. package/src/cli/commands/runScript/index.mjs +1 -0
  21. package/src/cli/commands/runScript/scriptRunFlow.mjs +213 -0
  22. package/src/cli/index.d.ts +749 -134
  23. package/src/config/public.d.ts +66 -2
  24. package/src/config/rootConfig/rootConfig.mjs +9 -9
  25. package/src/config/rootConfig/rootConfigSchema.mjs +3 -0
  26. package/src/config/workspaceConfig/mergeWorkspaceConfig.mjs +33 -19
  27. package/src/config/workspaceConfig/workspaceConfig.mjs +3 -0
  28. package/src/config/workspaceConfig/workspaceConfigSchema.mjs +26 -0
  29. package/src/index.d.ts +307 -5
  30. package/src/index.mjs +1 -0
  31. package/src/internal/bun/bunLock.mjs +33 -0
  32. package/src/internal/generated/aiDocs/docs.mjs +169 -9
  33. package/src/internal/generated/ajv/validateRootConfig.mjs +1 -1
  34. package/src/internal/generated/ajv/validateWorkspaceConfig.mjs +1 -1
  35. package/src/project/implementations/fileSystemProject/affectedWorkspaces.mjs +227 -0
  36. package/src/project/implementations/{fileSystemProject.mjs → fileSystemProject/fileSystemProject.mjs} +169 -12
  37. package/src/project/implementations/fileSystemProject/index.mjs +4 -0
  38. package/src/project/implementations/memoryProject.mjs +1 -0
  39. package/src/project/implementations/projectBase.mjs +11 -17
  40. package/src/project/index.mjs +1 -1
  41. package/src/rslib-runtime.mjs +0 -31
  42. package/src/workspaces/applyWorkspacePatternConfigs.mjs +16 -2
  43. package/src/workspaces/dependencyGraph/resolveDependencies.mjs +68 -18
  44. package/src/workspaces/dependencyGraph/validateDependencyRules.mjs +14 -7
  45. package/src/workspaces/findWorkspaces.mjs +3 -0
  46. package/src/workspaces/workspace.mjs +8 -2
  47. package/src/workspaces/workspacePattern.mjs +134 -46
@@ -0,0 +1,227 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import bun from "bun";
4
+ import { getFileAffectedWorkspaces } from "../../../affected/fileAffectedWorkspaces.mjs";
5
+ import { getGitAffectedWorkspaces } from "../../../affected/gitAffectedWorkspaces.mjs";
6
+
7
+ const isOptionsForDiffSource = (options, diffSource) =>
8
+ options.diffSource === diffSource;
9
+ const DEFAULT_INPUT_FILE_PATTERN = ".";
10
+ const DEFAULT_HEAD_REF = "HEAD";
11
+ const BUN_LOCK_PROJECT_RELATIVE_PATH = "bun.lock";
12
+ const FILE_PATTERN_NEGATION_PREFIX = "!";
13
+ const GLOB_CHARACTER_REGEX = /[*?[{]/;
14
+ const SKIPPED_DIR_NAMES = new Set(["node_modules", ".git"]);
15
+ const buildWorkspaceInputs = ({ project, script }) => {
16
+ const effectiveInputsByName = new Map();
17
+ const inputs = project.workspaces.map((workspace) => {
18
+ const workspaceConfig = project.config.workspaces[workspace.name];
19
+ const scriptInputs = script
20
+ ? workspaceConfig?.scripts[script]?.inputs
21
+ : undefined;
22
+ const sourceInputs = scriptInputs ?? workspaceConfig?.defaultInputs ?? {};
23
+ const effectiveFiles = sourceInputs.files ?? [DEFAULT_INPUT_FILE_PATTERN];
24
+ const effectiveWorkspacePatterns = sourceInputs.workspacePatterns ?? [];
25
+ const effectiveExternalDependencies = sourceInputs.externalDependencies;
26
+ effectiveInputsByName.set(workspace.name, {
27
+ files: effectiveFiles,
28
+ workspacePatterns: effectiveWorkspacePatterns,
29
+ ...(effectiveExternalDependencies !== undefined && {
30
+ externalDependencies: effectiveExternalDependencies,
31
+ }),
32
+ });
33
+ return {
34
+ workspace,
35
+ inputFilePatterns: effectiveFiles,
36
+ inputWorkspacePatterns: effectiveWorkspacePatterns,
37
+ ...(effectiveExternalDependencies !== undefined && {
38
+ inputExternalDependencyNames: effectiveExternalDependencies,
39
+ }),
40
+ };
41
+ });
42
+ return {
43
+ inputs,
44
+ effectiveInputsByName,
45
+ };
46
+ };
47
+ const buildLockfileChangeSyntheticEntries = (workspaces) => {
48
+ const result = new Map();
49
+ for (const workspace of workspaces) {
50
+ if (!workspace.externalDependencies.length) continue;
51
+ result.set(
52
+ workspace.name,
53
+ workspace.externalDependencies.map(({ name, source }) => ({
54
+ name,
55
+ source,
56
+ baseVersion: null,
57
+ headVersion: null,
58
+ })),
59
+ );
60
+ }
61
+ return result;
62
+ };
63
+ const normalizeChangedFilesPattern = (pattern) => {
64
+ let normalized = pattern.replaceAll("\\", "/");
65
+ while (normalized.startsWith("./")) normalized = normalized.slice(2);
66
+ normalized = normalized.replace(/^\/+/, "").replace(/\/+$/, "");
67
+ if (normalized === ".") return "";
68
+ return normalized;
69
+ };
70
+ const expandPatternToFiles = ({ rootDirectory, pattern }) => {
71
+ if (!pattern) return [];
72
+ const normalized = normalizeChangedFilesPattern(pattern);
73
+ if (normalized && GLOB_CHARACTER_REGEX.test(normalized)) {
74
+ return Array.from(
75
+ new bun.Glob(normalized).scanSync({
76
+ cwd: rootDirectory,
77
+ onlyFiles: true,
78
+ }),
79
+ ).map((match) => match.replaceAll("\\", "/"));
80
+ }
81
+ // Empty `normalized` means the input resolved to the project root (e.g. ".")
82
+ const isProjectRoot = normalized === "";
83
+ const absolute = isProjectRoot
84
+ ? rootDirectory
85
+ : path.join(rootDirectory, ...normalized.split("/"));
86
+ let stat;
87
+ try {
88
+ stat = fs.statSync(absolute);
89
+ } catch {
90
+ // Pass through paths that don't exist on disk (e.g. deleted files)
91
+ return isProjectRoot ? [] : [normalized];
92
+ }
93
+ if (stat.isFile()) return [normalized];
94
+ if (!stat.isDirectory()) return [];
95
+ const result = [];
96
+ const walk = (dir, baseRel) => {
97
+ for (const entry of fs.readdirSync(dir, {
98
+ withFileTypes: true,
99
+ })) {
100
+ if (entry.isDirectory() && SKIPPED_DIR_NAMES.has(entry.name)) continue;
101
+ const rel = baseRel ? `${baseRel}/${entry.name}` : entry.name;
102
+ if (entry.isDirectory()) {
103
+ walk(path.join(dir, entry.name), rel);
104
+ } else if (entry.isFile()) {
105
+ result.push(rel);
106
+ }
107
+ }
108
+ };
109
+ walk(absolute, normalized);
110
+ return result;
111
+ };
112
+ const expandChangedFilesPatterns = ({ rootDirectory, patterns }) => {
113
+ const includes = new Set();
114
+ const excludes = new Set();
115
+ for (const pattern of patterns) {
116
+ const isExclude = pattern.startsWith(FILE_PATTERN_NEGATION_PREFIX);
117
+ const stripped = isExclude
118
+ ? pattern.slice(FILE_PATTERN_NEGATION_PREFIX.length)
119
+ : pattern;
120
+ const target = isExclude ? excludes : includes;
121
+ for (const expanded of expandPatternToFiles({
122
+ rootDirectory,
123
+ pattern: stripped,
124
+ })) {
125
+ target.add(expanded);
126
+ }
127
+ }
128
+ for (const excluded of excludes) {
129
+ includes.delete(excluded);
130
+ }
131
+ return [...includes];
132
+ };
133
+ const toAffectedWorkspaceResult = (internal, effectiveInputsByName) => ({
134
+ workspace: internal.workspace,
135
+ inputs: effectiveInputsByName.get(internal.workspace.name) ?? {},
136
+ isAffected: internal.isAffected,
137
+ affectedReasons: {
138
+ changedFiles: internal.affectedReasons.changedFiles.map((file) => ({
139
+ projectFilePath: file.filePath,
140
+ inputMatch: file.inputPattern,
141
+ ...(file.fileMetadata?.git && {
142
+ gitReasons: file.fileMetadata.git.reasons,
143
+ }),
144
+ })),
145
+ dependencies: internal.affectedReasons.dependencies,
146
+ externalDependencies: internal.affectedReasons.externalDependencies,
147
+ },
148
+ });
149
+ const determineAffectedWorkspaces = async (project, options) => {
150
+ const ignoreWorkspaceDependencies =
151
+ options.ignoreWorkspaceDependencies ?? false;
152
+ const ignoreExternalDependencies =
153
+ options.ignoreExternalDependencies ?? false;
154
+ const { inputs: workspaceInputs, effectiveInputsByName } =
155
+ buildWorkspaceInputs({
156
+ project,
157
+ script: options.script,
158
+ });
159
+ if (isOptionsForDiffSource(options, "git")) {
160
+ const baseRef =
161
+ options.diffOptions?.baseRef ??
162
+ project.config.root.defaults.affectedBaseRef;
163
+ const headRef = options.diffOptions?.headRef ?? DEFAULT_HEAD_REF;
164
+ const { affectedWorkspaces, baseSha, headSha } =
165
+ await getGitAffectedWorkspaces({
166
+ rootDirectory: project.rootDirectory,
167
+ workspacesOptions: {
168
+ workspaceInputs,
169
+ workspaces: project.workspaces,
170
+ rootWorkspace: project.rootWorkspace,
171
+ ignoreWorkspaceDependencies,
172
+ ignoreExternalDependencies,
173
+ },
174
+ gitOptions: {
175
+ baseRef,
176
+ headRef,
177
+ ignoreUntracked: options.diffOptions?.ignoreUntracked,
178
+ ignoreStaged: options.diffOptions?.ignoreStaged,
179
+ ignoreUnstaged: options.diffOptions?.ignoreUnstaged,
180
+ ignoreUncommitted: options.diffOptions?.ignoreUncommitted,
181
+ },
182
+ });
183
+ return {
184
+ metadata: {
185
+ diffSource: "git",
186
+ git: {
187
+ baseRef,
188
+ headRef,
189
+ baseSha,
190
+ headSha,
191
+ },
192
+ },
193
+ workspaceResults: affectedWorkspaces.map((result) =>
194
+ toAffectedWorkspaceResult(result, effectiveInputsByName),
195
+ ),
196
+ };
197
+ }
198
+ const expandedChangedFilePaths = expandChangedFilesPatterns({
199
+ rootDirectory: project.rootDirectory,
200
+ patterns: options.changedFiles,
201
+ });
202
+ const lockfileInChangedFiles = expandedChangedFilePaths.includes(
203
+ BUN_LOCK_PROJECT_RELATIVE_PATH,
204
+ );
205
+ const externalDepChangesByWorkspace =
206
+ !ignoreExternalDependencies && lockfileInChangedFiles
207
+ ? buildLockfileChangeSyntheticEntries(project.workspaces)
208
+ : new Map();
209
+ const { affectedWorkspaces } = await getFileAffectedWorkspaces({
210
+ rootDirectory: project.rootDirectory,
211
+ workspaceInputs,
212
+ changedFilePaths: expandedChangedFilePaths,
213
+ rootWorkspace: project.rootWorkspace,
214
+ externalDepChangesByWorkspace,
215
+ ignoreWorkspaceDependencies,
216
+ });
217
+ return {
218
+ metadata: {
219
+ diffSource: "fileList",
220
+ },
221
+ workspaceResults: affectedWorkspaces.map((result) =>
222
+ toAffectedWorkspaceResult(result, effectiveInputsByName),
223
+ ),
224
+ };
225
+ };
226
+
227
+ export { determineAffectedWorkspaces, isOptionsForDiffSource };
@@ -1,8 +1,8 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { loadRootConfig } from "../../config/index.mjs";
4
- import { getUserEnvVar } from "../../config/userEnvVars/index.mjs";
5
- import { parse, quote } from "../../internal/bundledDeps/shellQuote.mjs";
3
+ import { loadRootConfig } from "../../../config/index.mjs";
4
+ import { getUserEnvVar } from "../../../config/userEnvVars/index.mjs";
5
+ import { parse, quote } from "../../../internal/bundledDeps/shellQuote.mjs";
6
6
  import {
7
7
  DEFAULT_TEMP_DIR,
8
8
  IS_WINDOWS,
@@ -11,25 +11,55 @@ import {
11
11
  isPlainObject,
12
12
  validateJSArray,
13
13
  validateJSTypes,
14
- } from "../../internal/core/index.mjs";
15
- import { logger } from "../../internal/logger/index.mjs";
14
+ } from "../../../internal/core/index.mjs";
15
+ import { logger } from "../../../internal/logger/index.mjs";
16
16
  import {
17
17
  createScriptRuntimeEnvVars,
18
18
  interpolateWorkspaceScriptMetadata,
19
19
  runScript,
20
20
  runScripts,
21
- } from "../../runScript/index.mjs";
22
- import { checkIsRecursiveScript } from "../../runScript/recursion.mjs";
23
- import { resolveScriptShell } from "../../runScript/scriptShellOption.mjs";
24
- import { findWorkspaces, sortWorkspaces } from "../../workspaces/index.mjs";
25
- import { preventDependencyCycles } from "../../workspaces/dependencyGraph/index.mjs";
26
- import { PROJECT_ERRORS } from "../errors.mjs";
21
+ } from "../../../runScript/index.mjs";
22
+ import { createMultiProcessOutput } from "../../../runScript/output/multiProcessOutput.mjs";
23
+ import { checkIsRecursiveScript } from "../../../runScript/recursion.mjs";
24
+ import { resolveScriptShell } from "../../../runScript/scriptShellOption.mjs";
25
+ import { findWorkspaces, sortWorkspaces } from "../../../workspaces/index.mjs";
26
+ import { preventDependencyCycles } from "../../../workspaces/dependencyGraph/index.mjs";
27
+ import { PROJECT_ERRORS } from "../../errors.mjs";
27
28
  import {
28
29
  ProjectBase,
29
30
  resolveRootWorkspaceSelector,
30
31
  resolveWorkspacePath,
31
- } from "./projectBase.mjs";
32
+ } from "../projectBase.mjs";
33
+ import { determineAffectedWorkspaces } from "./affectedWorkspaces.mjs";
32
34
 
35
+ /**
36
+ * Resolves the script name used to look up script-level inputs in
37
+ * `runAffectedWorkspaceScript`. Uses the inline-script name when running
38
+ * an inline command, or the script name otherwise.
39
+ */ const resolveInputsLookupScriptName = (scriptOptions) => {
40
+ if (!scriptOptions.inline) return scriptOptions.script;
41
+ if (typeof scriptOptions.inline === "object") {
42
+ return scriptOptions.inline.scriptName;
43
+ }
44
+ return undefined;
45
+ };
46
+ const createEmptyAffectedRunResult = () => {
47
+ const now = new Date().toISOString();
48
+ return {
49
+ output: createMultiProcessOutput([]),
50
+ summary: Promise.resolve({
51
+ totalCount: 0,
52
+ successCount: 0,
53
+ failureCount: 0,
54
+ allSuccess: true,
55
+ startTimeISO: now,
56
+ endTimeISO: now,
57
+ durationMs: 0,
58
+ scriptResults: [],
59
+ }),
60
+ workspaces: [],
61
+ };
62
+ };
33
63
  const quoteArg = (arg, shell) =>
34
64
  IS_WINDOWS && shell === "system"
35
65
  ? `"${arg.replace(/"/g, '""')}"`
@@ -497,6 +527,133 @@ class _FileSystemProject extends ProjectBase {
497
527
  workspaces,
498
528
  };
499
529
  }
530
+ /**
531
+ * Determine the affected workspaces based on the given options.
532
+ *
533
+ * Returns a summary of all workspaces, whether they are affected or not,
534
+ * and the reasons why they are affected.
535
+ */ async determineAffectedWorkspaces(options) {
536
+ validateJSTypes(
537
+ {
538
+ "diffSource option": {
539
+ value: options.diffSource,
540
+ typeofName: "string",
541
+ },
542
+ "ignoreWorkspaceDependencies option": {
543
+ value: options.ignoreWorkspaceDependencies,
544
+ typeofName: "boolean",
545
+ optional: true,
546
+ },
547
+ "ignoreExternalDependencies option": {
548
+ value: options.ignoreExternalDependencies,
549
+ typeofName: "boolean",
550
+ optional: true,
551
+ },
552
+ "script option": {
553
+ value: options.script,
554
+ typeofName: "string",
555
+ optional: true,
556
+ },
557
+ },
558
+ {
559
+ throw: true,
560
+ },
561
+ );
562
+ if (options.diffSource !== "git" && options.diffSource !== "fileList") {
563
+ throw new InvalidJSTypeError(
564
+ `Type error: diffSource option expects "git" | "fileList", received ${JSON.stringify(options.diffSource)}`,
565
+ );
566
+ }
567
+ if (options.diffSource === "git") {
568
+ validateJSTypes(
569
+ {
570
+ "diffOptions option": {
571
+ value: options.diffOptions,
572
+ typeofName: "object",
573
+ optional: true,
574
+ },
575
+ },
576
+ {
577
+ throw: true,
578
+ },
579
+ );
580
+ if (options.diffOptions !== undefined) {
581
+ validateJSTypes(
582
+ {
583
+ "diffOptions.baseRef option": {
584
+ value: options.diffOptions.baseRef,
585
+ typeofName: "string",
586
+ optional: true,
587
+ },
588
+ "diffOptions.headRef option": {
589
+ value: options.diffOptions.headRef,
590
+ typeofName: "string",
591
+ optional: true,
592
+ },
593
+ "diffOptions.ignoreUntracked option": {
594
+ value: options.diffOptions.ignoreUntracked,
595
+ typeofName: "boolean",
596
+ optional: true,
597
+ },
598
+ "diffOptions.ignoreStaged option": {
599
+ value: options.diffOptions.ignoreStaged,
600
+ typeofName: "boolean",
601
+ optional: true,
602
+ },
603
+ "diffOptions.ignoreUnstaged option": {
604
+ value: options.diffOptions.ignoreUnstaged,
605
+ typeofName: "boolean",
606
+ optional: true,
607
+ },
608
+ "diffOptions.ignoreUncommitted option": {
609
+ value: options.diffOptions.ignoreUncommitted,
610
+ typeofName: "boolean",
611
+ optional: true,
612
+ },
613
+ },
614
+ {
615
+ throw: true,
616
+ },
617
+ );
618
+ }
619
+ } else {
620
+ validateJSTypes(
621
+ {
622
+ "changedFiles option": {
623
+ value: options.changedFiles,
624
+ array: true,
625
+ itemOptions: {
626
+ typeofName: "string",
627
+ },
628
+ },
629
+ },
630
+ {
631
+ throw: true,
632
+ },
633
+ );
634
+ }
635
+ return determineAffectedWorkspaces(this, options);
636
+ }
637
+ /**
638
+ * Run the script across the affected workspaces.
639
+ *
640
+ * Similar to {@link runScriptAcrossWorkspaces}, but only runs the script across the affected workspaces.
641
+ */ async runAffectedWorkspaceScript({ affectedOptions, scriptOptions }) {
642
+ const { workspaceResults } = await this.determineAffectedWorkspaces({
643
+ ...affectedOptions,
644
+ script: resolveInputsLookupScriptName(scriptOptions),
645
+ });
646
+ const affectedNames = workspaceResults
647
+ .filter(({ isAffected }) => isAffected)
648
+ .map(({ workspace }) => workspace.name);
649
+ if (affectedNames.length === 0) {
650
+ return createEmptyAffectedRunResult();
651
+ }
652
+ return this.runScriptAcrossWorkspaces({
653
+ ...scriptOptions,
654
+ workspacePatterns: affectedNames,
655
+ });
656
+ }
500
657
  static #initialized = false;
501
658
  }
502
659
  /**
@@ -0,0 +1,4 @@
1
+ export * from "./fileSystemProject.mjs";
2
+ export * from "./affectedWorkspaces.mjs";
3
+
4
+ export {};
@@ -112,6 +112,7 @@ class _MemoryProject extends ProjectBase {
112
112
  tags: [],
113
113
  dependencies: [],
114
114
  dependents: [],
115
+ externalDependencies: [],
115
116
  };
116
117
  validateWorkspace(this.rootWorkspace);
117
118
  for (const workspace of this.workspaces) {
@@ -130,24 +130,18 @@ class ProjectBase {
130
130
  return this.workspaces.filter((workspace) => workspace.tags.includes(tag));
131
131
  }
132
132
  findWorkspacesByPattern(...workspacePatterns) {
133
- const workspaces = [];
134
- if (
135
- workspacePatterns.includes(
136
- /* inlined export .ROOT_WORKSPACE_SELECTOR */ "@root",
137
- )
138
- ) {
139
- workspaces.push(this.rootWorkspace);
140
- workspacePatterns = workspacePatterns.filter(
141
- (pattern) =>
142
- pattern !== /* inlined export .ROOT_WORKSPACE_SELECTOR */ "@root",
143
- );
144
- }
145
- workspaces.push(
146
- ...sortWorkspaces(
147
- matchWorkspacesByPatterns(workspacePatterns, this.workspaces),
148
- ),
133
+ const matched = matchWorkspacesByPatterns(
134
+ workspacePatterns,
135
+ this.workspaces,
136
+ this.rootWorkspace,
137
+ );
138
+ // Preserve historical ordering: root workspace first, then sorted others.
139
+ const rootName = this.rootWorkspace.name;
140
+ const rootMatch = matched.find((workspace) => workspace.name === rootName);
141
+ const rest = sortWorkspaces(
142
+ matched.filter((workspace) => workspace.name !== rootName),
149
143
  );
150
- return workspaces;
144
+ return rootMatch ? [rootMatch, ...rest] : rest;
151
145
  }
152
146
  createScriptCommand(options) {
153
147
  validateJSTypes(
@@ -1,6 +1,6 @@
1
1
  export * from "./errors.mjs";
2
2
  export * from "./implementations/projectBase.mjs";
3
- export * from "./implementations/fileSystemProject.mjs";
3
+ export * from "./implementations/fileSystemProject/index.mjs";
4
4
  export * from "./implementations/memoryProject.mjs";
5
5
 
6
6
  export {};
@@ -21,42 +21,11 @@ function __webpack_require__(moduleId) {
21
21
  // expose the modules object (__webpack_modules__)
22
22
  __webpack_require__.m = __webpack_modules__;
23
23
 
24
- // webpack/runtime/compat_get_default_export
25
- (() => {
26
- // getDefaultExport function for compatibility with non-ESM modules
27
- __webpack_require__.n = (module) => {
28
- var getter =
29
- module && module.__esModule ? () => module["default"] : () => module;
30
- __webpack_require__.d(getter, { a: getter });
31
- return getter;
32
- };
33
- })();
34
- // webpack/runtime/define_property_getters
35
- (() => {
36
- __webpack_require__.d = (exports, definition) => {
37
- for (var key in definition) {
38
- if (
39
- __webpack_require__.o(definition, key) &&
40
- !__webpack_require__.o(exports, key)
41
- ) {
42
- Object.defineProperty(exports, key, {
43
- enumerable: true,
44
- get: definition[key],
45
- });
46
- }
47
- }
48
- };
49
- })();
50
24
  // webpack/runtime/esm_register_module
51
25
  (() => {
52
26
  __webpack_require__.add = function registerModules(modules) {
53
27
  Object.assign(__webpack_require__.m, modules);
54
28
  };
55
29
  })();
56
- // webpack/runtime/has_own_property
57
- (() => {
58
- __webpack_require__.o = (obj, prop) =>
59
- Object.prototype.hasOwnProperty.call(obj, prop);
60
- })();
61
30
 
62
31
  export { __webpack_require__ };
@@ -4,11 +4,20 @@ import {
4
4
  } from "../config/index.mjs";
5
5
  import { matchWorkspacesByPatterns } from "./workspacePattern.mjs";
6
6
 
7
- const resolvedToWorkspaceConfig = ({ aliases, tags, scripts, rules }) => ({
7
+ const resolvedToWorkspaceConfig = ({
8
+ aliases,
9
+ tags,
10
+ scripts,
11
+ rules,
12
+ defaultInputs,
13
+ }) => ({
8
14
  alias: aliases,
9
15
  tags,
10
16
  scripts,
11
17
  rules,
18
+ ...(defaultInputs && {
19
+ defaultInputs,
20
+ }),
12
21
  });
13
22
  const makeContext = (workspace) => ({
14
23
  name: workspace.name,
@@ -24,9 +33,14 @@ const applyWorkspacePatternConfigs = (
24
33
  workspaceMap,
25
34
  workspaceAliases,
26
35
  patternConfigs,
36
+ rootWorkspace,
27
37
  ) => {
28
38
  for (const entry of patternConfigs) {
29
- const matched = matchWorkspacesByPatterns(entry.patterns, workspaces);
39
+ const matched = matchWorkspacesByPatterns(
40
+ entry.patterns,
41
+ workspaces,
42
+ rootWorkspace,
43
+ );
30
44
  for (const workspace of matched) {
31
45
  const mapEntry = workspaceMap[workspace.name];
32
46
  const prevConfig = mapEntry.config;
@@ -1,5 +1,11 @@
1
1
  import { resolveCatalogDependencyVersion } from "../packageJson.mjs";
2
2
 
3
+ const parseCatalogRef = (rawVersion) => {
4
+ if (!rawVersion.startsWith("catalog:")) return undefined;
5
+ return {
6
+ name: rawVersion.slice("catalog:".length),
7
+ };
8
+ };
3
9
  const resolveWorkspaceDependencies = (
4
10
  workspaceMap,
5
11
  includeRootWorkspace,
@@ -10,34 +16,78 @@ const resolveWorkspaceDependencies = (
10
16
  );
11
17
  const workspacesWithDependencies = workspacePackages.map(
12
18
  ({ workspace, packageJson }) => {
13
- for (const dependencyMap of [
14
- packageJson.dependencies,
15
- packageJson.devDependencies,
16
- packageJson.peerDependencies,
17
- packageJson.optionalDependencies,
18
- ]) {
19
- for (const [dependencyName, dependencyVersion] of Object.entries(
20
- dependencyMap,
21
- )) {
19
+ const externalAccumulator = new Map();
20
+ const dependencyMaps = [
21
+ {
22
+ map: packageJson.dependencies,
23
+ source: "dependencies",
24
+ },
25
+ {
26
+ map: packageJson.devDependencies,
27
+ source: "devDependencies",
28
+ },
29
+ {
30
+ map: packageJson.peerDependencies,
31
+ source: "peerDependencies",
32
+ },
33
+ {
34
+ map: packageJson.optionalDependencies,
35
+ source: "optionalDependencies",
36
+ },
37
+ ];
38
+ for (const { map, source } of dependencyMaps) {
39
+ for (const [dependencyName, dependencyVersion] of Object.entries(map)) {
40
+ const catalog = parseCatalogRef(dependencyVersion);
22
41
  const resolvedVersion =
23
- catalogs && dependencyVersion.startsWith("catalog:")
42
+ catalogs && catalog
24
43
  ? (resolveCatalogDependencyVersion(
25
44
  dependencyName,
26
45
  dependencyVersion,
27
46
  catalogs,
28
47
  ) ?? dependencyVersion)
29
48
  : dependencyVersion;
30
- if (
31
- resolvedVersion.startsWith("workspace:") &&
32
- workspaceMap[dependencyName]
33
- ) {
34
- workspace.dependencies.push(dependencyName);
35
- workspaceMap[dependencyName].workspace.dependents.push(
36
- workspace.name,
37
- );
49
+ if (resolvedVersion.startsWith("workspace:")) {
50
+ if (workspaceMap[dependencyName]) {
51
+ workspace.dependencies.push(dependencyName);
52
+ workspaceMap[dependencyName].workspace.dependents.push(
53
+ workspace.name,
54
+ );
55
+ }
56
+ continue;
57
+ }
58
+ // External dep — record. Source precedence: a non-`devDependencies`
59
+ // source overrides `devDependencies`; otherwise the first source
60
+ // seen wins. Version/catalog reflect the last entry seen for the name.
61
+ const existing = externalAccumulator.get(dependencyName);
62
+ if (!existing) {
63
+ externalAccumulator.set(dependencyName, {
64
+ source,
65
+ version: resolvedVersion,
66
+ catalog,
67
+ });
68
+ } else {
69
+ existing.version = resolvedVersion;
70
+ existing.catalog = catalog;
71
+ if (
72
+ existing.source === "devDependencies" &&
73
+ source !== "devDependencies"
74
+ ) {
75
+ existing.source = source;
76
+ }
38
77
  }
39
78
  }
40
79
  }
80
+ workspace.externalDependencies = [...externalAccumulator.entries()]
81
+ .map(([name, { source, version, catalog }]) => {
82
+ const entry = {
83
+ name,
84
+ version,
85
+ source,
86
+ };
87
+ if (catalog) entry.catalog = catalog;
88
+ return entry;
89
+ })
90
+ .sort((a, b) => a.name.localeCompare(b.name));
41
91
  return workspace;
42
92
  },
43
93
  );