@bluealba/platform-cli 1.1.0 → 1.2.0-alpha.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.
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Standalone Mode
|
|
3
|
+
description: Run a single application with a fully functional platform infrastructure without setting up a full product repository
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Aside, Steps, Tabs, TabItem, Card, CardGrid } from '@astrojs/starlight/components';
|
|
7
|
+
|
|
8
|
+
Standalone mode lets you run a single application with a fully functional platform infrastructure — gateway, database, and bootstrap service — without needing a full product repository. It is designed for rapid application development and testing in isolation.
|
|
9
|
+
|
|
10
|
+
<CardGrid>
|
|
11
|
+
<Card title="No product repo required">
|
|
12
|
+
Work entirely within your application monorepo. The CLI scaffolds a temporary platform core on demand.
|
|
13
|
+
</Card>
|
|
14
|
+
<Card title="Persistent configuration">
|
|
15
|
+
IDP and admin user settings are stored in `~/.ba-platform/standalone.json` and reused across all your standalone applications.
|
|
16
|
+
</Card>
|
|
17
|
+
<Card title="Foreground or detached">
|
|
18
|
+
Run with live output and Ctrl+C teardown, or use `--detach` for background execution.
|
|
19
|
+
</Card>
|
|
20
|
+
<Card title="First-run auto-detection">
|
|
21
|
+
The CLI reads your bootstrap service to detect platform and application identifiers automatically, so you rarely need to type them manually.
|
|
22
|
+
</Card>
|
|
23
|
+
</CardGrid>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## When to use standalone mode
|
|
28
|
+
|
|
29
|
+
Use standalone mode when you want to:
|
|
30
|
+
|
|
31
|
+
- Develop or test a single application in isolation, without standing up an entire platform product repository
|
|
32
|
+
- Iterate quickly on a new application before integrating it into a shared environment
|
|
33
|
+
- Run integration tests against a real gateway with a real database from a CI job
|
|
34
|
+
|
|
35
|
+
Use a full platform setup (via `platform init`) when you need to run multiple applications together or when you are working on the platform core itself.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Prerequisites
|
|
40
|
+
|
|
41
|
+
| Requirement | Notes |
|
|
42
|
+
|-------------|-------|
|
|
43
|
+
| Node.js >= 22 | Required by the platform services |
|
|
44
|
+
| Docker with Compose plugin | Used to run the gateway and database |
|
|
45
|
+
| An application monorepo | Created by `platform create-application` (either inside or outside an existing platform). Must have `docker-compose.yml` and `package.json` at the root. |
|
|
46
|
+
|
|
47
|
+
<Aside type="note">
|
|
48
|
+
Standalone mode is unavailable inside a directory that already contains an initialized platform (a `*-core/product.manifest.json` file). Run it from within the application monorepo directory itself, not the product repository root.
|
|
49
|
+
</Aside>
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Creating a standalone application
|
|
54
|
+
|
|
55
|
+
If you are starting from scratch, use `create-application` to scaffold an application monorepo that is ready for standalone mode. The command works the same whether you are inside a platform repository or not — the only difference is that outside a platform you must also supply `platformName` and `organizationName`:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
platform create-application \
|
|
59
|
+
platformName=myplatform \
|
|
60
|
+
organizationName=myorg \
|
|
61
|
+
applicationName=billing \
|
|
62
|
+
applicationDisplayName="Billing" \
|
|
63
|
+
applicationDescription="Invoice and payment management" \
|
|
64
|
+
hasUserInterface=yes \
|
|
65
|
+
hasBackendService=yes
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This creates a `myplatform-billing/` directory with:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
myplatform-billing/
|
|
72
|
+
├── package.json
|
|
73
|
+
├── docker-compose.yml ← Compose file for this app's services
|
|
74
|
+
├── services/
|
|
75
|
+
│ ├── myplatform-billing-bootstrap-service/
|
|
76
|
+
│ │ └── ... ← Bootstrap NestJS service (registers the app)
|
|
77
|
+
│ └── myplatform-billing-service/ ← NestJS backend service (if requested)
|
|
78
|
+
│ └── ...
|
|
79
|
+
└── ui/
|
|
80
|
+
└── myplatform-billing-ui/ ← React micro-frontend module (if requested)
|
|
81
|
+
└── ...
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
It also writes initial configuration to `~/.ba-platform/standalone.json`.
|
|
85
|
+
|
|
86
|
+
The scaffolded `package.json` includes convenience scripts so you can use npm instead of invoking the CLI directly:
|
|
87
|
+
|
|
88
|
+
| npm script | Equivalent CLI command |
|
|
89
|
+
|------------|----------------------|
|
|
90
|
+
| `npm run standalone` | `platform standalone` |
|
|
91
|
+
| `npm run standalone:stop` | `platform standalone-stop` |
|
|
92
|
+
|
|
93
|
+
If you created your application with `platform create-application` inside a full platform, the resulting application monorepo is already compatible with standalone mode. Copy or clone it anywhere and run `platform standalone` from its root.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Running standalone mode
|
|
98
|
+
|
|
99
|
+
<Steps>
|
|
100
|
+
|
|
101
|
+
1. **Navigate to the application monorepo root:**
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cd myplatform-billing
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
2. **Start the standalone platform:**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
platform standalone
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Or use the npm script included in the scaffolded `package.json`:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm run standalone
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
3. **Follow the first-time setup wizard** (if no config exists yet — see [First-time setup](#first-time-setup) below).
|
|
120
|
+
|
|
121
|
+
4. **Wait for the gateway to become healthy.** The CLI logs progress:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
Scaffolding temporary platform core...
|
|
125
|
+
Installing dependencies...
|
|
126
|
+
Building...
|
|
127
|
+
Starting containers...
|
|
128
|
+
Waiting for gateway to be healthy...
|
|
129
|
+
Gateway is healthy.
|
|
130
|
+
IDP provider "My Okta" configured successfully.
|
|
131
|
+
Admin user "you@example.com" configured successfully.
|
|
132
|
+
|
|
133
|
+
Platform is running. Press Ctrl+C to stop and clean up.
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
5. **Access the platform.** The gateway is available at `https://localhost:443` by default (self-signed certificate).
|
|
137
|
+
|
|
138
|
+
6. **Press Ctrl+C** to stop containers and remove the temporary platform core.
|
|
139
|
+
|
|
140
|
+
</Steps>
|
|
141
|
+
|
|
142
|
+
<Aside type="note" title="Temporary platform core location">
|
|
143
|
+
The CLI scaffolds a real platform core in `/tmp/platform-standalone-{platformName}/`. This directory is created fresh on every run and deleted on shutdown. All persistent application data lives in Docker volumes, which are also reset on each run to avoid database credential mismatches between runs.
|
|
144
|
+
</Aside>
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## First-time setup
|
|
149
|
+
|
|
150
|
+
When no standalone configuration is found for the current application, the CLI launches a setup wizard before starting.
|
|
151
|
+
|
|
152
|
+
**Auto-detection**: The CLI first scans your bootstrap service's `application.json` to detect the platform name, application name, and display name. It also looks in `~/.ba-platform/standalone.json` for existing defaults (from previous apps). Any detected values are pre-filled as prompt defaults.
|
|
153
|
+
|
|
154
|
+
**What the wizard prompts:**
|
|
155
|
+
|
|
156
|
+
| Prompt | Auto-detected from | Pre-filled from defaults if |
|
|
157
|
+
|--------|--------------------|------------------------------|
|
|
158
|
+
| Platform name | Bootstrap service directory name | `defaults.platformName` already set |
|
|
159
|
+
| Organization name | — | `defaults.organizationName` already set |
|
|
160
|
+
| Application name | `application.json` | — |
|
|
161
|
+
| Application display name | `application.json` | — |
|
|
162
|
+
| IDP configuration | — | `defaults.idp` already set (asked to confirm reuse) |
|
|
163
|
+
| Admin users | `git config user.email` (first user) | `defaults.adminUsers` already set (asked to confirm reuse) |
|
|
164
|
+
|
|
165
|
+
After the wizard, the CLI asks whether to run in detached mode.
|
|
166
|
+
|
|
167
|
+
**Subsequent runs**: If config exists in `~/.ba-platform/standalone.json` for the detected `platformName/applicationName` key, the wizard is skipped entirely. The platform starts immediately.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Detached mode
|
|
172
|
+
|
|
173
|
+
By default, `platform standalone` runs in the foreground. Logs stream to the terminal and Ctrl+C stops and cleans up everything.
|
|
174
|
+
|
|
175
|
+
Use detached mode when you want the platform to keep running in the background:
|
|
176
|
+
|
|
177
|
+
<Tabs>
|
|
178
|
+
<TabItem label="Interactive">
|
|
179
|
+
```bash
|
|
180
|
+
platform standalone
|
|
181
|
+
# When prompted "Run in detached mode (background)?", answer yes
|
|
182
|
+
```
|
|
183
|
+
</TabItem>
|
|
184
|
+
<TabItem label="Headless">
|
|
185
|
+
```bash
|
|
186
|
+
platform standalone detach=true
|
|
187
|
+
# or
|
|
188
|
+
platform standalone d=true
|
|
189
|
+
```
|
|
190
|
+
</TabItem>
|
|
191
|
+
</Tabs>
|
|
192
|
+
|
|
193
|
+
In detached mode, the CLI prints a confirmation and exits. To stop a detached platform:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
platform standalone-stop
|
|
197
|
+
# or
|
|
198
|
+
npm run standalone:stop
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
<Aside type="caution" title="One standalone platform at a time">
|
|
202
|
+
Only one standalone platform can run at a time, regardless of detach mode. If you attempt to start a second one while another is running, the CLI will print an error and exit. Run `platform standalone-stop` first.
|
|
203
|
+
</Aside>
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Centralized configuration
|
|
208
|
+
|
|
209
|
+
All standalone configuration is stored in `~/.ba-platform/standalone.json`. This file is owned by you (mode `0600`) and is never committed to any repository.
|
|
210
|
+
|
|
211
|
+
### File structure
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"defaults": {
|
|
216
|
+
"platformName": "myplatform",
|
|
217
|
+
"organizationName": "myorg",
|
|
218
|
+
"idp": {
|
|
219
|
+
"provider": "okta",
|
|
220
|
+
"name": "My Okta",
|
|
221
|
+
"issuer": "https://myorg.okta.com/oauth2/default",
|
|
222
|
+
"clientId": "0oa...",
|
|
223
|
+
"clientSecret": "..."
|
|
224
|
+
},
|
|
225
|
+
"adminUsers": ["you@example.com"]
|
|
226
|
+
},
|
|
227
|
+
"apps": {
|
|
228
|
+
"myplatform/billing": {
|
|
229
|
+
"applicationName": "billing",
|
|
230
|
+
"applicationDisplayName": "Billing"
|
|
231
|
+
},
|
|
232
|
+
"myplatform/hr": {
|
|
233
|
+
"applicationName": "hr",
|
|
234
|
+
"applicationDisplayName": "HR",
|
|
235
|
+
"adminUsers": ["hr-admin@example.com"]
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**`defaults`** holds values shared across all applications: platform name, organization name, IDP credentials, and admin users. You only need to enter IDP credentials once — they are reused every time you start standalone mode for any application.
|
|
242
|
+
|
|
243
|
+
**`apps`** holds per-application entries keyed by `platformName/applicationName`. Each entry requires `applicationName` and `applicationDisplayName`. Any field present in an app entry overrides the corresponding default for that application only — useful when a specific app needs a different IDP or different admin users.
|
|
244
|
+
|
|
245
|
+
### Resolution order
|
|
246
|
+
|
|
247
|
+
When starting standalone mode, the CLI merges the two sections:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
resolved = defaults + app override
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Fields in the app entry take precedence over fields in defaults. Fields absent from the app entry fall back to defaults.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Configuration management commands
|
|
258
|
+
|
|
259
|
+
### standalone-config-show
|
|
260
|
+
|
|
261
|
+
Shows the resolved configuration for the current application (auto-detected from the current directory), or the full contents of `~/.ba-platform/standalone.json` if run outside an app monorepo.
|
|
262
|
+
|
|
263
|
+
<Tabs>
|
|
264
|
+
<TabItem label="Interactive">
|
|
265
|
+
```bash
|
|
266
|
+
platform standalone-config-show
|
|
267
|
+
```
|
|
268
|
+
</TabItem>
|
|
269
|
+
<TabItem label="Headless — current app">
|
|
270
|
+
```bash
|
|
271
|
+
platform standalone-config-show
|
|
272
|
+
# Auto-detects app from cwd
|
|
273
|
+
```
|
|
274
|
+
</TabItem>
|
|
275
|
+
<TabItem label="Headless — specific app">
|
|
276
|
+
```bash
|
|
277
|
+
platform standalone-config-show app=myplatform/billing
|
|
278
|
+
```
|
|
279
|
+
</TabItem>
|
|
280
|
+
</Tabs>
|
|
281
|
+
|
|
282
|
+
### standalone-config-set
|
|
283
|
+
|
|
284
|
+
Edits defaults or app-specific overrides.
|
|
285
|
+
|
|
286
|
+
<Tabs>
|
|
287
|
+
<TabItem label="Interactive">
|
|
288
|
+
```bash
|
|
289
|
+
platform standalone-config-set
|
|
290
|
+
# Select "Defaults" or "App-specific config" and follow prompts
|
|
291
|
+
```
|
|
292
|
+
</TabItem>
|
|
293
|
+
<TabItem label="Headless — edit defaults">
|
|
294
|
+
```bash
|
|
295
|
+
platform standalone-config-set defaults=true platformName=myplatform organizationName=myorg
|
|
296
|
+
```
|
|
297
|
+
</TabItem>
|
|
298
|
+
<TabItem label="Headless — edit app">
|
|
299
|
+
```bash
|
|
300
|
+
platform standalone-config-set app=myplatform/billing applicationDisplayName="Billing v2"
|
|
301
|
+
# Auto-detects app from cwd if 'app' is omitted
|
|
302
|
+
```
|
|
303
|
+
</TabItem>
|
|
304
|
+
</Tabs>
|
|
305
|
+
|
|
306
|
+
<Aside type="note">
|
|
307
|
+
IDP and admin user configuration cannot be set via headless arguments for `standalone-config-set`. Use interactive mode to configure or update IDP credentials and admin user lists, as these fields contain sensitive information that should not appear in shell history.
|
|
308
|
+
</Aside>
|
|
309
|
+
|
|
310
|
+
### standalone-config-delete
|
|
311
|
+
|
|
312
|
+
Removes a saved app config entry from `~/.ba-platform/standalone.json`. Defaults are not affected.
|
|
313
|
+
|
|
314
|
+
<Tabs>
|
|
315
|
+
<TabItem label="Interactive">
|
|
316
|
+
```bash
|
|
317
|
+
platform standalone-config-delete
|
|
318
|
+
# Select from list, confirm deletion
|
|
319
|
+
```
|
|
320
|
+
</TabItem>
|
|
321
|
+
<TabItem label="Headless">
|
|
322
|
+
```bash
|
|
323
|
+
platform standalone-config-delete app=myplatform/billing
|
|
324
|
+
```
|
|
325
|
+
</TabItem>
|
|
326
|
+
</Tabs>
|
|
327
|
+
|
|
328
|
+
### standalone-config-list
|
|
329
|
+
|
|
330
|
+
Lists all configured applications with their resolved settings.
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
platform standalone-config-list
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Example output:
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
Config file: /Users/you/.ba-platform/standalone.json
|
|
340
|
+
|
|
341
|
+
Defaults:
|
|
342
|
+
Platform: myplatform
|
|
343
|
+
Organization: myorg
|
|
344
|
+
IDP: okta (My Okta)
|
|
345
|
+
Admin Users: you@example.com
|
|
346
|
+
|
|
347
|
+
Apps:
|
|
348
|
+
myplatform/billing — Billing [IDP: yes, Admins: 1]
|
|
349
|
+
myplatform/hr — HR [IDP: no, Admins: 1]
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Legacy migration
|
|
355
|
+
|
|
356
|
+
If your application monorepo contains a `standalone.json` file at its root (from an earlier version of the CLI), the standalone wizard detects it automatically and migrates the contents to `~/.ba-platform/standalone.json`. Shared fields (platform name, organization name, IDP, admin users) move to `defaults`; app-specific fields move to the `apps` section. You are prompted to delete the old file after migration.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Troubleshooting
|
|
361
|
+
|
|
362
|
+
### Gateway does not become healthy
|
|
363
|
+
|
|
364
|
+
The CLI waits up to 120 seconds for the gateway's `/health` endpoint to respond. If it times out:
|
|
365
|
+
|
|
366
|
+
1. Check the gateway container logs:
|
|
367
|
+
```bash
|
|
368
|
+
docker compose -p myplatform-platform logs pae-nestjs-gateway-service
|
|
369
|
+
```
|
|
370
|
+
2. Check that all containers are running:
|
|
371
|
+
```bash
|
|
372
|
+
docker ps
|
|
373
|
+
```
|
|
374
|
+
3. If you see a PostgreSQL authentication error, a stale Docker volume from a previous standalone run may be using an old password. The standalone orchestrator resets volumes automatically on each start, but if the volume was created by a non-standalone platform run with the same name, you may need to remove it manually:
|
|
375
|
+
```bash
|
|
376
|
+
docker volume ls | grep myplatform
|
|
377
|
+
docker volume rm <volume-name>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### IDP not configured
|
|
381
|
+
|
|
382
|
+
If you skipped IDP setup during the wizard, users will not be able to log in. Configure IDP interactively:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
platform standalone-config-set
|
|
386
|
+
# Choose "Defaults (shared across all apps)" and configure an IDP
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Then restart standalone mode.
|
|
390
|
+
|
|
391
|
+
### Platform already running error
|
|
392
|
+
|
|
393
|
+
Only one standalone platform can run at a time. If the CLI reports another instance is running but you do not have one:
|
|
394
|
+
|
|
395
|
+
1. Check for a stale marker file:
|
|
396
|
+
```bash
|
|
397
|
+
ls /tmp/platform-standalone-*/
|
|
398
|
+
```
|
|
399
|
+
2. Stop it cleanly (if containers are actually running):
|
|
400
|
+
```bash
|
|
401
|
+
platform standalone-stop
|
|
402
|
+
```
|
|
403
|
+
3. Or remove the directory manually if no containers are running:
|
|
404
|
+
```bash
|
|
405
|
+
rm -rf /tmp/platform-standalone-myplatform/
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Changes to application services not reflected
|
|
409
|
+
|
|
410
|
+
The temporary platform core is scaffolded fresh on every run, but your application's Docker image is rebuilt using the existing built artifacts. If you make source code changes, rebuild before running standalone:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
npm run build
|
|
414
|
+
platform standalone
|
|
415
|
+
```
|
package/package.json
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
"lint": "turbo run lint",
|
|
11
11
|
"changeset": "changeset",
|
|
12
12
|
"check-deps": "syncpack list-mismatches",
|
|
13
|
-
"fix-deps": "syncpack fix-mismatches"
|
|
13
|
+
"fix-deps": "syncpack fix-mismatches",
|
|
14
|
+
"standalone": "platform standalone",
|
|
15
|
+
"standalone:stop": "platform standalone-stop"
|
|
14
16
|
},
|
|
15
17
|
"packageManager": "npm@10.8.2",
|
|
16
18
|
"keywords": [],
|