gencow 0.1.259 → 0.1.261
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/lib/cli-command-runner.mjs +12 -0
- package/lib/cloud-targets.mjs +14 -4
- package/lib/db-command.mjs +16 -2
- package/lib/deploy-codegen-failure.mjs +21 -4
- package/lib/deploy-prepared-source.mjs +37 -0
- package/lib/deploy-runtime.mjs +85 -69
- package/lib/deploy-static-fullstack-runtime.mjs +18 -15
- package/lib/static-command.mjs +13 -3
- package/package.json +4 -4
- package/runtime/server.mjs +135 -140
- package/runtime/tooling.mjs +242 -65
- package/scripts/codegen-named-import-check.ts +224 -0
- package/scripts/tooling-codegen-runtime.ts +26 -2
|
@@ -86,6 +86,11 @@ const SAFE_LOCAL_ERROR_CODES = new Map([
|
|
|
86
86
|
message: "Deploy stopped before upload: a backend source file could not be loaded.",
|
|
87
87
|
stage: "codegen",
|
|
88
88
|
action: (caught) => {
|
|
89
|
+
if (safeMissingExportName(caught)) {
|
|
90
|
+
const name = safeMissingExportName(caught);
|
|
91
|
+
const where = safeSourceLocation(caught) ? "at the location above " : "";
|
|
92
|
+
return `Retryable: yes, after the import of "${name}" ${where}names an export its module does not have — use an exported name, or export it from that module, then run \`npx gencow@latest codegen\` to confirm it passes, then rerun your deploy command.`;
|
|
93
|
+
}
|
|
89
94
|
const cause =
|
|
90
95
|
"the top-level code that throws during module load, or an import path that does not resolve (check the path and that the imported package is installed)";
|
|
91
96
|
if (safeSourceLocation(caught)) {
|
|
@@ -169,6 +174,13 @@ function safeDisplayDir(caught) {
|
|
|
169
174
|
}
|
|
170
175
|
const SAFE_SOURCE_LOCATION_PATH = /^(?![/\\])(?!.*(?:^|\/)\.\.(?:\/|$))[^\u0000-\u001f\u007f]{1,240}$/u;
|
|
171
176
|
|
|
177
|
+
const SAFE_IMPORT_NAME = /^[A-Za-z_$][\w$]{0,127}$/u;
|
|
178
|
+
|
|
179
|
+
function safeMissingExportName(caught) {
|
|
180
|
+
const { missingExport } = caught;
|
|
181
|
+
return typeof missingExport === "string" && SAFE_IMPORT_NAME.test(missingExport) ? missingExport : null;
|
|
182
|
+
}
|
|
183
|
+
|
|
172
184
|
function safeSourceLocation(caught) {
|
|
173
185
|
const { sourceFile, line, column } = caught;
|
|
174
186
|
if (typeof sourceFile !== "string" || !SAFE_SOURCE_LOCATION_PATH.test(sourceFile)) return null;
|
package/lib/cloud-targets.mjs
CHANGED
|
@@ -47,6 +47,14 @@ export function resolveProdAppTarget({ explicitAppId = null, prodApp = null, acc
|
|
|
47
47
|
return { appId: prodApp };
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// Single rule for the implicit prod environment: an explicit app id that is this project's
|
|
51
|
+
// prod app selects the prod environment even without --prod. Every command that picks a
|
|
52
|
+
// cloud app (cloud targets, deploy) must use this helper instead of repeating the condition.
|
|
53
|
+
export function resolveImplicitProdEnvironment({ explicitApp = false, envTarget = "dev", appId = null, prodApp = null }) {
|
|
54
|
+
if (explicitApp && envTarget === "dev" && prodApp && appId === prodApp) return "prod";
|
|
55
|
+
return envTarget;
|
|
56
|
+
}
|
|
57
|
+
|
|
50
58
|
// Shared human message for a failed prod target; falls back to the call site's own text.
|
|
51
59
|
export function describeProdTargetFailure(result, fallbackMessage) {
|
|
52
60
|
if (result?.reason === "explicit_app_not_prod_app") {
|
|
@@ -81,10 +89,12 @@ export function resolveCloudAppTarget(restArgs, options = {}) {
|
|
|
81
89
|
if (projectTargets.invalid) {
|
|
82
90
|
return { error: "MIGRATION_PROJECT_CONFIG_INVALID" };
|
|
83
91
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
envTarget
|
|
87
|
-
|
|
92
|
+
envTarget = resolveImplicitProdEnvironment({
|
|
93
|
+
explicitApp,
|
|
94
|
+
envTarget,
|
|
95
|
+
appId,
|
|
96
|
+
prodApp: projectTargets.prodApp,
|
|
97
|
+
});
|
|
88
98
|
if (!appId) {
|
|
89
99
|
appId = envTarget === "prod" ? projectTargets.prodApp : projectTargets.appId;
|
|
90
100
|
}
|
package/lib/db-command.mjs
CHANGED
|
@@ -17,22 +17,36 @@ import { createDbCheckCommand, createDbPushCommand } from "./db-push-command.mjs
|
|
|
17
17
|
import { logEnvFileOperationWithType } from "./backend-env-resolver.mjs";
|
|
18
18
|
import { runDrizzleGenerateWithFallback } from "./drizzle-generate.mjs";
|
|
19
19
|
import { BOLD, CYAN, DIM, GREEN, RED, RESET, error, info, log, success, warn } from "./output.mjs";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
describeProdTargetFailure,
|
|
22
|
+
resolveImplicitProdEnvironment,
|
|
23
|
+
resolveProdAppTarget,
|
|
24
|
+
} from "./cloud-targets.mjs";
|
|
21
25
|
import { platformFetch, requireCreds } from "./platform-client.mjs";
|
|
22
26
|
import { readProjectMetadata } from "./project-context.mjs";
|
|
23
27
|
|
|
24
28
|
export function resolveDbCloudTarget(args, gencowJson = null) {
|
|
25
|
-
const isProd = args.includes("--prod");
|
|
26
29
|
let explicitAppId = null;
|
|
30
|
+
let hasExplicitApp = false;
|
|
27
31
|
let platformUrl = null;
|
|
28
32
|
|
|
29
33
|
for (let i = 0; i < args.length; i++) {
|
|
30
34
|
if (args[i] === "--app" || args[i] === "-a") {
|
|
31
35
|
explicitAppId = args[i + 1] ?? null;
|
|
36
|
+
hasExplicitApp = true;
|
|
32
37
|
i++;
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
|
|
41
|
+
// Same implicit prod rule as deploy and static: an --app naming the project's prodApp is prod even without --prod.
|
|
42
|
+
const isProd =
|
|
43
|
+
resolveImplicitProdEnvironment({
|
|
44
|
+
explicitApp: hasExplicitApp,
|
|
45
|
+
envTarget: args.includes("--prod") ? "prod" : "dev",
|
|
46
|
+
appId: explicitAppId,
|
|
47
|
+
prodApp: gencowJson?.prodApp || null,
|
|
48
|
+
}) === "prod";
|
|
49
|
+
|
|
36
50
|
if (gencowJson) {
|
|
37
51
|
platformUrl = gencowJson.platformUrl || null;
|
|
38
52
|
if (isProd) {
|
|
@@ -36,13 +36,24 @@ function toProjectRelativePath(rawPath, cwd, processCwd) {
|
|
|
36
36
|
// esbuild prints one diagnostic per line (`<file>:<line>:<col>: ERROR: <text>`) and the
|
|
37
37
|
// Bun loader prints `Could not resolve`/`Cannot find module` for an import path that does
|
|
38
38
|
// not exist. Those are load failures: the source is well-formed, its import is not.
|
|
39
|
+
// `No matching export` is an import of a name its module does not export (esbuild, or the
|
|
40
|
+
// named-import check in codegen-named-import-check.ts); the module itself is well-formed.
|
|
39
41
|
const DIAGNOSTIC_LINE_PATTERN = /ERROR: |Could not resolve "|Cannot find (?:module|package)\b/u;
|
|
40
|
-
const UNRESOLVED_MODULE_PATTERN = /Could not resolve "|Cannot find (?:module|package)\b/u;
|
|
42
|
+
const UNRESOLVED_MODULE_PATTERN = /Could not resolve "|Cannot find (?:module|package)\b|No matching export in "/u;
|
|
43
|
+
const MISSING_EXPORT_PATTERN = /No matching export in "[^"\n]*" for import "([A-Za-z_$][\w$]{0,127})"/u;
|
|
41
44
|
|
|
42
45
|
// The first diagnostic decides the class, matching how the first location is reported.
|
|
46
|
+
function firstDiagnosticLine(message) {
|
|
47
|
+
return message.split("\n").find((line) => DIAGNOSTIC_LINE_PATTERN.test(line)) ?? message;
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
function isUnresolvedModuleFailure(message) {
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
return UNRESOLVED_MODULE_PATTERN.test(firstDiagnosticLine(message));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Returns the imported name of a missing-export diagnostic (identifier only), or null.
|
|
55
|
+
function findMissingExportName(message) {
|
|
56
|
+
return MISSING_EXPORT_PATTERN.exec(firstDiagnosticLine(message))?.[1] ?? null;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
// Returns the first project-relative source location found in a raw message, or null.
|
|
@@ -67,7 +78,12 @@ export function classifyDeployCodegenFailure(error, { cwd, backendRoot = "gencow
|
|
|
67
78
|
const location = findProjectSourceLocation(message, { cwd, processCwd });
|
|
68
79
|
const backendLocation = location && location.sourceFile.startsWith(`${backendRoot}/`) ? location : null;
|
|
69
80
|
if (isUnresolvedModuleFailure(message)) {
|
|
70
|
-
|
|
81
|
+
const missingExport = findMissingExportName(message);
|
|
82
|
+
return {
|
|
83
|
+
code: CODEGEN_FAILURE_CODES.SOURCE_LOAD_FAILED,
|
|
84
|
+
...(backendLocation ?? {}),
|
|
85
|
+
...(missingExport ? { missingExport } : {}),
|
|
86
|
+
};
|
|
71
87
|
}
|
|
72
88
|
if (location) {
|
|
73
89
|
return {
|
|
@@ -140,6 +156,7 @@ export function createDeployCodegenFailure(classification, { correlationId } = {
|
|
|
140
156
|
error.line = classification.line;
|
|
141
157
|
if (classification.column !== undefined) error.column = classification.column;
|
|
142
158
|
}
|
|
159
|
+
if (classification.missingExport !== undefined) error.missingExport = classification.missingExport;
|
|
143
160
|
// Local reference only (no Platform request exists for a codegen failure).
|
|
144
161
|
if (correlationId !== undefined) error.correlationId = correlationId;
|
|
145
162
|
return error;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { unlinkSync } from "fs";
|
|
2
|
+
|
|
3
|
+
// Local-only backend source preparation for a first `deploy --prod`. Every step here
|
|
4
|
+
// reads the project on disk (capability check, migration generation, codegen, the
|
|
5
|
+
// packaging audits and the bundle with its round-trip check). It runs once, before the
|
|
6
|
+
// production app is created, so a rejection leaves no remote app behind.
|
|
7
|
+
export async function prepareBackendSourceForProdCreate(
|
|
8
|
+
runtime,
|
|
9
|
+
{ forceDeploy = false, requestId = null } = {},
|
|
10
|
+
) {
|
|
11
|
+
if ((await runtime.preflightBackendCapability?.()) === false) return null;
|
|
12
|
+
const generatorVersion = await runtime.prepareDeployProjectSource?.({ existingBundleMode: false });
|
|
13
|
+
const packageResult = await runtime.packageDeployProject({
|
|
14
|
+
forceDeploy,
|
|
15
|
+
existingBundleMode: false,
|
|
16
|
+
requestId,
|
|
17
|
+
sourcePrepared: true,
|
|
18
|
+
preparedGeneratorVersion: generatorVersion,
|
|
19
|
+
});
|
|
20
|
+
if (!packageResult) return null;
|
|
21
|
+
return { runtime, generatorVersion, packageResult };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Drops the temporary bundle file and codegen output of a prepared source that did not
|
|
25
|
+
// reach the backend deploy (which otherwise releases them itself). Safe to call twice.
|
|
26
|
+
export function releasePreparedBackendSource(prepared, { unlinkSyncImpl = unlinkSync } = {}) {
|
|
27
|
+
if (!prepared) return;
|
|
28
|
+
const tmpBundle = prepared.packageResult?.tmpBundle;
|
|
29
|
+
if (tmpBundle) {
|
|
30
|
+
try {
|
|
31
|
+
unlinkSyncImpl(tmpBundle);
|
|
32
|
+
} catch {
|
|
33
|
+
/* already removed */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
prepared.runtime?.cleanupPreparedDeploySource?.();
|
|
37
|
+
}
|
package/lib/deploy-runtime.mjs
CHANGED
|
@@ -19,6 +19,11 @@ import { detectStaticDeployBackend, preflightStaticDeployArtifact } from "./stat
|
|
|
19
19
|
import { formatCommandError } from "./cli-command-runner.mjs";
|
|
20
20
|
import { readJsonObjectResponse } from "./http-response-json.mjs";
|
|
21
21
|
import { ensureProductionDeployTarget } from "./deploy-prod-target.mjs";
|
|
22
|
+
import {
|
|
23
|
+
prepareBackendSourceForProdCreate,
|
|
24
|
+
releasePreparedBackendSource,
|
|
25
|
+
} from "./deploy-prepared-source.mjs";
|
|
26
|
+
import { resolveImplicitProdEnvironment } from "./cloud-targets.mjs";
|
|
22
27
|
|
|
23
28
|
export function parseDeployArgs(deployArgs) {
|
|
24
29
|
const parsed = {
|
|
@@ -183,14 +188,6 @@ function showUnknownDeployArgument(arg, { errorImpl = error, infoImpl = info, lo
|
|
|
183
188
|
infoImpl(" gencow static [dir] Deploy static files only");
|
|
184
189
|
}
|
|
185
190
|
|
|
186
|
-
// Returns the prepared backend source, or null when the capability check rejected it
|
|
187
|
-
// (the rejection is already rendered and exit is already requested).
|
|
188
|
-
async function prepareBackendSourceForProdCreate(runtime) {
|
|
189
|
-
if ((await runtime.preflightBackendCapability?.()) === false) return null;
|
|
190
|
-
const generatorVersion = await runtime.prepareDeployProjectSource?.({ existingBundleMode: false });
|
|
191
|
-
return { runtime, generatorVersion };
|
|
192
|
-
}
|
|
193
|
-
|
|
194
191
|
async function runRollbackDeploy({
|
|
195
192
|
appId,
|
|
196
193
|
envTarget,
|
|
@@ -432,6 +429,14 @@ export function createDeployCommand({
|
|
|
432
429
|
resolvePathImpl,
|
|
433
430
|
});
|
|
434
431
|
let { appId, displayName, gencowJsonPath, prodAppId, projectDir } = context;
|
|
432
|
+
// Same environment rule as cloud-targets.mjs: --app <project prod app> deploys to prod even without --prod.
|
|
433
|
+
// Every branch below (static, rollback, existing-bundle, backend) reads this promoted environment.
|
|
434
|
+
parsed.envTarget = resolveImplicitProdEnvironment({
|
|
435
|
+
explicitApp: Boolean(parsed.appId),
|
|
436
|
+
envTarget: parsed.envTarget,
|
|
437
|
+
appId: parsed.appId,
|
|
438
|
+
prodApp: prodAppId,
|
|
439
|
+
});
|
|
435
440
|
const rootAppId = appId;
|
|
436
441
|
appId = resolveEnvironmentDeployTarget({ appId, envTarget: parsed.envTarget, prodAppId });
|
|
437
442
|
const backendProjectRoot = projectDir ?? projectRoot;
|
|
@@ -524,14 +529,20 @@ export function createDeployCommand({
|
|
|
524
529
|
region: parsed.region,
|
|
525
530
|
prepareLocalSource: preparesBackendSource
|
|
526
531
|
? async () => {
|
|
527
|
-
preparedSource = await prepareBackendSourceForProdCreate(backendDeployRuntime
|
|
532
|
+
preparedSource = await prepareBackendSourceForProdCreate(backendDeployRuntime, {
|
|
533
|
+
forceDeploy: parsed.forceDeploy,
|
|
534
|
+
requestId: parsed.requestId,
|
|
535
|
+
});
|
|
528
536
|
return preparedSource !== null;
|
|
529
537
|
}
|
|
530
538
|
: null,
|
|
531
539
|
});
|
|
532
540
|
} finally {
|
|
533
|
-
// Prepared codegen output
|
|
534
|
-
if (!prodTarget)
|
|
541
|
+
// Prepared codegen output and bundle are temporary; drop them when no production app was created.
|
|
542
|
+
if (!prodTarget) {
|
|
543
|
+
backendDeployRuntime.cleanupPreparedDeploySource?.();
|
|
544
|
+
releasePreparedBackendSource(preparedSource, { unlinkSyncImpl });
|
|
545
|
+
}
|
|
535
546
|
}
|
|
536
547
|
if (!prodTarget) return;
|
|
537
548
|
appId = prodTarget;
|
|
@@ -544,64 +555,69 @@ export function createDeployCommand({
|
|
|
544
555
|
}
|
|
545
556
|
|
|
546
557
|
if (parsed.staticDeploy) {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
558
|
+
try {
|
|
559
|
+
await runStaticDeployFlow({
|
|
560
|
+
appId,
|
|
561
|
+
preparedSource,
|
|
562
|
+
backendRoot: backendProjectRoot,
|
|
563
|
+
creds,
|
|
564
|
+
displayName,
|
|
565
|
+
envTarget: parsed.envTarget,
|
|
566
|
+
forceDeploy: parsed.forceDeploy,
|
|
567
|
+
requestId: parsed.requestId,
|
|
568
|
+
resumeStaticOnly: parsed.resumeRequested,
|
|
569
|
+
gencowJsonPath,
|
|
570
|
+
hasDetectedBackend,
|
|
571
|
+
selectedClient,
|
|
572
|
+
staticDirArg: resolvedStaticDirArg,
|
|
573
|
+
staticArtifactPreflight,
|
|
574
|
+
createDeployPackageRuntimeForCwd,
|
|
575
|
+
cwdImpl,
|
|
576
|
+
deployPackageRuntime: backendDeployRuntime,
|
|
577
|
+
errorImpl,
|
|
578
|
+
existsSyncImpl,
|
|
579
|
+
exitImpl,
|
|
580
|
+
infoImpl,
|
|
581
|
+
logImpl,
|
|
582
|
+
resolvePathImpl,
|
|
583
|
+
runStaticDeployRuntimeImpl,
|
|
584
|
+
unlinkSyncImpl,
|
|
585
|
+
writeFileSyncImpl,
|
|
586
|
+
prepareReleaseAttempt: prepareReleaseAttemptImpl
|
|
587
|
+
? ({ appId: activeAppId, sourceRoot }) =>
|
|
588
|
+
prepareReleaseAttemptImpl({
|
|
589
|
+
root: sourceRoot || backendProjectRoot,
|
|
590
|
+
sourceRootKind: "fullstack",
|
|
591
|
+
components: ["backend", "static"],
|
|
592
|
+
cliVersion,
|
|
593
|
+
creds,
|
|
594
|
+
appId: activeAppId,
|
|
595
|
+
environment: parsed.envTarget,
|
|
596
|
+
requestId: parsed.requestId,
|
|
597
|
+
platformFetchImpl,
|
|
598
|
+
capabilityTimeoutMs: 15_000,
|
|
599
|
+
allowCapabilityTimeoutFallback: true,
|
|
600
|
+
warnImpl,
|
|
601
|
+
})
|
|
602
|
+
: undefined,
|
|
603
|
+
failReleaseAttempt: failReleaseAttemptImpl
|
|
604
|
+
? ({ appId: activeAppId, attemptId, failureStage, failureCode }) =>
|
|
605
|
+
failReleaseAttemptImpl({
|
|
606
|
+
creds,
|
|
607
|
+
appId: activeAppId,
|
|
608
|
+
attemptId,
|
|
609
|
+
environment: parsed.envTarget,
|
|
610
|
+
failureStage,
|
|
611
|
+
failureCode,
|
|
612
|
+
platformFetchImpl,
|
|
613
|
+
})
|
|
614
|
+
: undefined,
|
|
615
|
+
successImpl,
|
|
616
|
+
});
|
|
617
|
+
} finally {
|
|
618
|
+
// The static flow can return before the backend deploy consumes the prepared source.
|
|
619
|
+
releasePreparedBackendSource(preparedSource, { unlinkSyncImpl });
|
|
620
|
+
}
|
|
605
621
|
return 0;
|
|
606
622
|
}
|
|
607
623
|
|
|
@@ -125,22 +125,25 @@ export async function deployBackendPackage({
|
|
|
125
125
|
});
|
|
126
126
|
if (!activeAppId) return null;
|
|
127
127
|
} else {
|
|
128
|
-
if (
|
|
128
|
+
if (preparedSource) {
|
|
129
|
+
// Local preparation and packaging already ran once, before the production create.
|
|
130
|
+
packageResult = preparedSource.packageResult;
|
|
131
|
+
} else {
|
|
129
132
|
if ((await activePackageRuntime.preflightBackendCapability?.()) === false) return null;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
133
|
+
const preparedGeneratorVersion = await activePackageRuntime.prepareDeployProjectSource?.({
|
|
134
|
+
existingBundleMode,
|
|
135
|
+
});
|
|
136
|
+
packageResult = await activePackageRuntime.packageDeployProject({
|
|
137
|
+
forceDeploy,
|
|
138
|
+
existingBundleMode,
|
|
139
|
+
requestId,
|
|
140
|
+
sourcePrepared: true,
|
|
141
|
+
preparedGeneratorVersion,
|
|
142
|
+
});
|
|
143
|
+
if (!packageResult) {
|
|
144
|
+
await markAttemptFailed("package", "PACKAGE_FAILED");
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
activeAppId = await activePackageRuntime.createCloudAppIfNeeded({
|
package/lib/static-command.mjs
CHANGED
|
@@ -3,7 +3,11 @@ import { isAbsolute, resolve } from "path";
|
|
|
3
3
|
|
|
4
4
|
import { readProjectDisplayName } from "./cli-project-runtime.mjs";
|
|
5
5
|
import { formatCommandError } from "./cli-command-runner.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
describeProdTargetFailure,
|
|
8
|
+
resolveImplicitProdEnvironment,
|
|
9
|
+
resolveProdAppTarget,
|
|
10
|
+
} from "./cloud-targets.mjs";
|
|
7
11
|
import {
|
|
8
12
|
getCliInvocationSelection,
|
|
9
13
|
resolveProjectMetadataPath,
|
|
@@ -291,8 +295,14 @@ export function createStaticCommand(options = {}) {
|
|
|
291
295
|
return;
|
|
292
296
|
}
|
|
293
297
|
}
|
|
294
|
-
|
|
295
|
-
const envTarget =
|
|
298
|
+
// Same environment rule as deploy (cloud-targets.mjs): --app <project prod app> is prod even without --prod.
|
|
299
|
+
const envTarget = resolveImplicitProdEnvironment({
|
|
300
|
+
explicitApp: Boolean(parsed.appId),
|
|
301
|
+
envTarget: parsed.isProd ? "prod" : "dev",
|
|
302
|
+
appId: parsed.appId,
|
|
303
|
+
prodApp: prodAppId,
|
|
304
|
+
});
|
|
305
|
+
let deployTarget = envTarget === "prod" ? prodAppId || appId : appId;
|
|
296
306
|
|
|
297
307
|
if (parsed.isProd && !prodAppId) {
|
|
298
308
|
deployTarget = await ensureStaticProductionTarget({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gencow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.261",
|
|
4
4
|
"description": "Gencow — AI Backend Engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"ai": "^6.0.314",
|
|
41
41
|
"better-auth": "1.7.11",
|
|
42
42
|
"postgres": "^3.4.9",
|
|
43
|
+
"@gencow/react": "0.2.8",
|
|
43
44
|
"@gencow/client": "0.2.8",
|
|
44
|
-
"@gencow/shared": "0.0.0",
|
|
45
|
-
"@gencow/core": "0.1.47",
|
|
46
45
|
"@gencow/server": "0.1.3",
|
|
47
|
-
"@gencow/
|
|
46
|
+
"@gencow/core": "0.1.47",
|
|
47
|
+
"@gencow/shared": "0.0.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "node scripts/bundle-core.mjs && node scripts/bundle-shared.mjs && node scripts/bundle-server.mjs",
|