@solcreek/cli 0.4.7 → 0.4.9
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/deploy.js +121 -69
- package/package.json +2 -2
package/dist/commands/deploy.js
CHANGED
|
@@ -4,7 +4,7 @@ import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, rmSync
|
|
|
4
4
|
// ajv is lazy-imported only when --template --data is used (avoid top-level crash if deps missing)
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
6
|
import { execSync, execFileSync } from "node:child_process";
|
|
7
|
-
import { CreekClient, CreekAuthError, isSSRFramework, getSSRServerEntry, getClientAssetsDir, getDefaultBuildOutput, detectFramework, resolveConfig, formatDetectionSummary, resolvedConfigToResources, resolvedConfigToBindingRequirements, ConfigNotFoundError, getSSRServerDir, collectServerFiles, isPreBundledFramework, detectAstroCloudflareBuild, detectNextjsMode, detectMonorepo, } from "@solcreek/sdk";
|
|
7
|
+
import { CreekClient, CreekAuthError, isSSRFramework, getSSRServerEntry, getClientAssetsDir, getDefaultBuildOutput, detectFramework, resolveConfig, formatDetectionSummary, resolvedConfigToResources, resolvedConfigToBindingRequirements, ConfigNotFoundError, getSSRServerDir, collectServerFiles, isPreBundledFramework, detectAstroCloudflareBuild, detectNextjsMode, detectMonorepo, planDeploy, } from "@solcreek/sdk";
|
|
8
8
|
import { getToken, getApiUrl } from "../utils/config.js";
|
|
9
9
|
import { collectAssets } from "../utils/bundle.js";
|
|
10
10
|
import { bundleSSRServer } from "../utils/ssr-bundle.js";
|
|
@@ -724,79 +724,92 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
|
|
|
724
724
|
const outputDir = useAdapterOutput
|
|
725
725
|
? resolve(cwd, ".creek/adapter-output")
|
|
726
726
|
: resolve(cwd, resolved?.buildOutput ?? getDefaultBuildOutput(framework));
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
727
|
+
// Whether buildOutput exists is now an INPUT to planDeploy, not a
|
|
728
|
+
// hard precondition — pure-Worker projects legitimately have no
|
|
729
|
+
// build output directory, and planDeploy returns an explicit error
|
|
730
|
+
// for the cases that genuinely need one.
|
|
731
|
+
// Resolve deploy shape via the SDK's pure planner. All branching
|
|
732
|
+
// (SPA vs SSR vs Worker, with-or-without coexisting static assets,
|
|
733
|
+
// bundled vs source worker entry) lives in deploy-plan.ts and is
|
|
734
|
+
// table-tested. Don't re-derive these conditions inline.
|
|
735
|
+
const planResult = planDeploy({
|
|
736
|
+
framework,
|
|
737
|
+
workerEntry: resolved?.workerEntry ?? null,
|
|
738
|
+
workerEntryExists: !!resolved?.workerEntry &&
|
|
739
|
+
existsSync(resolve(cwd, resolved.workerEntry)),
|
|
740
|
+
buildOutput: resolved?.buildOutput ?? "dist",
|
|
741
|
+
buildOutputExists: existsSync(outputDir),
|
|
742
|
+
astroCF: null, // sandbox path doesn't run post-build adapter detection (yet)
|
|
743
|
+
});
|
|
744
|
+
if (!planResult.ok) {
|
|
745
|
+
consola.error(planResult.reason);
|
|
732
746
|
process.exit(1);
|
|
733
747
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
// Three shapes, mirroring the authenticated deploy path:
|
|
737
|
-
// 1. Framework-detected SSR (Astro/Nuxt/etc.) → bundle the framework's
|
|
738
|
-
// server entry, upload dist/ as assets.
|
|
739
|
-
// 2. User-declared Worker (`[build].worker` in creek.toml, no framework)
|
|
740
|
-
// → bundle the Worker entry with esbuild, serverFiles = { worker.js }.
|
|
741
|
-
// `dist/` assets are skipped for now — the "Workers + Static Assets
|
|
742
|
-
// coexist" zero-config pattern is tracked separately and requires
|
|
743
|
-
// build-pipeline changes; until it lands, users inline HTML/JS/CSS
|
|
744
|
-
// into the Worker (see docs).
|
|
745
|
-
// 3. Neither → plain SPA/static, everything goes as assets.
|
|
746
|
-
const isSSR = isSSRFramework(framework);
|
|
747
|
-
const isWorker = !framework && !!resolved?.workerEntry;
|
|
748
|
-
const renderMode = isWorker ? "worker" : (isSSR ? "ssr" : "spa");
|
|
748
|
+
const plan = planResult.plan;
|
|
749
|
+
const renderMode = plan.renderMode;
|
|
749
750
|
let clientAssets = {};
|
|
750
751
|
let fileList = [];
|
|
751
|
-
if (
|
|
752
|
-
let clientAssetsDir
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
const subdir = getClientAssetsDir(framework);
|
|
760
|
-
if (subdir)
|
|
761
|
-
clientAssetsDir = resolve(outputDir, subdir);
|
|
762
|
-
}
|
|
752
|
+
if (plan.assets.enabled && plan.assets.dir) {
|
|
753
|
+
let clientAssetsDir = useAdapterOutput
|
|
754
|
+
? resolve(outputDir, "assets")
|
|
755
|
+
: resolve(cwd, plan.assets.dir);
|
|
756
|
+
if (!useAdapterOutput && isSSRFramework(framework) && framework) {
|
|
757
|
+
const subdir = getClientAssetsDir(framework);
|
|
758
|
+
if (subdir)
|
|
759
|
+
clientAssetsDir = resolve(clientAssetsDir, subdir);
|
|
763
760
|
}
|
|
764
761
|
const collected = collectAssets(clientAssetsDir);
|
|
765
762
|
clientAssets = collected.assets;
|
|
766
763
|
fileList = collected.fileList;
|
|
764
|
+
if (plan.assets.excludeFile) {
|
|
765
|
+
delete clientAssets["/" + plan.assets.excludeFile];
|
|
766
|
+
delete clientAssets[plan.assets.excludeFile];
|
|
767
|
+
fileList = fileList.filter((p) => p !== plan.assets.excludeFile && p !== "/" + plan.assets.excludeFile);
|
|
768
|
+
}
|
|
767
769
|
}
|
|
768
770
|
section("Upload");
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
771
|
+
consola.info(` Mode: ${renderMode}${plan.worker.entry ? ` (worker: ${plan.worker.entry})` : ""}`);
|
|
772
|
+
if (plan.assets.enabled) {
|
|
773
773
|
consola.info(` ${fileList.length} assets (${assetSummary(fileList)})`);
|
|
774
774
|
}
|
|
775
775
|
let serverFiles;
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
776
|
+
switch (plan.worker.strategy) {
|
|
777
|
+
case "none":
|
|
778
|
+
break;
|
|
779
|
+
case "ssr-framework": {
|
|
780
|
+
// Sandbox path doesn't currently support pre-bundled SSR
|
|
781
|
+
// frameworks (Nuxt/SvelteKit/Astro CF); planDeploy only returns
|
|
782
|
+
// this strategy for SSR frameworks, which we still bundle via
|
|
783
|
+
// the legacy single-file path below to keep diff small.
|
|
784
|
+
const serverEntry = getSSRServerEntry(framework);
|
|
785
|
+
if (serverEntry) {
|
|
786
|
+
const serverEntryPath = resolve(outputDir, serverEntry);
|
|
787
|
+
if (existsSync(serverEntryPath)) {
|
|
788
|
+
consola.start(" Bundling SSR server...");
|
|
789
|
+
const bundled = await bundleSSRServer(serverEntryPath);
|
|
790
|
+
serverFiles = { "server.js": Buffer.from(bundled).toString("base64") };
|
|
791
|
+
consola.success(` SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
792
|
+
}
|
|
785
793
|
}
|
|
794
|
+
break;
|
|
786
795
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
796
|
+
case "esbuild-bundle": {
|
|
797
|
+
const workerEntryPath = resolve(cwd, plan.worker.entry);
|
|
798
|
+
consola.start(" Bundling worker...");
|
|
799
|
+
const bundled = await bundleWorker(workerEntryPath, cwd, {
|
|
800
|
+
hasClientAssets: plan.assets.enabled,
|
|
801
|
+
});
|
|
802
|
+
serverFiles = { "worker.js": Buffer.from(bundled).toString("base64") };
|
|
803
|
+
consola.success(` Worker bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
case "upload-asis": {
|
|
807
|
+
const workerEntryPath = resolve(cwd, plan.worker.entry);
|
|
808
|
+
const bytes = readFileSync(workerEntryPath);
|
|
809
|
+
serverFiles = { "worker.js": bytes.toString("base64") };
|
|
810
|
+
consola.success(` Worker (pre-bundled, ${Math.round(bytes.length / 1024)}KB)`);
|
|
811
|
+
break;
|
|
793
812
|
}
|
|
794
|
-
consola.start(" Bundling worker...");
|
|
795
|
-
const bundled = await bundleWorker(workerEntryPath, cwd, {
|
|
796
|
-
hasClientAssets: false,
|
|
797
|
-
});
|
|
798
|
-
serverFiles = { "worker.js": Buffer.from(bundled).toString("base64") };
|
|
799
|
-
consola.success(` Worker bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
800
813
|
}
|
|
801
814
|
// Deploy to sandbox
|
|
802
815
|
if (!jsonMode) {
|
|
@@ -807,7 +820,7 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
|
|
|
807
820
|
const result = await sandboxDeploy({
|
|
808
821
|
manifest: {
|
|
809
822
|
assets: fileList,
|
|
810
|
-
hasWorker:
|
|
823
|
+
hasWorker: plan.worker.strategy !== "none",
|
|
811
824
|
entrypoint: resolved?.workerEntry ?? null,
|
|
812
825
|
renderMode,
|
|
813
826
|
},
|
|
@@ -987,11 +1000,34 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
|
|
|
987
1000
|
if (!jsonMode)
|
|
988
1001
|
consola.success(` Created project: ${project.slug}`);
|
|
989
1002
|
}
|
|
990
|
-
// Determine deploy mode
|
|
1003
|
+
// Determine deploy mode via the SDK's pure planner. The downstream
|
|
1004
|
+
// framework-specific branches (Astro CF, Next.js adapter, Nuxt, etc.)
|
|
1005
|
+
// are kept as-is — planDeploy decides the SHAPE (spa / ssr / worker
|
|
1006
|
+
// and whether the worker is source vs prebundled), and the legacy
|
|
1007
|
+
// collection logic decides WHERE to read the bytes from for each
|
|
1008
|
+
// framework. astroCF detection happens post-build below; for the
|
|
1009
|
+
// initial plan we conservatively pass null and the framework SSR
|
|
1010
|
+
// branch handles the adapter case.
|
|
991
1011
|
const framework = resolved.framework;
|
|
992
1012
|
const isSSR = isSSRFramework(framework);
|
|
993
|
-
const
|
|
994
|
-
|
|
1013
|
+
const initialPlan = planDeploy({
|
|
1014
|
+
framework,
|
|
1015
|
+
workerEntry: resolved.workerEntry ?? null,
|
|
1016
|
+
workerEntryExists: !!resolved.workerEntry &&
|
|
1017
|
+
existsSync(resolve(cwd, resolved.workerEntry)),
|
|
1018
|
+
buildOutput: resolved.buildOutput,
|
|
1019
|
+
buildOutputExists: existsSync(resolve(cwd, resolved.buildOutput)),
|
|
1020
|
+
astroCF: null,
|
|
1021
|
+
});
|
|
1022
|
+
if (!initialPlan.ok) {
|
|
1023
|
+
consola.error(initialPlan.reason);
|
|
1024
|
+
process.exit(1);
|
|
1025
|
+
}
|
|
1026
|
+
const isWorker = initialPlan.plan.worker.strategy === "esbuild-bundle" ||
|
|
1027
|
+
initialPlan.plan.worker.strategy === "upload-asis";
|
|
1028
|
+
const workerIsPrebundled = initialPlan.plan.worker.strategy === "upload-asis";
|
|
1029
|
+
const workerExcludeFromAssets = initialPlan.plan.assets.excludeFile;
|
|
1030
|
+
const renderMode = initialPlan.plan.renderMode;
|
|
995
1031
|
// Detect Next.js mode for special build handling
|
|
996
1032
|
const pkg = existsSync(join(cwd, "package.json"))
|
|
997
1033
|
? JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"))
|
|
@@ -1174,10 +1210,22 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
|
|
|
1174
1210
|
}
|
|
1175
1211
|
}
|
|
1176
1212
|
else if (isWorker && resolved.workerEntry) {
|
|
1177
|
-
// Worker: auto-generate _setEnv wrapper + esbuild bundle
|
|
1178
1213
|
const workerEntryPath = resolve(cwd, resolved.workerEntry);
|
|
1179
|
-
if (existsSync(workerEntryPath)) {
|
|
1180
|
-
|
|
1214
|
+
if (!existsSync(workerEntryPath)) {
|
|
1215
|
+
consola.error(`Worker entry not found: ${resolved.workerEntry}`);
|
|
1216
|
+
process.exit(1);
|
|
1217
|
+
}
|
|
1218
|
+
section("Bundle");
|
|
1219
|
+
if (workerIsPrebundled) {
|
|
1220
|
+
// User's build script already produced a fully self-contained
|
|
1221
|
+
// bundle inside buildOutput; ship the bytes verbatim. No wrapper,
|
|
1222
|
+
// no Creek runtime injection — keeps the deployed Worker free of
|
|
1223
|
+
// any @solcreek/* dependency.
|
|
1224
|
+
const bytes = readFileSync(workerEntryPath);
|
|
1225
|
+
serverFiles = { "worker.js": bytes.toString("base64") };
|
|
1226
|
+
consola.success(` Worker (pre-bundled, ${Math.round(bytes.length / 1024)}KB)`);
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1181
1229
|
consola.start(" Bundling worker...");
|
|
1182
1230
|
const bundled = await bundleWorker(workerEntryPath, cwd, {
|
|
1183
1231
|
hasClientAssets: !!workerHasClientAssets,
|
|
@@ -1187,10 +1235,14 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
|
|
|
1187
1235
|
};
|
|
1188
1236
|
consola.success(` Worker bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
1189
1237
|
}
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1238
|
+
}
|
|
1239
|
+
// When the worker bundle lives INSIDE the static asset dir
|
|
1240
|
+
// (e.g. dist/_worker.mjs), drop it from clientAssets so it isn't
|
|
1241
|
+
// double-uploaded as a publicly accessible file.
|
|
1242
|
+
if (workerExcludeFromAssets) {
|
|
1243
|
+
delete clientAssets[workerExcludeFromAssets];
|
|
1244
|
+
delete clientAssets["/" + workerExcludeFromAssets];
|
|
1245
|
+
fileList = fileList.filter((p) => p !== workerExcludeFromAssets && p !== "/" + workerExcludeFromAssets);
|
|
1194
1246
|
}
|
|
1195
1247
|
section("Deploy");
|
|
1196
1248
|
consola.start(" Creating deployment...");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solcreek/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "CLI for the Creek deployment platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"esbuild": "^0.25.0",
|
|
34
34
|
"smol-toml": "^1.3.1",
|
|
35
35
|
"ws": "^8.20.0",
|
|
36
|
-
"@solcreek/sdk": "0.4.
|
|
36
|
+
"@solcreek/sdk": "0.4.4"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@testing-library/dom": "^10.4.1",
|