create-geonosis 2.2.0 → 2.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.
@@ -24,13 +24,13 @@ var SEARCH = {
24
24
  "import { pgFtsSearchIndex, type SearchIndex, type SearchProjections } from '@geonosis/search'"
25
25
  ],
26
26
  name: "@geonosis/search",
27
- version: "0.3.3"
27
+ version: "0.3.4"
28
28
  };
29
29
  var DOMAINS = [SEARCH];
30
30
  var DOMAIN_NAMES = DOMAINS.map((one) => one.field);
31
31
  var FOUNDATIONS = [
32
- { at: "foundations/db", name: "@geonosis/db", version: "0.5.1" },
33
- { at: "foundations/events", name: "@geonosis/events", version: "1.5.2" }
32
+ { at: "foundations/db", name: "@geonosis/db", version: "0.5.2" },
33
+ { at: "foundations/events", name: "@geonosis/events", version: "2.0.0" }
34
34
  ];
35
35
  var domainsNamed = (named) => named.map((one) => {
36
36
  const found = DOMAINS.find((domain) => domain.field === one);
@@ -120,6 +120,7 @@ var MEDUSA_RANGE = "^2.19.0";
120
120
  var MEDUSA_PACKAGES = ["@medusajs/framework", "@medusajs/medusa"];
121
121
  var VALUED = /* @__PURE__ */ new Set([
122
122
  "--backend",
123
+ "--presets",
123
124
  "--brand",
124
125
  "--domains",
125
126
  "--kit",
@@ -129,7 +130,8 @@ var VALUED = /* @__PURE__ */ new Set([
129
130
  "--themekit",
130
131
  "--ui"
131
132
  ]);
132
- var SWITCHES = /* @__PURE__ */ new Set(["--check", "--help", "-h", "--no-install"]);
133
+ var SWITCHES = /* @__PURE__ */ new Set(["--check", "--help", "-h", "--no-install", "--plan"]);
134
+ var parseArgs = (argv) => read(argv);
133
135
  var read = (argv) => {
134
136
  const flags = {};
135
137
  let dir;
@@ -406,7 +408,7 @@ var workspacesOf = (answers) => {
406
408
 
407
409
  // src/files.ts
408
410
  import { countersFor, LAW_SOURCE, rulesFor, tiersFor } from "@geonosis/cli";
409
- var VERSION = "2.2.0";
411
+ var VERSION = "2.3.0";
410
412
  var SCHEMA = "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json";
411
413
  var CATALOG = {
412
414
  "@types/node": "^24.3.0",
@@ -444,6 +446,10 @@ var answersForRules = (answers) => ({
444
446
  "no-raw-html-atoms": [
445
447
  "error",
446
448
  [{ atom: "Button", element: "button", importPath: `${answers.scope}/ui/atoms/button` }]
449
+ ],
450
+ "no-runtime-dead-affordance": [
451
+ "error",
452
+ [{ atom: "Button", element: "button", importPath: `${answers.scope}/ui/atoms/button` }]
447
453
  ]
448
454
  },
449
455
  ...answers.backend === "medusa" ? {
@@ -786,7 +792,11 @@ var tsconfigBase = (answers) => json({
786
792
  });
787
793
  var filesFor = (answers) => {
788
794
  const workspaces = workspacesOf(answers);
789
- const counters = countersFor(answers.runtime, LAW_SOURCE);
795
+ const counters = countersFor(
796
+ answers.runtime,
797
+ LAW_SOURCE,
798
+ workspaces.map((one) => ({ dir: one.dir, name: one.name }))
799
+ );
790
800
  const { rules } = rulesFor(presetsFor(answers), answersForRules(answers));
791
801
  const files = {
792
802
  "package.json": rootManifest(answers),
@@ -1140,6 +1150,7 @@ export {
1140
1150
  BACKENDS,
1141
1151
  UIS,
1142
1152
  MEDUSA_RANGE,
1153
+ parseArgs,
1143
1154
  parseAnswers,
1144
1155
  wantsInstall,
1145
1156
  CORPUS_DIR,
@@ -1,21 +1,198 @@
1
1
  import {
2
+ BACKENDS,
2
3
  DOMAIN_NAMES,
3
4
  MEDUSA_RANGE,
4
5
  PLATFORM_FILE,
6
+ UIS,
5
7
  checkScaffold,
6
8
  describeDrift,
7
9
  finish,
8
10
  parseAnswers,
11
+ parseArgs,
9
12
  wantsInstall,
10
13
  writeScaffold
11
- } from "./chunk-IQS75GD7.js";
14
+ } from "./chunk-UCGVZCVK.js";
15
+
16
+ // src/create-geonosis-cli.ts
17
+ import { existsSync as existsSync2 } from "fs";
18
+
19
+ // src/adopt.ts
20
+ import { existsSync, readdirSync, readFileSync } from "fs";
21
+ import { basename, join, resolve } from "path";
22
+ import { countersFor, rulesFor, runtimeOf, tiersFor } from "@geonosis/cli";
23
+ var ADOPT_USAGE = "create-geonosis --plan <dir> [--presets <a,b>] [--runtime pnpm|bun] [--backend medusa|sagaflow-cf|none] [--ui tiered-shadcn|atoms-only|none] \u2014 what adopting this repo would take, computed off the tree. Writes nothing.";
24
+ var LOCKFILES = ["bun.lock", "bun.lockb", "pnpm-lock.yaml"];
25
+ var MEDUSA = "@medusajs/";
26
+ var WORKERS = ["wrangler", "@cloudflare/workers-types", "sagaflow-js"];
27
+ var readJson = (at) => {
28
+ if (!existsSync(at)) return void 0;
29
+ try {
30
+ return JSON.parse(readFileSync(at, "utf8"));
31
+ } catch {
32
+ return void 0;
33
+ }
34
+ };
35
+ var manifestsIn = (dir) => {
36
+ const found = [readJson(join(dir, "package.json"))];
37
+ for (const group of ["apps", "packages"]) {
38
+ const at = join(dir, group);
39
+ if (!existsSync(at)) continue;
40
+ for (const entry of readdirSync(at, { withFileTypes: true })) {
41
+ if (entry.isDirectory()) found.push(readJson(join(at, entry.name, "package.json")));
42
+ }
43
+ }
44
+ return found.filter((one) => one !== void 0);
45
+ };
46
+ var dependencyNames = (manifests) => manifests.flatMap((one) => [
47
+ ...Object.keys(one.dependencies ?? {}),
48
+ ...Object.keys(one.devDependencies ?? {})
49
+ ]);
50
+ var backendOf = (manifests) => {
51
+ const names = dependencyNames(manifests);
52
+ if (names.some((one) => one.startsWith(MEDUSA))) return "medusa";
53
+ if (names.some((one) => WORKERS.includes(one))) return "sagaflow-cf";
54
+ return "none";
55
+ };
56
+ var chosen = (flag, given, allowed) => {
57
+ if (given === void 0) return void 0;
58
+ if (!allowed.includes(given)) {
59
+ throw new Error(`${flag} "${given}" is not one of ${allowed.join(", ")}`);
60
+ }
61
+ return given;
62
+ };
63
+ var uiOf = (dir, given) => {
64
+ if (given !== void 0) return given;
65
+ if (!existsSync(join(dir, "packages/ui"))) return "none";
66
+ throw new Error(
67
+ `${dir} has a packages/ui and no --ui was given \u2014 the tier decides which rules the plan proposes, and a directory listing cannot say which tier it is. Name --ui ${UIS.join("|")}.`
68
+ );
69
+ };
70
+ var doorFor = (block) => `@geonosis/${block}`;
71
+ var KIT_OWNED_BLOCKS = ["ledger", "review", "testbed", "verify", "walk"];
72
+ var planAdoption = ({ backend, dir, presets, runtime, ui }) => {
73
+ const at = resolve(dir);
74
+ if (!existsSync(at))
75
+ throw new Error(`${at} is not there \u2014 --plan reads a repo, it never makes one`);
76
+ const manifests = manifestsIn(at);
77
+ const chosenRuntime = chosen("--runtime", runtime, ["bun", "pnpm"]) ?? runtimeOf(at);
78
+ if (chosenRuntime === void 0) {
79
+ throw new Error(
80
+ `${at} has none of ${LOCKFILES.join(", ")}, so nothing there says which package manager it runs \u2014 name --runtime pnpm|bun.`
81
+ );
82
+ }
83
+ const answers = {
84
+ backend: chosen("--backend", backend, BACKENDS) ?? backendOf(manifests),
85
+ dir: at,
86
+ domains: [],
87
+ name: basename(at),
88
+ runtime: chosenRuntime,
89
+ scope: `@${basename(at).toLowerCase()}`,
90
+ ui: uiOf(at, chosen("--ui", ui, UIS))
91
+ };
92
+ const drift = checkScaffold(answers);
93
+ const enabled = new Set(
94
+ Object.keys(
95
+ readJson(join(at, ".oxlintrc.json"))?.rules ?? {}
96
+ )
97
+ );
98
+ const config = readJson(join(at, "geonosis.json")) ?? {};
99
+ const declaredTiers = config["verify"] ?? {};
100
+ const declaredCounters = new Set(
101
+ (readJson(
102
+ join(at, "geonosis.ratchet.json")
103
+ )?.counters ?? []).map((one) => one.key ?? one.counter ?? "")
104
+ );
105
+ const declaredPackages = new Set(dependencyNames(manifests));
106
+ const { unanswered } = rulesFor(presets);
107
+ const tiers = tiersFor({
108
+ rules: {},
109
+ runtime: chosenRuntime,
110
+ scripts: Object.keys(
111
+ readJson(join(at, "package.json"))?.scripts ?? {}
112
+ )
113
+ });
114
+ return {
115
+ backend: answers.backend,
116
+ counters: countersFor(chosenRuntime, "LAW.md").map((one) => {
117
+ const key = typeof one["key"] === "string" ? one["key"] : String(one["counter"]);
118
+ return { declared: declaredCounters.has(key), key };
119
+ }),
120
+ dir: at,
121
+ doors: [.../* @__PURE__ */ new Set([...KIT_OWNED_BLOCKS, ...Object.keys(config)])].filter((block) => KIT_OWNED_BLOCKS.includes(block)).toSorted().map((block) => ({
122
+ block,
123
+ declared: declaredPackages.has(doorFor(block)),
124
+ package: doorFor(block)
125
+ })),
126
+ files: drift.filter((one) => one.kind === "missing"),
127
+ keys: drift.filter((one) => one.kind === "key"),
128
+ presets: presets.map((name) => {
129
+ const brings = Object.keys(rulesFor([name]).rules);
130
+ return {
131
+ brings: brings.length,
132
+ enabled: brings.filter((id) => enabled.has(id)),
133
+ name
134
+ };
135
+ }),
136
+ runtime: chosenRuntime,
137
+ tiers: Object.entries(tiers).map(([name, steps]) => ({
138
+ declared: Object.hasOwn(declaredTiers, name),
139
+ name,
140
+ steps
141
+ })),
142
+ ui: answers.ui,
143
+ unanswered,
144
+ unreadable: drift.filter((one) => one.kind === "unreadable")
145
+ };
146
+ };
147
+ var section = (title, lines) => lines.length === 0 ? [`${title} \u2014 none`, ""] : [`${title} (${lines.length})`, ...lines, ""];
148
+ var formatPlan = (plan) => [
149
+ `adoption plan for ${plan.dir}`,
150
+ ` runtime ${plan.runtime} \xB7 backend ${plan.backend} \xB7 ui ${plan.ui}`,
151
+ "",
152
+ ...section(
153
+ "FILES the scaffold writes and this repo has none of",
154
+ plan.files.map((one) => ` ${one.file}`)
155
+ ),
156
+ ...section(
157
+ "KEYS the scaffold declares inside a file this repo has",
158
+ plan.keys.map((one) => ` ${one.file} \u2192 ${one.at}`)
159
+ ),
160
+ ...section(
161
+ "RULES the presets bring",
162
+ plan.presets.map(
163
+ (one) => ` ${one.name}: ${one.brings} rules, ${one.enabled.length} already enabled here`
164
+ )
165
+ ),
166
+ ...section(
167
+ "RULES left out until somebody answers their option",
168
+ plan.unanswered.map(([rule, option]) => ` ${rule} needs \`${option}\``)
169
+ ),
170
+ ...section(
171
+ "COUNTERS the ratchet would run",
172
+ plan.counters.map((one) => ` ${one.key}${one.declared ? " \u2014 declared" : ""}`)
173
+ ),
174
+ ...section(
175
+ "TIERS",
176
+ plan.tiers.map((one) => ` ${one.name}${one.declared ? " \u2014 declared" : ""}`)
177
+ ),
178
+ ...section(
179
+ "DOORS a block needs declared",
180
+ plan.doors.map(
181
+ (one) => ` ${one.package} for "${one.block}"${one.declared ? " \u2014 declared" : ""}`
182
+ )
183
+ ),
184
+ ...plan.unreadable.length === 0 ? [] : section(
185
+ "FILES this check could not read as JSON",
186
+ plan.unreadable.map((one) => ` ${one.file}`)
187
+ )
188
+ ].join("\n");
12
189
 
13
190
  // src/create-geonosis-cli.ts
14
- import { existsSync } from "fs";
15
191
  var USAGE = `create-geonosis <dir> --runtime pnpm|bun --backend medusa|sagaflow-cf|none --ui tiered-shadcn|atoms-only|none
16
192
  [--medusa <range>]
17
193
  [--domains <a,b>] [--brand <name>] [--themekit <name>] [--marketplace <path>] [--kit <path>] [--no-install]
18
194
  [--check]
195
+ create-geonosis --plan <dir> [--presets <a,b>] [--runtime \u2026] [--backend \u2026] [--ui \u2026]
19
196
 
20
197
  Writes a repo that passes its own gates on day one: a workspace with one catalog of shared versions,
21
198
  an exports map and no barrel in every package, typecheck + lint + test scripts in every workspace,
@@ -38,6 +215,12 @@ default borrowed from another repo would be that repo's stack hardcoded into thi
38
215
  packages after the install and rewrites the manifest to say so.
39
216
  --no-install write the files and stop. The gates cannot run until the two "geonosis sync
40
217
  --target" commands below have been run, and they are printed for you.
218
+ --plan what ADOPTING an existing repo would take, computed off its tree and written
219
+ nowhere: the files and keys it lacks of what the scaffold writes, the rules each
220
+ preset brings against the ones already enabled, the rules left out until somebody
221
+ answers their option, the counters, the tiers and the doors a block needs
222
+ declared. The runtime and the backend are read off the lockfile and the manifests;
223
+ a flag overrides one. Exit 0 \u2014 it is a report.
41
224
  --check say what an EXISTING repo is missing of what the scaffold writes today, and WRITE
42
225
  NOTHING. Files it has never had, and keys inside the JSON it has. Contents and
43
226
  values are never compared: a repo that has been worked in has rewritten them, and
@@ -64,9 +247,26 @@ var main = () => {
64
247
  `);
65
248
  return argv.length === 0 ? 2 : 0;
66
249
  }
250
+ if (argv.includes("--plan")) {
251
+ const { dir, flags } = parseArgs(argv);
252
+ if (dir === void 0) throw new Error(`--plan needs a directory \u2014 ${ADOPT_USAGE}`);
253
+ process.stdout.write(
254
+ `${formatPlan(
255
+ planAdoption({
256
+ ...flags["--backend"] === void 0 ? {} : { backend: flags["--backend"] },
257
+ dir,
258
+ presets: (flags["--presets"] ?? "frontend,tooling").split(",").map((one) => one.trim()).filter((one) => one !== ""),
259
+ ...flags["--runtime"] === void 0 ? {} : { runtime: flags["--runtime"] },
260
+ ...flags["--ui"] === void 0 ? {} : { ui: flags["--ui"] }
261
+ })
262
+ )}
263
+ `
264
+ );
265
+ return 0;
266
+ }
67
267
  const answers = parseAnswers(argv, process.cwd());
68
268
  if (argv.includes("--check")) {
69
- if (!existsSync(answers.dir)) {
269
+ if (!existsSync2(answers.dir)) {
70
270
  throw new Error(`${answers.dir} is not there \u2014 --check reads a repo, it never makes one`);
71
271
  }
72
272
  const drift = checkScaffold(answers);
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  wantsInstall,
24
24
  workspacesOf,
25
25
  writeScaffold
26
- } from "./chunk-IQS75GD7.js";
26
+ } from "./chunk-UCGVZCVK.js";
27
27
  export {
28
28
  BACKENDS,
29
29
  CORPUS_DIR,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-geonosis",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "types": "./dist/index.d.ts",
5
5
  "description": "Scaffold a microcompany repo that passes its own geonosis gates on day one.",
6
6
  "keywords": [
@@ -34,7 +34,7 @@
34
34
  "dist"
35
35
  ],
36
36
  "dependencies": {
37
- "@geonosis/cli": "2.2.0"
37
+ "@geonosis/cli": "2.3.0"
38
38
  },
39
39
  "engines": {
40
40
  "node": ">=22"