xgic-payload-cms-cli 0.2.0__tar.gz → 0.2.1__tar.gz

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.
Files changed (22) hide show
  1. xgic_payload_cms_cli-0.2.1/PKG-INFO +222 -0
  2. xgic_payload_cms_cli-0.2.1/README.md +187 -0
  3. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/pyproject.toml +1 -1
  4. xgic_payload_cms_cli-0.2.1/src/xgic/cli/payload/commands/dev.py +137 -0
  5. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/commands/payload_env.py +2 -2
  6. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/config.py +15 -4
  7. xgic_payload_cms_cli-0.2.1/src/xgic/cli/payload/layout.py +90 -0
  8. xgic_payload_cms_cli-0.2.1/src/xgic/cli/payload/project.py +441 -0
  9. xgic_payload_cms_cli-0.2.0/PKG-INFO +0 -113
  10. xgic_payload_cms_cli-0.2.0/README.md +0 -78
  11. xgic_payload_cms_cli-0.2.0/src/xgic/cli/payload/commands/dev.py +0 -87
  12. xgic_payload_cms_cli-0.2.0/src/xgic/cli/payload/project.py +0 -212
  13. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/.gitignore +0 -0
  14. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/LICENSE +0 -0
  15. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/NOTICE +0 -0
  16. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/__init__.py +0 -0
  17. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/commands/__init__.py +0 -0
  18. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/commands/reset.py +0 -0
  19. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/commands/schema.py +0 -0
  20. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/commands/setup.py +0 -0
  21. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/env_helpers.py +0 -0
  22. {xgic_payload_cms_cli-0.2.0 → xgic_payload_cms_cli-0.2.1}/src/xgic/cli/payload/plugin.py +0 -0
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.5
2
+ Name: xgic-payload-cms-cli
3
+ Version: 0.2.1
4
+ Summary: XGIC CLI Payload CMS module - product commands and helpers (xgic.cli.payload).
5
+ Project-URL: Homepage, https://github.com/xgic/payload-cms-cli
6
+ Project-URL: Repository, https://github.com/xgic/payload-cms-cli
7
+ Project-URL: Issues, https://github.com/xgic/payload-cms-cli/issues
8
+ Project-URL: Documentation, https://github.com/xgic/payload-cms-cli#readme
9
+ Project-URL: Changelog, https://github.com/xgic/payload-cms-cli/releases
10
+ Author: XGIC
11
+ License: Apache-2.0
12
+ License-File: LICENSE
13
+ License-File: NOTICE
14
+ Keywords: cli,orchestration,payload-cms,xgic
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Environment :: Console
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: Apache Software License
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.14
25
+ Requires-Dist: rich>=13.7
26
+ Requires-Dist: xgic-cli>=0.2.0
27
+ Requires-Dist: xgic-dev-cli>=0.2.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
32
+ Provides-Extra: test
33
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # XGIC Payload CMS CLI
37
+
38
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
39
+ [![PyPI](https://img.shields.io/pypi/v/xgic-payload-cms-cli.svg)](https://pypi.org/project/xgic-payload-cms-cli/)
40
+ [![Python](https://img.shields.io/pypi/pyversions/xgic-payload-cms-cli.svg)](https://pypi.org/project/xgic-payload-cms-cli/)
41
+ [![CI](https://github.com/xgic/payload-cms-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/xgic/payload-cms-cli/actions/workflows/ci.yml)
42
+ [![Release](https://img.shields.io/github/v/release/xgic/payload-cms-cli)](https://github.com/xgic/payload-cms-cli/releases)
43
+ [![Producer](https://img.shields.io/github/v/release/xgic/payload-cms-dev?label=payload-cms-dev)](https://github.com/xgic/payload-cms-dev/releases)
44
+
45
+ **Payload CMS product commands for the modular [XGIC CLI](https://github.com/xgic/cli).**
46
+
47
+ Namespace: **`xgic.cli.payload`** · Console group: **`xgic payload …`** · Brand: **XGIC CLI only** ([ADR-0005](https://github.com/xgic/ai/blob/main/docs/adr/0005-modular-xgic-cli-and-retirement-of-xde.md))
48
+
49
+ Standards hub: [xgic/ai](https://github.com/xgic/ai)
50
+
51
+ ---
52
+
53
+ ## Vision
54
+
55
+ Payload application teams—and the AI agents that help them—need a **small, stable command surface** for project ensure, environment status, smart dev start, and safe reset. This module owns that **product** surface. Generic Compose lifecycle stays in [dev-cli](https://github.com/xgic/dev-cli); the Dev Container **image** is built in [payload-cms-dev](https://github.com/xgic/payload-cms-dev); applications start from [payload-cms](https://github.com/xgic/payload-cms).
56
+
57
+ One brand (`xgic`), clear ownership, and dry-run-friendly destructive paths.
58
+
59
+ ---
60
+
61
+ ## Why this module exists
62
+
63
+ | Benefit | Detail |
64
+ |---------|--------|
65
+ | **Domain clarity** | Nested under `xgic payload`—no clash with generic `xgic up` / `down` |
66
+ | **AI + human parity** | Same commands in READMEs and [AGENTS.md](AGENTS.md) |
67
+ | **Safe operations** | Reset and regenerate paths support explicit confirmation / dry-run patterns |
68
+ | **Composable stack** | Depends on `xgic-cli` + `xgic-dev-cli`; ships on PyPI for image and host installs |
69
+ | **Open-source rigor** | Apache-2.0, Python 3.14+, RC → TestPyPI → PyPI |
70
+
71
+ ---
72
+
73
+ ## Ecosystem
74
+
75
+ | Package / repo | Role |
76
+ |----------------|------|
77
+ | [xgic/cli](https://github.com/xgic/cli) | Thin core framework (`xgic`) |
78
+ | [xgic/dev-cli](https://github.com/xgic/dev-cli) | Dev Container / Docker Compose lifecycle |
79
+ | **This repo** | Payload CMS product module (`xgic.cli.payload`) |
80
+ | [xgic/payload-cms-dev](https://github.com/xgic/payload-cms-dev) | Dev Container **image producer** (`ghcr.io/xgic/payload-cms-dev`) |
81
+ | [xgic/payload-cms](https://github.com/xgic/payload-cms) | End-user **template** (recommended app start) |
82
+
83
+ ---
84
+
85
+ ## Quick start
86
+
87
+ ### Install (PyPI)
88
+
89
+ ```bash
90
+ uv pip install \
91
+ "xgic-cli>=0.2.0,<0.3" \
92
+ "xgic-dev-cli>=0.2.0,<0.3" \
93
+ "xgic-payload-cms-cli>=0.2.1,<0.3"
94
+ xgic payload --help
95
+ ```
96
+
97
+ ### Development (editable)
98
+
99
+ ```bash
100
+ uv pip install -e ../cli
101
+ uv pip install -e ../dev-cli
102
+ uv pip install -e ".[dev]"
103
+ xgic payload --help
104
+ ```
105
+
106
+ ### Typical Payload session (inside a Dev Container)
107
+
108
+ ```bash
109
+ xgic check
110
+ xgic payload env --regenerate --yes # once
111
+ xgic payload setup # scaffold app (layout from config)
112
+ xgic up --profile postgres # DB if needed
113
+ xgic payload dev
114
+ ```
115
+
116
+ Prefer the end-user template for application work: [payload-cms](https://github.com/xgic/payload-cms).
117
+
118
+ ---
119
+
120
+ ## Console commands
121
+
122
+ All product commands nest under **`xgic payload`**:
123
+
124
+ | Command | Purpose |
125
+ |---------|---------|
126
+ | `xgic payload dev` | **Primary daily command** — smart start (up if needed, DB check, `pnpm dev`) |
127
+ | `xgic payload setup [--quiet]` | Ensure Payload project directory (idempotent) |
128
+ | `xgic payload env [--json]` | Product env status (project name, `.env`, services) |
129
+ | `xgic payload env --regenerate --yes` | Fresh credentials in `.devcontainer/.env` |
130
+ | `xgic payload schema` | Run template schema generator when present |
131
+ | `xgic payload reset` | Fast targeted reset (project folder + active DB volume) |
132
+
133
+ **Generic lifecycle** (`xgic up` / `down` / `check` / `env`) lives in **dev-cli**. Use **`xgic payload env`** for Payload credentials and product status.
134
+
135
+ ### Setup: automatic vs manual
136
+
137
+ | Mode | Guidance |
138
+ |------|----------|
139
+ | **Automatic** | Producer/image `postStart` may call `xgic payload setup` via a thin shell wrapper (idempotent). |
140
+ | **Manual / testing** | After `xgic payload reset --yes`, or when validating scaffold config—not a “daily” app ritual. |
141
+
142
+ Always prefer **`xgic payload reset --dry-run`** before destructive reset.
143
+
144
+ ### Historical command map (`xde` → XGIC CLI)
145
+
146
+ Living brand is **XGIC CLI only**. Historical map for agents migrating old notes:
147
+
148
+ | Historical (`xde`) | XGIC CLI |
149
+ |--------------------|----------|
150
+ | `xde dev` | `xgic payload dev` |
151
+ | `xde setup payloadcms` | `xgic payload setup` |
152
+ | `xde schema` | `xgic payload schema` |
153
+ | `xde env --regenerate` | `xgic payload env --regenerate --yes` |
154
+ | `xde reset` | `xgic payload reset` |
155
+ | `xde up` / `down` / … | `xgic up` / `down` / … (dev-cli) |
156
+
157
+ ---
158
+
159
+ ## Library API
160
+
161
+ ```python
162
+ from xgic.cli.payload import (
163
+ ensure_payload_project,
164
+ generate_fresh_env_content,
165
+ make_payload_docker_controller,
166
+ get_payload_project_name,
167
+ )
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Requirements
173
+
174
+ - Python **3.14+**
175
+ - `xgic-cli` ≥ 0.2.0
176
+ - `xgic-dev-cli` ≥ 0.2.0
177
+
178
+ ---
179
+
180
+ ## Publishing
181
+
182
+ Follow [python-package-release.md](https://github.com/xgic/ai/blob/main/docs/python-package-release.md).
183
+
184
+ Publish **after** `xgic-cli` and `xgic-dev-cli` for stack releases. Tags: `vX.Y.ZrcN` → TestPyPI; `vX.Y.Z` → PyPI.
185
+
186
+ ---
187
+
188
+ ## Working with AI assistants
189
+
190
+ High-signal prompts:
191
+
192
+ - “Run `xgic payload env` (no secrets) and recommend whether to start Postgres.”
193
+ - “Start with `xgic payload dev` and report the listen URL.”
194
+ - “Show `xgic payload reset --dry-run` before any reset.”
195
+
196
+ Ownership:
197
+
198
+ | Change | Repository |
199
+ |--------|------------|
200
+ | `xgic payload …` behavior | **This repo** |
201
+ | `xgic up` / `down` / `check` | [dev-cli](https://github.com/xgic/dev-cli) |
202
+ | Image / Dockerfile | [payload-cms-dev](https://github.com/xgic/payload-cms-dev) |
203
+ | App template pin / docs | [payload-cms](https://github.com/xgic/payload-cms) |
204
+
205
+ Public-safe gate: [BASE-STANDARDS](https://github.com/xgic/ai/blob/main/docs/BASE-STANDARDS-FOR-ORCHESTRATED-REPOS.md).
206
+
207
+ ---
208
+
209
+ ## Contributing
210
+
211
+ PRs with human UI review only. Conventional Commits; labels required. See [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md).
212
+
213
+ ---
214
+
215
+ ## License
216
+
217
+ Apache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
218
+ Copyright form: `Copyright 2026 XGIC`.
219
+
220
+ ---
221
+
222
+ **XGIC** — Modular CLI for open-source platforms: thin core, domain modules, and AI-operable Payload workflows.
@@ -0,0 +1,187 @@
1
+ # XGIC Payload CMS CLI
2
+
3
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
4
+ [![PyPI](https://img.shields.io/pypi/v/xgic-payload-cms-cli.svg)](https://pypi.org/project/xgic-payload-cms-cli/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/xgic-payload-cms-cli.svg)](https://pypi.org/project/xgic-payload-cms-cli/)
6
+ [![CI](https://github.com/xgic/payload-cms-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/xgic/payload-cms-cli/actions/workflows/ci.yml)
7
+ [![Release](https://img.shields.io/github/v/release/xgic/payload-cms-cli)](https://github.com/xgic/payload-cms-cli/releases)
8
+ [![Producer](https://img.shields.io/github/v/release/xgic/payload-cms-dev?label=payload-cms-dev)](https://github.com/xgic/payload-cms-dev/releases)
9
+
10
+ **Payload CMS product commands for the modular [XGIC CLI](https://github.com/xgic/cli).**
11
+
12
+ Namespace: **`xgic.cli.payload`** · Console group: **`xgic payload …`** · Brand: **XGIC CLI only** ([ADR-0005](https://github.com/xgic/ai/blob/main/docs/adr/0005-modular-xgic-cli-and-retirement-of-xde.md))
13
+
14
+ Standards hub: [xgic/ai](https://github.com/xgic/ai)
15
+
16
+ ---
17
+
18
+ ## Vision
19
+
20
+ Payload application teams—and the AI agents that help them—need a **small, stable command surface** for project ensure, environment status, smart dev start, and safe reset. This module owns that **product** surface. Generic Compose lifecycle stays in [dev-cli](https://github.com/xgic/dev-cli); the Dev Container **image** is built in [payload-cms-dev](https://github.com/xgic/payload-cms-dev); applications start from [payload-cms](https://github.com/xgic/payload-cms).
21
+
22
+ One brand (`xgic`), clear ownership, and dry-run-friendly destructive paths.
23
+
24
+ ---
25
+
26
+ ## Why this module exists
27
+
28
+ | Benefit | Detail |
29
+ |---------|--------|
30
+ | **Domain clarity** | Nested under `xgic payload`—no clash with generic `xgic up` / `down` |
31
+ | **AI + human parity** | Same commands in READMEs and [AGENTS.md](AGENTS.md) |
32
+ | **Safe operations** | Reset and regenerate paths support explicit confirmation / dry-run patterns |
33
+ | **Composable stack** | Depends on `xgic-cli` + `xgic-dev-cli`; ships on PyPI for image and host installs |
34
+ | **Open-source rigor** | Apache-2.0, Python 3.14+, RC → TestPyPI → PyPI |
35
+
36
+ ---
37
+
38
+ ## Ecosystem
39
+
40
+ | Package / repo | Role |
41
+ |----------------|------|
42
+ | [xgic/cli](https://github.com/xgic/cli) | Thin core framework (`xgic`) |
43
+ | [xgic/dev-cli](https://github.com/xgic/dev-cli) | Dev Container / Docker Compose lifecycle |
44
+ | **This repo** | Payload CMS product module (`xgic.cli.payload`) |
45
+ | [xgic/payload-cms-dev](https://github.com/xgic/payload-cms-dev) | Dev Container **image producer** (`ghcr.io/xgic/payload-cms-dev`) |
46
+ | [xgic/payload-cms](https://github.com/xgic/payload-cms) | End-user **template** (recommended app start) |
47
+
48
+ ---
49
+
50
+ ## Quick start
51
+
52
+ ### Install (PyPI)
53
+
54
+ ```bash
55
+ uv pip install \
56
+ "xgic-cli>=0.2.0,<0.3" \
57
+ "xgic-dev-cli>=0.2.0,<0.3" \
58
+ "xgic-payload-cms-cli>=0.2.1,<0.3"
59
+ xgic payload --help
60
+ ```
61
+
62
+ ### Development (editable)
63
+
64
+ ```bash
65
+ uv pip install -e ../cli
66
+ uv pip install -e ../dev-cli
67
+ uv pip install -e ".[dev]"
68
+ xgic payload --help
69
+ ```
70
+
71
+ ### Typical Payload session (inside a Dev Container)
72
+
73
+ ```bash
74
+ xgic check
75
+ xgic payload env --regenerate --yes # once
76
+ xgic payload setup # scaffold app (layout from config)
77
+ xgic up --profile postgres # DB if needed
78
+ xgic payload dev
79
+ ```
80
+
81
+ Prefer the end-user template for application work: [payload-cms](https://github.com/xgic/payload-cms).
82
+
83
+ ---
84
+
85
+ ## Console commands
86
+
87
+ All product commands nest under **`xgic payload`**:
88
+
89
+ | Command | Purpose |
90
+ |---------|---------|
91
+ | `xgic payload dev` | **Primary daily command** — smart start (up if needed, DB check, `pnpm dev`) |
92
+ | `xgic payload setup [--quiet]` | Ensure Payload project directory (idempotent) |
93
+ | `xgic payload env [--json]` | Product env status (project name, `.env`, services) |
94
+ | `xgic payload env --regenerate --yes` | Fresh credentials in `.devcontainer/.env` |
95
+ | `xgic payload schema` | Run template schema generator when present |
96
+ | `xgic payload reset` | Fast targeted reset (project folder + active DB volume) |
97
+
98
+ **Generic lifecycle** (`xgic up` / `down` / `check` / `env`) lives in **dev-cli**. Use **`xgic payload env`** for Payload credentials and product status.
99
+
100
+ ### Setup: automatic vs manual
101
+
102
+ | Mode | Guidance |
103
+ |------|----------|
104
+ | **Automatic** | Producer/image `postStart` may call `xgic payload setup` via a thin shell wrapper (idempotent). |
105
+ | **Manual / testing** | After `xgic payload reset --yes`, or when validating scaffold config—not a “daily” app ritual. |
106
+
107
+ Always prefer **`xgic payload reset --dry-run`** before destructive reset.
108
+
109
+ ### Historical command map (`xde` → XGIC CLI)
110
+
111
+ Living brand is **XGIC CLI only**. Historical map for agents migrating old notes:
112
+
113
+ | Historical (`xde`) | XGIC CLI |
114
+ |--------------------|----------|
115
+ | `xde dev` | `xgic payload dev` |
116
+ | `xde setup payloadcms` | `xgic payload setup` |
117
+ | `xde schema` | `xgic payload schema` |
118
+ | `xde env --regenerate` | `xgic payload env --regenerate --yes` |
119
+ | `xde reset` | `xgic payload reset` |
120
+ | `xde up` / `down` / … | `xgic up` / `down` / … (dev-cli) |
121
+
122
+ ---
123
+
124
+ ## Library API
125
+
126
+ ```python
127
+ from xgic.cli.payload import (
128
+ ensure_payload_project,
129
+ generate_fresh_env_content,
130
+ make_payload_docker_controller,
131
+ get_payload_project_name,
132
+ )
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Requirements
138
+
139
+ - Python **3.14+**
140
+ - `xgic-cli` ≥ 0.2.0
141
+ - `xgic-dev-cli` ≥ 0.2.0
142
+
143
+ ---
144
+
145
+ ## Publishing
146
+
147
+ Follow [python-package-release.md](https://github.com/xgic/ai/blob/main/docs/python-package-release.md).
148
+
149
+ Publish **after** `xgic-cli` and `xgic-dev-cli` for stack releases. Tags: `vX.Y.ZrcN` → TestPyPI; `vX.Y.Z` → PyPI.
150
+
151
+ ---
152
+
153
+ ## Working with AI assistants
154
+
155
+ High-signal prompts:
156
+
157
+ - “Run `xgic payload env` (no secrets) and recommend whether to start Postgres.”
158
+ - “Start with `xgic payload dev` and report the listen URL.”
159
+ - “Show `xgic payload reset --dry-run` before any reset.”
160
+
161
+ Ownership:
162
+
163
+ | Change | Repository |
164
+ |--------|------------|
165
+ | `xgic payload …` behavior | **This repo** |
166
+ | `xgic up` / `down` / `check` | [dev-cli](https://github.com/xgic/dev-cli) |
167
+ | Image / Dockerfile | [payload-cms-dev](https://github.com/xgic/payload-cms-dev) |
168
+ | App template pin / docs | [payload-cms](https://github.com/xgic/payload-cms) |
169
+
170
+ Public-safe gate: [BASE-STANDARDS](https://github.com/xgic/ai/blob/main/docs/BASE-STANDARDS-FOR-ORCHESTRATED-REPOS.md).
171
+
172
+ ---
173
+
174
+ ## Contributing
175
+
176
+ PRs with human UI review only. Conventional Commits; labels required. See [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md).
177
+
178
+ ---
179
+
180
+ ## License
181
+
182
+ Apache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
183
+ Copyright form: `Copyright 2026 XGIC`.
184
+
185
+ ---
186
+
187
+ **XGIC** — Modular CLI for open-source platforms: thin core, domain modules, and AI-operable Payload workflows.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "xgic-payload-cms-cli"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "XGIC CLI Payload CMS module - product commands and helpers (xgic.cli.payload)."
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -0,0 +1,137 @@
1
+ """``xgic payload dev`` — smart Payload CMS development server start."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ from pathlib import Path
7
+
8
+ from xgic.cli.app import CommandContext
9
+ from xgic.cli.core.environment import EnvironmentType
10
+ from xgic.cli.payload.config import (
11
+ DEFAULT_COMPOSE_PROJECT,
12
+ DEFAULT_PRIMARY_SERVICE,
13
+ db_ready,
14
+ get_db_profile,
15
+ make_payload_docker_controller,
16
+ )
17
+ from xgic.cli.payload.layout import display_project_location, resolve_project_dir
18
+ from xgic.cli.payload.project import (
19
+ ensure_db_services,
20
+ is_payload_project_complete,
21
+ load_create_payload_config,
22
+ )
23
+ from xgic.cli.utils.output import print_info, print_success, print_warning
24
+
25
+
26
+ def _app_cwd(project_dir: Path) -> Path:
27
+ if project_dir == Path("."):
28
+ return Path.cwd()
29
+ return (Path.cwd() / project_dir).resolve()
30
+
31
+
32
+ def run_dev(ctx: CommandContext) -> int:
33
+ """Start DB if needed and launch the Payload CMS app dev server."""
34
+ env = ctx.env
35
+ cfg = load_create_payload_config()
36
+ project_dir = resolve_project_dir(cfg)
37
+
38
+ if not is_payload_project_complete(project_dir):
39
+ print_warning(
40
+ "Payload CMS app is not set up yet at "
41
+ f"{display_project_location(project_dir)}."
42
+ )
43
+ print_info("Run first: xgic payload env --regenerate --yes")
44
+ print_info("Then: xgic payload setup")
45
+ print_info("Then: xgic payload dev")
46
+ return 1
47
+
48
+ print_info("Starting Payload CMS development server...")
49
+ print_info(f"App location: {display_project_location(project_dir)}")
50
+
51
+ docker = make_payload_docker_controller(env)
52
+ docker.project_name = DEFAULT_COMPOSE_PROJECT
53
+ profile = get_db_profile()
54
+
55
+ # Never recreate the primary Dev Container service; only ensure DB.
56
+ if not db_ready(docker):
57
+ print_warning(
58
+ f"Database ({profile}) not ready. Starting DB service only..."
59
+ )
60
+ db_rc = ensure_db_services(quiet=False)
61
+ if db_rc != 0:
62
+ print_warning(
63
+ "Could not start database. Fix Compose/DB, then re-run "
64
+ "xgic payload dev."
65
+ )
66
+ return db_rc
67
+ else:
68
+ print_success("Database is ready")
69
+
70
+ app_cwd = _app_cwd(project_dir)
71
+ if not (app_cwd / "package.json").is_file():
72
+ print_warning(f"No package.json under {app_cwd}")
73
+ return 1
74
+
75
+ if env.env_type in (
76
+ EnvironmentType.DEV_CONTAINER,
77
+ EnvironmentType.GENERIC_CONTAINER,
78
+ ):
79
+ try:
80
+ print_info(f"Launching pnpm dev in {app_cwd}...")
81
+ result = subprocess.run(
82
+ ["sh", "-c", 'trap "exit 0" INT TERM; exec pnpm dev'],
83
+ cwd=str(app_cwd),
84
+ check=False,
85
+ )
86
+ if result.returncode in (130, -2, 2):
87
+ print_info("Development server stopped by user (Ctrl+C).")
88
+ return 0
89
+ if result.returncode != 0:
90
+ print_warning(f"pnpm dev exited with code {result.returncode}.")
91
+ print_info(
92
+ f"Fallback: cd {display_project_location(project_dir)} "
93
+ "&& pnpm dev"
94
+ )
95
+ return result.returncode or 1
96
+ print_info("Development server exited cleanly.")
97
+ return 0
98
+ except KeyboardInterrupt:
99
+ print_info("Development server stopped by user (Ctrl+C).")
100
+ return 0
101
+ except FileNotFoundError:
102
+ print_warning(
103
+ "pnpm not found. Run inside the Dev Container image "
104
+ "(or install pnpm on PATH)."
105
+ )
106
+ return 1
107
+
108
+ # Host: try docker exec into primary service (optional path)
109
+ rel = (
110
+ "."
111
+ if project_dir == Path(".")
112
+ else project_dir.as_posix().strip("/")
113
+ )
114
+ try:
115
+ print_info(
116
+ f"Launching pnpm dev via container service "
117
+ f"{DEFAULT_PRIMARY_SERVICE!r}..."
118
+ )
119
+ docker.exec(
120
+ DEFAULT_PRIMARY_SERVICE,
121
+ "sh",
122
+ "-c",
123
+ f"cd /workspace/{rel} && "
124
+ "sh -c 'trap \"exit 0\" INT TERM; exec pnpm dev'",
125
+ check=False,
126
+ )
127
+ except Exception as e:
128
+ print_warning(f"Failed to launch pnpm dev from host: {e}")
129
+ print_info(
130
+ "Prefer: Dev Containers → Reopen in Container, then "
131
+ "xgic payload dev"
132
+ )
133
+ return 1
134
+
135
+ print_success("Environment ready for development.")
136
+ print_info("Environment context: " + env.describe())
137
+ return 0
@@ -57,9 +57,9 @@ def run_payload_env(ctx: CommandContext) -> int:
57
57
  "(use: xgic payload env --regenerate --yes)"
58
58
  )
59
59
  if services_ok:
60
- print_success("Compose services: appear to be running")
60
+ print_success("Docker Compose services: appear to be running")
61
61
  else:
62
- print_info("Compose services: not detected as running")
62
+ print_info("Docker Compose services: not detected as running")
63
63
  print_info(f"Configured Payload CMS project: {payload_project}")
64
64
  print_info("Environment context: " + ctx.env.describe())
65
65
  return 0
@@ -13,8 +13,9 @@ from typing import Any
13
13
  from xgic.cli.core.environment import EnvironmentContext
14
14
  from xgic.cli.dev.docker import DockerComposeController
15
15
 
16
- DEFAULT_COMPOSE_PROJECT = "xgic-payload-cms-dev-containers"
17
- DEFAULT_PRIMARY_SERVICE = "xgic-payload-cms-dev-containers"
16
+ # Match producer + thin template Compose service names (not legacy *-dev-containers).
17
+ DEFAULT_COMPOSE_PROJECT = "xgic-payload-cms-dev"
18
+ DEFAULT_PRIMARY_SERVICE = "xgic-payload-cms-dev"
18
19
  DEFAULT_CONFIG_FILE = Path(".devcontainer/create-payload-config.json")
19
20
  DEFAULT_COMPOSE_FILE = ".devcontainer/docker-compose.yml"
20
21
 
@@ -22,7 +23,7 @@ DEFAULT_COMPOSE_FILE = ".devcontainer/docker-compose.yml"
22
23
  def get_payload_project_name(
23
24
  config_file: Path = DEFAULT_CONFIG_FILE,
24
25
  ) -> str:
25
- """Return the name of the generated Payload CMS project folder."""
26
+ """Return projectName identity (npm/display; not always the filesystem path)."""
26
27
  if config_file.exists():
27
28
  try:
28
29
  with open(config_file, encoding="utf-8") as f:
@@ -34,6 +35,16 @@ def get_payload_project_name(
34
35
  return "my-payload-cms"
35
36
 
36
37
 
38
+ def get_payload_project_dir(
39
+ config_file: Path = DEFAULT_CONFIG_FILE,
40
+ ) -> Path:
41
+ """Return resolved app directory Path (see layout.resolve_project_dir)."""
42
+ from xgic.cli.payload.layout import resolve_project_dir
43
+ from xgic.cli.payload.project import load_create_payload_config
44
+
45
+ return resolve_project_dir(load_create_payload_config(config_file))
46
+
47
+
37
48
  def get_db_config(
38
49
  config_file: Path = DEFAULT_CONFIG_FILE,
39
50
  ) -> tuple[str, str]:
@@ -86,7 +97,7 @@ def get_db_profile(config_file: Path = DEFAULT_CONFIG_FILE) -> str:
86
97
  def make_payload_docker_controller(
87
98
  env: EnvironmentContext,
88
99
  ) -> DockerComposeController:
89
- """Build a Compose controller with Payload CMS template defaults."""
100
+ """Build a Docker Compose controller with Payload CMS template defaults."""
90
101
  return DockerComposeController(
91
102
  env=env,
92
103
  compose_file=DEFAULT_COMPOSE_FILE,