@cedarjs/cli 1.0.0-canary.13037 → 1.0.0-canary.13040
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/commands/upgrade.js +251 -6
- package/package.json +12 -11
package/dist/commands/upgrade.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { builtinModules } from "node:module";
|
|
2
|
+
import os from "node:os";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
|
|
3
5
|
import execa from "execa";
|
|
4
6
|
import fs from "fs-extra";
|
|
5
7
|
import latestVersion from "latest-version";
|
|
6
8
|
import { Listr } from "listr2";
|
|
9
|
+
import semver from "semver";
|
|
7
10
|
import { terminalLink } from "termi-link";
|
|
8
11
|
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
9
12
|
import { getConfig } from "@cedarjs/project-config";
|
|
@@ -41,6 +44,11 @@ const builder = (yargs) => {
|
|
|
41
44
|
describe: "Skip prompts and use defaults",
|
|
42
45
|
default: false,
|
|
43
46
|
type: "boolean"
|
|
47
|
+
}).option("force", {
|
|
48
|
+
alias: "f",
|
|
49
|
+
describe: "Force upgrade even if pre-upgrade checks fail",
|
|
50
|
+
default: false,
|
|
51
|
+
type: "boolean"
|
|
44
52
|
}).epilogue(
|
|
45
53
|
`Also see the ${terminalLink(
|
|
46
54
|
"CedarJS CLI Reference for the upgrade command",
|
|
@@ -70,15 +78,18 @@ const validateTag = (tag) => {
|
|
|
70
78
|
}
|
|
71
79
|
return tag;
|
|
72
80
|
};
|
|
73
|
-
const handler = async ({ dryRun, tag, verbose, dedupe, yes }) => {
|
|
81
|
+
const handler = async ({ dryRun, tag, verbose, dedupe, yes, force }) => {
|
|
74
82
|
recordTelemetryAttributes({
|
|
75
83
|
command: "upgrade",
|
|
76
84
|
dryRun,
|
|
77
85
|
tag,
|
|
78
86
|
verbose,
|
|
79
87
|
dedupe,
|
|
80
|
-
yes
|
|
88
|
+
yes,
|
|
89
|
+
force
|
|
81
90
|
});
|
|
91
|
+
let preUpgradeMessage = "";
|
|
92
|
+
let preUpgradeError = "";
|
|
82
93
|
const tasks = new Listr(
|
|
83
94
|
[
|
|
84
95
|
{
|
|
@@ -117,38 +128,55 @@ const handler = async ({ dryRun, tag, verbose, dedupe, yes }) => {
|
|
|
117
128
|
title: "Checking latest version",
|
|
118
129
|
task: async (ctx) => setLatestVersionToContext(ctx, tag)
|
|
119
130
|
},
|
|
131
|
+
{
|
|
132
|
+
title: "Running pre-upgrade scripts",
|
|
133
|
+
task: async (ctx, task) => {
|
|
134
|
+
await runPreUpgradeScripts(ctx, task, { verbose, force });
|
|
135
|
+
if (ctx.preUpgradeMessage) {
|
|
136
|
+
preUpgradeMessage = ctx.preUpgradeMessage;
|
|
137
|
+
}
|
|
138
|
+
if (ctx.preUpgradeError) {
|
|
139
|
+
preUpgradeError = ctx.preUpgradeError;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
enabled: (ctx) => !!ctx.versionToUpgradeTo
|
|
143
|
+
},
|
|
120
144
|
{
|
|
121
145
|
title: "Updating your CedarJS version",
|
|
122
146
|
task: (ctx) => updateCedarJSDepsForAllSides(ctx, { dryRun, verbose }),
|
|
123
|
-
enabled: (ctx) => !!ctx.versionToUpgradeTo
|
|
147
|
+
enabled: (ctx) => !!ctx.versionToUpgradeTo && !ctx.preUpgradeError
|
|
124
148
|
},
|
|
125
149
|
{
|
|
126
150
|
title: "Updating other packages in your package.json(s)",
|
|
127
151
|
task: (ctx) => updatePackageVersionsFromTemplate(ctx, { dryRun, verbose }),
|
|
128
|
-
enabled: (ctx) => ctx.versionToUpgradeTo?.includes("canary")
|
|
152
|
+
enabled: (ctx) => ctx.versionToUpgradeTo?.includes("canary") && !ctx.preUpgradeError
|
|
129
153
|
},
|
|
130
154
|
{
|
|
131
155
|
title: "Downloading yarn patches",
|
|
132
156
|
task: (ctx) => downloadYarnPatches(ctx, { dryRun, verbose }),
|
|
133
|
-
enabled: (ctx) => ctx.versionToUpgradeTo?.includes("canary")
|
|
157
|
+
enabled: (ctx) => ctx.versionToUpgradeTo?.includes("canary") && !ctx.preUpgradeError
|
|
134
158
|
},
|
|
135
159
|
{
|
|
136
160
|
title: "Removing CLI cache",
|
|
137
|
-
task: (ctx) => removeCliCache(ctx, { dryRun, verbose })
|
|
161
|
+
task: (ctx) => removeCliCache(ctx, { dryRun, verbose }),
|
|
162
|
+
enabled: (ctx) => !ctx.preUpgradeError
|
|
138
163
|
},
|
|
139
164
|
{
|
|
140
165
|
title: "Running yarn install",
|
|
141
166
|
task: (ctx) => yarnInstall(ctx, { dryRun, verbose }),
|
|
167
|
+
enabled: (ctx) => !ctx.preUpgradeError,
|
|
142
168
|
skip: () => dryRun
|
|
143
169
|
},
|
|
144
170
|
{
|
|
145
171
|
title: "Refreshing the Prisma client",
|
|
146
172
|
task: (_ctx, task) => refreshPrismaClient(task, { verbose }),
|
|
173
|
+
enabled: (ctx) => !ctx.preUpgradeError,
|
|
147
174
|
skip: () => dryRun
|
|
148
175
|
},
|
|
149
176
|
{
|
|
150
177
|
title: "De-duplicating dependencies",
|
|
151
178
|
skip: () => dryRun || !dedupe,
|
|
179
|
+
enabled: (ctx) => !ctx.preUpgradeError,
|
|
152
180
|
task: (_ctx, task) => dedupeDeps(task, { verbose })
|
|
153
181
|
},
|
|
154
182
|
{
|
|
@@ -208,6 +236,21 @@ const handler = async ({ dryRun, tag, verbose, dedupe, yes }) => {
|
|
|
208
236
|
}
|
|
209
237
|
);
|
|
210
238
|
await tasks.run();
|
|
239
|
+
if (preUpgradeError) {
|
|
240
|
+
console.error("");
|
|
241
|
+
console.error(` \u274C ${c.error("Pre-upgrade Error:")}
|
|
242
|
+
`);
|
|
243
|
+
console.error(" " + preUpgradeError.replace(/\n/g, "\n "));
|
|
244
|
+
if (!force) {
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (preUpgradeMessage) {
|
|
249
|
+
console.log("");
|
|
250
|
+
console.log(` \u{1F4E3} ${c.info("Pre-upgrade Message:")}
|
|
251
|
+
`);
|
|
252
|
+
console.log(" " + preUpgradeMessage.replace(/\n/g, "\n "));
|
|
253
|
+
}
|
|
211
254
|
};
|
|
212
255
|
async function yarnInstall({ verbose }) {
|
|
213
256
|
try {
|
|
@@ -459,10 +502,212 @@ const dedupeDeps = async (_task, { verbose }) => {
|
|
|
459
502
|
}
|
|
460
503
|
await yarnInstall({ verbose });
|
|
461
504
|
};
|
|
505
|
+
async function runPreUpgradeScripts(ctx, task, { verbose, force }) {
|
|
506
|
+
if (!ctx.versionToUpgradeTo) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const version = ctx.versionToUpgradeTo;
|
|
510
|
+
const parsed = semver.parse(version);
|
|
511
|
+
const baseUrl = "https://raw.githubusercontent.com/cedarjs/cedar/main/upgrade-scripts/";
|
|
512
|
+
const manifestUrl = `${baseUrl}manifest.json`;
|
|
513
|
+
let manifest = [];
|
|
514
|
+
try {
|
|
515
|
+
const res = await fetch(manifestUrl);
|
|
516
|
+
if (res.status === 200) {
|
|
517
|
+
manifest = await res.json();
|
|
518
|
+
} else {
|
|
519
|
+
if (verbose) {
|
|
520
|
+
console.log("No upgrade script manifest found.");
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
} catch (e) {
|
|
524
|
+
if (verbose) {
|
|
525
|
+
console.log("Failed to fetch upgrade script manifest", e);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
if (!Array.isArray(manifest) || manifest.length === 0) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const checkLevels = [];
|
|
532
|
+
if (parsed) {
|
|
533
|
+
checkLevels.push({
|
|
534
|
+
id: "exact",
|
|
535
|
+
candidates: [`${version}.ts`, `${version}/index.ts`]
|
|
536
|
+
});
|
|
537
|
+
checkLevels.push({
|
|
538
|
+
id: "patch",
|
|
539
|
+
candidates: [
|
|
540
|
+
`${parsed.major}.${parsed.minor}.x.ts`,
|
|
541
|
+
`${parsed.major}.${parsed.minor}.x/index.ts`
|
|
542
|
+
]
|
|
543
|
+
});
|
|
544
|
+
checkLevels.push({
|
|
545
|
+
id: "minor",
|
|
546
|
+
candidates: [`${parsed.major}.x.ts`, `${parsed.major}.x/index.ts`]
|
|
547
|
+
});
|
|
548
|
+
} else {
|
|
549
|
+
checkLevels.push({
|
|
550
|
+
id: "tag",
|
|
551
|
+
candidates: [`${version}.ts`, `${version}/index.ts`]
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
const scriptsToRun = [];
|
|
555
|
+
for (const level of checkLevels) {
|
|
556
|
+
for (const candidate of level.candidates) {
|
|
557
|
+
if (manifest.includes(candidate)) {
|
|
558
|
+
scriptsToRun.push(candidate);
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (scriptsToRun.length === 0) {
|
|
564
|
+
if (verbose) {
|
|
565
|
+
console.log(`No upgrade scripts found for ${version}`);
|
|
566
|
+
}
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
ctx.preUpgradeMessage = "";
|
|
570
|
+
ctx.preUpgradeError = "";
|
|
571
|
+
for (const scriptName of scriptsToRun) {
|
|
572
|
+
task.output = `Found upgrade check script: ${scriptName}. Downloading...`;
|
|
573
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "cedar-upgrade-"));
|
|
574
|
+
const scriptPath = path.join(tempDir, "script.ts");
|
|
575
|
+
const isDirectoryScript = scriptName.includes("/");
|
|
576
|
+
if (isDirectoryScript) {
|
|
577
|
+
const dirName = scriptName.split("/")[0];
|
|
578
|
+
const githubApiUrl = `https://api.github.com/repos/cedarjs/cedar/contents/upgrade-scripts/${dirName}`;
|
|
579
|
+
try {
|
|
580
|
+
const dirRes = await fetch(githubApiUrl, {
|
|
581
|
+
headers: {
|
|
582
|
+
Accept: "application/vnd.github.v3+json"
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
if (dirRes.status !== 200) {
|
|
586
|
+
throw new Error(
|
|
587
|
+
`Failed to fetch directory contents: ${dirRes.statusText}`
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
const files = await dirRes.json();
|
|
591
|
+
for (const file of files) {
|
|
592
|
+
if (file.type === "file") {
|
|
593
|
+
task.output = `Downloading ${file.name}...`;
|
|
594
|
+
const fileRes = await fetch(file.download_url);
|
|
595
|
+
if (fileRes.status !== 200) {
|
|
596
|
+
throw new Error(`Failed to download ${file.name}`);
|
|
597
|
+
}
|
|
598
|
+
const fileContent = await fileRes.text();
|
|
599
|
+
const filePath = path.join(tempDir, file.name);
|
|
600
|
+
await fs.writeFile(filePath, fileContent);
|
|
601
|
+
if (file.name === "index.ts") {
|
|
602
|
+
await fs.rename(filePath, scriptPath);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
} catch (e) {
|
|
607
|
+
if (verbose) {
|
|
608
|
+
console.error(e);
|
|
609
|
+
}
|
|
610
|
+
throw new Error(
|
|
611
|
+
`Failed to download upgrade script directory from ${githubApiUrl}`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
} else {
|
|
615
|
+
const scriptUrl = `${baseUrl}${scriptName}`;
|
|
616
|
+
try {
|
|
617
|
+
const res = await fetch(scriptUrl);
|
|
618
|
+
if (res.status !== 200) {
|
|
619
|
+
throw new Error(`Failed to download script: ${res.statusText}`);
|
|
620
|
+
}
|
|
621
|
+
const scriptContent2 = await res.text();
|
|
622
|
+
await fs.writeFile(scriptPath, scriptContent2);
|
|
623
|
+
} catch (e) {
|
|
624
|
+
if (verbose) {
|
|
625
|
+
console.error(e);
|
|
626
|
+
}
|
|
627
|
+
throw new Error(`Failed to download upgrade script from ${scriptUrl}`);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const scriptContent = await fs.readFile(scriptPath, "utf8");
|
|
631
|
+
const deps = extractDependencies(scriptContent);
|
|
632
|
+
if (deps.length > 0) {
|
|
633
|
+
const depList = deps.join(", ");
|
|
634
|
+
task.output = `Installing dependencies for ${scriptName}: ${depList}...`;
|
|
635
|
+
await fs.writeJson(path.join(tempDir, "package.json"), {
|
|
636
|
+
name: "pre-upgrade-script",
|
|
637
|
+
version: "0.0.0",
|
|
638
|
+
dependencies: {}
|
|
639
|
+
});
|
|
640
|
+
await execa("yarn", ["add", ...deps], { cwd: tempDir });
|
|
641
|
+
}
|
|
642
|
+
task.output = `Running pre-upgrade script: ${scriptName}...`;
|
|
643
|
+
let shouldCleanup = true;
|
|
644
|
+
try {
|
|
645
|
+
const { stdout } = await execa(
|
|
646
|
+
"node",
|
|
647
|
+
["script.ts", "--verbose", verbose, "--force", force],
|
|
648
|
+
{ cwd: tempDir }
|
|
649
|
+
);
|
|
650
|
+
if (stdout) {
|
|
651
|
+
if (ctx.preUpgradeMessage) {
|
|
652
|
+
ctx.preUpgradeMessage += "\n\n";
|
|
653
|
+
}
|
|
654
|
+
ctx.preUpgradeMessage += `
|
|
655
|
+
${stdout}`;
|
|
656
|
+
}
|
|
657
|
+
} catch (e) {
|
|
658
|
+
const errorOutput = e.stdout || e.stderr || e.message || "";
|
|
659
|
+
const errorMessage = `Pre-upgrade check ${scriptName} failed:
|
|
660
|
+
${errorOutput}`;
|
|
661
|
+
if (ctx.preUpgradeError) {
|
|
662
|
+
ctx.preUpgradeError += "\n\n";
|
|
663
|
+
}
|
|
664
|
+
ctx.preUpgradeError += errorMessage;
|
|
665
|
+
if (!force) {
|
|
666
|
+
await fs.remove(tempDir);
|
|
667
|
+
shouldCleanup = false;
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
} finally {
|
|
671
|
+
if (shouldCleanup) {
|
|
672
|
+
await fs.remove(tempDir);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
const extractDependencies = (content) => {
|
|
678
|
+
const deps = /* @__PURE__ */ new Map();
|
|
679
|
+
const commentRegex = /\/\/\s*@dependency:\s*(\S+)/g;
|
|
680
|
+
let match;
|
|
681
|
+
while ((match = commentRegex.exec(content)) !== null) {
|
|
682
|
+
const spec = match[1];
|
|
683
|
+
const nameMatch = spec.match(/^(@?[^@\s]+)(?:@.+)?$/);
|
|
684
|
+
if (nameMatch) {
|
|
685
|
+
deps.set(nameMatch[1], spec);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
const importRegex = /(?:import|from)\s*\(?['"]([^'"]+)['"]\)?/g;
|
|
689
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
690
|
+
let name = match[1];
|
|
691
|
+
if (name.startsWith(".") || name.startsWith("/") || name.startsWith("node:") || builtinModules.includes(name)) {
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
const parts = name.split("/");
|
|
695
|
+
if (name.startsWith("@") && parts.length >= 2) {
|
|
696
|
+
name = parts.slice(0, 2).join("/");
|
|
697
|
+
} else if (parts.length >= 1) {
|
|
698
|
+
name = parts[0];
|
|
699
|
+
}
|
|
700
|
+
if (!deps.has(name)) {
|
|
701
|
+
deps.set(name, name);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return Array.from(deps.values());
|
|
705
|
+
};
|
|
462
706
|
export {
|
|
463
707
|
builder,
|
|
464
708
|
command,
|
|
465
709
|
description,
|
|
466
710
|
handler,
|
|
711
|
+
runPreUpgradeScripts,
|
|
467
712
|
validateTag
|
|
468
713
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/cli",
|
|
3
|
-
"version": "1.0.0-canary.
|
|
3
|
+
"version": "1.0.0-canary.13040+853b364fd",
|
|
4
4
|
"description": "The CedarJS Command Line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@babel/preset-typescript": "7.28.5",
|
|
33
33
|
"@babel/runtime-corejs3": "7.28.4",
|
|
34
|
-
"@cedarjs/api-server": "1.0.0-canary.
|
|
35
|
-
"@cedarjs/cli-helpers": "1.0.0-canary.
|
|
36
|
-
"@cedarjs/fastify-web": "1.0.0-canary.
|
|
37
|
-
"@cedarjs/internal": "1.0.0-canary.
|
|
38
|
-
"@cedarjs/prerender": "1.0.0-canary.
|
|
39
|
-
"@cedarjs/project-config": "1.0.0-canary.
|
|
40
|
-
"@cedarjs/structure": "1.0.0-canary.
|
|
41
|
-
"@cedarjs/telemetry": "1.0.0-canary.
|
|
42
|
-
"@cedarjs/web-server": "1.0.0-canary.
|
|
34
|
+
"@cedarjs/api-server": "1.0.0-canary.13040",
|
|
35
|
+
"@cedarjs/cli-helpers": "1.0.0-canary.13040",
|
|
36
|
+
"@cedarjs/fastify-web": "1.0.0-canary.13040",
|
|
37
|
+
"@cedarjs/internal": "1.0.0-canary.13040",
|
|
38
|
+
"@cedarjs/prerender": "1.0.0-canary.13040",
|
|
39
|
+
"@cedarjs/project-config": "1.0.0-canary.13040",
|
|
40
|
+
"@cedarjs/structure": "1.0.0-canary.13040",
|
|
41
|
+
"@cedarjs/telemetry": "1.0.0-canary.13040",
|
|
42
|
+
"@cedarjs/web-server": "1.0.0-canary.13040",
|
|
43
43
|
"@listr2/prompt-adapter-enquirer": "2.0.16",
|
|
44
44
|
"@opentelemetry/api": "1.8.0",
|
|
45
45
|
"@opentelemetry/core": "1.22.0",
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
"@types/archiver": "^6",
|
|
95
95
|
"memfs": "4.51.1",
|
|
96
96
|
"node-ssh": "13.2.1",
|
|
97
|
+
"ts-dedent": "2.2.0",
|
|
97
98
|
"tsx": "4.21.0",
|
|
98
99
|
"typescript": "5.9.3",
|
|
99
100
|
"vitest": "3.2.4"
|
|
@@ -101,5 +102,5 @@
|
|
|
101
102
|
"publishConfig": {
|
|
102
103
|
"access": "public"
|
|
103
104
|
},
|
|
104
|
-
"gitHead": "
|
|
105
|
+
"gitHead": "853b364fd7336788a4a48b99a6c879b17ac3824b"
|
|
105
106
|
}
|