gencow 0.1.261 → 0.1.263

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.
@@ -24,6 +24,7 @@ import {
24
24
 
25
25
  export { APP_DELETE_OPERATION_PATTERN } from "./app-delete-diagnostic.mjs";
26
26
 
27
+ const APP_DELETE_DIAGNOSTIC_STAGES = new Set(["admission", "runtime-stop", "tenant-database", "catalog-finalize"]);
27
28
  const RETRY_CLASSES = new Set(["operator-action", "platform-action", "retryable-infra", "terminal-client"]);
28
29
  const USER_ACTIONS = new Set([
29
30
  "CONTACT_SUPPORT",
@@ -102,8 +103,13 @@ export function appResponseError(body, fallback, response = null, options = {})
102
103
  if (/^[A-Za-z0-9_-]{8,128}$/u.test(body.correlationId ?? "")) {
103
104
  lines.push(`Correlation ID: ${body.correlationId}`);
104
105
  }
105
- if (body.stage === "admission") lines.push("Stage: admission");
106
- if (body.stateImpact === "This deletion request made no ownership or resource change.") {
106
+ // Delete-stage diagnoses from the Platform name the failed stage and its state impact.
107
+ if (APP_DELETE_DIAGNOSTIC_STAGES.has(body.stage)) lines.push(`Stage: ${body.stage}`);
108
+ if (
109
+ APP_DELETE_DIAGNOSTIC_STAGES.has(body.stage) &&
110
+ typeof body.stateImpact === "string" &&
111
+ /^[A-Za-z0-9 ,.;:-]{1,200}$/u.test(body.stateImpact)
112
+ ) {
107
113
  lines.push(`State impact: ${body.stateImpact}`);
108
114
  }
109
115
  if (typeof body.retryPrecondition === "string" &&
@@ -21,6 +21,7 @@ export function createCloudAppIfNeeded({
21
21
  envTarget = "dev",
22
22
  gencowJsonPath,
23
23
  allowMissingAppReplacement = true,
24
+ explicitApp = false,
24
25
  }) {
25
26
  const resolvedAppId = await resolveDeployAppId({
26
27
  creds,
@@ -29,6 +30,7 @@ export function createCloudAppIfNeeded({
29
30
  environment: envTarget,
30
31
  platformFetchImpl,
31
32
  allowMissingAppReplacement,
33
+ explicitApp,
32
34
  infoImpl,
33
35
  errorImpl,
34
36
  exitImpl,
@@ -1,3 +1,4 @@
1
+ import { appNotFoundDiagnostic } from "./app-response-contract.mjs";
1
2
  import { readJsonObjectResponse } from "./http-response-json.mjs";
2
3
 
3
4
  const PUBLIC_LOOKUP_ERROR_CODES = new Set([
@@ -48,6 +49,30 @@ function formatLookupFailure(failure, target) {
48
49
  return lines.join("\n");
49
50
  }
50
51
 
52
+ // Rejection for an app ID the user named explicitly with --app. Such an ID is never replaced:
53
+ // a replacement would create a different app and rewrite gencow.json without the user asking.
54
+ function explicitAppNotFoundMessage({ appId, target = "dev", correlationId = null }) {
55
+ const lines = [
56
+ ...appNotFoundDiagnostic().split("\n"),
57
+ "Stage: deploy target lookup",
58
+ `App ID: ${appId}${target === "prod" ? " (requested with --prod)" : ""}`,
59
+ "Changed: nothing. No replacement app was created, gencow.json was not modified, and app data and the serving state were not changed.",
60
+ "Retry: only after --app names an app you own. Retrying the same ID fails the same way.",
61
+ "Next: gencow app list (find the app ID you own)",
62
+ " gencow app create <name> (create a new app, then deploy to its ID)",
63
+ ];
64
+ if (typeof correlationId === "string" && SAFE_CORRELATION_ID.test(correlationId)) {
65
+ lines.push(`Correlation ID: ${correlationId}`);
66
+ }
67
+ return lines.join("\n");
68
+ }
69
+
70
+ export function rejectExplicitAppNotFound({ appId, target, correlationId, errorImpl, exitImpl }) {
71
+ errorImpl(explicitAppNotFoundMessage({ appId, target, correlationId }));
72
+ exitImpl(1);
73
+ return false;
74
+ }
75
+
51
76
  export async function lookupOwnedApp({ creds, appId, environment, platformFetchImpl }) {
52
77
  try {
53
78
  const response = await platformFetchImpl(
@@ -79,6 +104,7 @@ export async function resolveDeployAppId({
79
104
  environment = "dev",
80
105
  platformFetchImpl,
81
106
  allowMissingAppReplacement,
107
+ explicitApp = false,
82
108
  infoImpl,
83
109
  errorImpl,
84
110
  exitImpl,
@@ -91,6 +117,9 @@ export async function resolveDeployAppId({
91
117
  exitImpl(1);
92
118
  return false;
93
119
  }
120
+ if (explicitApp) {
121
+ return rejectExplicitAppNotFound({ appId, target: environment, errorImpl, exitImpl });
122
+ }
94
123
  if (!allowMissingAppReplacement) {
95
124
  errorImpl(
96
125
  `APP_NOT_FOUND: The existing app ID "${appId}" is unavailable. This deployment requires the original app; restore access before retrying. No replacement app was created.`,
@@ -110,6 +139,7 @@ export async function reconcileProductionAppTarget({
110
139
  gencowJsonPath,
111
140
  platformFetchImpl,
112
141
  createCloudAppIfNeeded,
142
+ explicitApp = false,
113
143
  infoImpl,
114
144
  errorImpl,
115
145
  exitImpl,
@@ -156,6 +186,9 @@ export async function reconcileProductionAppTarget({
156
186
  }
157
187
 
158
188
  if (productionParentAppId && parentState === "missing") {
189
+ if (explicitApp) {
190
+ return rejectExplicitAppNotFound({ appId: productionParentAppId, target: "prod", errorImpl, exitImpl });
191
+ }
159
192
  infoImpl(`Configured app ID is no longer available. Creating a new app named "${displayName}"...`);
160
193
  productionParentAppId = await createCloudAppIfNeeded({
161
194
  creds,
@@ -5,6 +5,8 @@ import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFil
5
5
  import { dirname, resolve } from "path";
6
6
  import { fetchAppDiagnosticLogsViaRest, normalizeDiagnosticLogLines } from "./app-diagnostics.mjs";
7
7
  import { createCloudAppIfNeeded as createCloudAppIfNeededImpl } from "./deploy-app-creation.mjs";
8
+ import { rejectExplicitAppNotFound } from "./deploy-app-target.mjs";
9
+ import { loadProjectConfigForDeploy } from "./deploy-project-config-load.mjs";
8
10
  import { resolveConfiguredAuditorImplementation } from "./auditor-mode.mjs";
9
11
  import {
10
12
  loadDeployMigrationGenerationContext,
@@ -52,41 +54,9 @@ import { buildClientUserFixableDiagnostic } from "./migration-client-diagnostic.
52
54
  import { assertRuntimeAssetsWithinBackendRoot } from "./deploy-runtime-asset-audit.mjs";
53
55
  import { formatBundleSummaryLines } from "./deploy-bundle-summary.mjs";
54
56
  import { warnRuntimePathsOutsideBackendRoot } from "./deploy-runtime-path-audit.mjs";
55
- async function loadProjectConfigDefault(options) {
56
- const { loadConfig } = await import("./cli-project-runtime.mjs");
57
- return loadConfig(options);
58
- }
59
57
  export function isExplicitEmptyBackendApi(source) {
60
58
  return /\bdefineApi\s*\(\s*\{\s*procedures\s*:\s*\{\s*\}\s*,?\s*\}\s*\)\s*;?\s*$/u.test(source);
61
59
  }
62
- async function loadProjectConfigForDeploy({
63
- cwd,
64
- existsSyncImpl,
65
- readFileSyncImpl,
66
- resolvePathImpl,
67
- statSyncImpl,
68
- warnImpl,
69
- errorImpl,
70
- loadConfigImpl,
71
- throwOnInvalid = false,
72
- }) {
73
- const loadConfig = loadConfigImpl ?? loadProjectConfigDefault;
74
- try {
75
- return await loadConfig({
76
- cwd,
77
- existsSyncImpl,
78
- readFileSyncImpl,
79
- resolvePathImpl,
80
- statSyncImpl,
81
- warnImpl,
82
- errorImpl,
83
- throwOnInvalid,
84
- });
85
- } catch (caught) {
86
- if (throwOnInvalid) throw caught;
87
- return null;
88
- }
89
- }
90
60
  async function loadInternalToolingDefault() {
91
61
  return loadToolingRuntime({
92
62
  required: ["analyzerAudit"],
@@ -604,6 +574,7 @@ export function createDeployPackageRuntime({
604
574
  resumeExistingReceipt = false,
605
575
  releaseAttemptId = null,
606
576
  clientName = null,
577
+ explicitApp = false,
607
578
  }) {
608
579
  lastDeployOutcome = "pending";
609
580
  const cwd = cwdImpl();
@@ -707,6 +678,19 @@ export function createDeployPackageRuntime({
707
678
  if (!deployRes.ok && deployRes.status === 404) {
708
679
  if (preserveSavedReceiptAfterMissingApp(receipt, targetAppId, envTarget)) return null;
709
680
  if (receipt) deployReceiptStore.releaseDeployReceipt(receipt);
681
+ if (explicitApp) {
682
+ // The user named this app with --app: report it instead of creating a replacement.
683
+ const notFoundBody = await readJsonObjectResponse(deployRes);
684
+ lastDeployOutcome = "failed";
685
+ rejectExplicitAppNotFound({
686
+ appId: targetAppId,
687
+ target: envTarget,
688
+ correlationId: notFoundBody?.correlationId,
689
+ errorImpl,
690
+ exitImpl,
691
+ });
692
+ return null;
693
+ }
710
694
  warnImpl(`App "${targetAppId}" not found. Creating new one...`);
711
695
  targetAppId = await createCloudAppIfNeeded({
712
696
  creds,
@@ -27,6 +27,7 @@ export async function ensureProductionDeployTarget({
27
27
  exitImpl = (code) => process.exit(code),
28
28
  prodAppId = null,
29
29
  region = null,
30
+ explicitApp = false,
30
31
  prepareLocalSource = null,
31
32
  }) {
32
33
  const confirmMode = resolveConfirmationMode({
@@ -50,6 +51,7 @@ export async function ensureProductionDeployTarget({
50
51
  gencowJsonPath,
51
52
  platformFetchImpl,
52
53
  createCloudAppIfNeeded,
54
+ explicitApp,
53
55
  infoImpl,
54
56
  errorImpl,
55
57
  exitImpl,
@@ -0,0 +1,32 @@
1
+ async function loadProjectConfigDefault(options) {
2
+ const { loadConfig } = await import("./cli-project-runtime.mjs");
3
+ return loadConfig(options);
4
+ }
5
+ export async function loadProjectConfigForDeploy({
6
+ cwd,
7
+ existsSyncImpl,
8
+ readFileSyncImpl,
9
+ resolvePathImpl,
10
+ statSyncImpl,
11
+ warnImpl,
12
+ errorImpl,
13
+ loadConfigImpl,
14
+ throwOnInvalid = false,
15
+ }) {
16
+ const loadConfig = loadConfigImpl ?? loadProjectConfigDefault;
17
+ try {
18
+ return await loadConfig({
19
+ cwd,
20
+ existsSyncImpl,
21
+ readFileSyncImpl,
22
+ resolvePathImpl,
23
+ statSyncImpl,
24
+ warnImpl,
25
+ errorImpl,
26
+ throwOnInvalid,
27
+ });
28
+ } catch (caught) {
29
+ if (throwOnInvalid) throw caught;
30
+ return null;
31
+ }
32
+ }
@@ -527,6 +527,7 @@ export function createDeployCommand({
527
527
  exitImpl,
528
528
  prodAppId,
529
529
  region: parsed.region,
530
+ explicitApp: Boolean(parsed.appId),
530
531
  prepareLocalSource: preparesBackendSource
531
532
  ? async () => {
532
533
  preparedSource = await prepareBackendSourceForProdCreate(backendDeployRuntime, {
@@ -565,6 +566,7 @@ export function createDeployCommand({
565
566
  envTarget: parsed.envTarget,
566
567
  forceDeploy: parsed.forceDeploy,
567
568
  requestId: parsed.requestId,
569
+ explicitApp: Boolean(parsed.appId),
568
570
  resumeStaticOnly: parsed.resumeRequested,
569
571
  gencowJsonPath,
570
572
  hasDetectedBackend,
@@ -657,6 +659,7 @@ export function createDeployCommand({
657
659
  envTarget: parsed.envTarget,
658
660
  forceDeploy: parsed.forceDeploy,
659
661
  existingBundleMode: parsed.existingBundleMode,
662
+ explicitApp: Boolean(parsed.appId),
660
663
  requestId: parsed.requestId,
661
664
  resumeExistingReceipt: parsed.resumeRequested,
662
665
  gencowJsonPath: activeGencowJsonPath,
@@ -93,6 +93,8 @@ export async function deployBackendPackage({
93
93
  failReleaseAttempt,
94
94
  sourceRoot = null,
95
95
  clientName = null,
96
+ // True when the user named the app with --app. Such an ID is never replaced.
97
+ explicitApp = false,
96
98
  successImpl = success,
97
99
  }) {
98
100
  let packageResult = null;
@@ -122,6 +124,7 @@ export async function deployBackendPackage({
122
124
  envTarget,
123
125
  gencowJsonPath,
124
126
  allowMissingAppReplacement: false,
127
+ explicitApp,
125
128
  });
126
129
  if (!activeAppId) return null;
127
130
  } else {
@@ -152,7 +155,8 @@ export async function deployBackendPackage({
152
155
  displayName,
153
156
  envTarget,
154
157
  gencowJsonPath,
155
- allowMissingAppReplacement: !existingBundleMode,
158
+ allowMissingAppReplacement: !existingBundleMode && !explicitApp,
159
+ explicitApp,
156
160
  });
157
161
  if (!activeAppId) return null;
158
162
 
@@ -201,6 +205,7 @@ export async function deployBackendPackage({
201
205
  resumeExistingReceipt,
202
206
  releaseAttemptId: releaseAttempt?.attemptId ?? null,
203
207
  clientName,
208
+ explicitApp,
204
209
  });
205
210
  if (deployed && Object.hasOwn(deployed, "releaseAttemptId")) {
206
211
  releaseAttempt = deployed.releaseAttemptId ? { attemptId: deployed.releaseAttemptId } : null;
@@ -298,6 +303,7 @@ export async function runStaticDeployFlow({
298
303
  prepareReleaseAttempt,
299
304
  failReleaseAttempt,
300
305
  selectedClient = null,
306
+ explicitApp = false,
301
307
  successImpl = success,
302
308
  }) {
303
309
  if (!runStaticDeployRuntimeImpl) {
@@ -363,6 +369,7 @@ export async function runStaticDeployFlow({
363
369
  failReleaseAttempt,
364
370
  sourceRoot: backendRoot,
365
371
  clientName: selectedClient?.name ?? null,
372
+ explicitApp,
366
373
  successImpl,
367
374
  });
368
375
  if (!deployed) return;
@@ -10,6 +10,56 @@ import { resolveCloudAppTarget } from "./cloud-targets.mjs";
10
10
  import { BOLD, CYAN, DIM, GREEN, RESET, error, info, log, success, warn } from "./output.mjs";
11
11
  import { platformFetch, requireCreds } from "./platform-client.mjs";
12
12
 
13
+ const ENV_RESPONSE_UNREADABLE_CODE = "ENV_RESPONSE_UNREADABLE";
14
+
15
+ // Reads a failed platform response. A JSON `null`, an empty body, or a non-object body
16
+ // normalizes to `message: null`, so callers never dereference the parsed value.
17
+ async function readEnvErrorResponse(response) {
18
+ const parsed = await response.json().catch(() => null);
19
+ const body = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
20
+ const message = typeof body?.error === "string" && body.error.trim() ? body.error.trim() : null;
21
+ return { ...envResponseFacts(response), message };
22
+ }
23
+
24
+ function envResponseFacts(response) {
25
+ const correlationId = response.headers?.get?.("x-correlation-id") ?? null;
26
+ return {
27
+ status: response.status,
28
+ correlationId: /^[A-Za-z0-9_-]{8,128}$/u.test(correlationId ?? "") ? correlationId : null,
29
+ };
30
+ }
31
+
32
+ // A typed `{error}` text is kept verbatim. Without one, the CLI uses the same labels as
33
+ // renderProjectionResult, with state reported as unknown because the CLI cannot observe it.
34
+ function formatEnvErrorMessage(failure, { stage, checkCommand, retryable = isRetryableEnvStatus(failure.status) }) {
35
+ if (failure.message) return failure.message;
36
+ return [
37
+ "Platform returned an empty or unreadable error response",
38
+ `Code: ${ENV_RESPONSE_UNREADABLE_CODE}`,
39
+ `Stage: ${stage}`,
40
+ `HTTP ${failure.status}`,
41
+ failure.correlationId ? `Correlation ID: ${failure.correlationId}` : null,
42
+ "Catalog changed: unknown",
43
+ "Serving process changed: unknown",
44
+ `Retryable: ${retryable ? "yes" : "no"}`,
45
+ `Next action: run ${checkCommand}, then retry only if the change is not applied.`,
46
+ ]
47
+ .filter(Boolean)
48
+ .join("\n");
49
+ }
50
+
51
+ function isRetryableEnvStatus(status) {
52
+ return status === 408 || status === 429 || status >= 500;
53
+ }
54
+
55
+ function envTargetFlags(appId, envTarget) {
56
+ return envTarget === "prod" ? "--prod" : `--app ${appId}`;
57
+ }
58
+
59
+ function envListCommand(appId, envTarget) {
60
+ return `gencow env list ${envTargetFlags(appId, envTarget)}`;
61
+ }
62
+
13
63
  export function sanitizeCloudEnvKey(rawKey) {
14
64
  return rawKey
15
65
  .trim()
@@ -86,29 +136,36 @@ export function createEnvCommand(deps = {}) {
86
136
  const sleepImpl = deps.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms)));
87
137
  const projectionPollAttempts = deps.projectionPollAttempts ?? 40;
88
138
 
89
- async function loadProjectionStatus(creds, appId, operationId) {
139
+ async function loadProjectionStatus(creds, appId, operationId, envTarget) {
90
140
  const response = await platformFetchImpl(
91
141
  creds,
92
142
  `/platform/apps/${appId}/env/operations/${encodeURIComponent(operationId)}`,
93
143
  { method: "GET" },
94
144
  );
95
- const body = await response.json().catch(() => ({}));
96
- if (!response.ok) throw new Error(body.error || `HTTP ${response.status}`);
97
- return body;
145
+ if (!response.ok) {
146
+ throw new Error(
147
+ formatEnvErrorMessage(await readEnvErrorResponse(response), {
148
+ stage: "env_status",
149
+ checkCommand: `gencow env status --operation ${operationId} ${envTargetFlags(appId, envTarget)}`,
150
+ }),
151
+ );
152
+ }
153
+ const body = await response.json().catch(() => null);
154
+ return body && typeof body === "object" ? body : {};
98
155
  }
99
156
 
100
- async function waitForProjection(creds, appId, initial) {
157
+ async function waitForProjection(creds, appId, initial, envTarget) {
101
158
  if (!initial?.operationId || initial.runtimeState !== "pending") return initial ?? {};
102
159
  let current = initial;
103
160
  for (let attempt = 0; attempt < projectionPollAttempts; attempt += 1) {
104
161
  await sleepImpl(Number(current.retryAfterMs) || 500);
105
162
  try {
106
- current = await loadProjectionStatus(creds, appId, initial.operationId);
163
+ current = await loadProjectionStatus(creds, appId, initial.operationId, envTarget);
107
164
  } catch {
108
165
  return {
109
166
  ...current,
110
167
  statusQueryFailed: true,
111
- nextAction: `Run gencow env status --operation ${initial.operationId}`,
168
+ nextAction: `Run gencow env status --operation ${initial.operationId} ${envTargetFlags(appId, envTarget)}`,
112
169
  };
113
170
  }
114
171
  if (current.runtimeState !== "pending") return current;
@@ -205,7 +262,7 @@ export function createEnvCommand(deps = {}) {
205
262
  return;
206
263
  }
207
264
  try {
208
- return renderProjectionResult(await loadProjectionStatus(creds, appId, operationId));
265
+ return renderProjectionResult(await loadProjectionStatus(creds, appId, operationId, envTarget));
209
266
  } catch (e) {
210
267
  error(`Failed to fetch env operation: ${e.message}`);
211
268
  return 1;
@@ -223,7 +280,20 @@ export function createEnvCommand(deps = {}) {
223
280
  const reason = typeof body?.error === "string" && body.error ? body.error : null;
224
281
  throw new Error(reason ?? `HTTP ${res.status}`);
225
282
  }
226
- const vars = await res.json();
283
+ const vars = await res.json().catch(() => null);
284
+ if (!Array.isArray(vars)) {
285
+ throw new Error(
286
+ formatEnvErrorMessage(
287
+ { ...envResponseFacts(res), message: null },
288
+ {
289
+ stage: "env_list",
290
+ checkCommand: envListCommand(appId, envTarget),
291
+ // A successful list read is side-effect free, so retrying it is safe.
292
+ retryable: true,
293
+ },
294
+ ),
295
+ );
296
+ }
227
297
 
228
298
  log(
229
299
  `\n${BOLD}Environment Variables${RESET} ${DIM}(cloud: ${appId}, ${envTarget}, ${vars.length} total)${RESET}\n`,
@@ -297,11 +367,15 @@ export function createEnvCommand(deps = {}) {
297
367
  body: JSON.stringify({ key: name, value, env: envTarget }),
298
368
  });
299
369
  if (!res.ok) {
300
- const body = await res.json().catch(() => ({}));
301
- throw new Error(body.error || `HTTP ${res.status}`);
370
+ throw new Error(
371
+ formatEnvErrorMessage(await readEnvErrorResponse(res), {
372
+ stage: "env_set",
373
+ checkCommand: envListCommand(appId, envTarget),
374
+ }),
375
+ );
302
376
  }
303
377
  const mutation = await res.json().catch(() => ({}));
304
- const projection = await waitForProjection(creds, appId, mutation);
378
+ const projection = await waitForProjection(creds, appId, mutation, envTarget);
305
379
  const projectionExitCode = renderProjectionResult(projection);
306
380
  if (projectionExitCode === 0) {
307
381
  success(`Stored ${BOLD}${name}${RESET} ${DIM}(cloud: ${appId}, ${envTarget})${RESET}`);
@@ -346,11 +420,15 @@ export function createEnvCommand(deps = {}) {
346
420
  },
347
421
  );
348
422
  if (!res.ok) {
349
- const body = await res.json().catch(() => ({}));
350
- throw new Error(body.error || `HTTP ${res.status}`);
423
+ throw new Error(
424
+ formatEnvErrorMessage(await readEnvErrorResponse(res), {
425
+ stage: "env_unset",
426
+ checkCommand: envListCommand(appId, envTarget),
427
+ }),
428
+ );
351
429
  }
352
430
  const mutation = await res.json().catch(() => ({}));
353
- const projection = await waitForProjection(creds, appId, mutation);
431
+ const projection = await waitForProjection(creds, appId, mutation, envTarget);
354
432
  const projectionExitCode = renderProjectionResult(projection);
355
433
  if (projectionExitCode === 0) {
356
434
  success(`Removed ${BOLD}${key}${RESET} ${DIM}(cloud: ${appId}, ${envTarget})${RESET}`);
@@ -435,15 +513,19 @@ export function createEnvCommand(deps = {}) {
435
513
  body: JSON.stringify({ vars, env: envTarget }),
436
514
  });
437
515
  if (!res.ok) {
438
- const body = await res.json().catch(() => ({}));
439
- throw new Error(body.error || `HTTP ${res.status}`);
516
+ throw new Error(
517
+ formatEnvErrorMessage(await readEnvErrorResponse(res), {
518
+ stage: "env_push",
519
+ checkCommand: envListCommand(appId, envTarget),
520
+ }),
521
+ );
440
522
  }
441
- const data = await res.json();
523
+ const data = (await res.json().catch(() => null)) ?? {};
442
524
  for (const key of Object.keys(vars)) {
443
525
  success(`${key}`);
444
526
  }
445
527
  log(`\n ${GREEN}${data.count || count} set${RESET} ${DIM}(cloud: ${appId}, ${envTarget})${RESET}`);
446
- commandFailed = renderProjectionResult(await waitForProjection(creds, appId, data)) !== 0;
528
+ commandFailed = renderProjectionResult(await waitForProjection(creds, appId, data, envTarget)) !== 0;
447
529
  } catch (e) {
448
530
  error(`Failed to push env vars: ${e.message}`);
449
531
  commandFailed = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.261",
3
+ "version": "0.1.263",
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",
44
43
  "@gencow/client": "0.2.8",
45
- "@gencow/server": "0.1.3",
44
+ "@gencow/react": "0.2.8",
46
45
  "@gencow/core": "0.1.47",
47
- "@gencow/shared": "0.0.0"
46
+ "@gencow/shared": "0.0.0",
47
+ "@gencow/server": "0.1.3"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "node scripts/bundle-core.mjs && node scripts/bundle-shared.mjs && node scripts/bundle-server.mjs",