@geonosis/release 1.2.0 → 1.3.0

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/README.md CHANGED
@@ -101,11 +101,25 @@ An **identifier** argument (`this.addSql(dropOperationChecks)`) and a **template
101
101
  are refused BY NAME with exit 2. Resolving either is name resolution — a TypeScript parser — and
102
102
  this package will not grow one. A migration nobody could read is not a migration that passed.
103
103
 
104
- ### squawk
104
+ ### squawk — an OPTIONAL peer
105
105
 
106
- `squawk-cli` is a pinned dependency of this package, spawned from its own `node_modules/.bin`. Its
107
- bin is called `squawk`, and `squawk` on a public registry is an unrelated package that exits 0 on
108
- anything — a gate that passes because it linted nothing. Nothing here asks a resolver.
106
+ ```bash
107
+ pnpm add -D squawk-cli@2.63.0 # only if release.migrations names postgres or mikro-orm-ts
108
+ ```
109
+
110
+ `squawk-cli` ships platform binaries, and as a hard dependency of this package it grew one
111
+ consumer's lockfile by **395 lines** for a Postgres linter that repo never configured. It is a peer
112
+ marked optional: nothing installs it for you.
113
+
114
+ - a `release.migrations` naming only the **`sqlite`** dialect never calls it, and needs none of it;
115
+ - a `postgres` or `mikro-orm-ts` dialect with squawk absent is **exit 2**, with the install line
116
+ above — the dialect cannot be measured, and a gate that cannot measure has not passed.
117
+
118
+ It is pinned exactly, because a squawk that renamed a rule would change what a release argues from,
119
+ and that is a decision rather than an install. It is spawned from the `node_modules/.bin` beside
120
+ this package: its bin is called `squawk`, and `squawk` on a public registry is an unrelated package
121
+ that exits 0 on anything — a gate that passes because it linted nothing. Nothing here asks a
122
+ resolver.
109
123
 
110
124
  Exit 0 is clean and exit 1 is findings. **Anything else is exit 2**, one line naming it: a linter
111
125
  that could not start has not measured, and a gate that cannot measure has not passed.
@@ -12,26 +12,33 @@ var strings = (value2, where) => {
12
12
  }
13
13
  return value2;
14
14
  };
15
+ var ENTRY_KEYS = "expected { dir, dialect, phases?, squawk? }";
15
16
  var oneDir = (value2, index) => {
16
- if (!isRecord(value2)) throw new CannotRun(`release.migrations[${index}] must be an object`);
17
+ const at = `release.migrations[${index}]`;
18
+ if (!isRecord(value2)) throw new CannotRun(`${at} must be an object \u2014 ${ENTRY_KEYS}`);
19
+ const known = /* @__PURE__ */ new Set(["dialect", "dir", "phases", "squawk"]);
20
+ const unknown = Object.keys(value2).find((key) => !known.has(key));
21
+ if (unknown !== void 0) {
22
+ throw new CannotRun(`${at}.${unknown} is not a key it takes \u2014 ${ENTRY_KEYS}`);
23
+ }
17
24
  const dir = value2["dir"];
18
25
  const dialect = value2["dialect"];
19
26
  if (typeof dir !== "string" || dir === "") {
20
- throw new CannotRun(`release.migrations[${index}].dir must name a directory`);
27
+ throw new CannotRun(`${at}.dir must name a directory \u2014 ${ENTRY_KEYS}`);
21
28
  }
22
29
  if (typeof dialect !== "string" || !DIALECTS.has(dialect)) {
23
30
  throw new CannotRun(
24
- `release.migrations[${index}].dialect must be one of ${[...DIALECTS].toSorted().join(", ")}`
31
+ `${at}.dialect must be one of ${[...DIALECTS].toSorted().join(", ")} \u2014 ${ENTRY_KEYS}`
25
32
  );
26
33
  }
27
- const phases = strings(value2["phases"], `release.migrations[${index}].phases`);
34
+ const phases = strings(value2["phases"], `${at}.phases`);
28
35
  for (const phase of phases) {
29
36
  if (phase !== "up" && phase !== "down") {
30
- throw new CannotRun(`release.migrations[${index}].phases may only hold "up" and "down"`);
37
+ throw new CannotRun(`${at}.phases may only hold "up" and "down"`);
31
38
  }
32
39
  }
33
40
  const squawk = value2["squawk"];
34
- const exclude = isRecord(squawk) ? strings(squawk["exclude"], `release.migrations[${index}].squawk.exclude`) : [];
41
+ const exclude = isRecord(squawk) ? strings(squawk["exclude"], `${at}.squawk.exclude`) : [];
35
42
  return {
36
43
  dialect,
37
44
  dir,
@@ -49,13 +56,27 @@ var EMPTY = {
49
56
  workers: [],
50
57
  wrangler: []
51
58
  };
59
+ var BLOCK_KEYS = "expected { migrations?, proof?, secrets?, steps?, workers?, wrangler?, wranglerEnv? }";
52
60
  var parseReleaseConfig = (raw) => {
53
61
  if (!isRecord(raw)) return EMPTY;
54
62
  const release = raw["release"];
55
63
  if (!isRecord(release)) return EMPTY;
64
+ const known = /* @__PURE__ */ new Set([
65
+ "migrations",
66
+ "proof",
67
+ "secrets",
68
+ "steps",
69
+ "workers",
70
+ "wrangler",
71
+ "wranglerEnv"
72
+ ]);
73
+ const unknown = Object.keys(release).find((key) => !known.has(key));
74
+ if (unknown !== void 0) {
75
+ throw new CannotRun(`release.${unknown} is not a key it reads \u2014 ${BLOCK_KEYS}`);
76
+ }
56
77
  const migrations = release["migrations"];
57
78
  if (migrations !== void 0 && !Array.isArray(migrations)) {
58
- throw new CannotRun("release.migrations must be a list");
79
+ throw new CannotRun(`release.migrations must be a list \u2014 ${ENTRY_KEYS}, per entry`);
59
80
  }
60
81
  const proof = release["proof"];
61
82
  return {
@@ -571,6 +592,7 @@ import { existsSync as existsSync3 } from "fs";
571
592
  import { dirname, resolve as resolve4 } from "path";
572
593
  import { fileURLToPath } from "url";
573
594
  var HERE = dirname(fileURLToPath(import.meta.url));
595
+ var PINNED = "2.63.0";
574
596
  var findSquawk = (from = HERE) => {
575
597
  for (let dir = from; ; dir = dirname(dir)) {
576
598
  const candidate = resolve4(dir, "node_modules/.bin/squawk");
@@ -578,7 +600,11 @@ var findSquawk = (from = HERE) => {
578
600
  if (dirname(dir) === dir) break;
579
601
  }
580
602
  throw new CannotRun(
581
- "squawk-cli is not installed beside this package \u2014 the Postgres dialect cannot be measured, and a gate that cannot measure has not passed"
603
+ `squawk-cli is not installed beside this package, and the postgres and mikro-orm-ts dialects cannot be measured without it \u2014 a gate that cannot measure has not passed. Install it:
604
+
605
+ pnpm add -D squawk-cli@${PINNED}
606
+
607
+ It is an optional peer: a repo whose release.migrations names only the sqlite dialect needs none of this.`
582
608
  );
583
609
  };
584
610
  var squawkOn = (input) => {
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ import {
28
28
  runMigrations,
29
29
  runPlan,
30
30
  statementsOf
31
- } from "./chunk-BOTEFN3W.js";
31
+ } from "./chunk-D5IC766I.js";
32
32
  export {
33
33
  DEPLOYED_FILE,
34
34
  NARROWING,
@@ -10,7 +10,7 @@ import {
10
10
  runDeployed,
11
11
  runMigrations,
12
12
  runPlan
13
- } from "./chunk-BOTEFN3W.js";
13
+ } from "./chunk-D5IC766I.js";
14
14
 
15
15
  // src/release-cli.ts
16
16
  import { resolve } from "path";
@@ -134,8 +134,30 @@ var deployed = (parsed, cwd) => {
134
134
  );
135
135
  return report.ok ? 0 : 1;
136
136
  };
137
+ var CONFIG_SHAPE = `geonosis-release reads geonosis.json
138
+
139
+ geonosis.json \u2192 "release" every key optional; a repo that configured nothing gets nothing
140
+ migrations Entry[]? the directories whose migrations a release examines
141
+ dir string required \u2014 the directory, relative to the root
142
+ dialect string required \u2014 one of mikro-orm-ts, postgres, sqlite
143
+ phases string[]? "up" and/or "down" (default ["up"])
144
+ squawk object? { exclude: string[] } \u2014 the rule ids to leave out
145
+ proof object? { mustAssertVersion: boolean }
146
+ secrets string[]? the secret names a deployment carries
147
+ steps string[]? the release steps
148
+ workers string[]? the workers it deploys
149
+ wrangler string[]? the wrangler configs it carries
150
+ wranglerEnv string? the named environment block to read out of them
151
+
152
+ A key outside either list is refused BY NAME, with the accepted set. This shape had to be read out
153
+ of a bundled chunk file by a consumer once (#75).`;
137
154
  var main = async () => {
138
155
  const argv = process.argv.slice(2);
156
+ if (argv.includes("--print-config-shape")) {
157
+ process.stdout.write(`${CONFIG_SHAPE}
158
+ `);
159
+ return 0;
160
+ }
139
161
  if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
140
162
  process.stdout.write(USAGE);
141
163
  return 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geonosis/release",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "types": "./dist/index.d.ts",
5
5
  "description": "The release contract with its proofs: an expand-only migration gate over three dialects, a smoke that must name the version that answered it, and declared ≠ deployed.",
6
6
  "keywords": [
@@ -35,7 +35,15 @@
35
35
  "bin",
36
36
  "dist"
37
37
  ],
38
- "dependencies": {
38
+ "peerDependencies": {
39
+ "squawk-cli": "2.63.0"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "squawk-cli": {
43
+ "optional": true
44
+ }
45
+ },
46
+ "devDependencies": {
39
47
  "squawk-cli": "2.63.0"
40
48
  },
41
49
  "engines": {