@solcreek/cli 0.4.8 → 0.4.10
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 +37 -315
- package/dist/utils/prepare-bundle.d.ts +63 -0
- package/dist/utils/prepare-bundle.js +266 -0
- package/package.json +2 -2
package/dist/commands/deploy.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { defineCommand } from "citty";
|
|
2
2
|
import consola from "consola";
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync,
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, rmSync } from "node:fs";
|
|
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,
|
|
7
|
+
import { CreekClient, CreekAuthError, detectFramework, resolveConfig, formatDetectionSummary, resolvedConfigToResources, resolvedConfigToBindingRequirements, ConfigNotFoundError, detectNextjsMode, detectMonorepo, } from "@solcreek/sdk";
|
|
8
8
|
import { getToken, getApiUrl } from "../utils/config.js";
|
|
9
9
|
import { collectAssets } from "../utils/bundle.js";
|
|
10
|
-
import { bundleSSRServer } from "../utils/ssr-bundle.js";
|
|
11
|
-
import { bundleWorker } from "../utils/worker-bundle.js";
|
|
12
10
|
import { sandboxDeploy, pollSandboxStatus, printSandboxSuccess } from "../utils/sandbox.js";
|
|
11
|
+
import { prepareDeployBundle } from "../utils/prepare-bundle.js";
|
|
13
12
|
import { isTTY, jsonOutput, resolveJsonMode, globalArgs, shouldAutoConfirm, AUTH_BREADCRUMBS, NO_PROJECT_BREADCRUMBS } from "../utils/output.js";
|
|
14
13
|
import { ensureTosAccepted } from "../utils/tos.js";
|
|
15
|
-
import {
|
|
14
|
+
import { hasAdapterOutput } from "../utils/nextjs.js";
|
|
16
15
|
import { isRepoUrl, parseRepoUrl, validateRepoUrl, validateSubpath, RepoUrlError } from "../utils/repo-url.js";
|
|
17
16
|
import { checkGitInstalled, cloneRepo, detectPackageManager, installDependencies, cleanupDir as cleanupCloneDir, GitCloneError } from "../utils/git-clone.js";
|
|
18
17
|
function section(name) {
|
|
@@ -676,7 +675,6 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
|
|
|
676
675
|
}
|
|
677
676
|
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
678
677
|
const framework = resolved?.framework ?? detectFramework(pkg);
|
|
679
|
-
// Detect Next.js mode (static vs opennext SSR)
|
|
680
678
|
const nextjsMode = framework === "nextjs" ? detectNextjsMode(pkg, cwd) : null;
|
|
681
679
|
const monorepo = detectMonorepo(cwd);
|
|
682
680
|
section("Detect");
|
|
@@ -684,120 +682,22 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
|
|
|
684
682
|
if (nextjsMode)
|
|
685
683
|
consola.info(` Next.js mode: ${nextjsMode}${monorepo.isMonorepo ? " (monorepo)" : ""}`);
|
|
686
684
|
consola.info(" Mode: sandbox (60 min preview)");
|
|
687
|
-
// Build
|
|
688
|
-
|
|
685
|
+
// Pre-build header so the section banner ("Build") still appears
|
|
686
|
+
// before build output streams. Then prepareDeployBundle owns the
|
|
687
|
+
// actual build + plan + collect + bundle pipeline.
|
|
688
|
+
if (!skipBuild)
|
|
689
689
|
section("Build");
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
consola.error("Next.js build failed");
|
|
697
|
-
process.exit(1);
|
|
698
|
-
}
|
|
699
|
-
consola.success(" Build complete");
|
|
700
|
-
}
|
|
701
|
-
else {
|
|
702
|
-
const buildCommand = resolved?.buildCommand || "npm run build";
|
|
703
|
-
if (!buildCommand) {
|
|
704
|
-
consola.error("No build script found in package.json.");
|
|
705
|
-
consola.info("Add a 'build' script or use --skip-build if already built.");
|
|
706
|
-
process.exit(1);
|
|
707
|
-
}
|
|
708
|
-
consola.start(` ${buildCommand}`);
|
|
709
|
-
try {
|
|
710
|
-
execSync(buildCommand, { cwd, stdio: "inherit" });
|
|
711
|
-
}
|
|
712
|
-
catch {
|
|
713
|
-
consola.error("Build failed");
|
|
714
|
-
consola.info("");
|
|
715
|
-
consola.info(" Common fixes:");
|
|
716
|
-
consola.info(" npm install (missing dependencies?)");
|
|
717
|
-
consola.info(" Check for TypeScript errors");
|
|
718
|
-
process.exit(1);
|
|
719
|
-
}
|
|
720
|
-
consola.success(" Build complete");
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
const useAdapterOutput = framework === "nextjs" && hasAdapterOutput(cwd);
|
|
724
|
-
const outputDir = useAdapterOutput
|
|
725
|
-
? resolve(cwd, ".creek/adapter-output")
|
|
726
|
-
: resolve(cwd, resolved?.buildOutput ?? getDefaultBuildOutput(framework));
|
|
727
|
-
if (!existsSync(outputDir)) {
|
|
728
|
-
consola.error(`Build output not found: ${outputDir}`);
|
|
729
|
-
if (framework) {
|
|
730
|
-
consola.info(`Expected output for ${framework}: ${getDefaultBuildOutput(framework)}`);
|
|
731
|
-
}
|
|
732
|
-
process.exit(1);
|
|
733
|
-
}
|
|
734
|
-
// Collect assets + determine render mode.
|
|
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");
|
|
749
|
-
let clientAssets = {};
|
|
750
|
-
let fileList = [];
|
|
751
|
-
if (!isWorker) {
|
|
752
|
-
let clientAssetsDir;
|
|
753
|
-
if (useAdapterOutput) {
|
|
754
|
-
clientAssetsDir = resolve(outputDir, "assets");
|
|
755
|
-
}
|
|
756
|
-
else {
|
|
757
|
-
clientAssetsDir = outputDir;
|
|
758
|
-
if (isSSR && framework) {
|
|
759
|
-
const subdir = getClientAssetsDir(framework);
|
|
760
|
-
if (subdir)
|
|
761
|
-
clientAssetsDir = resolve(outputDir, subdir);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
const collected = collectAssets(clientAssetsDir);
|
|
765
|
-
clientAssets = collected.assets;
|
|
766
|
-
fileList = collected.fileList;
|
|
767
|
-
}
|
|
690
|
+
const prepared = await prepareDeployBundle({
|
|
691
|
+
cwd,
|
|
692
|
+
resolved: resolved ?? {}, // sandbox path can be called without resolved when delegating; guarded above
|
|
693
|
+
skipBuild,
|
|
694
|
+
});
|
|
695
|
+
const { plan, fileList, assets: clientAssets, serverFiles, effectiveRenderMode } = prepared;
|
|
768
696
|
section("Upload");
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
697
|
+
consola.info(` Mode: ${effectiveRenderMode}${plan.worker.entry ? ` (worker: ${plan.worker.entry})` : ""}`);
|
|
698
|
+
if (plan.assets.enabled) {
|
|
773
699
|
consola.info(` ${fileList.length} assets (${assetSummary(fileList)})`);
|
|
774
700
|
}
|
|
775
|
-
let serverFiles;
|
|
776
|
-
if (isSSR && framework) {
|
|
777
|
-
const serverEntry = getSSRServerEntry(framework);
|
|
778
|
-
if (serverEntry) {
|
|
779
|
-
const serverEntryPath = resolve(outputDir, serverEntry);
|
|
780
|
-
if (existsSync(serverEntryPath)) {
|
|
781
|
-
consola.start(" Bundling SSR server...");
|
|
782
|
-
const bundled = await bundleSSRServer(serverEntryPath);
|
|
783
|
-
serverFiles = { "server.js": Buffer.from(bundled).toString("base64") };
|
|
784
|
-
consola.success(` SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
else if (isWorker && resolved?.workerEntry) {
|
|
789
|
-
const workerEntryPath = resolve(cwd, resolved.workerEntry);
|
|
790
|
-
if (!existsSync(workerEntryPath)) {
|
|
791
|
-
consola.error(`Worker entry not found: ${resolved.workerEntry}`);
|
|
792
|
-
process.exit(1);
|
|
793
|
-
}
|
|
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
|
-
}
|
|
801
701
|
// Deploy to sandbox
|
|
802
702
|
if (!jsonMode) {
|
|
803
703
|
section("Deploy");
|
|
@@ -807,13 +707,13 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
|
|
|
807
707
|
const result = await sandboxDeploy({
|
|
808
708
|
manifest: {
|
|
809
709
|
assets: fileList,
|
|
810
|
-
hasWorker:
|
|
811
|
-
entrypoint:
|
|
812
|
-
renderMode,
|
|
710
|
+
hasWorker: prepared.serverFiles !== undefined,
|
|
711
|
+
entrypoint: prepared.effectiveEntrypoint,
|
|
712
|
+
renderMode: effectiveRenderMode,
|
|
813
713
|
},
|
|
814
714
|
assets: clientAssets,
|
|
815
715
|
serverFiles,
|
|
816
|
-
framework: framework ?? undefined,
|
|
716
|
+
framework: prepared.framework ?? undefined,
|
|
817
717
|
source: "cli",
|
|
818
718
|
...(resolved
|
|
819
719
|
? { bindings: resolvedConfigToBindingRequirements(resolved) }
|
|
@@ -987,20 +887,19 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
|
|
|
987
887
|
if (!jsonMode)
|
|
988
888
|
consola.success(` Created project: ${project.slug}`);
|
|
989
889
|
}
|
|
990
|
-
//
|
|
890
|
+
// Framework is resolved upstream; everything else (SSR / worker /
|
|
891
|
+
// assets / bundling) is decided inside prepareDeployBundle via the
|
|
892
|
+
// SDK's planDeploy resolver.
|
|
991
893
|
const framework = resolved.framework;
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
const renderMode = isWorker ? "worker" : (isSSR ? "ssr" : "spa");
|
|
995
|
-
// Detect Next.js mode for special build handling
|
|
894
|
+
// Detect Next.js mode for the info banner only — actual handling is
|
|
895
|
+
// inside prepareDeployBundle.
|
|
996
896
|
const pkg = existsSync(join(cwd, "package.json"))
|
|
997
897
|
? JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"))
|
|
998
898
|
: {};
|
|
999
899
|
const nextjsMode = framework === "nextjs" ? detectNextjsMode(pkg, cwd) : null;
|
|
1000
900
|
const monorepo = framework === "nextjs" ? detectMonorepo(cwd) : { isMonorepo: false, root: null };
|
|
1001
|
-
if (nextjsMode) {
|
|
1002
|
-
|
|
1003
|
-
consola.info(` Next.js mode: ${nextjsMode}${monorepo.isMonorepo ? " (monorepo)" : ""}`);
|
|
901
|
+
if (nextjsMode && !jsonMode) {
|
|
902
|
+
consola.info(` Next.js mode: ${nextjsMode}${monorepo.isMonorepo ? " (monorepo)" : ""}`);
|
|
1004
903
|
}
|
|
1005
904
|
// --- ⚡ Turbo deploy: check if server has a cached build for this commit ---
|
|
1006
905
|
// Read the local git HEAD SHA. If the working tree is clean and the
|
|
@@ -1010,198 +909,21 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
|
|
|
1010
909
|
if (turboResult) {
|
|
1011
910
|
return; // ⚡ done — server deployed from cache
|
|
1012
911
|
}
|
|
1013
|
-
//
|
|
1014
|
-
|
|
912
|
+
// Single source of truth for build → plan → collect → bundle. Both
|
|
913
|
+
// sandbox and authenticated paths call the same function; they
|
|
914
|
+
// diverge only in where the bundle gets POSTed.
|
|
915
|
+
if (!skipBuild && resolved.buildCommand)
|
|
1015
916
|
section("Build");
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
consola.error("Next.js build failed");
|
|
1022
|
-
process.exit(1);
|
|
1023
|
-
}
|
|
1024
|
-
consola.success(" Build complete");
|
|
1025
|
-
}
|
|
1026
|
-
else {
|
|
1027
|
-
const buildCmd = resolved.buildCommand;
|
|
1028
|
-
if (buildCmd.length > 500) {
|
|
1029
|
-
consola.error("Invalid build command (too long)");
|
|
1030
|
-
process.exit(1);
|
|
1031
|
-
}
|
|
1032
|
-
consola.start(` ${buildCmd}`);
|
|
1033
|
-
try {
|
|
1034
|
-
execSync(buildCmd, { cwd, stdio: "inherit" });
|
|
1035
|
-
}
|
|
1036
|
-
catch {
|
|
1037
|
-
consola.error("Build failed");
|
|
1038
|
-
process.exit(1);
|
|
1039
|
-
}
|
|
1040
|
-
consola.success(" Build complete");
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
// Post-build detection: Astro + @astrojs/cloudflare produces a
|
|
1044
|
-
// pre-bundled Worker (dist/server/entry.mjs) + split client assets
|
|
1045
|
-
// (dist/client/). We can only detect this after build — before
|
|
1046
|
-
// build `framework === "astro"` could mean SSG or CF-adapter-SSR.
|
|
1047
|
-
const astroCF = framework === "astro" ? detectAstroCloudflareBuild(cwd) : null;
|
|
1048
|
-
// Collect client assets
|
|
1049
|
-
// Worker + SPA hybrid: if a Worker project has buildOutput with built files, collect them too
|
|
1050
|
-
let clientAssets = {};
|
|
1051
|
-
let fileList = [];
|
|
1052
|
-
const workerHasClientAssets = isWorker && resolved.buildOutput && resolved.buildOutput !== "." &&
|
|
1053
|
-
existsSync(resolve(cwd, resolved.buildOutput));
|
|
1054
|
-
if (!isWorker || workerHasClientAssets) {
|
|
1055
|
-
let clientAssetsDir;
|
|
1056
|
-
// Adapter output takes precedence for Next.js
|
|
1057
|
-
if (framework === "nextjs" && hasAdapterOutput(cwd)) {
|
|
1058
|
-
clientAssetsDir = resolve(cwd, ".creek/adapter-output/assets");
|
|
1059
|
-
}
|
|
1060
|
-
else if (astroCF) {
|
|
1061
|
-
// Astro CF adapter splits its output: client assets live in
|
|
1062
|
-
// dist/client/ (not dist/), so redirect the collector there.
|
|
1063
|
-
clientAssetsDir = resolve(cwd, astroCF.assetsDir);
|
|
1064
|
-
}
|
|
1065
|
-
else {
|
|
1066
|
-
const outputDir = resolve(cwd, resolved.buildOutput);
|
|
1067
|
-
if (!existsSync(outputDir)) {
|
|
1068
|
-
consola.error(`Build output directory not found: ${resolved.buildOutput}`);
|
|
1069
|
-
process.exit(1);
|
|
1070
|
-
}
|
|
1071
|
-
clientAssetsDir = outputDir;
|
|
1072
|
-
if (isSSR && framework) {
|
|
1073
|
-
const clientSubdir = getClientAssetsDir(framework);
|
|
1074
|
-
if (clientSubdir) {
|
|
1075
|
-
clientAssetsDir = resolve(outputDir, clientSubdir);
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
section("Upload");
|
|
1080
|
-
({ assets: clientAssets, fileList } = collectAssets(clientAssetsDir));
|
|
1081
|
-
consola.info(` ${fileList.length} assets (${assetSummary(fileList)})`);
|
|
1082
|
-
}
|
|
1083
|
-
// Bundle server/worker files
|
|
1084
|
-
let serverFiles;
|
|
1085
|
-
if (astroCF) {
|
|
1086
|
-
// Astro CF adapter: upload dist/server/ as worker modules
|
|
1087
|
-
// (same shape Nuxt/SolidStart use — pre-bundled, do not re-bundle).
|
|
1088
|
-
const serverDir = resolve(cwd, astroCF.serverDir);
|
|
1089
|
-
if (existsSync(serverDir)) {
|
|
1090
|
-
consola.start(" Collecting Astro CF server files...");
|
|
1091
|
-
const collected = collectServerFiles(serverDir);
|
|
1092
|
-
const fileCount = Object.keys(collected).length;
|
|
1093
|
-
serverFiles = Object.fromEntries(Object.entries(collected).map(([p, buf]) => [p, buf.toString("base64")]));
|
|
1094
|
-
consola.success(` Astro CF worker: ${fileCount} files`);
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
else if (isSSR && framework) {
|
|
1098
|
-
if (framework === "nextjs" && hasAdapterOutput(cwd)) {
|
|
1099
|
-
// Adapter path: read pre-bundled output from .creek/adapter-output/
|
|
1100
|
-
const adapterServerDir = resolve(cwd, ".creek/adapter-output/server");
|
|
1101
|
-
consola.start(" Collecting adapter output...");
|
|
1102
|
-
const collected = {};
|
|
1103
|
-
if (existsSync(adapterServerDir)) {
|
|
1104
|
-
for (const f of readdirSync(adapterServerDir)) {
|
|
1105
|
-
const fp = join(adapterServerDir, f);
|
|
1106
|
-
if (!statSync(fp).isFile())
|
|
1107
|
-
continue;
|
|
1108
|
-
if (f.endsWith(".map"))
|
|
1109
|
-
continue;
|
|
1110
|
-
let content = readFileSync(fp);
|
|
1111
|
-
// Patch bare Node.js module imports → node: prefix (workerd requires it)
|
|
1112
|
-
// Note: nodejs_compat_v2 handles most modules, but bare specifiers
|
|
1113
|
-
// (without node: prefix) still need patching.
|
|
1114
|
-
if (f.endsWith(".js") || f.endsWith(".mjs")) {
|
|
1115
|
-
content = Buffer.from(patchBareNodeImports(content.toString("utf-8")));
|
|
1116
|
-
}
|
|
1117
|
-
collected[f] = content;
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
const fileCount = Object.keys(collected).length;
|
|
1121
|
-
serverFiles = Object.fromEntries(Object.entries(collected).map(([p, buf]) => [p, buf.toString("base64")]));
|
|
1122
|
-
consola.success(` Worker bundled: ${fileCount} files (${Math.round(Object.values(collected).reduce((s, b) => s + b.length, 0) / 1024)}KB)`);
|
|
1123
|
-
}
|
|
1124
|
-
else if (framework === "nextjs") {
|
|
1125
|
-
// Legacy path: use wrangler to produce a single bundled worker
|
|
1126
|
-
const bundleDir = resolve(cwd, ".creek/bundled");
|
|
1127
|
-
consola.start(" Bundling Next.js worker (legacy)...");
|
|
1128
|
-
execSync(`npx wrangler deploy --dry-run --outdir "${bundleDir}"`, { cwd, stdio: "pipe" });
|
|
1129
|
-
patchBundledWorker(bundleDir, resolve(cwd, ".open-next"));
|
|
1130
|
-
const collected = {};
|
|
1131
|
-
if (existsSync(bundleDir)) {
|
|
1132
|
-
for (const f of readdirSync(bundleDir)) {
|
|
1133
|
-
const fp = join(bundleDir, f);
|
|
1134
|
-
if (!statSync(fp).isFile())
|
|
1135
|
-
continue;
|
|
1136
|
-
if (f.endsWith(".map") || f === "README.md")
|
|
1137
|
-
continue;
|
|
1138
|
-
collected[f] = readFileSync(fp);
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
const fileCount = Object.keys(collected).length;
|
|
1142
|
-
serverFiles = Object.fromEntries(Object.entries(collected).map(([p, buf]) => [p, buf.toString("base64")]));
|
|
1143
|
-
consola.success(` Worker bundled: ${fileCount} files (${Math.round(Object.values(collected).reduce((s, b) => s + b.length, 0) / 1024)}KB)`);
|
|
1144
|
-
}
|
|
1145
|
-
else if (isPreBundledFramework(framework)) {
|
|
1146
|
-
// Other pre-bundled SSR frameworks (Nuxt, SvelteKit, etc.)
|
|
1147
|
-
const serverDirRel = getSSRServerDir(framework);
|
|
1148
|
-
if (serverDirRel) {
|
|
1149
|
-
const serverDir = resolve(cwd, serverDirRel);
|
|
1150
|
-
if (existsSync(serverDir)) {
|
|
1151
|
-
consola.start(" Collecting SSR server files...");
|
|
1152
|
-
const collected = collectServerFiles(serverDir);
|
|
1153
|
-
const fileCount = Object.keys(collected).length;
|
|
1154
|
-
serverFiles = Object.fromEntries(Object.entries(collected).map(([p, buf]) => [p, buf.toString("base64")]));
|
|
1155
|
-
consola.success(` SSR server: ${fileCount} files`);
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
else {
|
|
1160
|
-
// Non-pre-bundled SSR: esbuild single-file bundle (fallback)
|
|
1161
|
-
const outputDir = resolve(cwd, resolved.buildOutput);
|
|
1162
|
-
const serverEntry = getSSRServerEntry(framework);
|
|
1163
|
-
if (serverEntry) {
|
|
1164
|
-
const serverEntryPath = resolve(outputDir, serverEntry);
|
|
1165
|
-
if (existsSync(serverEntryPath)) {
|
|
1166
|
-
consola.start(" Bundling SSR server...");
|
|
1167
|
-
const bundled = await bundleSSRServer(serverEntryPath);
|
|
1168
|
-
serverFiles = {
|
|
1169
|
-
"server.js": Buffer.from(bundled).toString("base64"),
|
|
1170
|
-
};
|
|
1171
|
-
consola.success(` SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
else if (isWorker && resolved.workerEntry) {
|
|
1177
|
-
// Worker: auto-generate _setEnv wrapper + esbuild bundle
|
|
1178
|
-
const workerEntryPath = resolve(cwd, resolved.workerEntry);
|
|
1179
|
-
if (existsSync(workerEntryPath)) {
|
|
1180
|
-
section("Bundle");
|
|
1181
|
-
consola.start(" Bundling worker...");
|
|
1182
|
-
const bundled = await bundleWorker(workerEntryPath, cwd, {
|
|
1183
|
-
hasClientAssets: !!workerHasClientAssets,
|
|
1184
|
-
});
|
|
1185
|
-
serverFiles = {
|
|
1186
|
-
"worker.js": Buffer.from(bundled).toString("base64"),
|
|
1187
|
-
};
|
|
1188
|
-
consola.success(` Worker bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
1189
|
-
}
|
|
1190
|
-
else {
|
|
1191
|
-
consola.error(`Worker entry not found: ${resolved.workerEntry}`);
|
|
1192
|
-
process.exit(1);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
917
|
+
const prepared = await prepareDeployBundle({ cwd, resolved, skipBuild });
|
|
918
|
+
const { plan, framework: detectedFramework, effectiveRenderMode, effectiveEntrypoint, fileList, assets: clientAssets, serverFiles, } = prepared;
|
|
919
|
+
void detectedFramework; // framework var above is the source of truth here
|
|
920
|
+
section("Upload");
|
|
921
|
+
consola.info(` ${fileList.length} assets (${assetSummary(fileList)})`);
|
|
1195
922
|
section("Deploy");
|
|
1196
923
|
consola.start(" Creating deployment...");
|
|
1197
924
|
const { deployment } = await client.createDeployment(project.id);
|
|
1198
925
|
consola.start(" Uploading bundle...");
|
|
1199
|
-
|
|
1200
|
-
// SSR (not SPA): overwrite the pre-build-computed renderMode and
|
|
1201
|
-
// point the entrypoint at the adapter-emitted entry.mjs.
|
|
1202
|
-
const effectiveRenderMode = astroCF ? "ssr" : renderMode;
|
|
1203
|
-
const effectiveHasWorker = astroCF ? true : (isSSR || isWorker);
|
|
1204
|
-
const effectiveEntrypoint = astroCF ? "entry.mjs" : resolved.workerEntry;
|
|
926
|
+
const effectiveHasWorker = serverFiles !== undefined;
|
|
1205
927
|
const bundle = {
|
|
1206
928
|
manifest: {
|
|
1207
929
|
assets: fileList,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prepareDeployBundle — single source of truth for "given a project,
|
|
3
|
+
* produce the bundle that gets shipped to either sandbox-api or
|
|
4
|
+
* control-plane". Both `deploySandbox` and `deployAuthenticated` call
|
|
5
|
+
* this; they only differ in (a) whether they auth/look-up a project
|
|
6
|
+
* and (b) which API receives the bundle.
|
|
7
|
+
*
|
|
8
|
+
* Historically these two paths each rolled their own copy of the
|
|
9
|
+
* detect → build → collect → bundle pipeline. They drifted: the
|
|
10
|
+
* sandbox path was missing the worker branch for ~2 weeks (cli@0.4.6
|
|
11
|
+
* regression) and again missed the workers+assets coexist pattern.
|
|
12
|
+
* That divergence is the architectural smell — this file kills it.
|
|
13
|
+
*
|
|
14
|
+
* The function:
|
|
15
|
+
* 1. Reads framework from package.json (or accepts pre-resolved one)
|
|
16
|
+
* 2. Runs the build script (skip with skipBuild: true)
|
|
17
|
+
* 3. Calls SDK's planDeploy() to decide spa/ssr/worker shape
|
|
18
|
+
* 4. Detects post-build framework adapters (Astro CF) and refines
|
|
19
|
+
* 5. Collects static assets per the plan
|
|
20
|
+
* 6. Bundles the worker per the plan (5 framework-aware strategies)
|
|
21
|
+
* 7. Filters worker file out of clientAssets when it lives inside
|
|
22
|
+
* 8. Returns the canonical bundle envelope
|
|
23
|
+
*
|
|
24
|
+
* IO is not abstracted — the function calls execSync, readFileSync,
|
|
25
|
+
* esbuild. Callers needing test isolation should use fixture dirs.
|
|
26
|
+
*/
|
|
27
|
+
import { type DeployPlan, type Framework, type ResolvedConfig } from "@solcreek/sdk";
|
|
28
|
+
export interface PrepareDeployBundleInput {
|
|
29
|
+
/** Absolute project directory. */
|
|
30
|
+
cwd: string;
|
|
31
|
+
/** Pre-resolved config (creek.toml or wrangler.* parse). Required. */
|
|
32
|
+
resolved: ResolvedConfig;
|
|
33
|
+
/** When true, skip the build script. Caller is asserting dist/ is current. */
|
|
34
|
+
skipBuild: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface PreparedDeployBundle {
|
|
37
|
+
/** The plan that drove preparation — passed back so callers can
|
|
38
|
+
* inspect renderMode / worker strategy without re-deriving. */
|
|
39
|
+
plan: DeployPlan;
|
|
40
|
+
/** Framework detected (or pre-resolved). null = static / vanilla worker. */
|
|
41
|
+
framework: Framework | null;
|
|
42
|
+
/** Whether Astro `@astrojs/cloudflare` adapter fired post-build. */
|
|
43
|
+
astroAdapter: {
|
|
44
|
+
serverDir: string;
|
|
45
|
+
assetsDir: string;
|
|
46
|
+
} | null;
|
|
47
|
+
/**
|
|
48
|
+
* Render mode after post-build refinement. Equal to plan.renderMode
|
|
49
|
+
* unless an adapter (e.g. Astro CF) upgraded an SPA-classified
|
|
50
|
+
* project to true SSR.
|
|
51
|
+
*/
|
|
52
|
+
effectiveRenderMode: "spa" | "ssr" | "worker";
|
|
53
|
+
/** Main module name the deploy API should treat as the worker entry. */
|
|
54
|
+
effectiveEntrypoint: string | null;
|
|
55
|
+
/** Asset list (paths relative to root, with leading `/`). */
|
|
56
|
+
fileList: string[];
|
|
57
|
+
/** Asset bytes, base64-encoded, keyed by path. */
|
|
58
|
+
assets: Record<string, string>;
|
|
59
|
+
/** Server / worker files, base64-encoded. Undefined for pure SPA. */
|
|
60
|
+
serverFiles?: Record<string, string>;
|
|
61
|
+
}
|
|
62
|
+
export declare function prepareDeployBundle(input: PrepareDeployBundleInput): Promise<PreparedDeployBundle>;
|
|
63
|
+
//# sourceMappingURL=prepare-bundle.d.ts.map
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prepareDeployBundle — single source of truth for "given a project,
|
|
3
|
+
* produce the bundle that gets shipped to either sandbox-api or
|
|
4
|
+
* control-plane". Both `deploySandbox` and `deployAuthenticated` call
|
|
5
|
+
* this; they only differ in (a) whether they auth/look-up a project
|
|
6
|
+
* and (b) which API receives the bundle.
|
|
7
|
+
*
|
|
8
|
+
* Historically these two paths each rolled their own copy of the
|
|
9
|
+
* detect → build → collect → bundle pipeline. They drifted: the
|
|
10
|
+
* sandbox path was missing the worker branch for ~2 weeks (cli@0.4.6
|
|
11
|
+
* regression) and again missed the workers+assets coexist pattern.
|
|
12
|
+
* That divergence is the architectural smell — this file kills it.
|
|
13
|
+
*
|
|
14
|
+
* The function:
|
|
15
|
+
* 1. Reads framework from package.json (or accepts pre-resolved one)
|
|
16
|
+
* 2. Runs the build script (skip with skipBuild: true)
|
|
17
|
+
* 3. Calls SDK's planDeploy() to decide spa/ssr/worker shape
|
|
18
|
+
* 4. Detects post-build framework adapters (Astro CF) and refines
|
|
19
|
+
* 5. Collects static assets per the plan
|
|
20
|
+
* 6. Bundles the worker per the plan (5 framework-aware strategies)
|
|
21
|
+
* 7. Filters worker file out of clientAssets when it lives inside
|
|
22
|
+
* 8. Returns the canonical bundle envelope
|
|
23
|
+
*
|
|
24
|
+
* IO is not abstracted — the function calls execSync, readFileSync,
|
|
25
|
+
* esbuild. Callers needing test isolation should use fixture dirs.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
28
|
+
import { join, resolve } from "node:path";
|
|
29
|
+
import { execSync } from "node:child_process";
|
|
30
|
+
import consola from "consola";
|
|
31
|
+
import { detectFramework, detectAstroCloudflareBuild, detectMonorepo, detectNextjsMode, getSSRServerDir, getSSRServerEntry, getClientAssetsDir, getDefaultBuildOutput, isSSRFramework, isPreBundledFramework, collectServerFiles, planDeploy, } from "@solcreek/sdk";
|
|
32
|
+
import { collectAssets } from "./bundle.js";
|
|
33
|
+
import { bundleSSRServer } from "./ssr-bundle.js";
|
|
34
|
+
import { bundleWorker } from "./worker-bundle.js";
|
|
35
|
+
import { hasAdapterOutput, buildNextjs, patchBundledWorker } from "./nextjs.js";
|
|
36
|
+
import { patchBareNodeImports } from "../commands/deploy.js";
|
|
37
|
+
export async function prepareDeployBundle(input) {
|
|
38
|
+
const { cwd, resolved, skipBuild } = input;
|
|
39
|
+
// 1. Framework detection. Trust the resolved config if it carries
|
|
40
|
+
// one (creek.toml can pin it); otherwise re-read package.json. We
|
|
41
|
+
// re-read here rather than rely solely on resolved so that a project
|
|
42
|
+
// without creek.toml still gets the auto-detected framework when
|
|
43
|
+
// running against a pre-existing wrangler.* config.
|
|
44
|
+
const pkgJsonPath = join(cwd, "package.json");
|
|
45
|
+
const pkg = existsSync(pkgJsonPath)
|
|
46
|
+
? JSON.parse(readFileSync(pkgJsonPath, "utf-8"))
|
|
47
|
+
: null;
|
|
48
|
+
const framework = resolved.framework ?? (pkg ? detectFramework(pkg) : null);
|
|
49
|
+
const nextjsMode = framework === "nextjs" && pkg ? detectNextjsMode(pkg, cwd) : null;
|
|
50
|
+
const monorepo = framework === "nextjs" ? detectMonorepo(cwd) : { isMonorepo: false, root: null };
|
|
51
|
+
// 2. Build (when not skipped). Framework-specific build for Next.js
|
|
52
|
+
// adapter; otherwise the user's build script.
|
|
53
|
+
if (!skipBuild && resolved.buildCommand) {
|
|
54
|
+
if (nextjsMode === "opennext") {
|
|
55
|
+
try {
|
|
56
|
+
buildNextjs(cwd, monorepo.isMonorepo);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
consola.error("Next.js build failed");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const buildCmd = resolved.buildCommand;
|
|
65
|
+
if (buildCmd.length > 500) {
|
|
66
|
+
consola.error("Invalid build command (too long)");
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
consola.start(` ${buildCmd}`);
|
|
70
|
+
try {
|
|
71
|
+
execSync(buildCmd, { cwd, stdio: "inherit" });
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
consola.error("Build failed");
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
consola.success(" Build complete");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// 3. Compute output dir. Next.js adapter writes to .creek/adapter-output;
|
|
81
|
+
// everything else honours [build].output.
|
|
82
|
+
const useAdapterOutput = framework === "nextjs" && hasAdapterOutput(cwd);
|
|
83
|
+
const outputDir = useAdapterOutput
|
|
84
|
+
? resolve(cwd, ".creek/adapter-output")
|
|
85
|
+
: resolve(cwd, resolved.buildOutput || getDefaultBuildOutput(framework));
|
|
86
|
+
// 4. Post-build framework adapter detection. Astro can be either SSG
|
|
87
|
+
// or CF-adapter-SSR; we only know which after build.
|
|
88
|
+
const astroAdapter = framework === "astro" ? detectAstroCloudflareBuild(cwd) : null;
|
|
89
|
+
// 5. Plan the deploy shape. planDeploy is a pure function — pass in
|
|
90
|
+
// detection results, get out a structured plan with explicit error
|
|
91
|
+
// cases. All branching that used to be inline in deploy.ts lives in
|
|
92
|
+
// deploy-plan.ts now (table-tested).
|
|
93
|
+
const planResult = planDeploy({
|
|
94
|
+
framework,
|
|
95
|
+
workerEntry: resolved.workerEntry ?? null,
|
|
96
|
+
workerEntryExists: !!resolved.workerEntry &&
|
|
97
|
+
existsSync(resolve(cwd, resolved.workerEntry)),
|
|
98
|
+
buildOutput: resolved.buildOutput || "dist",
|
|
99
|
+
buildOutputExists: existsSync(outputDir),
|
|
100
|
+
astroCF: astroAdapter,
|
|
101
|
+
});
|
|
102
|
+
if (!planResult.ok) {
|
|
103
|
+
consola.error(planResult.reason);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
const plan = planResult.plan;
|
|
107
|
+
// 6. Collect client assets. The dir depends on framework (Next.js
|
|
108
|
+
// adapter, Astro CF split output) but the inclusion decision is the
|
|
109
|
+
// plan's call.
|
|
110
|
+
let clientAssets = {};
|
|
111
|
+
let fileList = [];
|
|
112
|
+
if (plan.assets.enabled && plan.assets.dir) {
|
|
113
|
+
let clientAssetsDir;
|
|
114
|
+
if (useAdapterOutput) {
|
|
115
|
+
clientAssetsDir = resolve(outputDir, "assets");
|
|
116
|
+
}
|
|
117
|
+
else if (astroAdapter) {
|
|
118
|
+
clientAssetsDir = resolve(cwd, astroAdapter.assetsDir);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
clientAssetsDir = resolve(cwd, plan.assets.dir);
|
|
122
|
+
// SSR frameworks split client assets into a sub-dir of buildOutput.
|
|
123
|
+
if (isSSRFramework(framework) && framework) {
|
|
124
|
+
const subdir = getClientAssetsDir(framework);
|
|
125
|
+
if (subdir)
|
|
126
|
+
clientAssetsDir = resolve(clientAssetsDir, subdir);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const collected = collectAssets(clientAssetsDir);
|
|
130
|
+
clientAssets = collected.assets;
|
|
131
|
+
fileList = collected.fileList;
|
|
132
|
+
}
|
|
133
|
+
// 7. Bundle server / worker. Five strategies, dispatched by either
|
|
134
|
+
// (a) the framework when it's pre-bundled SSR, or (b) the plan's
|
|
135
|
+
// worker.strategy for user-declared workers.
|
|
136
|
+
let serverFiles;
|
|
137
|
+
if (astroAdapter) {
|
|
138
|
+
// Astro CF adapter writes a pre-bundled worker we just upload.
|
|
139
|
+
const serverDir = resolve(cwd, astroAdapter.serverDir);
|
|
140
|
+
if (existsSync(serverDir)) {
|
|
141
|
+
consola.start(" Collecting Astro CF server files...");
|
|
142
|
+
const collected = collectServerFiles(serverDir);
|
|
143
|
+
serverFiles = base64ServerFiles(collected);
|
|
144
|
+
consola.success(` Astro CF worker: ${Object.keys(collected).length} files`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (isSSRFramework(framework) && framework) {
|
|
148
|
+
if (framework === "nextjs" && hasAdapterOutput(cwd)) {
|
|
149
|
+
// Next.js adapter output → patch bare imports, upload as-is.
|
|
150
|
+
const adapterServerDir = resolve(cwd, ".creek/adapter-output/server");
|
|
151
|
+
consola.start(" Collecting adapter output...");
|
|
152
|
+
const collected = {};
|
|
153
|
+
if (existsSync(adapterServerDir)) {
|
|
154
|
+
for (const f of readdirSync(adapterServerDir)) {
|
|
155
|
+
const fp = join(adapterServerDir, f);
|
|
156
|
+
if (!statSync(fp).isFile() || f.endsWith(".map"))
|
|
157
|
+
continue;
|
|
158
|
+
let content = readFileSync(fp);
|
|
159
|
+
if (f.endsWith(".js") || f.endsWith(".mjs")) {
|
|
160
|
+
content = Buffer.from(patchBareNodeImports(content.toString("utf-8")));
|
|
161
|
+
}
|
|
162
|
+
collected[f] = content;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
serverFiles = base64ServerFiles(collected);
|
|
166
|
+
consola.success(` Worker bundled: ${Object.keys(collected).length} files (${kb(collected)}KB)`);
|
|
167
|
+
}
|
|
168
|
+
else if (framework === "nextjs") {
|
|
169
|
+
// Legacy Next.js: wrangler dry-run produces the bundle.
|
|
170
|
+
const bundleDir = resolve(cwd, ".creek/bundled");
|
|
171
|
+
consola.start(" Bundling Next.js worker (legacy)...");
|
|
172
|
+
execSync(`npx wrangler deploy --dry-run --outdir "${bundleDir}"`, { cwd, stdio: "pipe" });
|
|
173
|
+
patchBundledWorker(bundleDir, resolve(cwd, ".open-next"));
|
|
174
|
+
const collected = {};
|
|
175
|
+
if (existsSync(bundleDir)) {
|
|
176
|
+
for (const f of readdirSync(bundleDir)) {
|
|
177
|
+
const fp = join(bundleDir, f);
|
|
178
|
+
if (!statSync(fp).isFile() || f.endsWith(".map") || f === "README.md")
|
|
179
|
+
continue;
|
|
180
|
+
collected[f] = readFileSync(fp);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
serverFiles = base64ServerFiles(collected);
|
|
184
|
+
consola.success(` Worker bundled: ${Object.keys(collected).length} files (${kb(collected)}KB)`);
|
|
185
|
+
}
|
|
186
|
+
else if (isPreBundledFramework(framework)) {
|
|
187
|
+
// Nuxt / SvelteKit / SolidStart — the framework already produced
|
|
188
|
+
// a bundled server; we just collect.
|
|
189
|
+
const serverDirRel = getSSRServerDir(framework);
|
|
190
|
+
if (serverDirRel) {
|
|
191
|
+
const serverDir = resolve(cwd, serverDirRel);
|
|
192
|
+
if (existsSync(serverDir)) {
|
|
193
|
+
consola.start(" Collecting SSR server files...");
|
|
194
|
+
const collected = collectServerFiles(serverDir);
|
|
195
|
+
serverFiles = base64ServerFiles(collected);
|
|
196
|
+
consola.success(` SSR server: ${Object.keys(collected).length} files`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Fallback for SSR frameworks that emit a single entry file.
|
|
202
|
+
const serverEntry = getSSRServerEntry(framework);
|
|
203
|
+
if (serverEntry) {
|
|
204
|
+
const serverEntryPath = resolve(outputDir, serverEntry);
|
|
205
|
+
if (existsSync(serverEntryPath)) {
|
|
206
|
+
consola.start(" Bundling SSR server...");
|
|
207
|
+
const bundled = await bundleSSRServer(serverEntryPath);
|
|
208
|
+
serverFiles = { "server.js": Buffer.from(bundled).toString("base64") };
|
|
209
|
+
consola.success(` SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else if (plan.worker.strategy === "esbuild-bundle" && plan.worker.entry) {
|
|
215
|
+
const workerEntryPath = resolve(cwd, plan.worker.entry);
|
|
216
|
+
consola.start(" Bundling worker...");
|
|
217
|
+
const bundled = await bundleWorker(workerEntryPath, cwd, {
|
|
218
|
+
hasClientAssets: plan.assets.enabled,
|
|
219
|
+
});
|
|
220
|
+
serverFiles = { "worker.js": Buffer.from(bundled).toString("base64") };
|
|
221
|
+
consola.success(` Worker bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
222
|
+
}
|
|
223
|
+
else if (plan.worker.strategy === "upload-asis" && plan.worker.entry) {
|
|
224
|
+
// Pre-bundled worker (e.g. dist/_worker.mjs from the user's own
|
|
225
|
+
// esbuild step). Ship verbatim — no Creek runtime wrapper, no
|
|
226
|
+
// re-bundle. This is the path that keeps deployed bundles free of
|
|
227
|
+
// any @solcreek/* dependency.
|
|
228
|
+
const bytes = readFileSync(resolve(cwd, plan.worker.entry));
|
|
229
|
+
serverFiles = { "worker.js": bytes.toString("base64") };
|
|
230
|
+
consola.success(` Worker (pre-bundled, ${Math.round(bytes.length / 1024)}KB)`);
|
|
231
|
+
}
|
|
232
|
+
// 8. When the worker bundle lives INSIDE the asset dir
|
|
233
|
+
// (dist/_worker.mjs), drop it from clientAssets so it isn't also
|
|
234
|
+
// served as a publicly accessible static file.
|
|
235
|
+
if (plan.assets.excludeFile) {
|
|
236
|
+
delete clientAssets[plan.assets.excludeFile];
|
|
237
|
+
delete clientAssets["/" + plan.assets.excludeFile];
|
|
238
|
+
fileList = fileList.filter((p) => p !== plan.assets.excludeFile && p !== "/" + plan.assets.excludeFile);
|
|
239
|
+
}
|
|
240
|
+
// 9. Resolve effective render mode + entrypoint. Astro CF post-build
|
|
241
|
+
// detection upgrades a pre-build "spa" classification to true SSR.
|
|
242
|
+
const effectiveRenderMode = astroAdapter
|
|
243
|
+
? "ssr"
|
|
244
|
+
: plan.renderMode;
|
|
245
|
+
const effectiveEntrypoint = astroAdapter
|
|
246
|
+
? "entry.mjs"
|
|
247
|
+
: (plan.worker.entry ?? null);
|
|
248
|
+
return {
|
|
249
|
+
plan,
|
|
250
|
+
framework,
|
|
251
|
+
astroAdapter,
|
|
252
|
+
effectiveRenderMode,
|
|
253
|
+
effectiveEntrypoint,
|
|
254
|
+
fileList,
|
|
255
|
+
assets: clientAssets,
|
|
256
|
+
serverFiles,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
// --- helpers ---
|
|
260
|
+
function base64ServerFiles(collected) {
|
|
261
|
+
return Object.fromEntries(Object.entries(collected).map(([p, buf]) => [p, buf.toString("base64")]));
|
|
262
|
+
}
|
|
263
|
+
function kb(collected) {
|
|
264
|
+
return Math.round(Object.values(collected).reduce((s, b) => s + b.length, 0) / 1024);
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=prepare-bundle.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solcreek/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
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",
|