@turbo/workspaces 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,840 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/index.ts
24
+ var src_exports = {};
25
+ __export(src_exports, {
26
+ MANAGERS: () => managers_default,
27
+ convertMonorepo: () => convertMonorepo,
28
+ getWorkspaceDetails: () => getWorkspaceDetails,
29
+ install: () => install_default
30
+ });
31
+ module.exports = __toCommonJS(src_exports);
32
+ var import_turbo_utils = require("turbo-utils");
33
+
34
+ // src/errors.ts
35
+ var ConvertError = class extends Error {
36
+ constructor(message) {
37
+ super(message);
38
+ this.name = "ConvertError";
39
+ Error.captureStackTrace(this, ConvertError);
40
+ }
41
+ };
42
+
43
+ // src/managers/pnpm.ts
44
+ var import_fs_extra3 = __toESM(require("fs-extra"));
45
+ var import_path3 = __toESM(require("path"));
46
+ var import_execa = __toESM(require("execa"));
47
+
48
+ // src/updateDependencies.ts
49
+ var import_fs_extra2 = __toESM(require("fs-extra"));
50
+ var import_chalk = __toESM(require("chalk"));
51
+ var import_path2 = __toESM(require("path"));
52
+
53
+ // src/utils.ts
54
+ var import_fs_extra = __toESM(require("fs-extra"));
55
+ var import_path = __toESM(require("path"));
56
+ var import_fast_glob = __toESM(require("fast-glob"));
57
+ var import_js_yaml = __toESM(require("js-yaml"));
58
+ var PACKAGE_MANAGER_REGEX = /^(?!_)(.+)@(.+)$/;
59
+ function getPackageJson({
60
+ workspaceRoot
61
+ }) {
62
+ const packageJsonPath = import_path.default.join(workspaceRoot, "package.json");
63
+ try {
64
+ return import_fs_extra.default.readJsonSync(packageJsonPath, "utf8");
65
+ } catch (err) {
66
+ if (err && typeof err === "object" && "code" in err) {
67
+ if (err.code === "ENOENT") {
68
+ throw new ConvertError(`no "package.json" found at ${workspaceRoot}`);
69
+ }
70
+ if (err.code === "EJSONPARSE") {
71
+ throw new ConvertError(`failed to parse "package.json" at ${workspaceRoot}`);
72
+ }
73
+ }
74
+ throw new Error(`unexpected error reading "package.json" at ${workspaceRoot}`);
75
+ }
76
+ }
77
+ function getWorkspacePackageManager({
78
+ workspaceRoot
79
+ }) {
80
+ const { packageManager } = getPackageJson({ workspaceRoot });
81
+ if (packageManager) {
82
+ try {
83
+ const match = packageManager.match(PACKAGE_MANAGER_REGEX);
84
+ if (match) {
85
+ const [_, manager] = match;
86
+ return manager;
87
+ }
88
+ } catch (err) {
89
+ }
90
+ }
91
+ return void 0;
92
+ }
93
+ function getWorkspaceName({
94
+ workspaceRoot
95
+ }) {
96
+ const packageJson = getPackageJson({ workspaceRoot });
97
+ if (packageJson.name) {
98
+ return packageJson.name;
99
+ }
100
+ const workspaceDirectory = import_path.default.basename(workspaceRoot);
101
+ return workspaceDirectory;
102
+ }
103
+ function getPnpmWorkspaces({
104
+ workspaceRoot
105
+ }) {
106
+ const workspaceFile = import_path.default.join(workspaceRoot, "pnpm-workspace.yaml");
107
+ if (import_fs_extra.default.existsSync(workspaceFile)) {
108
+ try {
109
+ const workspaceConfig = import_js_yaml.default.load(import_fs_extra.default.readFileSync(workspaceFile, "utf8"));
110
+ if (workspaceConfig instanceof Object && "packages" in workspaceConfig && Array.isArray(workspaceConfig.packages)) {
111
+ return workspaceConfig.packages;
112
+ }
113
+ } catch (err) {
114
+ throw new ConvertError(`failed to parse ${workspaceFile}`);
115
+ }
116
+ }
117
+ return [];
118
+ }
119
+ function expandPaths({
120
+ root,
121
+ lockFile,
122
+ workspaceConfig
123
+ }) {
124
+ const fromRoot = (p) => import_path.default.join(root, p);
125
+ const paths = {
126
+ root,
127
+ lockfile: fromRoot(lockFile),
128
+ packageJson: fromRoot("package.json"),
129
+ nodeModules: fromRoot("node_modules")
130
+ };
131
+ if (workspaceConfig) {
132
+ paths.workspaceConfig = fromRoot(workspaceConfig);
133
+ }
134
+ return paths;
135
+ }
136
+ function expandWorkspaces({
137
+ workspaceRoot,
138
+ workspaceGlobs
139
+ }) {
140
+ if (!workspaceGlobs) {
141
+ return [];
142
+ }
143
+ return workspaceGlobs.flatMap((workspaceGlob) => {
144
+ const workspacePackageJsonGlob = `${workspaceGlob}/package.json`;
145
+ return import_fast_glob.default.sync(workspacePackageJsonGlob, {
146
+ onlyFiles: true,
147
+ absolute: true,
148
+ cwd: workspaceRoot
149
+ });
150
+ }).map((workspacePackageJson) => {
151
+ const workspaceRoot2 = import_path.default.dirname(workspacePackageJson);
152
+ const name = getWorkspaceName({ workspaceRoot: workspaceRoot2 });
153
+ return {
154
+ name,
155
+ paths: {
156
+ root: workspaceRoot2,
157
+ packageJson: workspacePackageJson,
158
+ nodeModules: import_path.default.join(workspaceRoot2, "node_modules")
159
+ }
160
+ };
161
+ });
162
+ }
163
+ function directoryInfo({ directory }) {
164
+ const dir = import_path.default.resolve(process.cwd(), directory);
165
+ return { exists: import_fs_extra.default.existsSync(dir), absolute: dir };
166
+ }
167
+
168
+ // src/updateDependencies.ts
169
+ function updateDependencyList({
170
+ dependencyList,
171
+ project,
172
+ to
173
+ }) {
174
+ const updated = [];
175
+ project.workspaceData.workspaces.forEach((workspace) => {
176
+ const { name } = workspace;
177
+ if (dependencyList[name]) {
178
+ const workspaceVersion = dependencyList[name];
179
+ const version = workspaceVersion.startsWith("workspace:") ? workspaceVersion.slice("workspace:".length) : workspaceVersion;
180
+ dependencyList[name] = to.name === "pnpm" ? `workspace:${version}` : version;
181
+ updated.push(name);
182
+ }
183
+ });
184
+ return { dependencyList, updated };
185
+ }
186
+ function updateDependencies({
187
+ project,
188
+ workspace,
189
+ to,
190
+ logger,
191
+ options
192
+ }) {
193
+ if (["yarn", "npm"].includes(to.name) && ["yarn", "npm"].includes(project.packageManager)) {
194
+ return;
195
+ }
196
+ const workspacePackageJson = getPackageJson({
197
+ workspaceRoot: workspace.paths.root
198
+ });
199
+ const stats = {
200
+ dependencies: [],
201
+ devDependencies: [],
202
+ peerDependencies: [],
203
+ optionalDependencies: []
204
+ };
205
+ const allDependencyKeys = [
206
+ "dependencies",
207
+ "devDependencies",
208
+ "peerDependencies",
209
+ "optionalDependencies"
210
+ ];
211
+ allDependencyKeys.forEach((depKey) => {
212
+ const depList = workspacePackageJson[depKey];
213
+ if (depList) {
214
+ const { updated, dependencyList } = updateDependencyList({
215
+ dependencyList: depList,
216
+ project,
217
+ to
218
+ });
219
+ workspacePackageJson[depKey] = dependencyList;
220
+ stats[depKey] = updated;
221
+ }
222
+ });
223
+ const toLog = (key) => {
224
+ const total = stats[key].length;
225
+ if (total > 0) {
226
+ return `${import_chalk.default.green(total.toString())} ${key}`;
227
+ }
228
+ return void 0;
229
+ };
230
+ const allChanges = allDependencyKeys.map(toLog).filter(Boolean);
231
+ const workspaceLocation = `./${import_path2.default.relative(project.paths.root, workspace.paths.packageJson)}`;
232
+ if (allChanges.length >= 1) {
233
+ let logLine = "updating";
234
+ allChanges.forEach((stat, idx) => {
235
+ if (allChanges.length === 1) {
236
+ logLine += ` ${stat} in ${workspaceLocation}`;
237
+ } else {
238
+ if (idx === allChanges.length - 1) {
239
+ logLine += `and ${stat} in ${workspaceLocation}`;
240
+ } else {
241
+ logLine += ` ${stat}, `;
242
+ }
243
+ }
244
+ });
245
+ logger.workspaceStep(logLine);
246
+ } else {
247
+ logger.workspaceStep(`no workspace dependencies found in ${workspaceLocation}`);
248
+ }
249
+ if (!(options == null ? void 0 : options.dry)) {
250
+ import_fs_extra2.default.writeJSONSync(workspace.paths.packageJson, workspacePackageJson, {
251
+ spaces: 2
252
+ });
253
+ }
254
+ }
255
+
256
+ // src/managers/pnpm.ts
257
+ async function detect(args) {
258
+ const lockFile = import_path3.default.join(args.workspaceRoot, "pnpm-lock.yaml");
259
+ const workspaceFile = import_path3.default.join(args.workspaceRoot, "pnpm-workspace.yaml");
260
+ const packageManager = getWorkspacePackageManager({
261
+ workspaceRoot: args.workspaceRoot
262
+ });
263
+ return import_fs_extra3.default.existsSync(lockFile) || import_fs_extra3.default.existsSync(workspaceFile) || packageManager === "pnpm";
264
+ }
265
+ async function read(args) {
266
+ const isPnpm = await detect(args);
267
+ if (!isPnpm) {
268
+ throw new ConvertError("Not a pnpm project");
269
+ }
270
+ return {
271
+ name: getWorkspaceName(args),
272
+ packageManager: "pnpm",
273
+ paths: expandPaths({
274
+ root: args.workspaceRoot,
275
+ lockFile: "pnpm-lock.yaml",
276
+ workspaceConfig: "pnpm-workspace.yaml"
277
+ }),
278
+ workspaceData: {
279
+ globs: getPnpmWorkspaces(args),
280
+ workspaces: expandWorkspaces({
281
+ workspaceGlobs: getPnpmWorkspaces(args),
282
+ ...args
283
+ })
284
+ }
285
+ };
286
+ }
287
+ async function create(args) {
288
+ const { project, to, logger, options } = args;
289
+ const hasWorkspaces = project.workspaceData.globs.length > 0;
290
+ logger.mainStep(`Creating ${project.packageManager}${hasWorkspaces ? "workspaces" : ""}`);
291
+ const packageJson = getPackageJson({ workspaceRoot: project.paths.root });
292
+ logger.rootHeader();
293
+ packageJson.packageManager = `${to.name}@${to.version}`;
294
+ logger.rootStep(`adding "packageManager" field to ${project.name} root "package.json"`);
295
+ if (!(options == null ? void 0 : options.dry)) {
296
+ import_fs_extra3.default.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 });
297
+ if (hasWorkspaces) {
298
+ logger.rootStep(`adding "pnpm-workspace.yaml"`);
299
+ import_fs_extra3.default.writeFileSync(import_path3.default.join(project.paths.root, "pnpm-workspace.yaml"), `packages:
300
+ ${project.workspaceData.globs.map((w) => ` - "${w}"`).join("\n")}`);
301
+ }
302
+ }
303
+ if (hasWorkspaces) {
304
+ updateDependencies({
305
+ workspace: { name: "root", paths: project.paths },
306
+ project,
307
+ to,
308
+ logger,
309
+ options
310
+ });
311
+ logger.workspaceHeader();
312
+ project.workspaceData.workspaces.forEach((workspace) => updateDependencies({ workspace, project, to, logger, options }));
313
+ }
314
+ }
315
+ async function remove(args) {
316
+ const { project, logger, options } = args;
317
+ const hasWorkspaces = project.workspaceData.globs.length > 0;
318
+ logger.mainStep(`Removing ${project.packageManager}${hasWorkspaces ? "workspaces" : ""}`);
319
+ const packageJson = getPackageJson({ workspaceRoot: project.paths.root });
320
+ if (project.paths.workspaceConfig && hasWorkspaces) {
321
+ logger.subStep(`removing "pnpm-workspace.yaml"`);
322
+ if (!(options == null ? void 0 : options.dry)) {
323
+ import_fs_extra3.default.rmSync(project.paths.workspaceConfig, { force: true });
324
+ }
325
+ }
326
+ logger.subStep(`removing "packageManager" field in ${project.name} root "package.json"`);
327
+ delete packageJson.packageManager;
328
+ if (!(options == null ? void 0 : options.dry)) {
329
+ import_fs_extra3.default.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 });
330
+ const allModulesDirs = [
331
+ project.paths.nodeModules,
332
+ ...project.workspaceData.workspaces.map((w) => w.paths.nodeModules)
333
+ ];
334
+ try {
335
+ logger.subStep(`removing "node_modules"`);
336
+ await Promise.all(allModulesDirs.map((dir) => import_fs_extra3.default.rm(dir, { recursive: true, force: true })));
337
+ } catch (err) {
338
+ throw new ConvertError("Failed to remove node_modules");
339
+ }
340
+ }
341
+ }
342
+ async function clean(args) {
343
+ const { project, logger, options } = args;
344
+ logger.subStep(`removing ${import_path3.default.relative(project.paths.root, project.paths.lockfile)}`);
345
+ if (!(options == null ? void 0 : options.dry)) {
346
+ import_fs_extra3.default.rmSync(project.paths.lockfile, { force: true });
347
+ }
348
+ }
349
+ async function convertLock(args) {
350
+ const { project, logger, options } = args;
351
+ if (project.packageManager !== "pnpm") {
352
+ logger.subStep(`converting ${import_path3.default.relative(project.paths.root, project.paths.lockfile)} to pnpm-lock.yaml`);
353
+ if (!(options == null ? void 0 : options.dry) && import_fs_extra3.default.existsSync(project.paths.lockfile)) {
354
+ try {
355
+ await (0, import_execa.default)("pnpm", ["import"], {
356
+ stdio: "ignore",
357
+ cwd: project.paths.root
358
+ });
359
+ } finally {
360
+ import_fs_extra3.default.rmSync(project.paths.lockfile, { force: true });
361
+ }
362
+ }
363
+ }
364
+ }
365
+ var pnpm = {
366
+ detect,
367
+ read,
368
+ create,
369
+ remove,
370
+ clean,
371
+ convertLock
372
+ };
373
+ var pnpm_default = pnpm;
374
+
375
+ // src/managers/npm.ts
376
+ var import_fs_extra4 = __toESM(require("fs-extra"));
377
+ var import_path4 = __toESM(require("path"));
378
+ async function detect2(args) {
379
+ const lockFile = import_path4.default.join(args.workspaceRoot, "package-lock.json");
380
+ const packageManager = getWorkspacePackageManager({
381
+ workspaceRoot: args.workspaceRoot
382
+ });
383
+ return import_fs_extra4.default.existsSync(lockFile) || packageManager === "npm";
384
+ }
385
+ async function read2(args) {
386
+ const isNpm = await detect2(args);
387
+ if (!isNpm) {
388
+ throw new ConvertError("Not an npm project");
389
+ }
390
+ const packageJson = getPackageJson(args);
391
+ return {
392
+ name: getWorkspaceName(args),
393
+ packageManager: "npm",
394
+ paths: expandPaths({
395
+ root: args.workspaceRoot,
396
+ lockFile: "package-lock.json"
397
+ }),
398
+ workspaceData: {
399
+ globs: packageJson.workspaces || [],
400
+ workspaces: expandWorkspaces({
401
+ workspaceGlobs: packageJson.workspaces,
402
+ ...args
403
+ })
404
+ }
405
+ };
406
+ }
407
+ async function create2(args) {
408
+ const { project, options, to, logger } = args;
409
+ const hasWorkspaces = project.workspaceData.globs.length > 0;
410
+ logger.mainStep(`Creating ${project.packageManager}${hasWorkspaces ? "workspaces" : ""}`);
411
+ const packageJson = getPackageJson({ workspaceRoot: project.paths.root });
412
+ logger.rootHeader();
413
+ logger.rootStep(`adding "packageManager" field to ${project.name} root "package.json"`);
414
+ packageJson.packageManager = `${to.name}@${to.version}`;
415
+ if (hasWorkspaces) {
416
+ logger.rootStep(`adding "workspaces" field to ${project.name} root "package.json"`);
417
+ packageJson.workspaces = project.workspaceData.globs;
418
+ updateDependencies({
419
+ workspace: { name: "root", paths: project.paths },
420
+ project,
421
+ to,
422
+ logger,
423
+ options
424
+ });
425
+ logger.workspaceHeader();
426
+ project.workspaceData.workspaces.forEach((workspace) => updateDependencies({ workspace, project, to, logger, options }));
427
+ }
428
+ if (!(options == null ? void 0 : options.dry)) {
429
+ import_fs_extra4.default.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 });
430
+ }
431
+ }
432
+ async function remove2(args) {
433
+ const { project, logger, options } = args;
434
+ const hasWorkspaces = project.workspaceData.globs.length > 0;
435
+ logger.mainStep(`Creating ${project.packageManager}${hasWorkspaces ? "workspaces" : ""}`);
436
+ const packageJson = getPackageJson({ workspaceRoot: project.paths.root });
437
+ if (hasWorkspaces) {
438
+ logger.subStep(`removing "workspaces" field in ${project.name} root "package.json"`);
439
+ delete packageJson.workspaces;
440
+ }
441
+ logger.subStep(`removing "packageManager" field in ${project.name} root "package.json"`);
442
+ delete packageJson.packageManager;
443
+ if (!(options == null ? void 0 : options.dry)) {
444
+ import_fs_extra4.default.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 });
445
+ const allModulesDirs = [
446
+ project.paths.nodeModules,
447
+ ...project.workspaceData.workspaces.map((w) => w.paths.nodeModules)
448
+ ];
449
+ try {
450
+ logger.subStep(`removing "node_modules"`);
451
+ await Promise.all(allModulesDirs.map((dir) => import_fs_extra4.default.rm(dir, { recursive: true, force: true })));
452
+ } catch (err) {
453
+ throw new ConvertError("Failed to remove node_modules");
454
+ }
455
+ }
456
+ }
457
+ async function clean2(args) {
458
+ const { project, logger, options } = args;
459
+ logger.subStep(`removing ${import_path4.default.relative(project.paths.root, project.paths.lockfile)}`);
460
+ if (!(options == null ? void 0 : options.dry)) {
461
+ import_fs_extra4.default.rmSync(project.paths.lockfile, { force: true });
462
+ }
463
+ }
464
+ async function convertLock2(args) {
465
+ const { project, options } = args;
466
+ if (project.packageManager !== "npm") {
467
+ if (!(options == null ? void 0 : options.dry)) {
468
+ import_fs_extra4.default.rmSync(project.paths.lockfile, { force: true });
469
+ }
470
+ }
471
+ }
472
+ var npm = {
473
+ detect: detect2,
474
+ read: read2,
475
+ create: create2,
476
+ remove: remove2,
477
+ clean: clean2,
478
+ convertLock: convertLock2
479
+ };
480
+ var npm_default = npm;
481
+
482
+ // src/managers/yarn.ts
483
+ var import_fs_extra5 = __toESM(require("fs-extra"));
484
+ var import_path5 = __toESM(require("path"));
485
+ async function detect3(args) {
486
+ const lockFile = import_path5.default.join(args.workspaceRoot, "yarn.lock");
487
+ const packageManager = getWorkspacePackageManager({
488
+ workspaceRoot: args.workspaceRoot
489
+ });
490
+ return import_fs_extra5.default.existsSync(lockFile) || packageManager === "yarn";
491
+ }
492
+ async function read3(args) {
493
+ const isYarn = await detect3(args);
494
+ if (!isYarn) {
495
+ throw new ConvertError("Not a yarn project");
496
+ }
497
+ const packageJson = getPackageJson(args);
498
+ return {
499
+ name: getWorkspaceName(args),
500
+ packageManager: "yarn",
501
+ paths: expandPaths({
502
+ root: args.workspaceRoot,
503
+ lockFile: "yarn.lock"
504
+ }),
505
+ workspaceData: {
506
+ globs: packageJson.workspaces || [],
507
+ workspaces: expandWorkspaces({
508
+ workspaceGlobs: packageJson.workspaces,
509
+ ...args
510
+ })
511
+ }
512
+ };
513
+ }
514
+ async function create3(args) {
515
+ const { project, to, logger, options } = args;
516
+ const hasWorkspaces = project.workspaceData.globs.length > 0;
517
+ logger.mainStep(`Creating ${project.packageManager}${hasWorkspaces ? "workspaces" : ""}`);
518
+ const packageJson = getPackageJson({ workspaceRoot: project.paths.root });
519
+ logger.rootHeader();
520
+ logger.rootStep(`adding "packageManager" field to ${import_path5.default.relative(project.paths.root, project.paths.packageJson)}`);
521
+ packageJson.packageManager = `${to.name}@${to.version}`;
522
+ if (hasWorkspaces) {
523
+ logger.rootStep(`adding "workspaces" field to ${import_path5.default.relative(project.paths.root, project.paths.packageJson)}`);
524
+ packageJson.workspaces = project.workspaceData.globs;
525
+ updateDependencies({
526
+ workspace: { name: "root", paths: project.paths },
527
+ project,
528
+ to,
529
+ logger,
530
+ options
531
+ });
532
+ logger.workspaceHeader();
533
+ project.workspaceData.workspaces.forEach((workspace) => updateDependencies({ workspace, project, to, logger, options }));
534
+ }
535
+ if (!(options == null ? void 0 : options.dry)) {
536
+ import_fs_extra5.default.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 });
537
+ }
538
+ }
539
+ async function remove3(args) {
540
+ const { project, logger, options } = args;
541
+ const hasWorkspaces = project.workspaceData.globs.length > 0;
542
+ logger.mainStep(`Removing ${project.packageManager}${hasWorkspaces ? "workspaces" : ""}`);
543
+ const packageJson = getPackageJson({ workspaceRoot: project.paths.root });
544
+ if (hasWorkspaces) {
545
+ logger.subStep(`removing "workspaces" field in ${project.name} root "package.json"`);
546
+ delete packageJson.workspaces;
547
+ }
548
+ logger.subStep(`removing "packageManager" field in ${project.name} root "package.json"`);
549
+ delete packageJson.packageManager;
550
+ if (!(options == null ? void 0 : options.dry)) {
551
+ import_fs_extra5.default.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 });
552
+ const allModulesDirs = [
553
+ project.paths.nodeModules,
554
+ ...project.workspaceData.workspaces.map((w) => w.paths.nodeModules)
555
+ ];
556
+ try {
557
+ logger.subStep(`removing "node_modules"`);
558
+ await Promise.all(allModulesDirs.map((dir) => import_fs_extra5.default.rm(dir, { recursive: true, force: true })));
559
+ } catch (err) {
560
+ throw new ConvertError("Failed to remove node_modules");
561
+ }
562
+ }
563
+ }
564
+ async function clean3(args) {
565
+ const { project, logger, options } = args;
566
+ logger.subStep(`removing ${import_path5.default.relative(project.paths.root, project.paths.lockfile)}`);
567
+ if (!(options == null ? void 0 : options.dry)) {
568
+ import_fs_extra5.default.rmSync(project.paths.lockfile, { force: true });
569
+ }
570
+ }
571
+ async function convertLock3(args) {
572
+ const { project, options } = args;
573
+ if (project.packageManager !== "yarn") {
574
+ if (!(options == null ? void 0 : options.dry)) {
575
+ import_fs_extra5.default.rmSync(project.paths.lockfile, { force: true });
576
+ }
577
+ }
578
+ }
579
+ var yarn = {
580
+ detect: detect3,
581
+ read: read3,
582
+ create: create3,
583
+ remove: remove3,
584
+ clean: clean3,
585
+ convertLock: convertLock3
586
+ };
587
+ var yarn_default = yarn;
588
+
589
+ // src/managers/index.ts
590
+ var MANAGERS = {
591
+ pnpm: pnpm_default,
592
+ yarn: yarn_default,
593
+ npm: npm_default
594
+ };
595
+ var managers_default = MANAGERS;
596
+
597
+ // src/getWorkspaceDetails.ts
598
+ async function getWorkspaceDetails({
599
+ root
600
+ }) {
601
+ const { exists, absolute: workspaceRoot } = directoryInfo({
602
+ directory: root
603
+ });
604
+ if (!exists) {
605
+ throw new ConvertError(`Could not find directory at ${workspaceRoot}. Ensure the directory exists.`);
606
+ }
607
+ for (const { detect: detect4, read: read4 } of Object.values(managers_default)) {
608
+ if (await detect4({ workspaceRoot })) {
609
+ return read4({ workspaceRoot });
610
+ }
611
+ }
612
+ throw new ConvertError("Could not determine workspace manager. Add `packageManager` to `package.json` or ensure a lockfile is present.");
613
+ }
614
+
615
+ // src/convert.ts
616
+ var import_chalk2 = __toESM(require("chalk"));
617
+
618
+ // src/install.ts
619
+ var import_execa2 = __toESM(require("execa"));
620
+ var import_ora = __toESM(require("ora"));
621
+ var import_semver = require("semver");
622
+ var PACKAGE_MANAGERS = {
623
+ npm: [
624
+ {
625
+ name: "npm",
626
+ template: "npm",
627
+ command: "npm",
628
+ installArgs: ["install"],
629
+ version: "latest",
630
+ executable: "npx",
631
+ semver: "*"
632
+ }
633
+ ],
634
+ pnpm: [
635
+ {
636
+ name: "pnpm6",
637
+ template: "pnpm",
638
+ command: "pnpm",
639
+ installArgs: ["install"],
640
+ version: "latest-6",
641
+ executable: "pnpx",
642
+ semver: "6.x"
643
+ },
644
+ {
645
+ name: "pnpm",
646
+ template: "pnpm",
647
+ command: "pnpm",
648
+ installArgs: ["install"],
649
+ version: "latest",
650
+ executable: "pnpm dlx",
651
+ semver: ">=7"
652
+ }
653
+ ],
654
+ yarn: [
655
+ {
656
+ name: "yarn",
657
+ template: "yarn",
658
+ command: "yarn",
659
+ installArgs: ["install"],
660
+ version: "1.x",
661
+ executable: "npx",
662
+ semver: "<2"
663
+ },
664
+ {
665
+ name: "berry",
666
+ template: "berry",
667
+ command: "yarn",
668
+ installArgs: ["install", "--no-immutable"],
669
+ version: "stable",
670
+ executable: "yarn dlx",
671
+ semver: ">=2"
672
+ }
673
+ ]
674
+ };
675
+ async function install(args) {
676
+ const { to, logger, options } = args;
677
+ let packageManager = PACKAGE_MANAGERS[to.name].find((manager) => (0, import_semver.satisfies)(to.version, manager.semver));
678
+ if (!packageManager) {
679
+ throw new ConvertError("Unsupported package manager version.");
680
+ }
681
+ logger.subStep(`running "${packageManager.command} ${packageManager.installArgs}"`);
682
+ if (!(options == null ? void 0 : options.dry)) {
683
+ let spinner;
684
+ if (options == null ? void 0 : options.interactive) {
685
+ spinner = (0, import_ora.default)({
686
+ text: "Installing dependencies...",
687
+ spinner: {
688
+ frames: logger.installerFrames()
689
+ }
690
+ }).start();
691
+ }
692
+ try {
693
+ await (0, import_execa2.default)(packageManager.command, packageManager.installArgs, {
694
+ cwd: args.project.paths.root
695
+ });
696
+ logger.subStep(`dependencies installed`);
697
+ } catch (err) {
698
+ logger.subStepFailure(`failed to install dependencies`);
699
+ throw err;
700
+ } finally {
701
+ if (spinner) {
702
+ spinner.stop();
703
+ }
704
+ }
705
+ }
706
+ }
707
+ var install_default = install;
708
+
709
+ // src/convert.ts
710
+ async function convert({
711
+ project,
712
+ to,
713
+ logger,
714
+ options
715
+ }) {
716
+ logger.header(`Converting project from ${project.packageManager} to ${to.name}.`);
717
+ if (project.packageManager == to.name) {
718
+ throw new ConvertError("You are already using this package manager");
719
+ }
720
+ await managers_default[project.packageManager].remove({
721
+ project,
722
+ to,
723
+ logger,
724
+ options
725
+ });
726
+ await managers_default[to.name].create({ project, to, logger, options });
727
+ logger.mainStep("Installing dependencies");
728
+ if (!(options == null ? void 0 : options.skipInstall)) {
729
+ await managers_default[to.name].convertLock({ project, logger, options });
730
+ await install_default({ project, to, logger, options });
731
+ } else {
732
+ logger.subStep(import_chalk2.default.yellow("Skipping install"));
733
+ }
734
+ logger.mainStep(`Cleaning up ${project.packageManager} workspaces`);
735
+ await managers_default[project.packageManager].clean({ project, logger });
736
+ }
737
+ var convert_default = convert;
738
+
739
+ // src/logger.ts
740
+ var import_chalk3 = __toESM(require("chalk"));
741
+ var import_gradient_string = __toESM(require("gradient-string"));
742
+ var INDENTATION = 2;
743
+ var Logger = class {
744
+ constructor({
745
+ interactive,
746
+ dry
747
+ } = {}) {
748
+ this.interactive = interactive != null ? interactive : true;
749
+ this.dry = dry != null ? dry : false;
750
+ this.step = 1;
751
+ }
752
+ logger(...args) {
753
+ if (this.interactive) {
754
+ console.log(...args);
755
+ }
756
+ }
757
+ indented(level, ...args) {
758
+ this.logger(" ".repeat(INDENTATION * level), ...args);
759
+ }
760
+ header(title) {
761
+ this.blankLine();
762
+ this.logger(import_chalk3.default.bold(title));
763
+ }
764
+ installerFrames() {
765
+ const prefix = `${" ".repeat(INDENTATION)} - ${this.dry ? import_chalk3.default.yellow("SKIPPED | ") : import_chalk3.default.green("OK | ")}`;
766
+ return [`${prefix} `, `${prefix}> `, `${prefix}>> `, `${prefix}>>>`];
767
+ }
768
+ gradient(text) {
769
+ const turboGradient = (0, import_gradient_string.default)("#0099F7", "#F11712");
770
+ return turboGradient(text.toString());
771
+ }
772
+ hero() {
773
+ this.logger(import_chalk3.default.bold(this.gradient(`
774
+ >>> TURBOREPO
775
+ `)));
776
+ }
777
+ info(...args) {
778
+ this.logger(...args);
779
+ }
780
+ mainStep(title) {
781
+ this.blankLine();
782
+ this.logger(`${this.step}. ${import_chalk3.default.underline(title)}`);
783
+ this.step += 1;
784
+ }
785
+ subStep(...args) {
786
+ this.logger(" ".repeat(INDENTATION), `-`, this.dry ? import_chalk3.default.yellow("SKIPPED |") : import_chalk3.default.green("OK |"), ...args);
787
+ }
788
+ subStepFailure(...args) {
789
+ this.logger(" ".repeat(INDENTATION), `-`, import_chalk3.default.red("ERROR |"), ...args);
790
+ }
791
+ rootHeader() {
792
+ this.blankLine();
793
+ this.indented(2, "Root:");
794
+ }
795
+ rootStep(...args) {
796
+ this.logger(" ".repeat(INDENTATION * 3), `-`, this.dry ? import_chalk3.default.yellow("SKIPPED |") : import_chalk3.default.green("OK |"), ...args);
797
+ }
798
+ workspaceHeader() {
799
+ this.blankLine();
800
+ this.indented(2, "Workspaces:");
801
+ }
802
+ workspaceStep(...args) {
803
+ this.logger(" ".repeat(INDENTATION * 3), `-`, this.dry ? import_chalk3.default.yellow("SKIPPED |") : import_chalk3.default.green("OK |"), ...args);
804
+ }
805
+ blankLine() {
806
+ this.logger();
807
+ }
808
+ error(...args) {
809
+ console.error(...args);
810
+ }
811
+ };
812
+
813
+ // src/index.ts
814
+ async function convertMonorepo({
815
+ root,
816
+ to,
817
+ options
818
+ }) {
819
+ const logger = new Logger({ ...options, interactive: false });
820
+ const [project, availablePackageManagers] = await Promise.all([
821
+ getWorkspaceDetails({ root }),
822
+ (0, import_turbo_utils.getAvailablePackageManagers)()
823
+ ]);
824
+ await convert_default({
825
+ project,
826
+ to: {
827
+ name: to,
828
+ version: availablePackageManagers[to].version
829
+ },
830
+ logger,
831
+ options
832
+ });
833
+ }
834
+ // Annotate the CommonJS export names for ESM import in node:
835
+ 0 && (module.exports = {
836
+ MANAGERS,
837
+ convertMonorepo,
838
+ getWorkspaceDetails,
839
+ install
840
+ });