@wpmoo/odoo 0.8.52 → 0.8.53

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
@@ -30,14 +30,14 @@ files without touching product source code.
30
30
  - Node.js `>=20.17`
31
31
  - Git
32
32
  - Docker and Docker Compose for generated environment runtime commands
33
- - Optional: GitHub CLI (`gh`) for repository discovery, repository creation, and
34
- deeper diagnostics
33
+ - GitHub CLI (`gh`) is optional. Use it for repository discovery, repository
34
+ creation, and deeper diagnostics.
35
35
 
36
36
  The wizard currently offers Odoo `19.0`, `18.0`, `17.0`, and `16.0`. The copied
37
37
  Compose resource must include the matching `docker-compose_<version>.yml` file
38
38
  for the selected branch.
39
39
 
40
- Install GitHub CLI when you want WPMoo to discover your personal account and
40
+ Set up GitHub CLI only when you want WPMoo to discover your personal account and
41
41
  organizations or create missing repositories from the interactive wizard:
42
42
 
43
43
  ```bash
@@ -54,11 +54,18 @@ npx @wpmoo/odoo
54
54
  ```
55
55
 
56
56
  If the current directory is not already a WPMoo environment, the CLI opens the
57
- create flow. It asks for the product slug, Odoo version, dev environment repo,
58
- source repo URLs, optional extra source repos, project-local Agent Skills, and
59
- empty repository initialization behavior.
57
+ create flow. It asks for the product slug, Odoo version, and environment folder.
58
+ Choose any environment folder; the default is `./<product>_dev`.
60
59
 
61
- For non-interactive usage:
60
+ After folder selection, connect Git/GitHub to use repository URLs. Choose
61
+ local-only setup to skip Git/GitHub connection and source repo prompts. Add
62
+ source repositories later from the cockpit (`Repositories` -> `add-repo`) or
63
+ `npx @wpmoo/odoo add-repo`.
64
+
65
+ For non-interactive usage with repository URLs:
66
+
67
+ Direct `create` commands keep the existing repo URL options; use
68
+ `--target <path>` to choose a custom folder.
62
69
 
63
70
  ```bash
64
71
  npx @wpmoo/odoo create \
@@ -183,7 +190,8 @@ not search parent directories or run arbitrary script names.
183
190
  ## Generated Environment Layout
184
191
 
185
192
  A generated environment is a separate Git repository, usually named
186
- `<product>_dev`. Product source code stays in child source repositories.
193
+ `<product>_dev`, but the wizard and `--target` can use any folder. Product
194
+ source code stays in child source repositories.
187
195
 
188
196
  ```text
189
197
  odoo_sample_module_dev/
@@ -244,7 +252,8 @@ Compose commands.
244
252
 
245
253
  ## Repository and Module Management
246
254
 
247
- Add a source repository from the cockpit or direct command:
255
+ Add a source repository after local-only setup from the cockpit or direct
256
+ command:
248
257
 
249
258
  ```bash
250
259
  npx @wpmoo/odoo add-repo \
@@ -252,7 +261,8 @@ npx @wpmoo/odoo add-repo \
252
261
  --init-empty-repos
253
262
  ```
254
263
 
255
- When GitHub CLI is available and authenticated, the interactive flow can:
264
+ GitHub CLI is optional for repository setup. When it is available and
265
+ authenticated, the interactive flow can:
256
266
 
257
267
  - detect the owner or organization from the current environment;
258
268
  - suggest repository URLs;
package/dist/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { confirm, intro, isCancel, note, outro, select, text } from '@clack/prompts';
3
3
  import { realpathSync } from 'node:fs';
4
- import { resolve } from 'node:path';
4
+ import { basename, resolve } from 'node:path';
5
5
  import { fileURLToPath, pathToFileURL } from 'node:url';
6
- import { commandFromArgs, defaultTargetForProduct, isHelpRequested, isVersionRequested, optionsFromArgs, parseArgs, stripInternalFlags, } from './args.js';
6
+ import { commandFromArgs, isHelpRequested, isVersionRequested, optionsFromArgs, parseArgs, stripInternalFlags, } from './args.js';
7
7
  import { selectCockpitCommandFromPalette } from './cockpit/command-palette.js';
8
8
  import { collectDailyActionArgs } from './cockpit/daily-prompts.js';
9
9
  import { selectCockpitCategoryCommand, selectCockpitTopLevelMenu } from './cockpit/menu.js';
@@ -153,9 +153,27 @@ async function optionsFromPrompts(showIntro = true, cancelAction = 'exit') {
153
153
  placeholder: 'odoo_sample_module',
154
154
  validate: (value) => (value.trim() ? undefined : 'Enter a product/module slug.'),
155
155
  }), 'odoo_sample_module', cancelAction);
156
- const target = defaultTargetForProduct(product);
157
- note(renderRepositorySetupNote(product), 'Repository setup');
158
- const selectedGitHubOwner = await selectDefaultGitHubOwner(cancelAction);
156
+ const defaultTarget = `./${product}_dev`;
157
+ const target = resolve(asString(await text({
158
+ message: 'Environment folder',
159
+ placeholder: defaultTarget,
160
+ defaultValue: defaultTarget,
161
+ initialValue: defaultTarget,
162
+ }), defaultTarget, cancelAction));
163
+ const connectGitHub = await select({
164
+ message: 'Connect this environment to Git/GitHub now?',
165
+ options: [
166
+ { value: true, label: 'Yes, connect Git/GitHub repositories' },
167
+ { value: false, label: 'No, scaffold local-only' },
168
+ ],
169
+ initialValue: true,
170
+ });
171
+ handleCancel(connectGitHub, cancelAction);
172
+ let selectedGitHubOwner;
173
+ if (connectGitHub) {
174
+ note(renderRepositorySetupNote(product), 'Repository setup');
175
+ selectedGitHubOwner = await selectDefaultGitHubOwner(cancelAction);
176
+ }
159
177
  const selectedVersion = await select({
160
178
  message: menuPromptMessage('Odoo version', cancelAction),
161
179
  options: supportedOdooVersions.map((version) => ({ value: version, label: version })),
@@ -163,6 +181,37 @@ async function optionsFromPrompts(showIntro = true, cancelAction = 'exit') {
163
181
  });
164
182
  handleCancel(selectedVersion, cancelAction);
165
183
  const odooVersion = String(selectedVersion);
184
+ async function promptInstallAgentSkills() {
185
+ const installAgentSkills = await select({
186
+ message: 'Install project-local Odoo Agent Skills?',
187
+ options: [
188
+ { value: true, label: 'Yes, install latest default skills' },
189
+ { value: false, label: 'No' },
190
+ ],
191
+ initialValue: false,
192
+ });
193
+ handleCancel(installAgentSkills, cancelAction);
194
+ return Boolean(installAgentSkills);
195
+ }
196
+ if (!connectGitHub) {
197
+ const installAgentSkills = await promptInstallAgentSkills();
198
+ return {
199
+ product,
200
+ odooVersion,
201
+ engine: 'compose',
202
+ devRepo: basename(target),
203
+ devRepoUrl: target,
204
+ sourceRepos: [],
205
+ target,
206
+ dryRun: false,
207
+ initEmptyRepos: false,
208
+ stage: false,
209
+ agentSkillsTemplateUrl: installAgentSkills ? defaultAgentSkillsTemplateUrl : undefined,
210
+ createMissingRepos: false,
211
+ repoVisibility: 'private',
212
+ skipSubmodules: true,
213
+ };
214
+ }
166
215
  const detectedDevRepoUrl = await getOriginUrl(realGit, target);
167
216
  const defaultDevRepoUrl = selectedGitHubOwner
168
217
  ? githubRepositoryUrl(selectedGitHubOwner, `${product}_dev`)
@@ -204,15 +253,7 @@ async function optionsFromPrompts(showIntro = true, cancelAction = 'exit') {
204
253
  handleCancel(shouldAddAnother, cancelAction);
205
254
  addAnother = Boolean(shouldAddAnother);
206
255
  }
207
- const installAgentSkills = await select({
208
- message: 'Install project-local Odoo Agent Skills?',
209
- options: [
210
- { value: true, label: 'Yes, install latest default skills' },
211
- { value: false, label: 'No' },
212
- ],
213
- initialValue: false,
214
- });
215
- handleCancel(installAgentSkills, cancelAction);
256
+ const installAgentSkills = await promptInstallAgentSkills();
216
257
  const initEmpty = await select({
217
258
  message: 'Initialize repositories that exist but have no commits?',
218
259
  options: [
@@ -477,6 +518,9 @@ async function ensureGitHubRepositories(options, interactive) {
477
518
  if (options.dryRun) {
478
519
  return;
479
520
  }
521
+ if (options.skipSubmodules) {
522
+ return;
523
+ }
480
524
  if (!interactive && !options.createMissingRepos) {
481
525
  return;
482
526
  }
package/dist/help.js CHANGED
@@ -5,7 +5,7 @@ WPMoo Odoo lifecycle tooling.
5
5
 
6
6
  Usage:
7
7
  npx @wpmoo/odoo
8
- npx @wpmoo/odoo create --product <slug> --dev-repo-url <url> --source-repo-url <url>
8
+ npx @wpmoo/odoo create --product <slug> [--target <path>] --dev-repo-url <url> --source-repo-url <url>
9
9
  npx @wpmoo/odoo status
10
10
  npx @wpmoo/odoo add-repo --repo-url <url>
11
11
  npx @wpmoo/odoo remove-repo --repo <name>
@@ -31,7 +31,7 @@ Usage:
31
31
  Options:
32
32
  --product <slug> Product slug, for example my_odoo_module.
33
33
  --odoo-version <branch> Odoo branch to pin submodules to. Default: 19.0.
34
- --dev-repo-url <url> Development environment repository URL for docs.
34
+ --dev-repo-url <url> Optional development environment repository URL for docs.
35
35
  --target <path> Target dev repo directory. Default: ./<product>_dev.
36
36
  --engine <value> Environment engine: compose. Default: compose.
37
37
  --compose-template-url <url> Standalone compose resource source. Default: gh:wpmoo-org/odoo-docker-compose.
@@ -73,13 +73,22 @@ Cockpit:
73
73
  diagnostics, repositories, and maintenance categories.
74
74
  Direct commands such as npx @wpmoo/odoo status and npx @wpmoo/odoo test remain available.
75
75
 
76
+ Wizard local-only path:
77
+ Run npx @wpmoo/odoo from a workspace directory to open the create wizard.
78
+ Choose any environment folder; the default is ./<product>_dev.
79
+ Skip Git/GitHub connection to create a local-only environment.
80
+ Add source repos later from the cockpit or with add-repo.
81
+
76
82
  Status and doctor:
77
83
  status: fast and offline. Reads local environment metadata and files only.
78
84
  doctor: deeper health check. May check Docker CLI access and GitHub workflows.
79
85
 
80
86
  Task recipes:
81
87
  Create environment:
88
+ npx @wpmoo/odoo
82
89
  npx @wpmoo/odoo create --product <slug> --dev-repo-url <url> --source-repo-url <url>
90
+ Create local-only environment:
91
+ npx @wpmoo/odoo
83
92
  Add source repo:
84
93
  npx @wpmoo/odoo add-repo --repo-url <url>
85
94
  Add module:
@@ -100,6 +109,7 @@ Example:
100
109
  npx @wpmoo/odoo create \\
101
110
  --product odoo_sample_module \\
102
111
  --odoo-version 19.0 \\
112
+ --target ./custom_odoo_dev \\
103
113
  --dev-repo-url https://github.com/example-org/odoo_sample_module_dev.git \\
104
114
  --source-repo-url https://github.com/example-org/odoo_sample_module.git
105
115
 
package/dist/templates.js CHANGED
@@ -17,7 +17,13 @@ function yamlList(items) {
17
17
  function allAddons(options) {
18
18
  return options.sourceRepos.flatMap((repo) => repo.addons);
19
19
  }
20
+ function hasSourceRepos(options) {
21
+ return options.sourceRepos.length > 0;
22
+ }
20
23
  function repositoryLayout(options) {
24
+ const sourceRepoRows = hasSourceRepos(options)
25
+ ? options.sourceRepos.map((repo) => `│ ├── ${repo.path}/`).join('\n')
26
+ : '│ └── README.md';
21
27
  return `${options.devRepo}/
22
28
  ├── docker-compose_17.0.yml
23
29
  ├── docker-compose_18.0.yml
@@ -29,12 +35,17 @@ function repositoryLayout(options) {
29
35
  │ └── custom/
30
36
  │ └── src/
31
37
  │ └── private/
32
- ${options.sourceRepos.map((repo) => `│ ├── ${repo.path}/`).join('\n')}
38
+ ${sourceRepoRows}
33
39
  ├── docs/
34
40
  ├── README.md
35
41
  └── AGENTS.md`;
36
42
  }
37
43
  function sourceRepoDocs(options) {
44
+ if (!hasSourceRepos(options)) {
45
+ return `This environment was scaffolded without source repository submodules.
46
+ Add source repositories later from the cockpit or with \`npx @wpmoo/odoo add-repo\`.
47
+ They will be added under \`odoo/custom/src/private\`.`;
48
+ }
38
49
  return options.sourceRepos
39
50
  .map((repo) => `### ${repo.path}
40
51
 
@@ -58,6 +69,35 @@ ${repo.addons.map((addon) => `├── ${addon}/`).join('\n')}
58
69
  \`\`\``)
59
70
  .join('\n\n');
60
71
  }
72
+ function cloneDocs(options) {
73
+ if (!hasSourceRepos(options)) {
74
+ return `## Local Folder
75
+
76
+ This environment is ready in this folder:
77
+
78
+ \`\`\`bash
79
+ cd ${options.devRepo}
80
+ \`\`\`
81
+
82
+ If you later connect it to Git, commit the generated files after reviewing them.
83
+ `;
84
+ }
85
+ return `## Clone
86
+
87
+ Clone with submodules:
88
+
89
+ \`\`\`bash
90
+ git clone --recurse-submodules ${options.devRepoUrl}
91
+ cd ${options.devRepo}
92
+ \`\`\`
93
+
94
+ If already cloned:
95
+
96
+ \`\`\`bash
97
+ git submodule update --init --recursive
98
+ \`\`\`
99
+ `;
100
+ }
61
101
  function optionalAgentSkillsReadme(options) {
62
102
  if (!options.agentSkillsTemplateUrl)
63
103
  return '';
@@ -118,9 +158,9 @@ docker-compose_19.0.yml
118
158
  If copied from the standalone resource, additional compose documentation is kept
119
159
  in \`docs/compose.md\`.
120
160
 
121
- Source repositories stay under \`odoo/custom/src/private\`. At container startup,
122
- \`entrypoint.sh\` scans those repositories for addons and exposes them through
123
- \`/mnt/wpmoo-addons\`.
161
+ Source repositories stay under \`odoo/custom/src/private\` when configured. At
162
+ container startup, \`entrypoint.sh\` scans those repositories for addons and
163
+ exposes them through \`/mnt/wpmoo-addons\`.
124
164
 
125
165
  ## Daily Command Hub (\`./moo\`)
126
166
 
@@ -487,8 +527,9 @@ export function renderReadme(options) {
487
527
 
488
528
  Private ${environmentKind()} development environment for the ${title} product.
489
529
 
490
- This repository owns the development environment only. Product source code lives
491
- in source repository submodules under \`odoo/custom/src/private\`.
530
+ This folder owns the development environment only. Product source code lives
531
+ in source repository submodules under \`odoo/custom/src/private\` when source
532
+ repositories are connected.
492
533
 
493
534
  ## Repository Layout
494
535
 
@@ -496,20 +537,7 @@ in source repository submodules under \`odoo/custom/src/private\`.
496
537
  ${repositoryLayout(options)}
497
538
  \`\`\`
498
539
 
499
- ## Clone
500
-
501
- Clone with submodules:
502
-
503
- \`\`\`bash
504
- git clone --recurse-submodules ${options.devRepoUrl}
505
- cd ${options.devRepo}
506
- \`\`\`
507
-
508
- If already cloned:
509
-
510
- \`\`\`bash
511
- git submodule update --init --recursive
512
- \`\`\`
540
+ ${cloneDocs(options)}
513
541
 
514
542
  ## WPMoo CLI Shortcut
515
543
 
@@ -535,23 +563,34 @@ ${sourceRepoDocs(options)}
535
563
  ${environmentUsageDocs(options)}
536
564
  ## Branching
537
565
 
538
- Use Odoo major-version branches in source repositories:
566
+ Use Odoo major-version branches in source repositories when you add them:
539
567
 
540
568
  \`\`\`text
541
569
  ${options.odooVersion}
542
570
  \`\`\`
543
571
 
544
- This dev repository can stay on \`main\` and pin exact source commits through
545
- submodule references.
572
+ If this environment is connected to Git, the dev repository can stay on \`main\`
573
+ and pin exact source commits through submodule references.
546
574
  `;
547
575
  }
548
576
  export function renderAgents(options) {
549
- const repoList = options.sourceRepos
550
- .map((repo) => `- \`${repo.path}\`: \`${repo.url}\``)
551
- .join('\n');
552
- const addonList = options.sourceRepos
553
- .map((repo) => `\`${repo.path}\` addons:\n${repo.addons.map((addon) => `- \`${addon}\``).join('\n')}`)
554
- .join('\n\n');
577
+ const repoList = hasSourceRepos(options)
578
+ ? options.sourceRepos.map((repo) => `- \`${repo.path}\`: \`${repo.url}\``).join('\n')
579
+ : '- No source repositories are configured yet.';
580
+ const sourceLayout = hasSourceRepos(options)
581
+ ? `Product repositories are Git submodules:
582
+
583
+ \`\`\`text
584
+ ${options.sourceRepos.map((repo) => `odoo/custom/src/private/${repo.path}`).join('\n')}
585
+ \`\`\`
586
+
587
+ ${repoDuplicationNote()}`
588
+ : 'No source repositories are configured yet. Use `./moo add-repo` or the cockpit Repositories menu before module-specific work.';
589
+ const addonList = hasSourceRepos(options)
590
+ ? options.sourceRepos
591
+ .map((repo) => `\`${repo.path}\` addons:\n${repo.addons.map((addon) => `- \`${addon}\``).join('\n')}`)
592
+ .join('\n\n')
593
+ : 'No addon boundaries are known yet. Add source repositories before module-specific implementation.';
555
594
  return `# AGENTS.md
556
595
 
557
596
  ## Project
@@ -565,13 +604,7 @@ ${repoList}
565
604
 
566
605
  ## Source Layout
567
606
 
568
- Product repositories are Git submodules:
569
-
570
- \`\`\`text
571
- ${options.sourceRepos.map((repo) => `odoo/custom/src/private/${repo.path}`).join('\n')}
572
- \`\`\`
573
-
574
- ${repoDuplicationNote()}
607
+ ${sourceLayout}
575
608
  ${optionalAgentSkillsAgentsSection(options)}
576
609
  ## Addon Boundaries
577
610
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wpmoo/odoo",
3
- "version": "0.8.52",
3
+ "version": "0.8.53",
4
4
  "description": "WPMoo Odoo lifecycle tooling for development, staging, and production workflows.",
5
5
  "type": "module",
6
6
  "repository": {