@emeryld/manager 0.5.1 → 0.6.1

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
@@ -1,15 +1,52 @@
1
1
  # @emeryld/manager
2
2
 
3
- Dev dependency built for Codex agents: scaffold RRRoutes packages, read the generated structure, and ship changes without rebuilding boilerplate. Install it in a pnpm workspace and call `pnpm manager-cli` from the workspace root.
3
+ Dev dependency built for Codex agents: scan a pnpm workspace, scaffold RRRoutes packages, and ship releases without rebuilding boilerplate. Install it in a workspace and call `pnpm manager-cli` from the root to drive everything interactively or via arguments for headless automation.
4
4
 
5
- ## Quick start (agents)
5
+ ## Quick start
6
6
  - Install: `pnpm add -D @emeryld/manager`
7
7
  - Add a script: `"manager-cli": "manager-cli"` in the workspace `package.json`
8
- - Discover templates fast: `pnpm manager-cli templates` (alias `pnpm manager-cli create --list`)
9
- - Scaffold without prompts:
10
- `pnpm manager-cli create --variant rrr-server --dir packages/api --name @scope/api --contract @scope/contract --skip-install`
11
- - Prefer prompts: `pnpm manager-cli create` and follow the menu
12
- - After scaffolding, open the new package `README.md` for variant-specific scripts and usage
8
+ - Launch interactive manager: `pnpm manager-cli` (package picker action picker)
9
+ - List templates fast: `pnpm manager-cli templates` (alias `pnpm manager-cli create --list`)
10
+ - Headless scaffold (Codex/CI-ready): `pnpm manager-cli create --variant rrr-server --dir packages/api --name @scope/api --contract @scope/contract --skip-install`
11
+ - Headless publish: `pnpm manager-cli all --non-interactive --bump patch --tag next`
12
+
13
+ ## Running `manager-cli` interactively
14
+ - **Package selection**: scans for every `package.json` (ignores node_modules/dist). Menu entries include each package (color-coded), "All packages", and "Create package". Navigate with ↑/↓/j/k or digits to run instantly.
15
+ - **Action menu** for the selection:
16
+ - `update dependencies` → runs `pnpm -r update` (or filtered update), stages only dependency files, prompts for a commit message, commits, and pushes.
17
+ - `test` → `pnpm test` (filtered to the package when possible).
18
+ - `build` → `pnpm build` (filtered when a single package is selected).
19
+ - `publish` → ensures the working tree is committed, checks registry auth, prompts a version strategy, commits the bump, tags, publishes with pnpm, and pushes tags.
20
+ - `full` → update → test → build → publish in order.
21
+ - `back` → return to package selection. When a single package is chosen, its `package.json` scripts also appear as runnable entries.
22
+
23
+ ## Non-interactive release (Codex/CI)
24
+ - Syntax: `pnpm manager-cli <pkg|all> --non-interactive [publish flags]`
25
+ - Required: the selection (`<pkg>` or `all`) **and** one of `--bump <type>`, `--sync <version>`, or `--noop` (skip version change but still publish/tag).
26
+ - Flags:
27
+ - `--non-interactive`, `--ci`, `--yes`, `-y` → auto-confirm prompts.
28
+ - `--bump <patch|minor|major|prepatch|preminor|premajor|prerelease>` → bump versions (pre* keeps/previews prerelease ids).
29
+ - `--sync <version>` → set all selected packages to an exact version.
30
+ - `--tag <dist-tag>` → publish with a custom npm dist-tag (default inferred from prerelease suffix).
31
+ - `--dry-run` → pass through to `pnpm publish --dry-run`.
32
+ - `--provenance` → enable provenance on publish.
33
+ - `--noop` → skip version change but still tag/publish current versions.
34
+ - Behavior: commits any existing changes before running (prompting for a message), requires registry auth (`pnpm whoami`), and tags/pushes after publish.
35
+
36
+ ## Scaffolding packages
37
+ - Interactive: `pnpm manager-cli create` → prompts for template, path, package name, contract (for server/client), and client kind (for client/fullstack). Uses arrow keys/digits when the terminal supports raw mode.
38
+ - Headless (Codex/CI) flags:
39
+ - `--list`, `-l` → show available templates.
40
+ - `--describe`, `-d <variant>` → print scripts/files/notes for a template.
41
+ - `--variant`, `-v <id>` → pick a template without a prompt (ids below).
42
+ - `--dir`, `--path`, `-p <path>` → target directory.
43
+ - `--name`, `-n <pkg>` → package name (defaults to basename of `--dir`).
44
+ - `--contract <pkg>` → contract import for server/client templates.
45
+ - `--client-kind <vite-react|expo-react-native>` → choose client stack (client/fullstack).
46
+ - `--reset` → delete the target directory before scaffolding.
47
+ - `--skip-install` / `--skip-build` → skip post-create install/build.
48
+ - `--help`, `-h` → print help.
49
+ - After effects: ensures the target directory exists (warns if non-empty, or wipes it when `--reset`), writes shared tooling files (tsconfig, workspace helpers), scaffolds the template, runs `pnpm install`, then builds the new package and its workspace deps (fallbacks: full workspace build, then package-only build). Each scaffolded package includes its own README with variant-specific scripts.
13
50
 
14
51
  ## Templates at a glance
15
52
  | id | default dir | summary | key files |
@@ -23,20 +60,19 @@ Dev dependency built for Codex agents: scaffold RRRoutes packages, read the gene
23
60
 
24
61
  Use `pnpm manager-cli create --describe <variant>` to print the scripts, key files, and notes for any template before scaffolding.
25
62
 
26
- ## Create command reference
27
- - `pnpm manager-cli create --list` — show templates
28
- - `pnpm manager-cli create --describe rrr-server` see scripts/files/notes for one template
29
- - `pnpm manager-cli create --variant rrr-client --dir packages/web-client --name @scope/web-client` — scaffold directly (adds `--contract <id>` for server/client)
30
- - `--skip-install` / `--skip-build` bypass post-create steps when you want to install/build later
31
-
32
- ## Release helper (existing packages)
33
- - Run from the workspace root; the CLI discovers any workspace packages with a `package.json`.
34
- - `pnpm manager-cli` launches an interactive menu: pick packages, then run update → test → build → publish (or any single step).
35
- - Non-interactive publish: `pnpm manager-cli <pkg|all> --non-interactive --bump patch` (see CLI prompts for flags like `--sync` and `--tag`).
63
+ ## Agent-ready command crib
64
+ - Scaffold server without prompts:
65
+ `pnpm manager-cli create --variant rrr-server --dir packages/api --name @scope/api --contract @scope/contract --skip-install`
66
+ - Scaffold Expo client:
67
+ `pnpm manager-cli create --variant rrr-client --dir packages/mobile --name @scope/mobile --contract @scope/contract --client-kind expo-react-native`
68
+ - Publish a single package headlessly:
69
+ `pnpm manager-cli @scope/api --non-interactive --bump minor --tag next`
70
+ - Publish everything with a synced version:
71
+ `pnpm manager-cli all --non-interactive --sync 1.2.3 --provenance`
36
72
 
37
73
  ## Notes
38
- - Each helper script registers the bundled `ts-node/esm` loader with the correct path so the CLI works even when dependencies are hoisted.
39
- - The create flow runs `pnpm install` and `pnpm run build` when a build script exists; skip with `--skip-install`/`--skip-build` if you want to control timing.
74
+ - Helper scripts register the bundled `ts-node/esm` loader so the CLI works even when dependencies are hoisted.
75
+ - Install/build after scaffolding can be skipped when you need full control (`--skip-install` / `--skip-build`).
40
76
 
41
77
  ## Tests
42
78
  - `pnpm test` verifies the helper CLI loader registration.
@@ -7,7 +7,7 @@ import { colors, logGlobal } from '../utils/log.js';
7
7
  import { runHelperCli } from '../helper-cli.js';
8
8
  import { loadPackages } from '../packages.js';
9
9
  import { SCRIPT_DESCRIPTIONS, workspaceRoot, ensureWorkspaceToolingFiles, } from './shared.js';
10
- import { clientVariant } from './variants/client.js';
10
+ import { clientVariant, CLIENT_KIND_OPTIONS, DEFAULT_CLIENT_KIND, normalizeClientKind, } from './variants/client.js';
11
11
  import { contractVariant } from './variants/contract.js';
12
12
  import { dockerVariant } from './variants/docker.js';
13
13
  import { emptyVariant } from './variants/empty.js';
@@ -78,6 +78,32 @@ async function promptForContractName() {
78
78
  }
79
79
  return promptForContractNameWithHelper('Select a contract package (or skip)', contractOptions);
80
80
  }
81
+ async function promptForClientKind(existing) {
82
+ const defaultKind = normalizeClientKind(existing) ?? DEFAULT_CLIENT_KIND;
83
+ let selection;
84
+ const scripts = CLIENT_KIND_OPTIONS.map((opt) => ({
85
+ name: opt.label,
86
+ emoji: '💻',
87
+ description: opt.summary,
88
+ handler: () => {
89
+ selection = opt.id;
90
+ },
91
+ }));
92
+ scripts.push({
93
+ name: `Use default (${defaultKind})`,
94
+ emoji: '✅',
95
+ description: 'Keep the prior/default choice',
96
+ handler: () => {
97
+ selection = defaultKind;
98
+ },
99
+ });
100
+ await runHelperCli({
101
+ title: 'Select a client template',
102
+ scripts,
103
+ argv: [],
104
+ });
105
+ return selection ?? defaultKind;
106
+ }
81
107
  function resolveVariant(key) {
82
108
  if (!key)
83
109
  return undefined;
@@ -151,6 +177,10 @@ function parseCreateCliArgs(argv) {
151
177
  options.contractName = argv[++i];
152
178
  continue;
153
179
  }
180
+ if (arg === '--client-kind' || arg === '--client') {
181
+ options.clientKind = argv[++i];
182
+ continue;
183
+ }
154
184
  if (arg === '--skip-install') {
155
185
  options.skipInstall = true;
156
186
  continue;
@@ -190,6 +220,7 @@ function printCreateHelp() {
190
220
  console.log(' --dir, --path, -p Target directory (skips path prompt)');
191
221
  console.log(' --name, -n Package name (skips name prompt)');
192
222
  console.log(' --contract Contract import to inject (server/client variants)');
223
+ console.log(' --client-kind Client stack (vite-react | expo-react-native)');
193
224
  console.log(' --reset Remove the target directory if it already exists');
194
225
  console.log(' --skip-install Do not run pnpm install after scaffolding');
195
226
  console.log(' --skip-build Skip build after scaffolding');
@@ -431,11 +462,20 @@ async function gatherTarget(initial = {}) {
431
462
  contractName === undefined) {
432
463
  contractName = await promptForContractName();
433
464
  }
465
+ let clientKind = initial.clientKind;
466
+ if (variant.id === 'rrr-client' || variant.id === 'rrr-fullstack') {
467
+ const normalizedKind = normalizeClientKind(clientKind);
468
+ clientKind = normalizedKind ?? clientKind;
469
+ if (!clientKind) {
470
+ clientKind = await promptForClientKind();
471
+ }
472
+ }
434
473
  return {
435
474
  variant,
436
475
  targetDir,
437
476
  pkgName,
438
477
  contractName,
478
+ clientKind,
439
479
  reset: initial.reset,
440
480
  };
441
481
  }
@@ -448,6 +488,7 @@ export async function createRrrPackage(options = {}) {
448
488
  targetDir: target.targetDir,
449
489
  pkgName: target.pkgName,
450
490
  contractName: target.contractName ?? options.contractName,
491
+ clientKind: target.clientKind ?? options.clientKind,
451
492
  });
452
493
  await postCreateTasks(target.targetDir, {
453
494
  skipInstall: options.skipInstall,
@@ -486,6 +527,7 @@ export async function runCreatePackageCli(argv) {
486
527
  targetDir,
487
528
  pkgName: parsed.pkgName,
488
529
  contractName: parsed.contractName,
530
+ clientKind: normalizeClientKind(parsed.clientKind),
489
531
  reset: parsed.reset,
490
532
  skipInstall: parsed.skipInstall,
491
533
  skipBuild: parsed.skipBuild ?? parsed.skipInstall,