create-turbo-kit 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +4 -1
- package/dist/{chunk-6ZFG4OIY.js → chunk-Q43WSJ4J.js} +31 -2
- package/dist/chunk-Q43WSJ4J.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/helpers/transform.js +1 -1
- package/package.json +1 -1
- package/src/helpers/transform.ts +255 -215
- package/dist/chunk-6ZFG4OIY.js.map +0 -1
package/README.MD
CHANGED
|
@@ -28,4 +28,7 @@ To run the script (manually):
|
|
|
28
28
|
**Do not run in this directory!**
|
|
29
29
|
```bash
|
|
30
30
|
node <path-to-cli>/dist/cli.js
|
|
31
|
-
```
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Package manager support
|
|
34
|
+
Currently turbo-kit works with only pnpm. There is an issue with the template repo that breaks the conversion to other package managers that is typically handled by create-turbo.
|
|
@@ -39,6 +39,19 @@ var DOCKER_CONTAINERS = {
|
|
|
39
39
|
dependsOn: []
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
|
+
function sortPackageJsonDependencies(pkg) {
|
|
43
|
+
const depTypes = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
|
|
44
|
+
for (const depType of depTypes) {
|
|
45
|
+
const deps = pkg[depType];
|
|
46
|
+
if (deps && typeof deps === "object") {
|
|
47
|
+
const sorted = Object.keys(deps).sort().reduce((acc, key) => {
|
|
48
|
+
acc[key] = deps[key];
|
|
49
|
+
return acc;
|
|
50
|
+
}, {});
|
|
51
|
+
pkg[depType] = sorted;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
42
55
|
async function replaceScope(projectDir, newScope) {
|
|
43
56
|
const s = spinner();
|
|
44
57
|
s.start(`Replacing scope with ${color.cyan(newScope)}...`);
|
|
@@ -70,7 +83,23 @@ async function replaceScope(projectDir, newScope) {
|
|
|
70
83
|
}
|
|
71
84
|
})
|
|
72
85
|
);
|
|
73
|
-
s.
|
|
86
|
+
s.message("Sorting dependencies alphabetically...");
|
|
87
|
+
const packageJsonFiles = await fg("**/package.json", {
|
|
88
|
+
cwd: projectDir,
|
|
89
|
+
ignore: ["**/node_modules/**"],
|
|
90
|
+
absolute: true
|
|
91
|
+
});
|
|
92
|
+
await Promise.all(
|
|
93
|
+
packageJsonFiles.map(async (file) => {
|
|
94
|
+
try {
|
|
95
|
+
const pkg = await fs.readJson(file);
|
|
96
|
+
sortPackageJsonDependencies(pkg);
|
|
97
|
+
await fs.writeJson(file, pkg, { spaces: 2 });
|
|
98
|
+
} catch (e) {
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
s.stop(`Replaced scope with ${color.cyan(newScope)} and sorted dependencies`);
|
|
74
103
|
} catch (error) {
|
|
75
104
|
s.stop("Failed to replace scope");
|
|
76
105
|
throw error;
|
|
@@ -310,4 +339,4 @@ export {
|
|
|
310
339
|
removeReactEmail,
|
|
311
340
|
resolveCatalogVersions
|
|
312
341
|
};
|
|
313
|
-
//# sourceMappingURL=chunk-
|
|
342
|
+
//# sourceMappingURL=chunk-Q43WSJ4J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers/transform.ts"],"sourcesContent":["import fg from 'fast-glob';\r\nimport fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { spinner } from '@clack/prompts';\r\nimport color from 'picocolors';\r\nimport YAML from 'yaml';\r\nimport type { PackageManager } from '../utils/package-manager.js';\r\n\r\nconst DOCKER_CONTAINERS = {\r\n postgres: {\r\n label: 'PostgreSQL 16 (Database)',\r\n services: ['postgres'],\r\n volumes: ['postgres_data'],\r\n dependsOn: [], \r\n },\r\n pgadmin: {\r\n label: `pgAdmin 4.9 (Database management) [Depends on PostgreSQL]`,\r\n services: ['pgadmin'],\r\n volumes: [],\r\n dependsOn: ['postgres'],\r\n },\r\n redis: {\r\n label: 'Redis (Caching)',\r\n services: ['redis'],\r\n volumes: [],\r\n dependsOn: [],\r\n },\r\n mailpit: {\r\n label: 'Mailpit (Email testing)',\r\n services: ['mailpit'],\r\n volumes: [],\r\n dependsOn: [],\r\n },\r\n minio: {\r\n label: 'MinIO (S3-compatible storage)',\r\n services: ['minio', 'minio-create-bucket'],\r\n volumes: ['minio_data'],\r\n dependsOn: [],\r\n },\r\n} as const;\r\n\r\nexport type DockerContainer = keyof typeof DOCKER_CONTAINERS;\r\n\r\n/**\r\n * Sort dependencies alphabetically in a package.json object\r\n */\r\nfunction sortPackageJsonDependencies(pkg: PackageJson): void {\r\n const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const;\r\n \r\n for (const depType of depTypes) {\r\n const deps = pkg[depType];\r\n if (deps && typeof deps === 'object') {\r\n const sorted = Object.keys(deps)\r\n .sort()\r\n .reduce((acc, key) => {\r\n acc[key] = deps[key]!;\r\n return acc;\r\n }, {} as Record<string, string>);\r\n pkg[depType] = sorted;\r\n }\r\n }\r\n}\r\n\r\nexport async function replaceScope(projectDir: string, newScope: string) {\r\n const s = spinner();\r\n s.start(`Replacing scope with ${color.cyan(newScope)}...`);\r\n\r\n try {\r\n const files = await fg('**/*', {\r\n cwd: projectDir,\r\n ignore: [\r\n '**/.git/**',\r\n '**/node_modules/**',\r\n '**/.turbo/**',\r\n '**/dist/**',\r\n '**/.next/**',\r\n '**/pnpm-lock.yaml',\r\n '**/yarn.lock',\r\n '**/package-lock.json',\r\n '**/bun.lockb',\r\n ],\r\n absolute: true,\r\n });\r\n\r\n await Promise.all(\r\n files.map(async (file) => {\r\n try {\r\n const content = await fs.readFile(file, 'utf8');\r\n if (content.includes('@acme')) {\r\n const newContent = content.replace(/@acme/g, newScope);\r\n await fs.writeFile(file, newContent);\r\n }\r\n } catch (e) {\r\n }\r\n })\r\n );\r\n \r\n // Sort dependencies in all package.json files after replacing scope\r\n s.message('Sorting dependencies alphabetically...');\r\n const packageJsonFiles = await fg('**/package.json', {\r\n cwd: projectDir,\r\n ignore: ['**/node_modules/**'],\r\n absolute: true,\r\n });\r\n\r\n await Promise.all(\r\n packageJsonFiles.map(async (file) => {\r\n try {\r\n const pkg: PackageJson = await fs.readJson(file);\r\n sortPackageJsonDependencies(pkg);\r\n await fs.writeJson(file, pkg, { spaces: 2 });\r\n } catch (e) {\r\n // Ignore errors for malformed package.json files\r\n }\r\n })\r\n );\r\n \r\n s.stop(`Replaced scope with ${color.cyan(newScope)} and sorted dependencies`);\r\n } catch (error) {\r\n s.stop('Failed to replace scope');\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function setupEnv(projectDir: string) {\r\n const envExample = path.join(projectDir, '.env.example');\r\n const envDest = path.join(projectDir, '.env');\r\n\r\n if (await fs.pathExists(envExample)) {\r\n await fs.copy(envExample, envDest);\r\n }\r\n}\r\n\r\nexport function getDockerContainers() {\r\n return Object.entries(DOCKER_CONTAINERS).map(([value, config]) => ({\r\n value,\r\n label: config.label,\r\n }));\r\n}\r\n\r\nexport async function deleteDockerCompose(projectDir: string) {\r\n const s = spinner();\r\n s.start('Removing Docker Compose setup...');\r\n\r\n try {\r\n const dockerComposePath = path.join(projectDir, 'docker-compose.yml');\r\n if (await fs.pathExists(dockerComposePath)) {\r\n await fs.remove(dockerComposePath);\r\n s.message(`Removed ${color.cyan(dockerComposePath)}`);\r\n }\r\n const dockerDir = path.join(projectDir, 'docker');\r\n if (await fs.pathExists(dockerDir)) {\r\n await fs.remove(dockerDir);\r\n s.message(`Removed ${color.cyan(dockerDir)}`);\r\n }\r\n s.stop('Removed Docker Compose setup');\r\n } catch (error) {\r\n s.stop('Failed to remove Docker Compose setup');\r\n throw error;\r\n }\r\n}\r\n\r\nfunction resolveContainerDependencies(selectedContainers: string[]): string[] {\r\n const resolved = new Set<string>(selectedContainers);\r\n const queue = [...selectedContainers];\r\n\r\n while (queue.length > 0) {\r\n const current = queue.shift()!;\r\n const config = DOCKER_CONTAINERS[current as DockerContainer];\r\n \r\n if (config && config.dependsOn) {\r\n for (const dep of config.dependsOn) {\r\n if (!resolved.has(dep)) {\r\n resolved.add(dep);\r\n queue.push(dep);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return Array.from(resolved);\r\n}\r\n\r\nexport async function configureDockerCompose(projectDir: string, selectedContainers: string[]) {\r\n const s = spinner();\r\n s.start('Configuring Docker Compose...');\r\n\r\n try {\r\n const dockerComposePath = path.join(projectDir, 'docker-compose.yml');\r\n \r\n if (!(await fs.pathExists(dockerComposePath))) {\r\n s.stop('Docker Compose file not found');\r\n return;\r\n }\r\n\r\n const resolvedContainers = resolveContainerDependencies(selectedContainers);\r\n const addedDependencies = resolvedContainers.filter(c => !selectedContainers.includes(c));\r\n \r\n if (addedDependencies.length > 0) {\r\n s.message(`Auto-including dependencies: ${color.cyan(addedDependencies.join(', '))}`);\r\n }\r\n\r\n let content = await fs.readFile(dockerComposePath, 'utf8');\r\n\r\n const allContainers = Object.keys(DOCKER_CONTAINERS) as DockerContainer[];\r\n const containersToRemove = allContainers.filter(c => !resolvedContainers.includes(c));\r\n\r\n for (const container of containersToRemove) {\r\n const containerRegex = new RegExp(\r\n ` # -- ${container} --\\\\n[\\\\s\\\\S]*? # // ${container} //\\\\n`,\r\n 'g'\r\n );\r\n content = content.replace(containerRegex, '');\r\n\r\n // delete `./docker/<container>/`\r\n const dockerDirPath = path.join(projectDir, 'docker', container);\r\n if (await fs.pathExists(dockerDirPath)) {\r\n await fs.remove(dockerDirPath);\r\n s.message(`Removed ${color.cyan(dockerDirPath)}`);\r\n }\r\n }\r\n\r\n content = content.replace(/ # -- \\w+ --\\n/g, '');\r\n content = content.replace(/ # \\/\\/ \\w+ \\/\\/\\n/g, '');\r\n\r\n await fs.writeFile(dockerComposePath, content);\r\n\r\n // check if `./docker/` is empty\r\n const dockerDir = path.join(projectDir, 'docker');\r\n if (await fs.pathExists(dockerDir) && (await fs.readdir(dockerDir)).length === 0) {\r\n await fs.remove(dockerDir);\r\n s.message(`Removed ${color.cyan(dockerDir)} ${color.gray('(because it was empty)')}`);\r\n }\r\n \r\n s.stop(`Configured Docker Compose with ${color.cyan(resolvedContainers.length)} container(s)`);\r\n } catch (error) {\r\n s.stop('Failed to configure Docker Compose');\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function removePackages(\r\n packages: string[],\r\n packagePath: string,\r\n projectDir: string,\r\n s?: ReturnType<typeof spinner>\r\n) {\r\n const packageJsonPath = path.join(projectDir, packagePath, 'package.json');\r\n if (await fs.pathExists(packageJsonPath)) {\r\n const packageJson = await fs.readJson(packageJsonPath);\r\n let hasChanges = false;\r\n\r\n for (const dep of packages) {\r\n if (packageJson.dependencies && packageJson.dependencies[dep]) {\r\n delete packageJson.dependencies[dep];\r\n hasChanges = true;\r\n if (s) {\r\n s.message(`Removed ${color.cyan(dep)} from ${packagePath}/package.json`);\r\n }\r\n }\r\n }\r\n\r\n if (hasChanges) {\r\n await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });\r\n }\r\n }\r\n}\r\n\r\nexport async function removeReactEmail(projectDir: string) {\r\n const s = spinner();\r\n s.start('Removing react-email...');\r\n\r\n try {\r\n // remove email package\r\n const emailPackagePath = path.join(projectDir, 'packages', 'email');\r\n if (await fs.pathExists(emailPackagePath)) {\r\n await fs.remove(emailPackagePath);\r\n s.message(`Removed ${color.cyan(emailPackagePath)}`);\r\n }\r\n\r\n // remove @react-email/components from packages/api/package.json\r\n await removePackages(['@react-email/components', '@acme/email'], 'packages/api', projectDir, s);\r\n\r\n s.stop('Removed react-email');\r\n } catch (error) {\r\n s.stop('Failed to remove react-email');\r\n throw error;\r\n }\r\n}\r\n\r\ninterface PnpmWorkspace {\r\n packages?: string[];\r\n catalog?: Record<string, string>;\r\n catalogs?: Record<string, Record<string, string>>;\r\n overrides?: Record<string, string>;\r\n}\r\n\r\ninterface PackageJson {\r\n name?: string;\r\n packageManager?: string;\r\n dependencies?: Record<string, string>;\r\n devDependencies?: Record<string, string>;\r\n peerDependencies?: Record<string, string>;\r\n optionalDependencies?: Record<string, string>;\r\n pnpm?: {\r\n overrides?: Record<string, string>;\r\n [key: string]: unknown;\r\n };\r\n overrides?: Record<string, string>;\r\n resolutions?: Record<string, string>;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Resolves a version string that may contain catalog: or workspace: protocols\r\n */\r\nfunction resolveVersion(\r\n packageName: string,\r\n version: string,\r\n defaultCatalog: Record<string, string>,\r\n namedCatalogs: Record<string, Record<string, string>>\r\n): string {\r\n // Handle catalog: (default catalog)\r\n if (version === 'catalog:') {\r\n const resolved = defaultCatalog[packageName];\r\n if (resolved) {\r\n return resolved;\r\n }\r\n // If not found in catalog, keep original (will likely fail at install)\r\n return version;\r\n }\r\n\r\n // Handle catalog:catalogName (named catalog)\r\n if (version.startsWith('catalog:')) {\r\n const catalogName = version.slice('catalog:'.length);\r\n const catalog = namedCatalogs[catalogName];\r\n if (catalog && catalog[packageName]) {\r\n return catalog[packageName];\r\n }\r\n // If not found in named catalog, keep original\r\n return version;\r\n }\r\n\r\n // Handle workspace:* or workspace:^ etc.\r\n if (version.startsWith('workspace:')) {\r\n return '*';\r\n }\r\n\r\n return version;\r\n}\r\n\r\n/**\r\n * Resolves catalog versions in an overrides/resolutions object\r\n */\r\nfunction resolveOverrides(\r\n overrides: Record<string, string>,\r\n defaultCatalog: Record<string, string>,\r\n namedCatalogs: Record<string, Record<string, string>>\r\n): Record<string, string> {\r\n const resolved: Record<string, string> = {};\r\n \r\n for (const [pkg, version] of Object.entries(overrides)) {\r\n resolved[pkg] = resolveVersion(pkg, version, defaultCatalog, namedCatalogs);\r\n }\r\n \r\n return resolved;\r\n}\r\n\r\n/**\r\n * Resolves pnpm catalog versions in all package.json files when using a non-pnpm package manager.\r\n * \r\n * This transform:\r\n * 1. Parses pnpm-workspace.yaml to extract catalog version mappings\r\n * 2. Replaces catalog: and catalog:name versions with actual versions in all package.json files\r\n * 3. Replaces workspace:* references with *\r\n * 4. Converts pnpm.overrides to overrides (npm/bun) or resolutions (yarn)\r\n * 5. Removes the packageManager field from root package.json\r\n * 6. Deletes pnpm-workspace.yaml\r\n */\r\nexport async function resolveCatalogVersions(\r\n projectDir: string,\r\n packageManager: PackageManager\r\n) {\r\n const s = spinner();\r\n s.start('Resolving pnpm catalog versions...');\r\n\r\n try {\r\n // 1. Parse pnpm-workspace.yaml\r\n const workspaceYamlPath = path.join(projectDir, 'pnpm-workspace.yaml');\r\n \r\n if (!(await fs.pathExists(workspaceYamlPath))) {\r\n s.stop('No pnpm-workspace.yaml found, skipping catalog resolution');\r\n return;\r\n }\r\n\r\n const workspaceContent = await fs.readFile(workspaceYamlPath, 'utf8');\r\n const workspace: PnpmWorkspace = YAML.parse(workspaceContent);\r\n\r\n const defaultCatalog = workspace.catalog ?? {};\r\n const namedCatalogs = workspace.catalogs ?? {};\r\n\r\n // 2. Find all package.json files\r\n const packageJsonFiles = await fg('**/package.json', {\r\n cwd: projectDir,\r\n ignore: ['**/node_modules/**'],\r\n absolute: true,\r\n });\r\n\r\n let totalResolved = 0;\r\n\r\n // 3. Process each package.json\r\n for (const filePath of packageJsonFiles) {\r\n const pkg: PackageJson = await fs.readJson(filePath);\r\n let modified = false;\r\n const relativePath = path.relative(projectDir, filePath);\r\n\r\n // Process all dependency types\r\n const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const;\r\n \r\n for (const depType of depTypes) {\r\n const deps = pkg[depType];\r\n if (deps) {\r\n for (const [name, version] of Object.entries(deps)) {\r\n const resolved = resolveVersion(name, version, defaultCatalog, namedCatalogs);\r\n if (resolved !== version) {\r\n deps[name] = resolved;\r\n modified = true;\r\n totalResolved++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 4. Handle pnpm.overrides\r\n if (pkg.pnpm?.overrides) {\r\n const resolvedOverrides = resolveOverrides(\r\n pkg.pnpm.overrides,\r\n defaultCatalog,\r\n namedCatalogs\r\n );\r\n\r\n if (packageManager === 'yarn') {\r\n // Yarn uses 'resolutions'\r\n pkg.resolutions = { ...(pkg.resolutions ?? {}), ...resolvedOverrides };\r\n } else {\r\n // npm and bun use 'overrides'\r\n pkg.overrides = { ...(pkg.overrides ?? {}), ...resolvedOverrides };\r\n }\r\n\r\n // Remove pnpm-specific field\r\n delete pkg.pnpm;\r\n modified = true;\r\n s.message(`Converted pnpm.overrides in ${color.cyan(relativePath)}`);\r\n }\r\n\r\n // 5. Remove packageManager field from root package.json\r\n if (relativePath === 'package.json' && pkg.packageManager) {\r\n delete pkg.packageManager;\r\n modified = true;\r\n }\r\n\r\n if (modified) {\r\n await fs.writeJson(filePath, pkg, { spaces: 2 });\r\n }\r\n }\r\n\r\n // 6. Delete pnpm-workspace.yaml\r\n await fs.remove(workspaceYamlPath);\r\n\r\n s.stop(`Resolved ${color.cyan(totalResolved.toString())} catalog versions`);\r\n } catch (error) {\r\n s.stop('Failed to resolve catalog versions');\r\n throw error;\r\n }\r\n}\r\n\r\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
package/package.json
CHANGED
package/src/helpers/transform.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import fg from 'fast-glob';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { spinner } from '@clack/prompts';
|
|
5
|
-
import color from 'picocolors';
|
|
6
|
-
import YAML from 'yaml';
|
|
7
|
-
import type { PackageManager } from '../utils/package-manager.js';
|
|
1
|
+
import fg from 'fast-glob';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { spinner } from '@clack/prompts';
|
|
5
|
+
import color from 'picocolors';
|
|
6
|
+
import YAML from 'yaml';
|
|
7
|
+
import type { PackageManager } from '../utils/package-manager.js';
|
|
8
8
|
|
|
9
9
|
const DOCKER_CONTAINERS = {
|
|
10
10
|
postgres: {
|
|
@@ -41,6 +41,26 @@ const DOCKER_CONTAINERS = {
|
|
|
41
41
|
|
|
42
42
|
export type DockerContainer = keyof typeof DOCKER_CONTAINERS;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Sort dependencies alphabetically in a package.json object
|
|
46
|
+
*/
|
|
47
|
+
function sortPackageJsonDependencies(pkg: PackageJson): void {
|
|
48
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const;
|
|
49
|
+
|
|
50
|
+
for (const depType of depTypes) {
|
|
51
|
+
const deps = pkg[depType];
|
|
52
|
+
if (deps && typeof deps === 'object') {
|
|
53
|
+
const sorted = Object.keys(deps)
|
|
54
|
+
.sort()
|
|
55
|
+
.reduce((acc, key) => {
|
|
56
|
+
acc[key] = deps[key]!;
|
|
57
|
+
return acc;
|
|
58
|
+
}, {} as Record<string, string>);
|
|
59
|
+
pkg[depType] = sorted;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
44
64
|
export async function replaceScope(projectDir: string, newScope: string) {
|
|
45
65
|
const s = spinner();
|
|
46
66
|
s.start(`Replacing scope with ${color.cyan(newScope)}...`);
|
|
@@ -75,7 +95,27 @@ export async function replaceScope(projectDir: string, newScope: string) {
|
|
|
75
95
|
})
|
|
76
96
|
);
|
|
77
97
|
|
|
78
|
-
|
|
98
|
+
// Sort dependencies in all package.json files after replacing scope
|
|
99
|
+
s.message('Sorting dependencies alphabetically...');
|
|
100
|
+
const packageJsonFiles = await fg('**/package.json', {
|
|
101
|
+
cwd: projectDir,
|
|
102
|
+
ignore: ['**/node_modules/**'],
|
|
103
|
+
absolute: true,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await Promise.all(
|
|
107
|
+
packageJsonFiles.map(async (file) => {
|
|
108
|
+
try {
|
|
109
|
+
const pkg: PackageJson = await fs.readJson(file);
|
|
110
|
+
sortPackageJsonDependencies(pkg);
|
|
111
|
+
await fs.writeJson(file, pkg, { spaces: 2 });
|
|
112
|
+
} catch (e) {
|
|
113
|
+
// Ignore errors for malformed package.json files
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
s.stop(`Replaced scope with ${color.cyan(newScope)} and sorted dependencies`);
|
|
79
119
|
} catch (error) {
|
|
80
120
|
s.stop('Failed to replace scope');
|
|
81
121
|
throw error;
|
|
@@ -226,211 +266,211 @@ export async function removePackages(
|
|
|
226
266
|
}
|
|
227
267
|
}
|
|
228
268
|
|
|
229
|
-
export async function removeReactEmail(projectDir: string) {
|
|
230
|
-
const s = spinner();
|
|
231
|
-
s.start('Removing react-email...');
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
// remove email package
|
|
235
|
-
const emailPackagePath = path.join(projectDir, 'packages', 'email');
|
|
236
|
-
if (await fs.pathExists(emailPackagePath)) {
|
|
237
|
-
await fs.remove(emailPackagePath);
|
|
238
|
-
s.message(`Removed ${color.cyan(emailPackagePath)}`);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// remove @react-email/components from packages/api/package.json
|
|
242
|
-
await removePackages(['@react-email/components', '@acme/email'], 'packages/api', projectDir, s);
|
|
243
|
-
|
|
244
|
-
s.stop('Removed react-email');
|
|
245
|
-
} catch (error) {
|
|
246
|
-
s.stop('Failed to remove react-email');
|
|
247
|
-
throw error;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
interface PnpmWorkspace {
|
|
252
|
-
packages?: string[];
|
|
253
|
-
catalog?: Record<string, string>;
|
|
254
|
-
catalogs?: Record<string, Record<string, string>>;
|
|
255
|
-
overrides?: Record<string, string>;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
interface PackageJson {
|
|
259
|
-
name?: string;
|
|
260
|
-
packageManager?: string;
|
|
261
|
-
dependencies?: Record<string, string>;
|
|
262
|
-
devDependencies?: Record<string, string>;
|
|
263
|
-
peerDependencies?: Record<string, string>;
|
|
264
|
-
optionalDependencies?: Record<string, string>;
|
|
265
|
-
pnpm?: {
|
|
266
|
-
overrides?: Record<string, string>;
|
|
267
|
-
[key: string]: unknown;
|
|
268
|
-
};
|
|
269
|
-
overrides?: Record<string, string>;
|
|
270
|
-
resolutions?: Record<string, string>;
|
|
271
|
-
[key: string]: unknown;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Resolves a version string that may contain catalog: or workspace: protocols
|
|
276
|
-
*/
|
|
277
|
-
function resolveVersion(
|
|
278
|
-
packageName: string,
|
|
279
|
-
version: string,
|
|
280
|
-
defaultCatalog: Record<string, string>,
|
|
281
|
-
namedCatalogs: Record<string, Record<string, string>>
|
|
282
|
-
): string {
|
|
283
|
-
// Handle catalog: (default catalog)
|
|
284
|
-
if (version === 'catalog:') {
|
|
285
|
-
const resolved = defaultCatalog[packageName];
|
|
286
|
-
if (resolved) {
|
|
287
|
-
return resolved;
|
|
288
|
-
}
|
|
289
|
-
// If not found in catalog, keep original (will likely fail at install)
|
|
290
|
-
return version;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Handle catalog:catalogName (named catalog)
|
|
294
|
-
if (version.startsWith('catalog:')) {
|
|
295
|
-
const catalogName = version.slice('catalog:'.length);
|
|
296
|
-
const catalog = namedCatalogs[catalogName];
|
|
297
|
-
if (catalog && catalog[packageName]) {
|
|
298
|
-
return catalog[packageName];
|
|
299
|
-
}
|
|
300
|
-
// If not found in named catalog, keep original
|
|
301
|
-
return version;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Handle workspace:* or workspace:^ etc.
|
|
305
|
-
if (version.startsWith('workspace:')) {
|
|
306
|
-
return '*';
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return version;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Resolves catalog versions in an overrides/resolutions object
|
|
314
|
-
*/
|
|
315
|
-
function resolveOverrides(
|
|
316
|
-
overrides: Record<string, string>,
|
|
317
|
-
defaultCatalog: Record<string, string>,
|
|
318
|
-
namedCatalogs: Record<string, Record<string, string>>
|
|
319
|
-
): Record<string, string> {
|
|
320
|
-
const resolved: Record<string, string> = {};
|
|
321
|
-
|
|
322
|
-
for (const [pkg, version] of Object.entries(overrides)) {
|
|
323
|
-
resolved[pkg] = resolveVersion(pkg, version, defaultCatalog, namedCatalogs);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
return resolved;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Resolves pnpm catalog versions in all package.json files when using a non-pnpm package manager.
|
|
331
|
-
*
|
|
332
|
-
* This transform:
|
|
333
|
-
* 1. Parses pnpm-workspace.yaml to extract catalog version mappings
|
|
334
|
-
* 2. Replaces catalog: and catalog:name versions with actual versions in all package.json files
|
|
335
|
-
* 3. Replaces workspace:* references with *
|
|
336
|
-
* 4. Converts pnpm.overrides to overrides (npm/bun) or resolutions (yarn)
|
|
337
|
-
* 5. Removes the packageManager field from root package.json
|
|
338
|
-
* 6. Deletes pnpm-workspace.yaml
|
|
339
|
-
*/
|
|
340
|
-
export async function resolveCatalogVersions(
|
|
341
|
-
projectDir: string,
|
|
342
|
-
packageManager: PackageManager
|
|
343
|
-
) {
|
|
344
|
-
const s = spinner();
|
|
345
|
-
s.start('Resolving pnpm catalog versions...');
|
|
346
|
-
|
|
347
|
-
try {
|
|
348
|
-
// 1. Parse pnpm-workspace.yaml
|
|
349
|
-
const workspaceYamlPath = path.join(projectDir, 'pnpm-workspace.yaml');
|
|
350
|
-
|
|
351
|
-
if (!(await fs.pathExists(workspaceYamlPath))) {
|
|
352
|
-
s.stop('No pnpm-workspace.yaml found, skipping catalog resolution');
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const workspaceContent = await fs.readFile(workspaceYamlPath, 'utf8');
|
|
357
|
-
const workspace: PnpmWorkspace = YAML.parse(workspaceContent);
|
|
358
|
-
|
|
359
|
-
const defaultCatalog = workspace.catalog ?? {};
|
|
360
|
-
const namedCatalogs = workspace.catalogs ?? {};
|
|
361
|
-
|
|
362
|
-
// 2. Find all package.json files
|
|
363
|
-
const packageJsonFiles = await fg('**/package.json', {
|
|
364
|
-
cwd: projectDir,
|
|
365
|
-
ignore: ['**/node_modules/**'],
|
|
366
|
-
absolute: true,
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
let totalResolved = 0;
|
|
370
|
-
|
|
371
|
-
// 3. Process each package.json
|
|
372
|
-
for (const filePath of packageJsonFiles) {
|
|
373
|
-
const pkg: PackageJson = await fs.readJson(filePath);
|
|
374
|
-
let modified = false;
|
|
375
|
-
const relativePath = path.relative(projectDir, filePath);
|
|
376
|
-
|
|
377
|
-
// Process all dependency types
|
|
378
|
-
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const;
|
|
379
|
-
|
|
380
|
-
for (const depType of depTypes) {
|
|
381
|
-
const deps = pkg[depType];
|
|
382
|
-
if (deps) {
|
|
383
|
-
for (const [name, version] of Object.entries(deps)) {
|
|
384
|
-
const resolved = resolveVersion(name, version, defaultCatalog, namedCatalogs);
|
|
385
|
-
if (resolved !== version) {
|
|
386
|
-
deps[name] = resolved;
|
|
387
|
-
modified = true;
|
|
388
|
-
totalResolved++;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// 4. Handle pnpm.overrides
|
|
395
|
-
if (pkg.pnpm?.overrides) {
|
|
396
|
-
const resolvedOverrides = resolveOverrides(
|
|
397
|
-
pkg.pnpm.overrides,
|
|
398
|
-
defaultCatalog,
|
|
399
|
-
namedCatalogs
|
|
400
|
-
);
|
|
401
|
-
|
|
402
|
-
if (packageManager === 'yarn') {
|
|
403
|
-
// Yarn uses 'resolutions'
|
|
404
|
-
pkg.resolutions = { ...(pkg.resolutions ?? {}), ...resolvedOverrides };
|
|
405
|
-
} else {
|
|
406
|
-
// npm and bun use 'overrides'
|
|
407
|
-
pkg.overrides = { ...(pkg.overrides ?? {}), ...resolvedOverrides };
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// Remove pnpm-specific field
|
|
411
|
-
delete pkg.pnpm;
|
|
412
|
-
modified = true;
|
|
413
|
-
s.message(`Converted pnpm.overrides in ${color.cyan(relativePath)}`);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// 5. Remove packageManager field from root package.json
|
|
417
|
-
if (relativePath === 'package.json' && pkg.packageManager) {
|
|
418
|
-
delete pkg.packageManager;
|
|
419
|
-
modified = true;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (modified) {
|
|
423
|
-
await fs.writeJson(filePath, pkg, { spaces: 2 });
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// 6. Delete pnpm-workspace.yaml
|
|
428
|
-
await fs.remove(workspaceYamlPath);
|
|
429
|
-
|
|
430
|
-
s.stop(`Resolved ${color.cyan(totalResolved.toString())} catalog versions`);
|
|
431
|
-
} catch (error) {
|
|
432
|
-
s.stop('Failed to resolve catalog versions');
|
|
433
|
-
throw error;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
269
|
+
export async function removeReactEmail(projectDir: string) {
|
|
270
|
+
const s = spinner();
|
|
271
|
+
s.start('Removing react-email...');
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
// remove email package
|
|
275
|
+
const emailPackagePath = path.join(projectDir, 'packages', 'email');
|
|
276
|
+
if (await fs.pathExists(emailPackagePath)) {
|
|
277
|
+
await fs.remove(emailPackagePath);
|
|
278
|
+
s.message(`Removed ${color.cyan(emailPackagePath)}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// remove @react-email/components from packages/api/package.json
|
|
282
|
+
await removePackages(['@react-email/components', '@acme/email'], 'packages/api', projectDir, s);
|
|
283
|
+
|
|
284
|
+
s.stop('Removed react-email');
|
|
285
|
+
} catch (error) {
|
|
286
|
+
s.stop('Failed to remove react-email');
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
interface PnpmWorkspace {
|
|
292
|
+
packages?: string[];
|
|
293
|
+
catalog?: Record<string, string>;
|
|
294
|
+
catalogs?: Record<string, Record<string, string>>;
|
|
295
|
+
overrides?: Record<string, string>;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
interface PackageJson {
|
|
299
|
+
name?: string;
|
|
300
|
+
packageManager?: string;
|
|
301
|
+
dependencies?: Record<string, string>;
|
|
302
|
+
devDependencies?: Record<string, string>;
|
|
303
|
+
peerDependencies?: Record<string, string>;
|
|
304
|
+
optionalDependencies?: Record<string, string>;
|
|
305
|
+
pnpm?: {
|
|
306
|
+
overrides?: Record<string, string>;
|
|
307
|
+
[key: string]: unknown;
|
|
308
|
+
};
|
|
309
|
+
overrides?: Record<string, string>;
|
|
310
|
+
resolutions?: Record<string, string>;
|
|
311
|
+
[key: string]: unknown;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Resolves a version string that may contain catalog: or workspace: protocols
|
|
316
|
+
*/
|
|
317
|
+
function resolveVersion(
|
|
318
|
+
packageName: string,
|
|
319
|
+
version: string,
|
|
320
|
+
defaultCatalog: Record<string, string>,
|
|
321
|
+
namedCatalogs: Record<string, Record<string, string>>
|
|
322
|
+
): string {
|
|
323
|
+
// Handle catalog: (default catalog)
|
|
324
|
+
if (version === 'catalog:') {
|
|
325
|
+
const resolved = defaultCatalog[packageName];
|
|
326
|
+
if (resolved) {
|
|
327
|
+
return resolved;
|
|
328
|
+
}
|
|
329
|
+
// If not found in catalog, keep original (will likely fail at install)
|
|
330
|
+
return version;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Handle catalog:catalogName (named catalog)
|
|
334
|
+
if (version.startsWith('catalog:')) {
|
|
335
|
+
const catalogName = version.slice('catalog:'.length);
|
|
336
|
+
const catalog = namedCatalogs[catalogName];
|
|
337
|
+
if (catalog && catalog[packageName]) {
|
|
338
|
+
return catalog[packageName];
|
|
339
|
+
}
|
|
340
|
+
// If not found in named catalog, keep original
|
|
341
|
+
return version;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Handle workspace:* or workspace:^ etc.
|
|
345
|
+
if (version.startsWith('workspace:')) {
|
|
346
|
+
return '*';
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return version;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Resolves catalog versions in an overrides/resolutions object
|
|
354
|
+
*/
|
|
355
|
+
function resolveOverrides(
|
|
356
|
+
overrides: Record<string, string>,
|
|
357
|
+
defaultCatalog: Record<string, string>,
|
|
358
|
+
namedCatalogs: Record<string, Record<string, string>>
|
|
359
|
+
): Record<string, string> {
|
|
360
|
+
const resolved: Record<string, string> = {};
|
|
361
|
+
|
|
362
|
+
for (const [pkg, version] of Object.entries(overrides)) {
|
|
363
|
+
resolved[pkg] = resolveVersion(pkg, version, defaultCatalog, namedCatalogs);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return resolved;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Resolves pnpm catalog versions in all package.json files when using a non-pnpm package manager.
|
|
371
|
+
*
|
|
372
|
+
* This transform:
|
|
373
|
+
* 1. Parses pnpm-workspace.yaml to extract catalog version mappings
|
|
374
|
+
* 2. Replaces catalog: and catalog:name versions with actual versions in all package.json files
|
|
375
|
+
* 3. Replaces workspace:* references with *
|
|
376
|
+
* 4. Converts pnpm.overrides to overrides (npm/bun) or resolutions (yarn)
|
|
377
|
+
* 5. Removes the packageManager field from root package.json
|
|
378
|
+
* 6. Deletes pnpm-workspace.yaml
|
|
379
|
+
*/
|
|
380
|
+
export async function resolveCatalogVersions(
|
|
381
|
+
projectDir: string,
|
|
382
|
+
packageManager: PackageManager
|
|
383
|
+
) {
|
|
384
|
+
const s = spinner();
|
|
385
|
+
s.start('Resolving pnpm catalog versions...');
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
// 1. Parse pnpm-workspace.yaml
|
|
389
|
+
const workspaceYamlPath = path.join(projectDir, 'pnpm-workspace.yaml');
|
|
390
|
+
|
|
391
|
+
if (!(await fs.pathExists(workspaceYamlPath))) {
|
|
392
|
+
s.stop('No pnpm-workspace.yaml found, skipping catalog resolution');
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const workspaceContent = await fs.readFile(workspaceYamlPath, 'utf8');
|
|
397
|
+
const workspace: PnpmWorkspace = YAML.parse(workspaceContent);
|
|
398
|
+
|
|
399
|
+
const defaultCatalog = workspace.catalog ?? {};
|
|
400
|
+
const namedCatalogs = workspace.catalogs ?? {};
|
|
401
|
+
|
|
402
|
+
// 2. Find all package.json files
|
|
403
|
+
const packageJsonFiles = await fg('**/package.json', {
|
|
404
|
+
cwd: projectDir,
|
|
405
|
+
ignore: ['**/node_modules/**'],
|
|
406
|
+
absolute: true,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
let totalResolved = 0;
|
|
410
|
+
|
|
411
|
+
// 3. Process each package.json
|
|
412
|
+
for (const filePath of packageJsonFiles) {
|
|
413
|
+
const pkg: PackageJson = await fs.readJson(filePath);
|
|
414
|
+
let modified = false;
|
|
415
|
+
const relativePath = path.relative(projectDir, filePath);
|
|
416
|
+
|
|
417
|
+
// Process all dependency types
|
|
418
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const;
|
|
419
|
+
|
|
420
|
+
for (const depType of depTypes) {
|
|
421
|
+
const deps = pkg[depType];
|
|
422
|
+
if (deps) {
|
|
423
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
424
|
+
const resolved = resolveVersion(name, version, defaultCatalog, namedCatalogs);
|
|
425
|
+
if (resolved !== version) {
|
|
426
|
+
deps[name] = resolved;
|
|
427
|
+
modified = true;
|
|
428
|
+
totalResolved++;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 4. Handle pnpm.overrides
|
|
435
|
+
if (pkg.pnpm?.overrides) {
|
|
436
|
+
const resolvedOverrides = resolveOverrides(
|
|
437
|
+
pkg.pnpm.overrides,
|
|
438
|
+
defaultCatalog,
|
|
439
|
+
namedCatalogs
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
if (packageManager === 'yarn') {
|
|
443
|
+
// Yarn uses 'resolutions'
|
|
444
|
+
pkg.resolutions = { ...(pkg.resolutions ?? {}), ...resolvedOverrides };
|
|
445
|
+
} else {
|
|
446
|
+
// npm and bun use 'overrides'
|
|
447
|
+
pkg.overrides = { ...(pkg.overrides ?? {}), ...resolvedOverrides };
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Remove pnpm-specific field
|
|
451
|
+
delete pkg.pnpm;
|
|
452
|
+
modified = true;
|
|
453
|
+
s.message(`Converted pnpm.overrides in ${color.cyan(relativePath)}`);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// 5. Remove packageManager field from root package.json
|
|
457
|
+
if (relativePath === 'package.json' && pkg.packageManager) {
|
|
458
|
+
delete pkg.packageManager;
|
|
459
|
+
modified = true;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (modified) {
|
|
463
|
+
await fs.writeJson(filePath, pkg, { spaces: 2 });
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// 6. Delete pnpm-workspace.yaml
|
|
468
|
+
await fs.remove(workspaceYamlPath);
|
|
469
|
+
|
|
470
|
+
s.stop(`Resolved ${color.cyan(totalResolved.toString())} catalog versions`);
|
|
471
|
+
} catch (error) {
|
|
472
|
+
s.stop('Failed to resolve catalog versions');
|
|
473
|
+
throw error;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
436
476
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/helpers/transform.ts"],"sourcesContent":["import fg from 'fast-glob';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { spinner } from '@clack/prompts';\nimport color from 'picocolors';\nimport YAML from 'yaml';\nimport type { PackageManager } from '../utils/package-manager.js';\n\r\nconst DOCKER_CONTAINERS = {\r\n postgres: {\r\n label: 'PostgreSQL 16 (Database)',\r\n services: ['postgres'],\r\n volumes: ['postgres_data'],\r\n dependsOn: [], \r\n },\r\n pgadmin: {\r\n label: `pgAdmin 4.9 (Database management) [Depends on PostgreSQL]`,\r\n services: ['pgadmin'],\r\n volumes: [],\r\n dependsOn: ['postgres'],\r\n },\r\n redis: {\r\n label: 'Redis (Caching)',\r\n services: ['redis'],\r\n volumes: [],\r\n dependsOn: [],\r\n },\r\n mailpit: {\r\n label: 'Mailpit (Email testing)',\r\n services: ['mailpit'],\r\n volumes: [],\r\n dependsOn: [],\r\n },\r\n minio: {\r\n label: 'MinIO (S3-compatible storage)',\r\n services: ['minio', 'minio-create-bucket'],\r\n volumes: ['minio_data'],\r\n dependsOn: [],\r\n },\r\n} as const;\r\n\r\nexport type DockerContainer = keyof typeof DOCKER_CONTAINERS;\r\n\r\nexport async function replaceScope(projectDir: string, newScope: string) {\r\n const s = spinner();\r\n s.start(`Replacing scope with ${color.cyan(newScope)}...`);\r\n\r\n try {\r\n const files = await fg('**/*', {\r\n cwd: projectDir,\r\n ignore: [\r\n '**/.git/**',\r\n '**/node_modules/**',\r\n '**/.turbo/**',\r\n '**/dist/**',\r\n '**/.next/**',\r\n '**/pnpm-lock.yaml',\r\n '**/yarn.lock',\r\n '**/package-lock.json',\r\n '**/bun.lockb',\r\n ],\r\n absolute: true,\r\n });\r\n\r\n await Promise.all(\r\n files.map(async (file) => {\r\n try {\r\n const content = await fs.readFile(file, 'utf8');\r\n if (content.includes('@acme')) {\r\n const newContent = content.replace(/@acme/g, newScope);\r\n await fs.writeFile(file, newContent);\r\n }\r\n } catch (e) {\r\n }\r\n })\r\n );\r\n \r\n s.stop(`Replaced scope with ${color.cyan(newScope)}`);\r\n } catch (error) {\r\n s.stop('Failed to replace scope');\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function setupEnv(projectDir: string) {\r\n const envExample = path.join(projectDir, '.env.example');\r\n const envDest = path.join(projectDir, '.env');\r\n\r\n if (await fs.pathExists(envExample)) {\r\n await fs.copy(envExample, envDest);\r\n }\r\n}\r\n\r\nexport function getDockerContainers() {\r\n return Object.entries(DOCKER_CONTAINERS).map(([value, config]) => ({\r\n value,\r\n label: config.label,\r\n }));\r\n}\r\n\r\nexport async function deleteDockerCompose(projectDir: string) {\r\n const s = spinner();\r\n s.start('Removing Docker Compose setup...');\r\n\r\n try {\r\n const dockerComposePath = path.join(projectDir, 'docker-compose.yml');\r\n if (await fs.pathExists(dockerComposePath)) {\r\n await fs.remove(dockerComposePath);\r\n s.message(`Removed ${color.cyan(dockerComposePath)}`);\r\n }\r\n const dockerDir = path.join(projectDir, 'docker');\r\n if (await fs.pathExists(dockerDir)) {\r\n await fs.remove(dockerDir);\r\n s.message(`Removed ${color.cyan(dockerDir)}`);\r\n }\r\n s.stop('Removed Docker Compose setup');\r\n } catch (error) {\r\n s.stop('Failed to remove Docker Compose setup');\r\n throw error;\r\n }\r\n}\r\n\r\nfunction resolveContainerDependencies(selectedContainers: string[]): string[] {\r\n const resolved = new Set<string>(selectedContainers);\r\n const queue = [...selectedContainers];\r\n\r\n while (queue.length > 0) {\r\n const current = queue.shift()!;\r\n const config = DOCKER_CONTAINERS[current as DockerContainer];\r\n \r\n if (config && config.dependsOn) {\r\n for (const dep of config.dependsOn) {\r\n if (!resolved.has(dep)) {\r\n resolved.add(dep);\r\n queue.push(dep);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return Array.from(resolved);\r\n}\r\n\r\nexport async function configureDockerCompose(projectDir: string, selectedContainers: string[]) {\r\n const s = spinner();\r\n s.start('Configuring Docker Compose...');\r\n\r\n try {\r\n const dockerComposePath = path.join(projectDir, 'docker-compose.yml');\r\n \r\n if (!(await fs.pathExists(dockerComposePath))) {\r\n s.stop('Docker Compose file not found');\r\n return;\r\n }\r\n\r\n const resolvedContainers = resolveContainerDependencies(selectedContainers);\r\n const addedDependencies = resolvedContainers.filter(c => !selectedContainers.includes(c));\r\n \r\n if (addedDependencies.length > 0) {\r\n s.message(`Auto-including dependencies: ${color.cyan(addedDependencies.join(', '))}`);\r\n }\r\n\r\n let content = await fs.readFile(dockerComposePath, 'utf8');\r\n\r\n const allContainers = Object.keys(DOCKER_CONTAINERS) as DockerContainer[];\r\n const containersToRemove = allContainers.filter(c => !resolvedContainers.includes(c));\r\n\r\n for (const container of containersToRemove) {\r\n const containerRegex = new RegExp(\r\n ` # -- ${container} --\\\\n[\\\\s\\\\S]*? # // ${container} //\\\\n`,\r\n 'g'\r\n );\r\n content = content.replace(containerRegex, '');\r\n\r\n // delete `./docker/<container>/`\r\n const dockerDirPath = path.join(projectDir, 'docker', container);\r\n if (await fs.pathExists(dockerDirPath)) {\r\n await fs.remove(dockerDirPath);\r\n s.message(`Removed ${color.cyan(dockerDirPath)}`);\r\n }\r\n }\r\n\r\n content = content.replace(/ # -- \\w+ --\\n/g, '');\r\n content = content.replace(/ # \\/\\/ \\w+ \\/\\/\\n/g, '');\r\n\r\n await fs.writeFile(dockerComposePath, content);\r\n\r\n // check if `./docker/` is empty\r\n const dockerDir = path.join(projectDir, 'docker');\r\n if (await fs.pathExists(dockerDir) && (await fs.readdir(dockerDir)).length === 0) {\r\n await fs.remove(dockerDir);\r\n s.message(`Removed ${color.cyan(dockerDir)} ${color.gray('(because it was empty)')}`);\r\n }\r\n \r\n s.stop(`Configured Docker Compose with ${color.cyan(resolvedContainers.length)} container(s)`);\r\n } catch (error) {\r\n s.stop('Failed to configure Docker Compose');\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function removePackages(\r\n packages: string[],\r\n packagePath: string,\r\n projectDir: string,\r\n s?: ReturnType<typeof spinner>\r\n) {\r\n const packageJsonPath = path.join(projectDir, packagePath, 'package.json');\r\n if (await fs.pathExists(packageJsonPath)) {\r\n const packageJson = await fs.readJson(packageJsonPath);\r\n let hasChanges = false;\r\n\r\n for (const dep of packages) {\r\n if (packageJson.dependencies && packageJson.dependencies[dep]) {\r\n delete packageJson.dependencies[dep];\r\n hasChanges = true;\r\n if (s) {\r\n s.message(`Removed ${color.cyan(dep)} from ${packagePath}/package.json`);\r\n }\r\n }\r\n }\r\n\r\n if (hasChanges) {\r\n await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });\r\n }\r\n }\r\n}\r\n\r\nexport async function removeReactEmail(projectDir: string) {\n const s = spinner();\n s.start('Removing react-email...');\n\n try {\n // remove email package\n const emailPackagePath = path.join(projectDir, 'packages', 'email');\n if (await fs.pathExists(emailPackagePath)) {\n await fs.remove(emailPackagePath);\n s.message(`Removed ${color.cyan(emailPackagePath)}`);\n }\n\n // remove @react-email/components from packages/api/package.json\n await removePackages(['@react-email/components', '@acme/email'], 'packages/api', projectDir, s);\n\n s.stop('Removed react-email');\n } catch (error) {\n s.stop('Failed to remove react-email');\n throw error;\n }\n}\n\ninterface PnpmWorkspace {\n packages?: string[];\n catalog?: Record<string, string>;\n catalogs?: Record<string, Record<string, string>>;\n overrides?: Record<string, string>;\n}\n\ninterface PackageJson {\n name?: string;\n packageManager?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n pnpm?: {\n overrides?: Record<string, string>;\n [key: string]: unknown;\n };\n overrides?: Record<string, string>;\n resolutions?: Record<string, string>;\n [key: string]: unknown;\n}\n\n/**\n * Resolves a version string that may contain catalog: or workspace: protocols\n */\nfunction resolveVersion(\n packageName: string,\n version: string,\n defaultCatalog: Record<string, string>,\n namedCatalogs: Record<string, Record<string, string>>\n): string {\n // Handle catalog: (default catalog)\n if (version === 'catalog:') {\n const resolved = defaultCatalog[packageName];\n if (resolved) {\n return resolved;\n }\n // If not found in catalog, keep original (will likely fail at install)\n return version;\n }\n\n // Handle catalog:catalogName (named catalog)\n if (version.startsWith('catalog:')) {\n const catalogName = version.slice('catalog:'.length);\n const catalog = namedCatalogs[catalogName];\n if (catalog && catalog[packageName]) {\n return catalog[packageName];\n }\n // If not found in named catalog, keep original\n return version;\n }\n\n // Handle workspace:* or workspace:^ etc.\n if (version.startsWith('workspace:')) {\n return '*';\n }\n\n return version;\n}\n\n/**\n * Resolves catalog versions in an overrides/resolutions object\n */\nfunction resolveOverrides(\n overrides: Record<string, string>,\n defaultCatalog: Record<string, string>,\n namedCatalogs: Record<string, Record<string, string>>\n): Record<string, string> {\n const resolved: Record<string, string> = {};\n \n for (const [pkg, version] of Object.entries(overrides)) {\n resolved[pkg] = resolveVersion(pkg, version, defaultCatalog, namedCatalogs);\n }\n \n return resolved;\n}\n\n/**\n * Resolves pnpm catalog versions in all package.json files when using a non-pnpm package manager.\n * \n * This transform:\n * 1. Parses pnpm-workspace.yaml to extract catalog version mappings\n * 2. Replaces catalog: and catalog:name versions with actual versions in all package.json files\n * 3. Replaces workspace:* references with *\n * 4. Converts pnpm.overrides to overrides (npm/bun) or resolutions (yarn)\n * 5. Removes the packageManager field from root package.json\n * 6. Deletes pnpm-workspace.yaml\n */\nexport async function resolveCatalogVersions(\n projectDir: string,\n packageManager: PackageManager\n) {\n const s = spinner();\n s.start('Resolving pnpm catalog versions...');\n\n try {\n // 1. Parse pnpm-workspace.yaml\n const workspaceYamlPath = path.join(projectDir, 'pnpm-workspace.yaml');\n \n if (!(await fs.pathExists(workspaceYamlPath))) {\n s.stop('No pnpm-workspace.yaml found, skipping catalog resolution');\n return;\n }\n\n const workspaceContent = await fs.readFile(workspaceYamlPath, 'utf8');\n const workspace: PnpmWorkspace = YAML.parse(workspaceContent);\n\n const defaultCatalog = workspace.catalog ?? {};\n const namedCatalogs = workspace.catalogs ?? {};\n\n // 2. Find all package.json files\n const packageJsonFiles = await fg('**/package.json', {\n cwd: projectDir,\n ignore: ['**/node_modules/**'],\n absolute: true,\n });\n\n let totalResolved = 0;\n\n // 3. Process each package.json\n for (const filePath of packageJsonFiles) {\n const pkg: PackageJson = await fs.readJson(filePath);\n let modified = false;\n const relativePath = path.relative(projectDir, filePath);\n\n // Process all dependency types\n const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const;\n \n for (const depType of depTypes) {\n const deps = pkg[depType];\n if (deps) {\n for (const [name, version] of Object.entries(deps)) {\n const resolved = resolveVersion(name, version, defaultCatalog, namedCatalogs);\n if (resolved !== version) {\n deps[name] = resolved;\n modified = true;\n totalResolved++;\n }\n }\n }\n }\n\n // 4. Handle pnpm.overrides\n if (pkg.pnpm?.overrides) {\n const resolvedOverrides = resolveOverrides(\n pkg.pnpm.overrides,\n defaultCatalog,\n namedCatalogs\n );\n\n if (packageManager === 'yarn') {\n // Yarn uses 'resolutions'\n pkg.resolutions = { ...(pkg.resolutions ?? {}), ...resolvedOverrides };\n } else {\n // npm and bun use 'overrides'\n pkg.overrides = { ...(pkg.overrides ?? {}), ...resolvedOverrides };\n }\n\n // Remove pnpm-specific field\n delete pkg.pnpm;\n modified = true;\n s.message(`Converted pnpm.overrides in ${color.cyan(relativePath)}`);\n }\n\n // 5. Remove packageManager field from root package.json\n if (relativePath === 'package.json' && pkg.packageManager) {\n delete pkg.packageManager;\n modified = true;\n }\n\n if (modified) {\n await fs.writeJson(filePath, pkg, { spaces: 2 });\n }\n }\n\n // 6. Delete pnpm-workspace.yaml\n await fs.remove(workspaceYamlPath);\n\n s.stop(`Resolved ${color.cyan(totalResolved.toString())} catalog versions`);\n } catch (error) {\n s.stop('Failed to resolve catalog versions');\n throw error;\n }\n}\n\r\n"],"mappings":"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","names":[]}
|