@cloudwerk/cli 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +124 -33
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -324,7 +324,8 @@ async function build(pathArg, options) {
|
|
|
324
324
|
hydrationEndpoint: "/__cloudwerk",
|
|
325
325
|
renderer,
|
|
326
326
|
publicDir: cloudwerkConfig.publicDir ?? "public",
|
|
327
|
-
root: cwd
|
|
327
|
+
root: cwd,
|
|
328
|
+
isProduction: true
|
|
328
329
|
});
|
|
329
330
|
const tempEntryPath = path2.join(tempDir, "_server-entry.ts");
|
|
330
331
|
fs2.writeFileSync(tempEntryPath, serverEntryCode);
|
|
@@ -468,13 +469,102 @@ function formatSize(bytes) {
|
|
|
468
469
|
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
469
470
|
}
|
|
470
471
|
|
|
472
|
+
// src/commands/deploy.ts
|
|
473
|
+
import * as path3 from "path";
|
|
474
|
+
import * as fs3 from "fs";
|
|
475
|
+
import { spawn } from "child_process";
|
|
476
|
+
async function deploy(pathArg, options) {
|
|
477
|
+
const verbose = options.verbose ?? false;
|
|
478
|
+
const logger = createLogger(verbose);
|
|
479
|
+
try {
|
|
480
|
+
const cwd = pathArg ? path3.resolve(process.cwd(), pathArg) : process.cwd();
|
|
481
|
+
if (!fs3.existsSync(cwd)) {
|
|
482
|
+
throw new CliError(
|
|
483
|
+
`Directory does not exist: ${cwd}`,
|
|
484
|
+
"ENOENT",
|
|
485
|
+
`Make sure the path exists and try again.`
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
logger.debug(`Working directory: ${cwd}`);
|
|
489
|
+
const wranglerPath = path3.join(cwd, "wrangler.toml");
|
|
490
|
+
if (!fs3.existsSync(wranglerPath)) {
|
|
491
|
+
throw new CliError(
|
|
492
|
+
`wrangler.toml not found in ${cwd}`,
|
|
493
|
+
"ENOENT",
|
|
494
|
+
`Create a wrangler.toml file or run this command from a directory containing one.`
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
logger.debug(`Found wrangler.toml: ${wranglerPath}`);
|
|
498
|
+
if (!options.skipBuild) {
|
|
499
|
+
logger.info("Building project...");
|
|
500
|
+
await build(pathArg, {
|
|
501
|
+
config: options.config,
|
|
502
|
+
verbose: options.verbose
|
|
503
|
+
});
|
|
504
|
+
console.log();
|
|
505
|
+
}
|
|
506
|
+
const args = ["wrangler", "deploy"];
|
|
507
|
+
if (options.env) {
|
|
508
|
+
args.push("--env", options.env);
|
|
509
|
+
}
|
|
510
|
+
if (options.dryRun) {
|
|
511
|
+
args.push("--dry-run");
|
|
512
|
+
}
|
|
513
|
+
const envLabel = options.env ? ` to ${options.env}` : "";
|
|
514
|
+
const dryRunLabel = options.dryRun ? " (dry run)" : "";
|
|
515
|
+
logger.info(`Deploying${envLabel}${dryRunLabel}...`);
|
|
516
|
+
logger.debug(`Running: npx ${args.join(" ")}`);
|
|
517
|
+
const exitCode = await runCommand(args, cwd);
|
|
518
|
+
if (exitCode !== 0) {
|
|
519
|
+
throw new CliError(
|
|
520
|
+
`Deployment failed with exit code ${exitCode}`,
|
|
521
|
+
"EDEPLOY",
|
|
522
|
+
`Check the wrangler output above for details.`
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
if (!options.dryRun) {
|
|
526
|
+
logger.success("Deployment complete!");
|
|
527
|
+
} else {
|
|
528
|
+
logger.success("Dry run complete!");
|
|
529
|
+
}
|
|
530
|
+
} catch (error) {
|
|
531
|
+
if (error instanceof CliError) {
|
|
532
|
+
printError(error.message, error.suggestion);
|
|
533
|
+
process.exit(1);
|
|
534
|
+
}
|
|
535
|
+
if (error instanceof Error) {
|
|
536
|
+
printError(error.message);
|
|
537
|
+
if (verbose && error.stack) {
|
|
538
|
+
console.log(error.stack);
|
|
539
|
+
}
|
|
540
|
+
process.exit(1);
|
|
541
|
+
}
|
|
542
|
+
printError(String(error));
|
|
543
|
+
process.exit(1);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function runCommand(args, cwd) {
|
|
547
|
+
return new Promise((resolve4, reject) => {
|
|
548
|
+
const child = spawn("npx", args, {
|
|
549
|
+
cwd,
|
|
550
|
+
stdio: "inherit"
|
|
551
|
+
});
|
|
552
|
+
child.on("error", (error) => {
|
|
553
|
+
reject(error);
|
|
554
|
+
});
|
|
555
|
+
child.on("close", (code) => {
|
|
556
|
+
resolve4(code ?? 0);
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
|
|
471
561
|
// src/commands/config.ts
|
|
472
562
|
import * as readline from "readline";
|
|
473
563
|
import pc2 from "picocolors";
|
|
474
564
|
|
|
475
565
|
// src/utils/configWriter.ts
|
|
476
|
-
import * as
|
|
477
|
-
import * as
|
|
566
|
+
import * as fs4 from "fs";
|
|
567
|
+
import * as path4 from "path";
|
|
478
568
|
import { loadConfig as loadConfig2 } from "@cloudwerk/core/build";
|
|
479
569
|
var CONFIG_FILE_NAMES = [
|
|
480
570
|
"cloudwerk.config.ts",
|
|
@@ -483,8 +573,8 @@ var CONFIG_FILE_NAMES = [
|
|
|
483
573
|
];
|
|
484
574
|
function findConfigFile(cwd) {
|
|
485
575
|
for (const filename of CONFIG_FILE_NAMES) {
|
|
486
|
-
const configPath =
|
|
487
|
-
if (
|
|
576
|
+
const configPath = path4.join(cwd, filename);
|
|
577
|
+
if (fs4.existsSync(configPath)) {
|
|
488
578
|
return configPath;
|
|
489
579
|
}
|
|
490
580
|
}
|
|
@@ -495,7 +585,7 @@ function readCloudwerkConfig(cwd) {
|
|
|
495
585
|
if (!configPath) {
|
|
496
586
|
return {};
|
|
497
587
|
}
|
|
498
|
-
const content =
|
|
588
|
+
const content = fs4.readFileSync(configPath, "utf-8");
|
|
499
589
|
return parseConfigContent(content);
|
|
500
590
|
}
|
|
501
591
|
function parseConfigContent(content) {
|
|
@@ -516,16 +606,16 @@ function parseConfigContent(content) {
|
|
|
516
606
|
function writeCloudwerkConfig(cwd, updates) {
|
|
517
607
|
const configPath = findConfigFile(cwd);
|
|
518
608
|
if (!configPath) {
|
|
519
|
-
const newConfigPath =
|
|
609
|
+
const newConfigPath = path4.join(cwd, "cloudwerk.config.ts");
|
|
520
610
|
const content2 = generateMinimalConfig(updates);
|
|
521
|
-
|
|
611
|
+
fs4.writeFileSync(newConfigPath, content2, "utf-8");
|
|
522
612
|
return true;
|
|
523
613
|
}
|
|
524
|
-
let content =
|
|
614
|
+
let content = fs4.readFileSync(configPath, "utf-8");
|
|
525
615
|
if (updates.renderer !== void 0) {
|
|
526
616
|
content = updateRenderer(content, updates.renderer);
|
|
527
617
|
}
|
|
528
|
-
|
|
618
|
+
fs4.writeFileSync(configPath, content, "utf-8");
|
|
529
619
|
return true;
|
|
530
620
|
}
|
|
531
621
|
function updateRenderer(content, renderer) {
|
|
@@ -594,11 +684,11 @@ function generateMinimalConfig(updates) {
|
|
|
594
684
|
}
|
|
595
685
|
|
|
596
686
|
// src/utils/tsconfigWriter.ts
|
|
597
|
-
import * as
|
|
598
|
-
import * as
|
|
687
|
+
import * as fs5 from "fs";
|
|
688
|
+
import * as path5 from "path";
|
|
599
689
|
function findTsConfig(cwd) {
|
|
600
|
-
const tsconfigPath =
|
|
601
|
-
if (
|
|
690
|
+
const tsconfigPath = path5.join(cwd, "tsconfig.json");
|
|
691
|
+
if (fs5.existsSync(tsconfigPath)) {
|
|
602
692
|
return tsconfigPath;
|
|
603
693
|
}
|
|
604
694
|
return null;
|
|
@@ -609,7 +699,7 @@ function readTsConfig(cwd) {
|
|
|
609
699
|
return {};
|
|
610
700
|
}
|
|
611
701
|
try {
|
|
612
|
-
const content =
|
|
702
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
613
703
|
const config = JSON.parse(content);
|
|
614
704
|
return {
|
|
615
705
|
jsxImportSource: config.compilerOptions?.jsxImportSource,
|
|
@@ -625,7 +715,7 @@ function updateTsConfig(cwd, updates) {
|
|
|
625
715
|
return false;
|
|
626
716
|
}
|
|
627
717
|
try {
|
|
628
|
-
const content =
|
|
718
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
629
719
|
const config = JSON.parse(content);
|
|
630
720
|
if (!config.compilerOptions) {
|
|
631
721
|
config.compilerOptions = {};
|
|
@@ -633,7 +723,7 @@ function updateTsConfig(cwd, updates) {
|
|
|
633
723
|
if (updates.jsxImportSource !== void 0) {
|
|
634
724
|
config.compilerOptions.jsxImportSource = updates.jsxImportSource;
|
|
635
725
|
}
|
|
636
|
-
|
|
726
|
+
fs5.writeFileSync(tsconfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
637
727
|
return true;
|
|
638
728
|
} catch {
|
|
639
729
|
return false;
|
|
@@ -641,8 +731,8 @@ function updateTsConfig(cwd, updates) {
|
|
|
641
731
|
}
|
|
642
732
|
|
|
643
733
|
// src/utils/dependencyManager.ts
|
|
644
|
-
import * as
|
|
645
|
-
import * as
|
|
734
|
+
import * as fs6 from "fs";
|
|
735
|
+
import * as path6 from "path";
|
|
646
736
|
import { execFileSync } from "child_process";
|
|
647
737
|
var REACT_SPECIFIC_LIBRARIES = [
|
|
648
738
|
"@tanstack/react-query",
|
|
@@ -683,22 +773,22 @@ var REACT_SPECIFIC_LIBRARIES = [
|
|
|
683
773
|
"@use-gesture/react"
|
|
684
774
|
];
|
|
685
775
|
function detectPackageManager(cwd) {
|
|
686
|
-
if (
|
|
776
|
+
if (fs6.existsSync(path6.join(cwd, "pnpm-lock.yaml"))) {
|
|
687
777
|
return "pnpm";
|
|
688
778
|
}
|
|
689
|
-
if (
|
|
779
|
+
if (fs6.existsSync(path6.join(cwd, "yarn.lock"))) {
|
|
690
780
|
return "yarn";
|
|
691
781
|
}
|
|
692
|
-
if (
|
|
782
|
+
if (fs6.existsSync(path6.join(cwd, "bun.lockb"))) {
|
|
693
783
|
return "bun";
|
|
694
784
|
}
|
|
695
|
-
if (
|
|
785
|
+
if (fs6.existsSync(path6.join(cwd, "package-lock.json"))) {
|
|
696
786
|
return "npm";
|
|
697
787
|
}
|
|
698
|
-
const packageJsonPath =
|
|
699
|
-
if (
|
|
788
|
+
const packageJsonPath = path6.join(cwd, "package.json");
|
|
789
|
+
if (fs6.existsSync(packageJsonPath)) {
|
|
700
790
|
try {
|
|
701
|
-
const packageJson = JSON.parse(
|
|
791
|
+
const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
|
|
702
792
|
const pm = packageJson.packageManager;
|
|
703
793
|
if (pm) {
|
|
704
794
|
if (pm.startsWith("pnpm")) return "pnpm";
|
|
@@ -712,15 +802,15 @@ function detectPackageManager(cwd) {
|
|
|
712
802
|
return "npm";
|
|
713
803
|
}
|
|
714
804
|
function getInstalledDependencies(cwd) {
|
|
715
|
-
const packageJsonPath =
|
|
716
|
-
if (!
|
|
805
|
+
const packageJsonPath = path6.join(cwd, "package.json");
|
|
806
|
+
if (!fs6.existsSync(packageJsonPath)) {
|
|
717
807
|
return {
|
|
718
808
|
dependencies: {},
|
|
719
809
|
devDependencies: {}
|
|
720
810
|
};
|
|
721
811
|
}
|
|
722
812
|
try {
|
|
723
|
-
const content =
|
|
813
|
+
const content = fs6.readFileSync(packageJsonPath, "utf-8");
|
|
724
814
|
const packageJson = JSON.parse(content);
|
|
725
815
|
return {
|
|
726
816
|
dependencies: packageJson.dependencies || {},
|
|
@@ -1043,16 +1133,16 @@ async function askConfirmation(question, defaultValue) {
|
|
|
1043
1133
|
output: process.stdout
|
|
1044
1134
|
});
|
|
1045
1135
|
const hint = defaultValue ? "Y/n" : "y/N";
|
|
1046
|
-
return new Promise((
|
|
1136
|
+
return new Promise((resolve4) => {
|
|
1047
1137
|
rl.question(pc2.cyan("? ") + question + pc2.dim(` (${hint}) `), (answer) => {
|
|
1048
1138
|
rl.close();
|
|
1049
1139
|
const normalized = answer.trim().toLowerCase();
|
|
1050
1140
|
if (normalized === "") {
|
|
1051
|
-
|
|
1141
|
+
resolve4(defaultValue);
|
|
1052
1142
|
} else if (normalized === "y" || normalized === "yes") {
|
|
1053
|
-
|
|
1143
|
+
resolve4(true);
|
|
1054
1144
|
} else {
|
|
1055
|
-
|
|
1145
|
+
resolve4(false);
|
|
1056
1146
|
}
|
|
1057
1147
|
});
|
|
1058
1148
|
});
|
|
@@ -1062,6 +1152,7 @@ async function askConfirmation(question, defaultValue) {
|
|
|
1062
1152
|
program.name("cloudwerk").description("Cloudwerk CLI - Build and deploy full-stack apps to Cloudflare").version(VERSION);
|
|
1063
1153
|
program.command("dev [path]").description("Start development server").option("-p, --port <number>", "Port to listen on", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to bind", DEFAULT_HOST).option("-c, --config <path>", "Path to config file").option("--verbose", "Enable verbose logging").action(dev);
|
|
1064
1154
|
program.command("build [path]").description("Build project for production deployment to Cloudflare Workers").option("-o, --output <dir>", "Output directory", "./dist").option("--ssg", "Generate static pages for routes with rendering: static").option("--minify", "Minify bundles (default: true)").option("--no-minify", "Disable minification").option("--sourcemap", "Generate source maps").option("-c, --config <path>", "Path to config file").option("--verbose", "Enable verbose logging").action(build);
|
|
1155
|
+
program.command("deploy [path]").description("Deploy to Cloudflare Workers").option("-e, --env <environment>", "Environment to deploy to").option("--dry-run", "Preview deployment without executing").option("--skip-build", "Skip the build step").option("-c, --config <path>", "Path to config file").option("--verbose", "Enable verbose logging").action(deploy);
|
|
1065
1156
|
var configCmd = program.command("config").description("Manage Cloudwerk configuration");
|
|
1066
1157
|
configCmd.command("get <key>").description("Get a configuration value").action(configGet);
|
|
1067
1158
|
configCmd.command("set <key> <value>").description("Set a configuration value").action(configSet);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudwerk/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Dev server, build, deploy commands for Cloudwerk",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"esbuild": "^0.25.0",
|
|
29
29
|
"picocolors": "^1.1.0",
|
|
30
30
|
"vite": "^6.0.0",
|
|
31
|
-
"@cloudwerk/core": "^0.9.0",
|
|
32
31
|
"@cloudwerk/ui": "^0.9.0",
|
|
33
|
-
"@cloudwerk/vite-plugin": "^0.
|
|
32
|
+
"@cloudwerk/vite-plugin": "^0.4.0",
|
|
33
|
+
"@cloudwerk/core": "^0.9.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^20.0.0",
|