everything-dev 1.7.0 → 1.7.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/dist/cli/upgrade.cjs +70 -10
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +71 -11
- package/dist/cli/upgrade.mjs.map +1 -1
- package/package.json +2 -3
- package/src/cli/upgrade.ts +97 -13
package/dist/cli/upgrade.cjs
CHANGED
|
@@ -3,6 +3,7 @@ const require_cli_init = require('./init.cjs');
|
|
|
3
3
|
const require_sync = require('./sync.cjs');
|
|
4
4
|
let node_fs = require("node:fs");
|
|
5
5
|
let node_path = require("node:path");
|
|
6
|
+
let glob = require("glob");
|
|
6
7
|
|
|
7
8
|
//#region src/cli/upgrade.ts
|
|
8
9
|
const FRAMEWORK_PACKAGES = ["everything-dev", "every-plugin"];
|
|
@@ -28,18 +29,75 @@ function readInstalledVersion(projectDir, packageName) {
|
|
|
28
29
|
if (!version) return void 0;
|
|
29
30
|
return version.replace(/^[\^~>=]+/, "");
|
|
30
31
|
}
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
function isBumpedableVersion(value) {
|
|
33
|
+
if (!value) return false;
|
|
34
|
+
if (value === "workspace:*") return false;
|
|
35
|
+
if (value.startsWith("catalog:")) return false;
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
function bumpDepField(field, packageName, newVersion) {
|
|
39
|
+
if (!field) return false;
|
|
40
|
+
if (!(packageName in field)) return false;
|
|
41
|
+
const current = field[packageName];
|
|
42
|
+
if (!isBumpedableVersion(current)) return false;
|
|
43
|
+
field[packageName] = `^${newVersion}`;
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
function bumpCatalog(catalog, packageName, newVersion) {
|
|
47
|
+
if (!catalog) return false;
|
|
48
|
+
if (!(packageName in catalog)) return false;
|
|
49
|
+
const current = catalog[packageName];
|
|
50
|
+
if (!isBumpedableVersion(current)) return false;
|
|
51
|
+
catalog[packageName] = `^${newVersion}`;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function bumpPackageJson(pkg, packageName, newVersion) {
|
|
55
|
+
const fields = [];
|
|
56
|
+
for (const fieldName of [
|
|
57
|
+
"dependencies",
|
|
58
|
+
"devDependencies",
|
|
59
|
+
"peerDependencies"
|
|
60
|
+
]) {
|
|
61
|
+
const field = pkg[fieldName];
|
|
62
|
+
if (bumpDepField(field, packageName, newVersion)) fields.push(fieldName);
|
|
37
63
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
const workspaces = pkg.workspaces;
|
|
65
|
+
if (workspaces?.catalog && bumpCatalog(workspaces.catalog, packageName, newVersion)) fields.push("workspaces.catalog");
|
|
66
|
+
return {
|
|
67
|
+
modified: fields.length > 0,
|
|
68
|
+
fields
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function updatePackageVersionInFile(filePath, packageName, newVersion) {
|
|
72
|
+
const pkg = JSON.parse((0, node_fs.readFileSync)(filePath, "utf-8"));
|
|
73
|
+
const result = bumpPackageJson(pkg, packageName, newVersion);
|
|
74
|
+
if (result.modified) (0, node_fs.writeFileSync)(filePath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
75
|
+
return result.modified;
|
|
76
|
+
}
|
|
77
|
+
function updatePackageVersion(projectDir, packageName, newVersion) {
|
|
78
|
+
return updatePackageVersionInFile((0, node_path.join)(projectDir, "package.json"), packageName, newVersion);
|
|
79
|
+
}
|
|
80
|
+
async function findWorkspacePackageJsons(projectDir) {
|
|
81
|
+
const rootPkgPath = (0, node_path.join)(projectDir, "package.json");
|
|
82
|
+
if (!(0, node_fs.existsSync)(rootPkgPath)) return [];
|
|
83
|
+
const workspaceConfig = JSON.parse((0, node_fs.readFileSync)(rootPkgPath, "utf-8")).workspaces;
|
|
84
|
+
const patterns = [];
|
|
85
|
+
if (Array.isArray(workspaceConfig)) patterns.push(...workspaceConfig);
|
|
86
|
+
else if (workspaceConfig?.packages && Array.isArray(workspaceConfig.packages)) patterns.push(...workspaceConfig.packages);
|
|
87
|
+
if (patterns.length === 0) return [];
|
|
88
|
+
const pkgPaths = [];
|
|
89
|
+
for (const pattern of patterns) {
|
|
90
|
+
const matches = await (0, glob.glob)(pattern, {
|
|
91
|
+
cwd: projectDir,
|
|
92
|
+
dot: false,
|
|
93
|
+
absolute: false
|
|
94
|
+
});
|
|
95
|
+
for (const match of matches) {
|
|
96
|
+
const pkgPath = (0, node_path.join)(projectDir, match, "package.json");
|
|
97
|
+
if ((0, node_fs.existsSync)(pkgPath) && (0, node_fs.statSync)(pkgPath).isFile()) pkgPaths.push(pkgPath);
|
|
98
|
+
}
|
|
41
99
|
}
|
|
42
|
-
|
|
100
|
+
return [...new Set(pkgPaths)];
|
|
43
101
|
}
|
|
44
102
|
function buildChangelogUrl(oldVersion, newVersion, parentConfig) {
|
|
45
103
|
if (!oldVersion || oldVersion === newVersion) return void 0;
|
|
@@ -93,6 +151,8 @@ async function upgradeTemplate(projectDir, options) {
|
|
|
93
151
|
};
|
|
94
152
|
}
|
|
95
153
|
for (const pkg of packages) if (pkg.from !== void 0 && pkg.from !== pkg.to) updatePackageVersion(projectDir, pkg.name, pkg.to);
|
|
154
|
+
const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);
|
|
155
|
+
for (const pkgPath of workspacePkgPaths) for (const pkg of packages) if (pkg.from !== void 0 && pkg.from !== pkg.to) updatePackageVersionInFile(pkgPath, pkg.name, pkg.to);
|
|
96
156
|
if (hasUpdates && !options.noInstall) await require_cli_init.runBunInstall(projectDir);
|
|
97
157
|
let syncResult;
|
|
98
158
|
if (!options.noSync) syncResult = await require_sync.syncTemplate(projectDir, {
|
package/dist/cli/upgrade.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade.cjs","names":["runBunInstall","syncTemplate"],"sources":["../../src/cli/upgrade.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { UpgradeOptions, UpgradeResult } from \"../contract\";\nimport { runBunInstall } from \"./init\";\nimport { syncTemplate } from \"./sync\";\n\nconst FRAMEWORK_PACKAGES = [\"everything-dev\", \"every-plugin\"];\n\ninterface NpmPackageInfo {\n version: string;\n}\n\nasync function fetchLatestNpmVersion(packageName: string): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) return null;\n const data = (await response.json()) as NpmPackageInfo;\n return data.version;\n } catch {\n return null;\n }\n}\n\nfunction readInstalledVersion(projectDir: string, packageName: string): string | undefined {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n const version = deps[packageName] || devDeps[packageName];\n if (!version) return undefined;\n return version.replace(/^[\\^~>=]+/, \"\");\n}\n\nfunction updatePackageVersion(projectDir: string, packageName: string, newVersion: string): void {\n const pkgPath = join(projectDir, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n\n if (pkg.dependencies && typeof pkg.dependencies === \"object\") {\n const deps = pkg.dependencies as Record<string, string>;\n if (deps[packageName] !== undefined) {\n deps[packageName] = `^${newVersion}`;\n }\n }\n\n if (pkg.devDependencies && typeof pkg.devDependencies === \"object\") {\n const deps = pkg.devDependencies as Record<string, string>;\n if (deps[packageName] !== undefined) {\n deps[packageName] = `^${newVersion}`;\n }\n }\n\n writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n}\n\nfunction buildChangelogUrl(\n oldVersion: string | undefined,\n newVersion: string,\n parentConfig: Record<string, unknown> | null,\n): string | undefined {\n if (!oldVersion || oldVersion === newVersion) return undefined;\n const repoUrl = parentConfig?.repository as string | undefined;\n if (!repoUrl) return undefined;\n\n const githubMatch = repoUrl.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (!githubMatch) return undefined;\n\n const [, owner, repo] = githubMatch;\n return `https://github.com/${owner}/${repo}/compare/v${oldVersion}...v${newVersion}`;\n}\n\nexport async function upgradeTemplate(\n projectDir: string,\n options: UpgradeOptions,\n): Promise<UpgradeResult> {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) {\n return {\n status: \"error\",\n packages: [],\n error: \"No package.json found in current directory\",\n };\n }\n\n const packages: UpgradeResult[\"packages\"] = [];\n\n for (const name of FRAMEWORK_PACKAGES) {\n const installed = readInstalledVersion(projectDir, name);\n const latest = await fetchLatestNpmVersion(name);\n\n if (!latest) {\n packages.push({ name, from: installed, to: installed ?? \"unknown\" });\n continue;\n }\n\n packages.push({ name, from: installed, to: latest });\n }\n\n const hasUpdates = packages.some((p) => p.from !== p.to && p.from !== undefined);\n\n if (options.dryRun) {\n let changelogUrl: string | undefined;\n if (hasUpdates) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n }\n\n return {\n status: \"dry-run\",\n packages,\n changelogUrl,\n };\n }\n\n for (const pkg of packages) {\n if (pkg.from !== undefined && pkg.from !== pkg.to) {\n updatePackageVersion(projectDir, pkg.name, pkg.to);\n }\n }\n\n if (hasUpdates && !options.noInstall) {\n await runBunInstall(projectDir);\n }\n\n let syncResult: UpgradeResult[\"sync\"];\n if (!options.noSync) {\n syncResult = await syncTemplate(projectDir, {\n dryRun: false,\n force: options.force,\n noInstall: true,\n });\n }\n\n let changelogUrl: string | undefined;\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n\n return {\n status: \"upgraded\",\n packages,\n sync: syncResult,\n changelogUrl,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upgrade.cjs","names":["runBunInstall","syncTemplate"],"sources":["../../src/cli/upgrade.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { UpgradeOptions, UpgradeResult } from \"../contract\";\nimport { runBunInstall } from \"./init\";\nimport { syncTemplate } from \"./sync\";\n\nconst FRAMEWORK_PACKAGES = [\"everything-dev\", \"every-plugin\"];\n\ninterface NpmPackageInfo {\n version: string;\n}\n\nasync function fetchLatestNpmVersion(packageName: string): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) return null;\n const data = (await response.json()) as NpmPackageInfo;\n return data.version;\n } catch {\n return null;\n }\n}\n\nfunction readInstalledVersion(projectDir: string, packageName: string): string | undefined {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n const version = deps[packageName] || devDeps[packageName];\n if (!version) return undefined;\n return version.replace(/^[\\^~>=]+/, \"\");\n}\n\nfunction isBumpedableVersion(value: string | undefined): boolean {\n if (!value) return false;\n if (value === \"workspace:*\") return false;\n if (value.startsWith(\"catalog:\")) return false;\n return true;\n}\n\nfunction bumpDepField(\n field: Record<string, string> | undefined,\n packageName: string,\n newVersion: string,\n): boolean {\n if (!field) return false;\n if (!(packageName in field)) return false;\n const current = field[packageName];\n if (!isBumpedableVersion(current)) return false;\n field[packageName] = `^${newVersion}`;\n return true;\n}\n\nfunction bumpCatalog(catalog: Record<string, string> | undefined, packageName: string, newVersion: string): boolean {\n if (!catalog) return false;\n if (!(packageName in catalog)) return false;\n const current = catalog[packageName];\n if (!isBumpedableVersion(current)) return false;\n catalog[packageName] = `^${newVersion}`;\n return true;\n}\n\ninterface BumpResult {\n modified: boolean;\n fields: string[];\n}\n\nfunction bumpPackageJson(pkg: Record<string, unknown>, packageName: string, newVersion: string): BumpResult {\n const fields: string[] = [];\n\n for (const fieldName of [\"dependencies\", \"devDependencies\", \"peerDependencies\"] as const) {\n const field = pkg[fieldName] as Record<string, string> | undefined;\n if (bumpDepField(field, packageName, newVersion)) {\n fields.push(fieldName);\n }\n }\n\n const workspaces = pkg.workspaces as { catalog?: Record<string, string> } | undefined;\n if (workspaces?.catalog && bumpCatalog(workspaces.catalog, packageName, newVersion)) {\n fields.push(\"workspaces.catalog\");\n }\n\n return { modified: fields.length > 0, fields };\n}\n\nfunction updatePackageVersionInFile(filePath: string, packageName: string, newVersion: string): boolean {\n const pkg = JSON.parse(readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n const result = bumpPackageJson(pkg, packageName, newVersion);\n if (result.modified) {\n writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}\\n`);\n }\n return result.modified;\n}\n\nfunction updatePackageVersion(projectDir: string, packageName: string, newVersion: string): boolean {\n return updatePackageVersionInFile(join(projectDir, \"package.json\"), packageName, newVersion);\n}\n\nasync function findWorkspacePackageJsons(projectDir: string): Promise<string[]> {\n const rootPkgPath = join(projectDir, \"package.json\");\n if (!existsSync(rootPkgPath)) return [];\n\n const rootPkg = JSON.parse(readFileSync(rootPkgPath, \"utf-8\")) as Record<string, unknown>;\n const workspaceConfig = rootPkg.workspaces as { packages?: string[] } | string[] | undefined;\n\n const patterns: string[] = [];\n if (Array.isArray(workspaceConfig)) {\n patterns.push(...workspaceConfig);\n } else if (workspaceConfig?.packages && Array.isArray(workspaceConfig.packages)) {\n patterns.push(...workspaceConfig.packages);\n }\n\n if (patterns.length === 0) return [];\n\n const pkgPaths: string[] = [];\n for (const pattern of patterns) {\n const matches = await glob(pattern, { cwd: projectDir, dot: false, absolute: false });\n for (const match of matches) {\n const pkgPath = join(projectDir, match, \"package.json\");\n if (existsSync(pkgPath) && statSync(pkgPath).isFile()) {\n pkgPaths.push(pkgPath);\n }\n }\n }\n\n return [...new Set(pkgPaths)];\n}\n\nfunction buildChangelogUrl(\n oldVersion: string | undefined,\n newVersion: string,\n parentConfig: Record<string, unknown> | null,\n): string | undefined {\n if (!oldVersion || oldVersion === newVersion) return undefined;\n const repoUrl = parentConfig?.repository as string | undefined;\n if (!repoUrl) return undefined;\n\n const githubMatch = repoUrl.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (!githubMatch) return undefined;\n\n const [, owner, repo] = githubMatch;\n return `https://github.com/${owner}/${repo}/compare/v${oldVersion}...v${newVersion}`;\n}\n\nexport async function upgradeTemplate(\n projectDir: string,\n options: UpgradeOptions,\n): Promise<UpgradeResult> {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) {\n return {\n status: \"error\",\n packages: [],\n error: \"No package.json found in current directory\",\n };\n }\n\n const packages: UpgradeResult[\"packages\"] = [];\n\n for (const name of FRAMEWORK_PACKAGES) {\n const installed = readInstalledVersion(projectDir, name);\n const latest = await fetchLatestNpmVersion(name);\n\n if (!latest) {\n packages.push({ name, from: installed, to: installed ?? \"unknown\" });\n continue;\n }\n\n packages.push({ name, from: installed, to: latest });\n }\n\n const hasUpdates = packages.some((p) => p.from !== p.to && p.from !== undefined);\n\n if (options.dryRun) {\n let changelogUrl: string | undefined;\n if (hasUpdates) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n }\n\n return {\n status: \"dry-run\",\n packages,\n changelogUrl,\n };\n }\n\n for (const pkg of packages) {\n if (pkg.from !== undefined && pkg.from !== pkg.to) {\n updatePackageVersion(projectDir, pkg.name, pkg.to);\n }\n }\n\n const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);\n for (const pkgPath of workspacePkgPaths) {\n for (const pkg of packages) {\n if (pkg.from !== undefined && pkg.from !== pkg.to) {\n updatePackageVersionInFile(pkgPath, pkg.name, pkg.to);\n }\n }\n }\n\n if (hasUpdates && !options.noInstall) {\n await runBunInstall(projectDir);\n }\n\n let syncResult: UpgradeResult[\"sync\"];\n if (!options.noSync) {\n syncResult = await syncTemplate(projectDir, {\n dryRun: false,\n force: options.force,\n noInstall: true,\n });\n }\n\n let changelogUrl: string | undefined;\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n\n return {\n status: \"upgraded\",\n packages,\n sync: syncResult,\n changelogUrl,\n };\n}\n"],"mappings":"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"}
|
package/dist/cli/upgrade.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { runBunInstall } from "./init.mjs";
|
|
2
2
|
import { syncTemplate } from "./sync.mjs";
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { glob } from "glob";
|
|
5
6
|
|
|
6
7
|
//#region src/cli/upgrade.ts
|
|
7
8
|
const FRAMEWORK_PACKAGES = ["everything-dev", "every-plugin"];
|
|
@@ -27,18 +28,75 @@ function readInstalledVersion(projectDir, packageName) {
|
|
|
27
28
|
if (!version) return void 0;
|
|
28
29
|
return version.replace(/^[\^~>=]+/, "");
|
|
29
30
|
}
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
function isBumpedableVersion(value) {
|
|
32
|
+
if (!value) return false;
|
|
33
|
+
if (value === "workspace:*") return false;
|
|
34
|
+
if (value.startsWith("catalog:")) return false;
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
function bumpDepField(field, packageName, newVersion) {
|
|
38
|
+
if (!field) return false;
|
|
39
|
+
if (!(packageName in field)) return false;
|
|
40
|
+
const current = field[packageName];
|
|
41
|
+
if (!isBumpedableVersion(current)) return false;
|
|
42
|
+
field[packageName] = `^${newVersion}`;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
function bumpCatalog(catalog, packageName, newVersion) {
|
|
46
|
+
if (!catalog) return false;
|
|
47
|
+
if (!(packageName in catalog)) return false;
|
|
48
|
+
const current = catalog[packageName];
|
|
49
|
+
if (!isBumpedableVersion(current)) return false;
|
|
50
|
+
catalog[packageName] = `^${newVersion}`;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
function bumpPackageJson(pkg, packageName, newVersion) {
|
|
54
|
+
const fields = [];
|
|
55
|
+
for (const fieldName of [
|
|
56
|
+
"dependencies",
|
|
57
|
+
"devDependencies",
|
|
58
|
+
"peerDependencies"
|
|
59
|
+
]) {
|
|
60
|
+
const field = pkg[fieldName];
|
|
61
|
+
if (bumpDepField(field, packageName, newVersion)) fields.push(fieldName);
|
|
36
62
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
const workspaces = pkg.workspaces;
|
|
64
|
+
if (workspaces?.catalog && bumpCatalog(workspaces.catalog, packageName, newVersion)) fields.push("workspaces.catalog");
|
|
65
|
+
return {
|
|
66
|
+
modified: fields.length > 0,
|
|
67
|
+
fields
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function updatePackageVersionInFile(filePath, packageName, newVersion) {
|
|
71
|
+
const pkg = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
72
|
+
const result = bumpPackageJson(pkg, packageName, newVersion);
|
|
73
|
+
if (result.modified) writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
74
|
+
return result.modified;
|
|
75
|
+
}
|
|
76
|
+
function updatePackageVersion(projectDir, packageName, newVersion) {
|
|
77
|
+
return updatePackageVersionInFile(join(projectDir, "package.json"), packageName, newVersion);
|
|
78
|
+
}
|
|
79
|
+
async function findWorkspacePackageJsons(projectDir) {
|
|
80
|
+
const rootPkgPath = join(projectDir, "package.json");
|
|
81
|
+
if (!existsSync(rootPkgPath)) return [];
|
|
82
|
+
const workspaceConfig = JSON.parse(readFileSync(rootPkgPath, "utf-8")).workspaces;
|
|
83
|
+
const patterns = [];
|
|
84
|
+
if (Array.isArray(workspaceConfig)) patterns.push(...workspaceConfig);
|
|
85
|
+
else if (workspaceConfig?.packages && Array.isArray(workspaceConfig.packages)) patterns.push(...workspaceConfig.packages);
|
|
86
|
+
if (patterns.length === 0) return [];
|
|
87
|
+
const pkgPaths = [];
|
|
88
|
+
for (const pattern of patterns) {
|
|
89
|
+
const matches = await glob(pattern, {
|
|
90
|
+
cwd: projectDir,
|
|
91
|
+
dot: false,
|
|
92
|
+
absolute: false
|
|
93
|
+
});
|
|
94
|
+
for (const match of matches) {
|
|
95
|
+
const pkgPath = join(projectDir, match, "package.json");
|
|
96
|
+
if (existsSync(pkgPath) && statSync(pkgPath).isFile()) pkgPaths.push(pkgPath);
|
|
97
|
+
}
|
|
40
98
|
}
|
|
41
|
-
|
|
99
|
+
return [...new Set(pkgPaths)];
|
|
42
100
|
}
|
|
43
101
|
function buildChangelogUrl(oldVersion, newVersion, parentConfig) {
|
|
44
102
|
if (!oldVersion || oldVersion === newVersion) return void 0;
|
|
@@ -92,6 +150,8 @@ async function upgradeTemplate(projectDir, options) {
|
|
|
92
150
|
};
|
|
93
151
|
}
|
|
94
152
|
for (const pkg of packages) if (pkg.from !== void 0 && pkg.from !== pkg.to) updatePackageVersion(projectDir, pkg.name, pkg.to);
|
|
153
|
+
const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);
|
|
154
|
+
for (const pkgPath of workspacePkgPaths) for (const pkg of packages) if (pkg.from !== void 0 && pkg.from !== pkg.to) updatePackageVersionInFile(pkgPath, pkg.name, pkg.to);
|
|
95
155
|
if (hasUpdates && !options.noInstall) await runBunInstall(projectDir);
|
|
96
156
|
let syncResult;
|
|
97
157
|
if (!options.noSync) syncResult = await syncTemplate(projectDir, {
|
package/dist/cli/upgrade.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade.mjs","names":[],"sources":["../../src/cli/upgrade.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { UpgradeOptions, UpgradeResult } from \"../contract\";\nimport { runBunInstall } from \"./init\";\nimport { syncTemplate } from \"./sync\";\n\nconst FRAMEWORK_PACKAGES = [\"everything-dev\", \"every-plugin\"];\n\ninterface NpmPackageInfo {\n version: string;\n}\n\nasync function fetchLatestNpmVersion(packageName: string): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) return null;\n const data = (await response.json()) as NpmPackageInfo;\n return data.version;\n } catch {\n return null;\n }\n}\n\nfunction readInstalledVersion(projectDir: string, packageName: string): string | undefined {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n const version = deps[packageName] || devDeps[packageName];\n if (!version) return undefined;\n return version.replace(/^[\\^~>=]+/, \"\");\n}\n\nfunction updatePackageVersion(projectDir: string, packageName: string, newVersion: string): void {\n const pkgPath = join(projectDir, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n\n if (pkg.dependencies && typeof pkg.dependencies === \"object\") {\n const deps = pkg.dependencies as Record<string, string>;\n if (deps[packageName] !== undefined) {\n deps[packageName] = `^${newVersion}`;\n }\n }\n\n if (pkg.devDependencies && typeof pkg.devDependencies === \"object\") {\n const deps = pkg.devDependencies as Record<string, string>;\n if (deps[packageName] !== undefined) {\n deps[packageName] = `^${newVersion}`;\n }\n }\n\n writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n}\n\nfunction buildChangelogUrl(\n oldVersion: string | undefined,\n newVersion: string,\n parentConfig: Record<string, unknown> | null,\n): string | undefined {\n if (!oldVersion || oldVersion === newVersion) return undefined;\n const repoUrl = parentConfig?.repository as string | undefined;\n if (!repoUrl) return undefined;\n\n const githubMatch = repoUrl.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (!githubMatch) return undefined;\n\n const [, owner, repo] = githubMatch;\n return `https://github.com/${owner}/${repo}/compare/v${oldVersion}...v${newVersion}`;\n}\n\nexport async function upgradeTemplate(\n projectDir: string,\n options: UpgradeOptions,\n): Promise<UpgradeResult> {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) {\n return {\n status: \"error\",\n packages: [],\n error: \"No package.json found in current directory\",\n };\n }\n\n const packages: UpgradeResult[\"packages\"] = [];\n\n for (const name of FRAMEWORK_PACKAGES) {\n const installed = readInstalledVersion(projectDir, name);\n const latest = await fetchLatestNpmVersion(name);\n\n if (!latest) {\n packages.push({ name, from: installed, to: installed ?? \"unknown\" });\n continue;\n }\n\n packages.push({ name, from: installed, to: latest });\n }\n\n const hasUpdates = packages.some((p) => p.from !== p.to && p.from !== undefined);\n\n if (options.dryRun) {\n let changelogUrl: string | undefined;\n if (hasUpdates) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n }\n\n return {\n status: \"dry-run\",\n packages,\n changelogUrl,\n };\n }\n\n for (const pkg of packages) {\n if (pkg.from !== undefined && pkg.from !== pkg.to) {\n updatePackageVersion(projectDir, pkg.name, pkg.to);\n }\n }\n\n if (hasUpdates && !options.noInstall) {\n await runBunInstall(projectDir);\n }\n\n let syncResult: UpgradeResult[\"sync\"];\n if (!options.noSync) {\n syncResult = await syncTemplate(projectDir, {\n dryRun: false,\n force: options.force,\n noInstall: true,\n });\n }\n\n let changelogUrl: string | undefined;\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n\n return {\n status: \"upgraded\",\n packages,\n sync: syncResult,\n changelogUrl,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upgrade.mjs","names":[],"sources":["../../src/cli/upgrade.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { UpgradeOptions, UpgradeResult } from \"../contract\";\nimport { runBunInstall } from \"./init\";\nimport { syncTemplate } from \"./sync\";\n\nconst FRAMEWORK_PACKAGES = [\"everything-dev\", \"every-plugin\"];\n\ninterface NpmPackageInfo {\n version: string;\n}\n\nasync function fetchLatestNpmVersion(packageName: string): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) return null;\n const data = (await response.json()) as NpmPackageInfo;\n return data.version;\n } catch {\n return null;\n }\n}\n\nfunction readInstalledVersion(projectDir: string, packageName: string): string | undefined {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n const version = deps[packageName] || devDeps[packageName];\n if (!version) return undefined;\n return version.replace(/^[\\^~>=]+/, \"\");\n}\n\nfunction isBumpedableVersion(value: string | undefined): boolean {\n if (!value) return false;\n if (value === \"workspace:*\") return false;\n if (value.startsWith(\"catalog:\")) return false;\n return true;\n}\n\nfunction bumpDepField(\n field: Record<string, string> | undefined,\n packageName: string,\n newVersion: string,\n): boolean {\n if (!field) return false;\n if (!(packageName in field)) return false;\n const current = field[packageName];\n if (!isBumpedableVersion(current)) return false;\n field[packageName] = `^${newVersion}`;\n return true;\n}\n\nfunction bumpCatalog(catalog: Record<string, string> | undefined, packageName: string, newVersion: string): boolean {\n if (!catalog) return false;\n if (!(packageName in catalog)) return false;\n const current = catalog[packageName];\n if (!isBumpedableVersion(current)) return false;\n catalog[packageName] = `^${newVersion}`;\n return true;\n}\n\ninterface BumpResult {\n modified: boolean;\n fields: string[];\n}\n\nfunction bumpPackageJson(pkg: Record<string, unknown>, packageName: string, newVersion: string): BumpResult {\n const fields: string[] = [];\n\n for (const fieldName of [\"dependencies\", \"devDependencies\", \"peerDependencies\"] as const) {\n const field = pkg[fieldName] as Record<string, string> | undefined;\n if (bumpDepField(field, packageName, newVersion)) {\n fields.push(fieldName);\n }\n }\n\n const workspaces = pkg.workspaces as { catalog?: Record<string, string> } | undefined;\n if (workspaces?.catalog && bumpCatalog(workspaces.catalog, packageName, newVersion)) {\n fields.push(\"workspaces.catalog\");\n }\n\n return { modified: fields.length > 0, fields };\n}\n\nfunction updatePackageVersionInFile(filePath: string, packageName: string, newVersion: string): boolean {\n const pkg = JSON.parse(readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n const result = bumpPackageJson(pkg, packageName, newVersion);\n if (result.modified) {\n writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}\\n`);\n }\n return result.modified;\n}\n\nfunction updatePackageVersion(projectDir: string, packageName: string, newVersion: string): boolean {\n return updatePackageVersionInFile(join(projectDir, \"package.json\"), packageName, newVersion);\n}\n\nasync function findWorkspacePackageJsons(projectDir: string): Promise<string[]> {\n const rootPkgPath = join(projectDir, \"package.json\");\n if (!existsSync(rootPkgPath)) return [];\n\n const rootPkg = JSON.parse(readFileSync(rootPkgPath, \"utf-8\")) as Record<string, unknown>;\n const workspaceConfig = rootPkg.workspaces as { packages?: string[] } | string[] | undefined;\n\n const patterns: string[] = [];\n if (Array.isArray(workspaceConfig)) {\n patterns.push(...workspaceConfig);\n } else if (workspaceConfig?.packages && Array.isArray(workspaceConfig.packages)) {\n patterns.push(...workspaceConfig.packages);\n }\n\n if (patterns.length === 0) return [];\n\n const pkgPaths: string[] = [];\n for (const pattern of patterns) {\n const matches = await glob(pattern, { cwd: projectDir, dot: false, absolute: false });\n for (const match of matches) {\n const pkgPath = join(projectDir, match, \"package.json\");\n if (existsSync(pkgPath) && statSync(pkgPath).isFile()) {\n pkgPaths.push(pkgPath);\n }\n }\n }\n\n return [...new Set(pkgPaths)];\n}\n\nfunction buildChangelogUrl(\n oldVersion: string | undefined,\n newVersion: string,\n parentConfig: Record<string, unknown> | null,\n): string | undefined {\n if (!oldVersion || oldVersion === newVersion) return undefined;\n const repoUrl = parentConfig?.repository as string | undefined;\n if (!repoUrl) return undefined;\n\n const githubMatch = repoUrl.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (!githubMatch) return undefined;\n\n const [, owner, repo] = githubMatch;\n return `https://github.com/${owner}/${repo}/compare/v${oldVersion}...v${newVersion}`;\n}\n\nexport async function upgradeTemplate(\n projectDir: string,\n options: UpgradeOptions,\n): Promise<UpgradeResult> {\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) {\n return {\n status: \"error\",\n packages: [],\n error: \"No package.json found in current directory\",\n };\n }\n\n const packages: UpgradeResult[\"packages\"] = [];\n\n for (const name of FRAMEWORK_PACKAGES) {\n const installed = readInstalledVersion(projectDir, name);\n const latest = await fetchLatestNpmVersion(name);\n\n if (!latest) {\n packages.push({ name, from: installed, to: installed ?? \"unknown\" });\n continue;\n }\n\n packages.push({ name, from: installed, to: latest });\n }\n\n const hasUpdates = packages.some((p) => p.from !== p.to && p.from !== undefined);\n\n if (options.dryRun) {\n let changelogUrl: string | undefined;\n if (hasUpdates) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n }\n\n return {\n status: \"dry-run\",\n packages,\n changelogUrl,\n };\n }\n\n for (const pkg of packages) {\n if (pkg.from !== undefined && pkg.from !== pkg.to) {\n updatePackageVersion(projectDir, pkg.name, pkg.to);\n }\n }\n\n const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);\n for (const pkgPath of workspacePkgPaths) {\n for (const pkg of packages) {\n if (pkg.from !== undefined && pkg.from !== pkg.to) {\n updatePackageVersionInFile(pkgPath, pkg.name, pkg.to);\n }\n }\n }\n\n if (hasUpdates && !options.noInstall) {\n await runBunInstall(projectDir);\n }\n\n let syncResult: UpgradeResult[\"sync\"];\n if (!options.noSync) {\n syncResult = await syncTemplate(projectDir, {\n dryRun: false,\n force: options.force,\n noInstall: true,\n });\n }\n\n let changelogUrl: string | undefined;\n const mainPkg = packages.find((p) => p.name === \"everything-dev\");\n if (mainPkg?.from && mainPkg.from !== mainPkg.to) {\n const configPath = join(projectDir, \"bos.config.json\");\n let parentConfig: Record<string, unknown> | null = null;\n if (existsSync(configPath)) {\n try {\n parentConfig = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {}\n }\n changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);\n }\n\n return {\n status: \"upgraded\",\n packages,\n sync: syncResult,\n changelogUrl,\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "everything-dev",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -152,8 +152,7 @@
|
|
|
152
152
|
"gradient-string": "^3.0.0",
|
|
153
153
|
"hono": "^4.7.11",
|
|
154
154
|
"ink": "^6.8.0",
|
|
155
|
-
"tar": "^7.4.3"
|
|
156
|
-
"zod": "^4.3.6"
|
|
155
|
+
"tar": "^7.4.3"
|
|
157
156
|
},
|
|
158
157
|
"peerDependencies": {
|
|
159
158
|
"@tanstack/react-query": ">=5.0.0",
|
package/src/cli/upgrade.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { glob } from "glob";
|
|
3
4
|
import type { UpgradeOptions, UpgradeResult } from "../contract";
|
|
4
5
|
import { runBunInstall } from "./init";
|
|
5
6
|
import { syncTemplate } from "./sync";
|
|
@@ -35,25 +36,99 @@ function readInstalledVersion(projectDir: string, packageName: string): string |
|
|
|
35
36
|
return version.replace(/^[\^~>=]+/, "");
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
function isBumpedableVersion(value: string | undefined): boolean {
|
|
40
|
+
if (!value) return false;
|
|
41
|
+
if (value === "workspace:*") return false;
|
|
42
|
+
if (value.startsWith("catalog:")) return false;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function bumpDepField(
|
|
47
|
+
field: Record<string, string> | undefined,
|
|
48
|
+
packageName: string,
|
|
49
|
+
newVersion: string,
|
|
50
|
+
): boolean {
|
|
51
|
+
if (!field) return false;
|
|
52
|
+
if (!(packageName in field)) return false;
|
|
53
|
+
const current = field[packageName];
|
|
54
|
+
if (!isBumpedableVersion(current)) return false;
|
|
55
|
+
field[packageName] = `^${newVersion}`;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function bumpCatalog(catalog: Record<string, string> | undefined, packageName: string, newVersion: string): boolean {
|
|
60
|
+
if (!catalog) return false;
|
|
61
|
+
if (!(packageName in catalog)) return false;
|
|
62
|
+
const current = catalog[packageName];
|
|
63
|
+
if (!isBumpedableVersion(current)) return false;
|
|
64
|
+
catalog[packageName] = `^${newVersion}`;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
41
67
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
68
|
+
interface BumpResult {
|
|
69
|
+
modified: boolean;
|
|
70
|
+
fields: string[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function bumpPackageJson(pkg: Record<string, unknown>, packageName: string, newVersion: string): BumpResult {
|
|
74
|
+
const fields: string[] = [];
|
|
75
|
+
|
|
76
|
+
for (const fieldName of ["dependencies", "devDependencies", "peerDependencies"] as const) {
|
|
77
|
+
const field = pkg[fieldName] as Record<string, string> | undefined;
|
|
78
|
+
if (bumpDepField(field, packageName, newVersion)) {
|
|
79
|
+
fields.push(fieldName);
|
|
46
80
|
}
|
|
47
81
|
}
|
|
48
82
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
83
|
+
const workspaces = pkg.workspaces as { catalog?: Record<string, string> } | undefined;
|
|
84
|
+
if (workspaces?.catalog && bumpCatalog(workspaces.catalog, packageName, newVersion)) {
|
|
85
|
+
fields.push("workspaces.catalog");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { modified: fields.length > 0, fields };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function updatePackageVersionInFile(filePath: string, packageName: string, newVersion: string): boolean {
|
|
92
|
+
const pkg = JSON.parse(readFileSync(filePath, "utf-8")) as Record<string, unknown>;
|
|
93
|
+
const result = bumpPackageJson(pkg, packageName, newVersion);
|
|
94
|
+
if (result.modified) {
|
|
95
|
+
writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
96
|
+
}
|
|
97
|
+
return result.modified;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function updatePackageVersion(projectDir: string, packageName: string, newVersion: string): boolean {
|
|
101
|
+
return updatePackageVersionInFile(join(projectDir, "package.json"), packageName, newVersion);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function findWorkspacePackageJsons(projectDir: string): Promise<string[]> {
|
|
105
|
+
const rootPkgPath = join(projectDir, "package.json");
|
|
106
|
+
if (!existsSync(rootPkgPath)) return [];
|
|
107
|
+
|
|
108
|
+
const rootPkg = JSON.parse(readFileSync(rootPkgPath, "utf-8")) as Record<string, unknown>;
|
|
109
|
+
const workspaceConfig = rootPkg.workspaces as { packages?: string[] } | string[] | undefined;
|
|
110
|
+
|
|
111
|
+
const patterns: string[] = [];
|
|
112
|
+
if (Array.isArray(workspaceConfig)) {
|
|
113
|
+
patterns.push(...workspaceConfig);
|
|
114
|
+
} else if (workspaceConfig?.packages && Array.isArray(workspaceConfig.packages)) {
|
|
115
|
+
patterns.push(...workspaceConfig.packages);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (patterns.length === 0) return [];
|
|
119
|
+
|
|
120
|
+
const pkgPaths: string[] = [];
|
|
121
|
+
for (const pattern of patterns) {
|
|
122
|
+
const matches = await glob(pattern, { cwd: projectDir, dot: false, absolute: false });
|
|
123
|
+
for (const match of matches) {
|
|
124
|
+
const pkgPath = join(projectDir, match, "package.json");
|
|
125
|
+
if (existsSync(pkgPath) && statSync(pkgPath).isFile()) {
|
|
126
|
+
pkgPaths.push(pkgPath);
|
|
127
|
+
}
|
|
53
128
|
}
|
|
54
129
|
}
|
|
55
130
|
|
|
56
|
-
|
|
131
|
+
return [...new Set(pkgPaths)];
|
|
57
132
|
}
|
|
58
133
|
|
|
59
134
|
function buildChangelogUrl(
|
|
@@ -130,6 +205,15 @@ export async function upgradeTemplate(
|
|
|
130
205
|
}
|
|
131
206
|
}
|
|
132
207
|
|
|
208
|
+
const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);
|
|
209
|
+
for (const pkgPath of workspacePkgPaths) {
|
|
210
|
+
for (const pkg of packages) {
|
|
211
|
+
if (pkg.from !== undefined && pkg.from !== pkg.to) {
|
|
212
|
+
updatePackageVersionInFile(pkgPath, pkg.name, pkg.to);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
133
217
|
if (hasUpdates && !options.noInstall) {
|
|
134
218
|
await runBunInstall(projectDir);
|
|
135
219
|
}
|