create-geonosis 2.0.0 → 2.2.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
@@ -87,8 +87,8 @@ Two things are compared and two are deliberately not:
87
87
  - a **value** — never. `doctor.corpus` pointing somewhere else is that repo's answer, not a drift.
88
88
 
89
89
  **The workspaces are out of the question.** `packages/core/src/money.ts` is a sample that makes a
90
- new repo compile, not a shape a repo must hold. Measured over dielime: including them turned 24 real
91
- findings into 52, thirty of which were about a `packages/ui` that repo does not have.
90
+ new repo compile, not a shape a repo must hold. Measured over a consumer: including them turned 24 real
91
+ findings into 52, thirty of them about a sample workspace that repo does not have.
92
92
 
93
93
  Over dielime — a repo scaffolded before D-054 moved the law — it reads 24, among them `LAW.md`,
94
94
  `geonosis.json → law.file`, three architecture rules the plugin has since added, and
@@ -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.1.1"
27
+ version: "0.3.3"
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.2.0" },
33
- { at: "foundations/events", name: "@geonosis/events", version: "1.5.0" }
32
+ { at: "foundations/db", name: "@geonosis/db", version: "0.5.1" },
33
+ { at: "foundations/events", name: "@geonosis/events", version: "1.5.2" }
34
34
  ];
35
35
  var domainsNamed = (named) => named.map((one) => {
36
36
  const found = DOMAINS.find((domain) => domain.field === one);
@@ -116,12 +116,15 @@ import { basename, resolve } from "path";
116
116
  var RUNTIMES = ["bun", "pnpm"];
117
117
  var BACKENDS = ["medusa", "none", "sagaflow-cf"];
118
118
  var UIS = ["atoms-only", "none", "tiered-shadcn"];
119
+ var MEDUSA_RANGE = "^2.19.0";
120
+ var MEDUSA_PACKAGES = ["@medusajs/framework", "@medusajs/medusa"];
119
121
  var VALUED = /* @__PURE__ */ new Set([
120
122
  "--backend",
121
123
  "--brand",
122
124
  "--domains",
123
125
  "--kit",
124
126
  "--marketplace",
127
+ "--medusa",
125
128
  "--runtime",
126
129
  "--themekit",
127
130
  "--ui"
@@ -186,6 +189,7 @@ var parseAnswers = (argv, cwd) => {
186
189
  domains,
187
190
  ...flags["--kit"] === void 0 ? {} : { kit: resolve(cwd, flags["--kit"]) },
188
191
  ...flags["--marketplace"] === void 0 ? {} : { marketplace: flags["--marketplace"] },
192
+ ...flags["--medusa"] === void 0 ? {} : { medusa: flags["--medusa"] },
189
193
  name,
190
194
  runtime: choose("--runtime", flags["--runtime"], RUNTIMES),
191
195
  scope: scopeOf(name),
@@ -372,6 +376,11 @@ var workspacesOf = (answers) => {
372
376
  dir: "packages/backend",
373
377
  mayDependOn: ["core"],
374
378
  name: `${scope}/backend`,
379
+ ...answers.backend === "medusa" ? {
380
+ packages: Object.fromEntries(
381
+ MEDUSA_PACKAGES.map((one) => [one, answers.medusa ?? MEDUSA_RANGE])
382
+ )
383
+ } : {},
375
384
  sources: {
376
385
  "src/handler.ts": HANDLER,
377
386
  "src/handler.test.ts": BACKEND_TEST,
@@ -397,7 +406,7 @@ var workspacesOf = (answers) => {
397
406
 
398
407
  // src/files.ts
399
408
  import { countersFor, LAW_SOURCE, rulesFor, tiersFor } from "@geonosis/cli";
400
- var VERSION = "2.0.0";
409
+ var VERSION = "2.2.0";
401
410
  var SCHEMA = "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json";
402
411
  var CATALOG = {
403
412
  "@types/node": "^24.3.0",
@@ -497,9 +506,15 @@ var workspaceManifest = (workspace, answers, workspaces) => {
497
506
  return found === void 0 || found.name === workspace.name ? [] : [[found.name, "workspace:*"]];
498
507
  })
499
508
  ),
500
- // With --kit the floors are linked from a workspace AFTER the install, and the manifest is
501
- // rewritten to say so — the same reason the root's kit versions are left out.
502
- ...answers.kit === void 0 ? workspace.packages : {}
509
+ // With --kit the FLOORS are linked from a workspace AFTER the install, and the manifest is
510
+ // rewritten to say so — the same reason the root's kit versions are left out. Everything else
511
+ // a workspace declares is third-party and stays: an engine dropped here is an engine the
512
+ // doctor cannot find, and a rule that presumes it then reads as a rule with no finding.
513
+ ...Object.fromEntries(
514
+ Object.entries(workspace.packages ?? {}).filter(
515
+ ([name]) => answers.kit === void 0 || !name.startsWith("@geonosis/")
516
+ )
517
+ )
503
518
  }
504
519
  });
505
520
  };
@@ -512,12 +527,61 @@ var kitDependencies = (answers) => ({
512
527
  "@geonosis/verify": `^${VERSION}`,
513
528
  ...answers.themekit === void 0 ? {} : { "@geonosis/themekit": `^${VERSION}` }
514
529
  });
530
+ var GRAPH_SYNCS = [
531
+ { target: "turbo", write: "turbo.json" },
532
+ { target: "layer-walls", write: ".oxlintrc.json" }
533
+ ];
534
+ var graphScript = GRAPH_SYNCS.map(
535
+ ({ target, write: write2 }) => `geonosis-ledger sync --target ${target} --write ${write2}`
536
+ ).join(" && ");
537
+ var HOOK_INSTALLER = "scripts/install-hooks.mjs";
538
+ var hookInstaller = () => [
539
+ "import { spawnSync } from 'node:child_process'",
540
+ "import { existsSync, lstatSync } from 'node:fs'",
541
+ "import { join, resolve } from 'node:path'",
542
+ "",
543
+ "const git = (...args) => {",
544
+ " const done = spawnSync('git', args, { encoding: 'utf8' })",
545
+ "",
546
+ " return done.status === 0 ? done.stdout.trim() : undefined",
547
+ "}",
548
+ "",
549
+ "const say = (line) => process.stdout.write(`install-hooks: ${line}\n`)",
550
+ "",
551
+ "const common = git('rev-parse', '--path-format=absolute', '--git-common-dir')",
552
+ "if (common === undefined) {",
553
+ " say('git says nothing about this directory, so there is no hooks path to install into.')",
554
+ " process.exit(0)",
555
+ "}",
556
+ "",
557
+ "// A worktree's own .git is a FILE; the hooks it would install into belong to the checkout the",
558
+ "// common dir names, and writing them from here changes the tree somebody else is in.",
559
+ "const here = resolve(process.cwd(), '.git')",
560
+ "if (existsSync(here) && lstatSync(here).isFile() && resolve(common) !== here) {",
561
+ " say(`this is a git worktree and its hooks path is shared with ${common} \u2014 install them there instead.`)",
562
+ " process.exit(0)",
563
+ "}",
564
+ "",
565
+ "const lefthook = join(process.cwd(), 'node_modules/.bin/lefthook')",
566
+ "if (!existsSync(lefthook)) {",
567
+ " say('lefthook is not installed here yet, so no hook was written.')",
568
+ " process.exit(0)",
569
+ "}",
570
+ "",
571
+ "const done = spawnSync(lefthook, ['install'], { stdio: 'inherit' })",
572
+ "process.exit(done.status ?? 0)",
573
+ ""
574
+ ].join("\n");
515
575
  var rootScripts = ({ runtime }) => ({
516
576
  doctor: "geonosis-doctor",
577
+ prepare: `node ${HOOK_INSTALLER}`,
517
578
  "format:check": "oxfmt --config .oxfmtrc.json --check .",
518
579
  format: "oxfmt --config .oxfmtrc.json .",
519
580
  lint: "oxlint --config .oxlintrc.json .",
581
+ // A counter nothing has ever seen read its own planted finding has not been shown to measure.
582
+ prove: "geonosis-ratchet --prove",
520
583
  ratchet: "geonosis-ratchet",
584
+ "sync:graph": graphScript,
521
585
  sync: "geonosis sync",
522
586
  test: everyWorkspace(runtime, "test"),
523
587
  typecheck: everyWorkspace(runtime, "typecheck"),
@@ -799,6 +863,7 @@ var filesFor = (answers) => {
799
863
  )
800
864
  ),
801
865
  "skills-lock.json": json({ skills: {}, version: 1 }),
866
+ [HOOK_INSTALLER]: hookInstaller(),
802
867
  "lefthook.yml": [
803
868
  "# Staged scope only, so a commit never waits on a file it did not touch. When one fires, fix",
804
869
  "# or delete the code \u2014 never downgrade the rule to get past it.",
@@ -1010,8 +1075,9 @@ exec node "${join2(from, entry)}" "$@"
1010
1075
  )
1011
1076
  )
1012
1077
  );
1078
+ const rootDeclares = new Set(Object.keys(kitDependencies(answers)));
1013
1079
  for (const [name, from] of at) {
1014
- if (!owned.has(name)) {
1080
+ if (!owned.has(name) && rootDeclares.has(name)) {
1015
1081
  manifest.devDependencies = { ...manifest.devDependencies, [name]: `link:${from}` };
1016
1082
  }
1017
1083
  }
@@ -1042,22 +1108,17 @@ var finish = ({ answers, install }) => {
1042
1108
  }
1043
1109
  const ledger = join2(answers.dir, "node_modules/.bin/geonosis-ledger");
1044
1110
  if (existsSync2(ledger)) {
1045
- steps.push(
1046
- run("sync the edges table into turbo.json", answers.dir, ledger, [
1047
- "sync",
1048
- "--target",
1049
- "turbo",
1050
- "--write",
1051
- "turbo.json"
1052
- ]),
1053
- run("sync the edges table into .oxlintrc.json", answers.dir, ledger, [
1054
- "sync",
1055
- "--target",
1056
- "layer-walls",
1057
- "--write",
1058
- ".oxlintrc.json"
1059
- ])
1060
- );
1111
+ for (const { target, write: into } of GRAPH_SYNCS) {
1112
+ steps.push(
1113
+ run(`sync the edges table into ${into}`, answers.dir, ledger, [
1114
+ "sync",
1115
+ "--target",
1116
+ target,
1117
+ "--write",
1118
+ into
1119
+ ])
1120
+ );
1121
+ }
1061
1122
  }
1062
1123
  const oxfmt = join2(answers.dir, "node_modules/.bin/oxfmt");
1063
1124
  if (existsSync2(oxfmt)) {
@@ -1078,6 +1139,7 @@ export {
1078
1139
  RUNTIMES,
1079
1140
  BACKENDS,
1080
1141
  UIS,
1142
+ MEDUSA_RANGE,
1081
1143
  parseAnswers,
1082
1144
  wantsInstall,
1083
1145
  CORPUS_DIR,
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  DOMAIN_NAMES,
3
+ MEDUSA_RANGE,
3
4
  PLATFORM_FILE,
4
5
  checkScaffold,
5
6
  describeDrift,
@@ -7,11 +8,12 @@ import {
7
8
  parseAnswers,
8
9
  wantsInstall,
9
10
  writeScaffold
10
- } from "./chunk-PRX7MKFZ.js";
11
+ } from "./chunk-IQS75GD7.js";
11
12
 
12
13
  // src/create-geonosis-cli.ts
13
14
  import { existsSync } from "fs";
14
15
  var USAGE = `create-geonosis <dir> --runtime pnpm|bun --backend medusa|sagaflow-cf|none --ui tiered-shadcn|atoms-only|none
16
+ [--medusa <range>]
15
17
  [--domains <a,b>] [--brand <name>] [--themekit <name>] [--marketplace <path>] [--kit <path>] [--no-install]
16
18
  [--check]
17
19
 
@@ -27,6 +29,11 @@ default borrowed from another repo would be that repo's stack hardcoded into thi
27
29
  --domains the domains this repo composes \u2014 ${DOMAIN_NAMES.join(", ")}. Each one writes its
28
30
  store into the app's ${PLATFORM_FILE}: the composition root, in two lifetimes, with
29
31
  the tenant session opened before any store is built. A name nothing ships is refused.
32
+ --medusa <range>
33
+ the Medusa a --backend medusa tree declares. Defaults to ${MEDUSA_RANGE}, the version
34
+ the one Medusa consumer of this kit runs (measured 2026-09-02): the Medusa rules
35
+ the scaffold turns on presume the engine, and a tree that enables them while
36
+ declaring no @medusajs/* earns nine doctor WARNs for rules with no finding.
30
37
  --kit <path> read the kit from a workspace instead of the registry. A proof aid: it symlinks the
31
38
  packages after the install and rewrites the manifest to say so.
32
39
  --no-install write the files and stop. The gates cannot run until the two "geonosis sync
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@ type Answers = {
13
13
  /** The kit read from a workspace instead of the registry — a proof aid, never the default. */
14
14
  kit?: string;
15
15
  marketplace?: string;
16
+ /** The Medusa range a `--backend medusa` tree declares. `MEDUSA_RANGE` unless one is named. */
17
+ medusa?: string;
16
18
  name: string;
17
19
  runtime: Runtime;
18
20
  scope: string;
@@ -129,7 +131,7 @@ declare const corpusFor: (answers: Answers, workspaces: Workspace[]) => Record<s
129
131
  declare const filesFor: (answers: Answers) => Record<string, string>;
130
132
  declare const presetsChosenBy: (answers: Answers) => string[];
131
133
 
132
- /** The kit packages a scaffolded repo declares, and therefore the ones `--kit` has to link. */
134
+ /** The kit packages a scaffolded repo RESOLVES, and therefore the ones `--kit` has to link. */
133
135
  declare const KIT_PACKAGES: string[];
134
136
  /**
135
137
  * Every file, and never over the top of anything. A scaffold that overwrote a tree is a scaffold
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  wantsInstall,
24
24
  workspacesOf,
25
25
  writeScaffold
26
- } from "./chunk-PRX7MKFZ.js";
26
+ } from "./chunk-IQS75GD7.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.0.0",
3
+ "version": "2.2.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.0.0"
37
+ "@geonosis/cli": "2.2.0"
38
38
  },
39
39
  "engines": {
40
40
  "node": ">=22"