@everystack/cli 0.4.7 → 0.4.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everystack/cli",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "CLI and OTA updates for Expo apps on everystack",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "Scalable Technology, Inc. <licensing@scalable.technology>",
@@ -82,7 +82,7 @@
82
82
  "structured-headers": "1.0.1",
83
83
  "tsx": "4.21.0",
84
84
  "typescript": "5.9.3",
85
- "@everystack/model": "0.4.1"
85
+ "@everystack/model": "0.4.2"
86
86
  },
87
87
  "peerDependencies": {
88
88
  "@everystack/server": ">=0.1.0",
@@ -35,6 +35,7 @@ import { resolveDbSource, createUrlRunner, connectingVia, type DbSource } from '
35
35
  import { resolveConfig, opsFunction } from '../config.js';
36
36
  import { invokeAction, lambdaQueryRunner } from '../aws.js';
37
37
  import { executeApplyPlan, type ApplyPlanResult } from '../apply-execute.js';
38
+ import { pgDumpPreflightError } from './db-backup.js';
38
39
  import { step, success, fail, info, warn } from '../output.js';
39
40
 
40
41
  // The apply core lives in apply-execute.ts (shared with the ops Lambda's
@@ -116,6 +117,19 @@ async function applyPlanViaStage(
116
117
 
117
118
  info(`plan ${planHash(plan).slice(0, 12)}: ${plan.fromFingerprint.slice(0, 12)} → ${plan.toFingerprint.slice(0, 12)} (${plan.executable} statement(s)${plan.destructive ? `, ${plan.destructive} destructive` : ''})`);
118
119
 
120
+ // A destructive staged apply snapshots via db:backup INSIDE the Lambda, before the DDL. Preflight
121
+ // that capability HERE so a missing/incompatible pg_dump layer fails fast with the install remedy —
122
+ // not deep in the ceremony after the authority check, the way it once surfaced mid-apply.
123
+ if (plan.destructive > 0) {
124
+ step('Preflighting the pg_dump layer (the destructive apply snapshots before the DDL)...');
125
+ const probe: any = await invokeAction(region, fn, 'db:backup:probe', {}).catch((err: any) => ({ error: err?.message ?? String(err) }));
126
+ const remedy = pgDumpPreflightError(probe);
127
+ if (remedy) {
128
+ fail(`Cannot take the pre-apply snapshot — the destructive plan was NOT applied.\n${remedy}`);
129
+ process.exit(1);
130
+ }
131
+ }
132
+
119
133
  try {
120
134
  // Descent — the fast-forward rule needs the git checkout, so the CLI
121
135
  // decides it (the Lambda has no checkout). Read the stage's state read-only
@@ -48,7 +48,7 @@ export async function dbBackupProbeCommand(flags: Record<string, string>): Promi
48
48
 
49
49
  if (result?.error) {
50
50
  fail(result.error);
51
- info('Build + publish the layer with scripts/build-pgdump-layer.sh, export PGDUMP_LAYER_ARN, then redeploy.');
51
+ info('Install @everystack/pg-tools and redeploy — the layer attaches automatically. For a bring-your-own layer, pass pgDumpLayer(..., { layerArn }) in sst.config.ts.');
52
52
  process.exit(1);
53
53
  }
54
54
 
@@ -71,7 +71,7 @@ export async function dbBackupProbeCommand(flags: Record<string, string>): Promi
71
71
  export function pgDumpPreflightError(probe: any): string | null {
72
72
  if (!probe || probe.error) {
73
73
  const detail = probe?.error ?? 'the pg_dump layer probe returned no result';
74
- return `${detail}\nBuild + publish the layer with scripts/build-pgdump-layer.sh, export PGDUMP_LAYER_ARN, then redeploy.`;
74
+ return `${detail}\nInstall @everystack/pg-tools and redeploy — the layer attaches automatically. For a bring-your-own layer, pass pgDumpLayer(..., { layerArn }) in sst.config.ts.`;
75
75
  }
76
76
  if (probe.compatible === false) {
77
77
  return `pg_dump ${probe.pgDump ?? '(unknown)'} (major ${probe.pgDumpMajor}) is older than the server (major ${probe.serverMajor}) — it will refuse to dump (no bypass exists). Rebuild the layer with pg_dump >= ${probe.serverMajor}.`;
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import { spawn } from 'node:child_process';
14
- import { step, success, fail, info } from '../output.js';
14
+ import { step, success, fail, info, warn } from '../output.js';
15
15
  import { invalidateCachedConfig } from '../discover.js';
16
16
  import { resolveConfig } from '../config.js';
17
17
  import { probeDeployedFunctions } from '../deploy-probe.js';
@@ -23,11 +23,11 @@ export function buildDeployArgs(flags: Record<string, string>): string[] {
23
23
  }
24
24
 
25
25
  /**
26
- * The environment the sst child receives: the FULL ambient environment plus color.
27
- * Pinned as an explicit, tested contract because a consumer observed PGDUMP_LAYER_ARN
28
- * reaching sst when invoked directly but not through this wrapper sst.config.ts
29
- * conditionals like `process.env.PGDUMP_LAYER_ARN ? { layers: [...] } : {}` silently
30
- * collapse when a variable goes missing, and the deploy still exits green.
26
+ * The environment the sst child receives: the FULL ambient environment plus color. The wrapper
27
+ * forwards everything so a consumer's own sst.config.ts env reads behave the same run directly or
28
+ * through `everystack deploy`. (This contract was pinned when the pg_dump layer depended on
29
+ * PGDUMP_LAYER_ARN reaching sst now deprecated: the layer ships via @everystack/pg-tools +
30
+ * pgDumpLayer() and reads no ambient env at deploy.)
31
31
  */
32
32
  export function deployEnv(base: Record<string, string | undefined>): Record<string, string | undefined> {
33
33
  return { ...base, FORCE_COLOR: '1' };
@@ -38,11 +38,11 @@ export async function deployCommand(flags: Record<string, string>): Promise<void
38
38
  const args = buildDeployArgs(flags);
39
39
 
40
40
  step(`Deploying stage "${stage}"...`);
41
- // Say what the wrapper sees: an sst.config.ts conditional on an env var collapses
42
- // SILENTLY when the var is missing, and the deploy still exits green the operator
43
- // must be able to tell "the wrapper never saw it" from "sst ignored it" at a glance.
41
+ // PGDUMP_LAYER_ARN is deprecated: the layer now ships via @everystack/pg-tools and pgDumpLayer()
42
+ // needs no env var. Still forwarded to sst for one more minor (pgDumpLayer honors it as an alias),
43
+ // then removed surface it loudly so the operator migrates off it.
44
44
  if (process.env.PGDUMP_LAYER_ARN) {
45
- info(`pg_dump layer: PGDUMP_LAYER_ARN is set forwarded to sst (${process.env.PGDUMP_LAYER_ARN})`);
45
+ warn('PGDUMP_LAYER_ARN is DEPRECATED and will be removed next minor. The pg_dump layer now ships via @everystack/pg-tools + pgDumpLayer() with no env var. Drop it once your sst.config.ts uses pgDumpLayer().');
46
46
  }
47
47
  await new Promise<void>((resolve) => {
48
48
  // `npx` resolves the consumer's local sst (the same way the export step runs expo).