@cloudwerk/cli 0.8.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 +127 -33
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -323,7 +323,9 @@ async function build(pathArg, options) {
|
|
|
323
323
|
verbose,
|
|
324
324
|
hydrationEndpoint: "/__cloudwerk",
|
|
325
325
|
renderer,
|
|
326
|
-
|
|
326
|
+
publicDir: cloudwerkConfig.publicDir ?? "public",
|
|
327
|
+
root: cwd,
|
|
328
|
+
isProduction: true
|
|
327
329
|
});
|
|
328
330
|
const tempEntryPath = path2.join(tempDir, "_server-entry.ts");
|
|
329
331
|
fs2.writeFileSync(tempEntryPath, serverEntryCode);
|
|
@@ -364,6 +366,8 @@ async function build(pathArg, options) {
|
|
|
364
366
|
root: cwd,
|
|
365
367
|
mode: "production",
|
|
366
368
|
logLevel: verbose ? "info" : "warn",
|
|
369
|
+
// Disable publicDir for server build - static assets are already in dist/static/ from client build
|
|
370
|
+
publicDir: false,
|
|
367
371
|
plugins: [
|
|
368
372
|
cloudwerk2({ verbose })
|
|
369
373
|
],
|
|
@@ -465,13 +469,102 @@ function formatSize(bytes) {
|
|
|
465
469
|
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
466
470
|
}
|
|
467
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
|
+
|
|
468
561
|
// src/commands/config.ts
|
|
469
562
|
import * as readline from "readline";
|
|
470
563
|
import pc2 from "picocolors";
|
|
471
564
|
|
|
472
565
|
// src/utils/configWriter.ts
|
|
473
|
-
import * as
|
|
474
|
-
import * as
|
|
566
|
+
import * as fs4 from "fs";
|
|
567
|
+
import * as path4 from "path";
|
|
475
568
|
import { loadConfig as loadConfig2 } from "@cloudwerk/core/build";
|
|
476
569
|
var CONFIG_FILE_NAMES = [
|
|
477
570
|
"cloudwerk.config.ts",
|
|
@@ -480,8 +573,8 @@ var CONFIG_FILE_NAMES = [
|
|
|
480
573
|
];
|
|
481
574
|
function findConfigFile(cwd) {
|
|
482
575
|
for (const filename of CONFIG_FILE_NAMES) {
|
|
483
|
-
const configPath =
|
|
484
|
-
if (
|
|
576
|
+
const configPath = path4.join(cwd, filename);
|
|
577
|
+
if (fs4.existsSync(configPath)) {
|
|
485
578
|
return configPath;
|
|
486
579
|
}
|
|
487
580
|
}
|
|
@@ -492,7 +585,7 @@ function readCloudwerkConfig(cwd) {
|
|
|
492
585
|
if (!configPath) {
|
|
493
586
|
return {};
|
|
494
587
|
}
|
|
495
|
-
const content =
|
|
588
|
+
const content = fs4.readFileSync(configPath, "utf-8");
|
|
496
589
|
return parseConfigContent(content);
|
|
497
590
|
}
|
|
498
591
|
function parseConfigContent(content) {
|
|
@@ -513,16 +606,16 @@ function parseConfigContent(content) {
|
|
|
513
606
|
function writeCloudwerkConfig(cwd, updates) {
|
|
514
607
|
const configPath = findConfigFile(cwd);
|
|
515
608
|
if (!configPath) {
|
|
516
|
-
const newConfigPath =
|
|
609
|
+
const newConfigPath = path4.join(cwd, "cloudwerk.config.ts");
|
|
517
610
|
const content2 = generateMinimalConfig(updates);
|
|
518
|
-
|
|
611
|
+
fs4.writeFileSync(newConfigPath, content2, "utf-8");
|
|
519
612
|
return true;
|
|
520
613
|
}
|
|
521
|
-
let content =
|
|
614
|
+
let content = fs4.readFileSync(configPath, "utf-8");
|
|
522
615
|
if (updates.renderer !== void 0) {
|
|
523
616
|
content = updateRenderer(content, updates.renderer);
|
|
524
617
|
}
|
|
525
|
-
|
|
618
|
+
fs4.writeFileSync(configPath, content, "utf-8");
|
|
526
619
|
return true;
|
|
527
620
|
}
|
|
528
621
|
function updateRenderer(content, renderer) {
|
|
@@ -591,11 +684,11 @@ function generateMinimalConfig(updates) {
|
|
|
591
684
|
}
|
|
592
685
|
|
|
593
686
|
// src/utils/tsconfigWriter.ts
|
|
594
|
-
import * as
|
|
595
|
-
import * as
|
|
687
|
+
import * as fs5 from "fs";
|
|
688
|
+
import * as path5 from "path";
|
|
596
689
|
function findTsConfig(cwd) {
|
|
597
|
-
const tsconfigPath =
|
|
598
|
-
if (
|
|
690
|
+
const tsconfigPath = path5.join(cwd, "tsconfig.json");
|
|
691
|
+
if (fs5.existsSync(tsconfigPath)) {
|
|
599
692
|
return tsconfigPath;
|
|
600
693
|
}
|
|
601
694
|
return null;
|
|
@@ -606,7 +699,7 @@ function readTsConfig(cwd) {
|
|
|
606
699
|
return {};
|
|
607
700
|
}
|
|
608
701
|
try {
|
|
609
|
-
const content =
|
|
702
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
610
703
|
const config = JSON.parse(content);
|
|
611
704
|
return {
|
|
612
705
|
jsxImportSource: config.compilerOptions?.jsxImportSource,
|
|
@@ -622,7 +715,7 @@ function updateTsConfig(cwd, updates) {
|
|
|
622
715
|
return false;
|
|
623
716
|
}
|
|
624
717
|
try {
|
|
625
|
-
const content =
|
|
718
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
626
719
|
const config = JSON.parse(content);
|
|
627
720
|
if (!config.compilerOptions) {
|
|
628
721
|
config.compilerOptions = {};
|
|
@@ -630,7 +723,7 @@ function updateTsConfig(cwd, updates) {
|
|
|
630
723
|
if (updates.jsxImportSource !== void 0) {
|
|
631
724
|
config.compilerOptions.jsxImportSource = updates.jsxImportSource;
|
|
632
725
|
}
|
|
633
|
-
|
|
726
|
+
fs5.writeFileSync(tsconfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
634
727
|
return true;
|
|
635
728
|
} catch {
|
|
636
729
|
return false;
|
|
@@ -638,8 +731,8 @@ function updateTsConfig(cwd, updates) {
|
|
|
638
731
|
}
|
|
639
732
|
|
|
640
733
|
// src/utils/dependencyManager.ts
|
|
641
|
-
import * as
|
|
642
|
-
import * as
|
|
734
|
+
import * as fs6 from "fs";
|
|
735
|
+
import * as path6 from "path";
|
|
643
736
|
import { execFileSync } from "child_process";
|
|
644
737
|
var REACT_SPECIFIC_LIBRARIES = [
|
|
645
738
|
"@tanstack/react-query",
|
|
@@ -680,22 +773,22 @@ var REACT_SPECIFIC_LIBRARIES = [
|
|
|
680
773
|
"@use-gesture/react"
|
|
681
774
|
];
|
|
682
775
|
function detectPackageManager(cwd) {
|
|
683
|
-
if (
|
|
776
|
+
if (fs6.existsSync(path6.join(cwd, "pnpm-lock.yaml"))) {
|
|
684
777
|
return "pnpm";
|
|
685
778
|
}
|
|
686
|
-
if (
|
|
779
|
+
if (fs6.existsSync(path6.join(cwd, "yarn.lock"))) {
|
|
687
780
|
return "yarn";
|
|
688
781
|
}
|
|
689
|
-
if (
|
|
782
|
+
if (fs6.existsSync(path6.join(cwd, "bun.lockb"))) {
|
|
690
783
|
return "bun";
|
|
691
784
|
}
|
|
692
|
-
if (
|
|
785
|
+
if (fs6.existsSync(path6.join(cwd, "package-lock.json"))) {
|
|
693
786
|
return "npm";
|
|
694
787
|
}
|
|
695
|
-
const packageJsonPath =
|
|
696
|
-
if (
|
|
788
|
+
const packageJsonPath = path6.join(cwd, "package.json");
|
|
789
|
+
if (fs6.existsSync(packageJsonPath)) {
|
|
697
790
|
try {
|
|
698
|
-
const packageJson = JSON.parse(
|
|
791
|
+
const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
|
|
699
792
|
const pm = packageJson.packageManager;
|
|
700
793
|
if (pm) {
|
|
701
794
|
if (pm.startsWith("pnpm")) return "pnpm";
|
|
@@ -709,15 +802,15 @@ function detectPackageManager(cwd) {
|
|
|
709
802
|
return "npm";
|
|
710
803
|
}
|
|
711
804
|
function getInstalledDependencies(cwd) {
|
|
712
|
-
const packageJsonPath =
|
|
713
|
-
if (!
|
|
805
|
+
const packageJsonPath = path6.join(cwd, "package.json");
|
|
806
|
+
if (!fs6.existsSync(packageJsonPath)) {
|
|
714
807
|
return {
|
|
715
808
|
dependencies: {},
|
|
716
809
|
devDependencies: {}
|
|
717
810
|
};
|
|
718
811
|
}
|
|
719
812
|
try {
|
|
720
|
-
const content =
|
|
813
|
+
const content = fs6.readFileSync(packageJsonPath, "utf-8");
|
|
721
814
|
const packageJson = JSON.parse(content);
|
|
722
815
|
return {
|
|
723
816
|
dependencies: packageJson.dependencies || {},
|
|
@@ -1040,16 +1133,16 @@ async function askConfirmation(question, defaultValue) {
|
|
|
1040
1133
|
output: process.stdout
|
|
1041
1134
|
});
|
|
1042
1135
|
const hint = defaultValue ? "Y/n" : "y/N";
|
|
1043
|
-
return new Promise((
|
|
1136
|
+
return new Promise((resolve4) => {
|
|
1044
1137
|
rl.question(pc2.cyan("? ") + question + pc2.dim(` (${hint}) `), (answer) => {
|
|
1045
1138
|
rl.close();
|
|
1046
1139
|
const normalized = answer.trim().toLowerCase();
|
|
1047
1140
|
if (normalized === "") {
|
|
1048
|
-
|
|
1141
|
+
resolve4(defaultValue);
|
|
1049
1142
|
} else if (normalized === "y" || normalized === "yes") {
|
|
1050
|
-
|
|
1143
|
+
resolve4(true);
|
|
1051
1144
|
} else {
|
|
1052
|
-
|
|
1145
|
+
resolve4(false);
|
|
1053
1146
|
}
|
|
1054
1147
|
});
|
|
1055
1148
|
});
|
|
@@ -1059,6 +1152,7 @@ async function askConfirmation(question, defaultValue) {
|
|
|
1059
1152
|
program.name("cloudwerk").description("Cloudwerk CLI - Build and deploy full-stack apps to Cloudflare").version(VERSION);
|
|
1060
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);
|
|
1061
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);
|
|
1062
1156
|
var configCmd = program.command("config").description("Manage Cloudwerk configuration");
|
|
1063
1157
|
configCmd.command("get <key>").description("Get a configuration value").action(configGet);
|
|
1064
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/
|
|
32
|
-
"@cloudwerk/
|
|
33
|
-
"@cloudwerk/
|
|
31
|
+
"@cloudwerk/ui": "^0.9.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",
|