container-superposition 0.1.3 → 0.1.4

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 (62) hide show
  1. package/README.md +365 -9
  2. package/dist/scripts/init.js +220 -94
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/commands/doctor.js +2 -2
  5. package/dist/tool/commands/explain.d.ts.map +1 -1
  6. package/dist/tool/commands/explain.js +88 -0
  7. package/dist/tool/commands/explain.js.map +1 -1
  8. package/dist/tool/commands/plan.d.ts +51 -0
  9. package/dist/tool/commands/plan.d.ts.map +1 -1
  10. package/dist/tool/commands/plan.js +523 -1
  11. package/dist/tool/commands/plan.js.map +1 -1
  12. package/dist/tool/questionnaire/composer.d.ts +12 -3
  13. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  14. package/dist/tool/questionnaire/composer.js +133 -20
  15. package/dist/tool/questionnaire/composer.js.map +1 -1
  16. package/dist/tool/schema/types.d.ts +18 -0
  17. package/dist/tool/schema/types.d.ts.map +1 -1
  18. package/dist/tool/utils/gitignore.d.ts +15 -0
  19. package/dist/tool/utils/gitignore.d.ts.map +1 -0
  20. package/dist/tool/utils/gitignore.js +41 -0
  21. package/dist/tool/utils/gitignore.js.map +1 -0
  22. package/dist/tool/utils/services-export.d.ts +14 -0
  23. package/dist/tool/utils/services-export.d.ts.map +1 -0
  24. package/dist/tool/utils/services-export.js +478 -0
  25. package/dist/tool/utils/services-export.js.map +1 -0
  26. package/dist/tool/utils/summary.d.ts +69 -0
  27. package/dist/tool/utils/summary.d.ts.map +1 -0
  28. package/dist/tool/utils/summary.js +260 -0
  29. package/dist/tool/utils/summary.js.map +1 -0
  30. package/docs/overlays.md +48 -5
  31. package/overlays/.presets/microservice.yml +32 -6
  32. package/overlays/.presets/web-api.yml +76 -56
  33. package/overlays/cloudflared/README.md +190 -0
  34. package/overlays/cloudflared/devcontainer.patch.json +3 -0
  35. package/overlays/cloudflared/overlay.yml +15 -0
  36. package/overlays/cloudflared/setup.sh +49 -0
  37. package/overlays/cloudflared/verify.sh +21 -0
  38. package/overlays/direnv/README.md +6 -4
  39. package/overlays/direnv/setup.sh +0 -12
  40. package/overlays/grpc-tools/README.md +242 -0
  41. package/overlays/grpc-tools/devcontainer.patch.json +14 -0
  42. package/overlays/grpc-tools/overlay.yml +14 -0
  43. package/overlays/grpc-tools/setup.sh +57 -0
  44. package/overlays/grpc-tools/verify.sh +47 -0
  45. package/overlays/keycloak/.env.example +5 -0
  46. package/overlays/keycloak/README.md +238 -0
  47. package/overlays/keycloak/devcontainer.patch.json +17 -0
  48. package/overlays/keycloak/docker-compose.yml +32 -0
  49. package/overlays/keycloak/overlay.yml +23 -0
  50. package/overlays/keycloak/verify.sh +54 -0
  51. package/overlays/mailpit/.env.example +4 -0
  52. package/overlays/mailpit/README.md +191 -0
  53. package/overlays/mailpit/devcontainer.patch.json +20 -0
  54. package/overlays/mailpit/docker-compose.yml +17 -0
  55. package/overlays/mailpit/overlay.yml +26 -0
  56. package/overlays/mailpit/verify.sh +52 -0
  57. package/overlays/ngrok/overlay.yml +2 -1
  58. package/overlays/python/README.md +51 -35
  59. package/overlays/python/devcontainer.patch.json +7 -4
  60. package/overlays/python/setup.sh +50 -23
  61. package/overlays/python/verify.sh +29 -1
  62. package/package.json +1 -1
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Summary utilities for post-generation output
3
+ */
4
+ import chalk from 'chalk';
5
+ import boxen from 'boxen';
6
+ import { generateUrl } from './port-utils.js';
7
+ /**
8
+ * Detect warnings based on selected overlays and configuration
9
+ */
10
+ export function detectWarnings(overlays, answers) {
11
+ const warnings = [];
12
+ // Check for docker-sock security warning
13
+ const hasDockerSock = overlays.some((o) => o.id === 'docker-sock');
14
+ if (hasDockerSock) {
15
+ warnings.push('docker-sock overlay provides root access to host Docker daemon\n Use only for trusted code. Consider docker-in-docker for isolation.');
16
+ }
17
+ // Check for target mismatch
18
+ const target = answers.target || 'local';
19
+ if (hasDockerSock && target === 'codespaces') {
20
+ warnings.push('docker-sock may not work in GitHub Codespaces\n Consider using docker-in-docker instead.');
21
+ }
22
+ // Check for high port count
23
+ const portCount = overlays.reduce((count, o) => count + (o.ports?.length || 0), 0);
24
+ const hasHighPortCountWarning = portCount > 10;
25
+ if (hasHighPortCountWarning) {
26
+ warnings.push(`High port count (${portCount} ports) may cause conflicts\n Consider using --port-offset to avoid conflicts with other projects.`);
27
+ }
28
+ // Check for no port offset with multiple services
29
+ const hasServices = overlays.some((o) => o.category === 'database' || o.category === 'observability');
30
+ if (!hasHighPortCountWarning &&
31
+ hasServices &&
32
+ (!answers.portOffset || answers.portOffset === 0)) {
33
+ warnings.push('Running multiple devcontainers simultaneously may cause port conflicts\n Use --port-offset 100 (or higher) to avoid conflicts.');
34
+ }
35
+ return warnings;
36
+ }
37
+ /**
38
+ * Generate helpful tips based on configuration
39
+ */
40
+ export function generateTips(overlays, answers) {
41
+ const tips = [];
42
+ // Suggest committing manifest
43
+ if (!answers.preset) {
44
+ tips.push('Commit superposition.json to enable team regeneration');
45
+ }
46
+ // Suggest customization directory
47
+ const hasCustomDir = overlays.length > 3;
48
+ if (hasCustomDir) {
49
+ tips.push('Preserve customizations in .devcontainer/custom/');
50
+ }
51
+ // Suggest regen command
52
+ tips.push('Regenerate anytime: npx container-superposition regen');
53
+ return tips;
54
+ }
55
+ /**
56
+ * Generate next steps based on mode
57
+ */
58
+ export function generateNextSteps(isManifestOnly, isRegen) {
59
+ if (isManifestOnly) {
60
+ return [
61
+ 'Review the generated superposition.json file',
62
+ 'Commit it to your repository',
63
+ 'Team members can run "npx container-superposition regen"',
64
+ ];
65
+ }
66
+ if (isRegen) {
67
+ return [
68
+ 'Rebuild container:\n Open Command Palette (Ctrl+Shift+P / Cmd+Shift+P) → "Dev Containers: Rebuild Container"',
69
+ 'Test changes manually',
70
+ 'Review any customizations in .devcontainer/custom/',
71
+ ];
72
+ }
73
+ return [
74
+ 'Customize environment:\n cp .devcontainer/.env.example .devcontainer/.env',
75
+ 'Open in VS Code:\n code .',
76
+ 'Reopen in Container:\n Open Command Palette (Ctrl+Shift+P / Cmd+Shift+P) → "Dev Containers: Reopen in Container"',
77
+ 'Verify setup:\n npx container-superposition doctor',
78
+ ];
79
+ }
80
+ /**
81
+ * Convert overlay metadata to service info
82
+ */
83
+ export function overlaysToServices(overlays) {
84
+ return overlays.map((overlay) => {
85
+ // Extract version from name if present (e.g., "PostgreSQL 16" -> version: "16")
86
+ const versionMatch = overlay.name.match(/\d+(?:\.\d+)?/);
87
+ const version = versionMatch ? versionMatch[0] : undefined;
88
+ return {
89
+ name: overlay.name,
90
+ category: overlay.category,
91
+ version,
92
+ };
93
+ });
94
+ }
95
+ /**
96
+ * Convert normalized ports to port info with URLs
97
+ */
98
+ export function portsToPortInfo(ports, connectionStrings) {
99
+ return ports.map((port) => {
100
+ const service = port.service || 'unknown';
101
+ const url = generateUrl(port);
102
+ // Try to find connection string for this service
103
+ let connectionString;
104
+ if (connectionStrings[service]) {
105
+ connectionString = connectionStrings[service];
106
+ }
107
+ else if (connectionStrings[`${service}-url`]) {
108
+ connectionString = connectionStrings[`${service}-url`];
109
+ }
110
+ return {
111
+ service,
112
+ port: port.port,
113
+ actualPort: port.actualPort,
114
+ url,
115
+ connectionString,
116
+ };
117
+ });
118
+ }
119
+ /**
120
+ * Format and print generation summary.
121
+ *
122
+ * @param summary The generation summary to render.
123
+ * @param quiet When true, suppresses all console output. This parameter is
124
+ * reserved for callers (for example, CLI commands or tests)
125
+ * that need to generate a summary object but handle user
126
+ * messaging themselves.
127
+ */
128
+ export function printSummary(summary, quiet = false) {
129
+ // If quiet mode is enabled, skip printing while still allowing callers
130
+ // to invoke this function consistently. See the JSDoc for intended usage.
131
+ if (quiet) {
132
+ return;
133
+ }
134
+ const lines = [];
135
+ // Header
136
+ const title = summary.isManifestOnly
137
+ ? '📋 Manifest Generated'
138
+ : summary.backupPath
139
+ ? '🔄 DevContainer Regenerated'
140
+ : '✨ DevContainer Generated';
141
+ lines.push(chalk.bold.green(title));
142
+ lines.push('');
143
+ // Backup notification (for regen)
144
+ if (summary.backupPath) {
145
+ lines.push(chalk.yellow(`Backup created: ${summary.backupPath}`));
146
+ lines.push('');
147
+ }
148
+ // Files created (manifest-only shows just manifest)
149
+ if (summary.isManifestOnly) {
150
+ lines.push(chalk.white('Manifest:'));
151
+ lines.push(chalk.gray(` ${summary.manifestPath || 'superposition.json'}`));
152
+ lines.push('');
153
+ }
154
+ else {
155
+ lines.push(chalk.white('Files created:'));
156
+ for (const file of summary.files.slice(0, 8)) {
157
+ lines.push(chalk.gray(` ${file}`));
158
+ }
159
+ if (summary.files.length > 8) {
160
+ lines.push(chalk.gray(` ... and ${summary.files.length - 8} more`));
161
+ }
162
+ lines.push('');
163
+ }
164
+ // Services included
165
+ if (summary.services.length > 0) {
166
+ lines.push(chalk.white('Services included:'));
167
+ const displayServices = summary.services.slice(0, 10);
168
+ for (const service of displayServices) {
169
+ const versionStr = service.version ? ` ${service.version}` : '';
170
+ const categoryStr = chalk.dim(` (${service.category})`);
171
+ lines.push(chalk.green(` ✓ ${service.name}${versionStr}`) + categoryStr);
172
+ }
173
+ if (summary.services.length > 10) {
174
+ lines.push(chalk.gray(` ... and ${summary.services.length - 10} more`));
175
+ }
176
+ lines.push('');
177
+ }
178
+ // Port mappings and service URLs
179
+ if (summary.ports.length > 0) {
180
+ lines.push(chalk.white('🌐 Service Access'));
181
+ lines.push('');
182
+ // Group by HTTP services and database services
183
+ const httpPorts = summary.ports.filter((p) => p.url);
184
+ const dbPorts = summary.ports.filter((p) => p.connectionString && !p.url);
185
+ // Show application/HTTP services first
186
+ if (httpPorts.length > 0) {
187
+ for (const port of httpPorts) {
188
+ const label = port.service.charAt(0).toUpperCase() + port.service.slice(1);
189
+ lines.push(chalk.cyan(` ${label}:`));
190
+ lines.push(chalk.gray(` ${port.url}`));
191
+ }
192
+ lines.push('');
193
+ }
194
+ // Show database/infrastructure services
195
+ if (dbPorts.length > 0) {
196
+ lines.push(chalk.white(' Infrastructure:'));
197
+ for (const port of dbPorts) {
198
+ const label = port.service.charAt(0).toUpperCase() + port.service.slice(1);
199
+ lines.push(chalk.cyan(` ${label}:`));
200
+ lines.push(chalk.gray(` ${port.connectionString}`));
201
+ }
202
+ lines.push('');
203
+ }
204
+ // Port offset info
205
+ if (summary.portOffset > 0) {
206
+ lines.push(chalk.dim(` Port offset: ${summary.portOffset}`));
207
+ }
208
+ else {
209
+ lines.push(chalk.dim(' Port offset: 0 (use --port-offset to avoid conflicts)'));
210
+ }
211
+ lines.push('');
212
+ }
213
+ // Warnings
214
+ if (summary.warnings.length > 0) {
215
+ lines.push(chalk.yellow('⚠️ Warnings'));
216
+ lines.push('');
217
+ for (const warning of summary.warnings) {
218
+ const warningLines = warning.split('\n');
219
+ lines.push(chalk.yellow(` • ${warningLines[0]}`));
220
+ for (let i = 1; i < warningLines.length; i++) {
221
+ lines.push(chalk.dim(` ${warningLines[i]}`));
222
+ }
223
+ }
224
+ lines.push('');
225
+ }
226
+ // Tips
227
+ if (summary.tips.length > 0) {
228
+ lines.push(chalk.cyan('💡 Tips'));
229
+ lines.push('');
230
+ for (const tip of summary.tips) {
231
+ lines.push(chalk.gray(` • ${tip}`));
232
+ }
233
+ lines.push('');
234
+ }
235
+ // Next steps
236
+ lines.push(chalk.white('📝 Next Steps'));
237
+ lines.push('');
238
+ for (let i = 0; i < summary.nextSteps.length; i++) {
239
+ const step = summary.nextSteps[i];
240
+ const stepLines = step.split('\n');
241
+ lines.push(chalk.gray(` ${i + 1}. ${stepLines[0]}`));
242
+ for (let j = 1; j < stepLines.length; j++) {
243
+ lines.push(chalk.dim(` ${stepLines[j]}`));
244
+ }
245
+ }
246
+ // Footer
247
+ if (!summary.isManifestOnly) {
248
+ lines.push('');
249
+ lines.push(chalk.dim(`Generated in .devcontainer/ • Manifest: ${summary.manifestPath || 'superposition.json'}`));
250
+ }
251
+ // Print with boxen
252
+ console.log('\n' +
253
+ boxen(lines.join('\n'), {
254
+ padding: 1,
255
+ borderColor: 'green',
256
+ borderStyle: 'round',
257
+ margin: 1,
258
+ }));
259
+ }
260
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../tool/utils/summary.ts"],"names":[],"mappings":"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"}
package/docs/overlays.md CHANGED
@@ -442,6 +442,16 @@ Infrastructure as Code with HCL (includes tflint)
442
442
 
443
443
  ## Dev Tool Overlays
444
444
 
445
+ ### Cloudflared (`cloudflared`)
446
+
447
+ Cloudflare Tunnel for securely exposing local services to the internet
448
+
449
+ | Property | Value |
450
+ | ------------- | ----------------------------------------- |
451
+ | **Category** | dev |
452
+ | **Conflicts** | `ngrok` |
453
+ | **Tags** | `dev`, `tunneling`, `proxy`, `cloudflare` |
454
+
445
455
  ### Codex (`codex`)
446
456
 
447
457
  OpenAI Codex CLI for AI-powered code generation and assistance
@@ -501,6 +511,15 @@ Git LFS, GitHub CLI, GPG/SSH support for secure Git operations
501
511
  | **Category** | dev |
502
512
  | **Tags** | `dev`, `git`, `security`, `ssh`, `gpg` |
503
513
 
514
+ ### gRPC Tools (`grpc-tools`)
515
+
516
+ Protocol Buffers compiler, Buf, and grpcurl for gRPC development
517
+
518
+ | Property | Value |
519
+ | ------------ | -------------------------------- |
520
+ | **Category** | dev |
521
+ | **Tags** | `dev`, `grpc`, `protobuf`, `api` |
522
+
504
523
  ### Just Task Runner (`just`)
505
524
 
506
525
  Fast, simple command runner (Rust-based alternative to Make)
@@ -510,6 +529,29 @@ Fast, simple command runner (Rust-based alternative to Make)
510
529
  | **Category** | dev |
511
530
  | **Tags** | `dev`, `automation`, `tasks` |
512
531
 
532
+ ### Keycloak (`keycloak`)
533
+
534
+ Open-source identity and access management (OIDC/OAuth2)
535
+
536
+ | Property | Value |
537
+ | ------------ | ------------------------------------------- |
538
+ | **Category** | dev |
539
+ | **Supports** | compose |
540
+ | **Requires** | `postgres` |
541
+ | **Tags** | `dev`, `auth`, `oidc`, `oauth2`, `identity` |
542
+ | **Ports** | [object Object] |
543
+
544
+ ### Mailpit (`mailpit`)
545
+
546
+ Email testing tool with web UI and SMTP server
547
+
548
+ | Property | Value |
549
+ | ------------ | --------------------------------- |
550
+ | **Category** | dev |
551
+ | **Supports** | compose |
552
+ | **Tags** | `dev`, `email`, `smtp`, `testing` |
553
+ | **Ports** | [object Object], [object Object] |
554
+
513
555
  ### Modern CLI Tools (`modern-cli-tools`)
514
556
 
515
557
  jq, yq, ripgrep, fd, bat - Essential modern command-line tools
@@ -523,11 +565,12 @@ jq, yq, ripgrep, fd, bat - Essential modern command-line tools
523
565
 
524
566
  Secure tunneling for webhook testing and external access
525
567
 
526
- | Property | Value |
527
- | ------------ | ------------------------------ |
528
- | **Category** | dev |
529
- | **Tags** | `dev`, `tunneling`, `webhooks` |
530
- | **Ports** | 4040 |
568
+ | Property | Value |
569
+ | ------------- | ------------------------------ |
570
+ | **Category** | dev |
571
+ | **Conflicts** | `cloudflared` |
572
+ | **Tags** | `dev`, `tunneling`, `webhooks` |
573
+ | **Ports** | 4040 |
531
574
 
532
575
  ### OpenAPI Tools (`openapi-tools`)
533
576
 
@@ -26,11 +26,35 @@ selects:
26
26
  options: [dotnet, nodejs, python, go, java]
27
27
  defaultOption: nodejs
28
28
 
29
- messaging:
30
- id: messaging
31
- prompt: Select message broker
32
- options: [rabbitmq, redpanda, nats]
33
- defaultOption: rabbitmq
29
+ # Parameterized slots
30
+ parameters:
31
+ broker:
32
+ description: 'Message broker'
33
+ default: rabbitmq
34
+ options:
35
+ - id: rabbitmq
36
+ overlays: [rabbitmq]
37
+ description: 'RabbitMQ AMQP message broker'
38
+ - id: nats
39
+ overlays: [nats]
40
+ description: 'NATS lightweight messaging'
41
+ - id: redpanda
42
+ overlays: [redpanda]
43
+ description: 'Redpanda Kafka-compatible streaming'
44
+ - id: none
45
+ overlays: []
46
+ description: 'No message broker'
47
+
48
+ observability:
49
+ description: 'Observability stack level'
50
+ default: standard
51
+ options:
52
+ - id: standard
53
+ overlays: []
54
+ description: 'Standard (Jaeger + Prometheus + Grafana, already included)'
55
+ - id: full
56
+ overlays: [loki]
57
+ description: 'Full stack - adds Loki for log aggregation'
34
58
 
35
59
  # Glue configuration - integration helpers
36
60
  glueConfig:
@@ -66,11 +90,12 @@ glueConfig:
66
90
 
67
91
  ### Services
68
92
 
69
- - **Message Broker**: Async communication between services
93
+ - **Message Broker**: Async communication between services (RabbitMQ/NATS/Redpanda based on your choice)
70
94
  - **OpenTelemetry Collector**: Distributed tracing collection (ports 4317, 4318)
71
95
  - **Jaeger**: Distributed tracing UI (port 16686)
72
96
  - **Prometheus**: Metrics storage (port 9090)
73
97
  - **Grafana**: Unified observability dashboard (port 3000)
98
+ - **Loki** _(full observability only)_: Log aggregation (port 3100)
74
99
 
75
100
  ### Connection Strings
76
101
 
@@ -100,6 +125,7 @@ glueConfig:
100
125
  2. Publish/subscribe to messages via your chosen broker
101
126
  3. View distributed traces in Jaeger at http://localhost:16686
102
127
  4. Monitor metrics in Grafana at http://localhost:3000
128
+ 5. _(Full observability)_ Query logs in Loki via Grafana at http://localhost:3000
103
129
 
104
130
  ### Distributed Tracing
105
131
 
@@ -12,13 +12,7 @@ tags: [preset, api, web, backend, observability]
12
12
  # Overlays to select
13
13
  selects:
14
14
  # Always included
15
- required:
16
- - postgres
17
- - redis
18
- - otel-collector
19
- - prometheus
20
- - grafana
21
- - loki
15
+ required: []
22
16
 
23
17
  # User makes choices
24
18
  userChoice:
@@ -28,31 +22,70 @@ selects:
28
22
  options: [dotnet, nodejs, python, go, java]
29
23
  defaultOption: nodejs
30
24
 
25
+ # Parameterized slots - users can customize these without micro-managing individual overlays
26
+ parameters:
27
+ database:
28
+ description: 'Primary data store'
29
+ default: postgres
30
+ options:
31
+ - id: postgres
32
+ overlays: [postgres]
33
+ description: 'PostgreSQL relational database'
34
+ - id: mongodb
35
+ overlays: [mongodb]
36
+ description: 'MongoDB document database'
37
+ - id: mysql
38
+ overlays: [mysql]
39
+ description: 'MySQL relational database'
40
+ - id: none
41
+ overlays: []
42
+ description: 'No database (manage separately)'
43
+
44
+ cache:
45
+ description: 'In-memory cache'
46
+ default: redis
47
+ options:
48
+ - id: redis
49
+ overlays: [redis]
50
+ description: 'Redis cache and session store'
51
+ - id: none
52
+ overlays: []
53
+ description: 'No cache'
54
+
55
+ broker:
56
+ description: 'Message broker (optional)'
57
+ default: none
58
+ options:
59
+ - id: rabbitmq
60
+ overlays: [rabbitmq]
61
+ description: 'RabbitMQ AMQP message broker'
62
+ - id: nats
63
+ overlays: [nats]
64
+ description: 'NATS lightweight messaging'
65
+ - id: redpanda
66
+ overlays: [redpanda]
67
+ description: 'Redpanda Kafka-compatible streaming'
68
+ - id: none
69
+ overlays: []
70
+ description: 'No message broker'
71
+
72
+ observability:
73
+ description: 'Monitoring and observability stack'
74
+ default: standard
75
+ options:
76
+ - id: minimal
77
+ overlays: []
78
+ description: 'No observability tools'
79
+ - id: standard
80
+ overlays: [prometheus, grafana]
81
+ description: 'Metrics and dashboards'
82
+ - id: full
83
+ overlays: [otel-collector, prometheus, grafana, loki]
84
+ description: 'Full stack - metrics, logs, and traces'
85
+
31
86
  # Glue configuration - integration helpers
32
87
  glueConfig:
33
- # Pre-configured environment variables
34
- environment:
35
- # Database connection
36
- DATABASE_URL: 'postgresql://postgres:postgres@postgres:5432/myapp'
37
- POSTGRES_HOST: 'postgres'
38
- POSTGRES_PORT: '5432'
39
- POSTGRES_DB: 'myapp'
40
- POSTGRES_USER: 'postgres'
41
- POSTGRES_PASSWORD: 'postgres'
42
-
43
- # Redis connection
44
- REDIS_URL: 'redis://redis:6379'
45
- REDIS_HOST: 'redis'
46
- REDIS_PORT: '6379'
47
-
48
- # OpenTelemetry configuration
49
- OTEL_EXPORTER_OTLP_ENDPOINT: 'http://otel-collector:4317'
50
- OTEL_SERVICE_NAME: 'api-service'
51
- OTEL_METRICS_EXPORTER: 'otlp'
52
- OTEL_TRACES_EXPORTER: 'otlp'
53
- OTEL_LOGS_EXPORTER: 'otlp'
54
-
55
- # Suggested port mappings
88
+ # Suggested port mappings (actual ports depend on chosen overlays)
56
89
  portMappings:
57
90
  api: 8000
58
91
  grafana: 3000
@@ -62,40 +95,28 @@ glueConfig:
62
95
  readme: |
63
96
  ## Web API Stack
64
97
 
65
- This devcontainer is configured with a complete API development stack:
66
-
67
- ### Services
68
-
69
- - **PostgreSQL**: Primary database (port 5432)
70
- - **Redis**: Cache and session store (port 6379)
71
- - **OpenTelemetry Collector**: Telemetry aggregation (ports 4317, 4318)
72
- - **Prometheus**: Metrics storage (port 9090)
73
- - **Grafana**: Observability dashboard (port 3000)
74
- - **Loki**: Log aggregation (port 3100)
98
+ This devcontainer is configured for web API development. The exact services depend
99
+ on the parameters you chose (database, cache, broker, observability).
75
100
 
76
101
  ### Connection Strings
77
102
 
78
- ```bash
79
- # PostgreSQL
80
- DATABASE_URL="postgresql://postgres:postgres@postgres:5432/myapp"
81
-
82
- # Redis
83
- REDIS_URL="redis://redis:6379"
103
+ Connection strings for each service are defined in `.devcontainer/.env.example`.
104
+ Copy that file to `.env` and adjust values as needed:
84
105
 
85
- # OpenTelemetry
86
- OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-collector:4317"
106
+ ```bash
107
+ cd .devcontainer
108
+ cp .env.example .env
87
109
  ```
88
110
 
89
111
  ### Quick Start
90
112
 
91
- 1. Start your API on port 8000 (configured in this preset)
92
- 2. Access Grafana at http://localhost:3000 (admin/admin)
93
- 3. View metrics in Prometheus at http://localhost:9090
94
- 4. Check logs in Loki via Grafana
113
+ 1. Start your API (default suggested port: 8000)
114
+ 2. Access Grafana at http://localhost:3000 (admin/admin) — if observability was enabled
115
+ 3. View metrics in Prometheus at http://localhost:9090 — if observability was enabled
95
116
 
96
117
  ### Health Checks
97
118
 
98
- All services include health checks. Verify with:
119
+ Verify all services are running:
99
120
 
100
121
  ```bash
101
122
  docker-compose ps
@@ -103,7 +124,6 @@ glueConfig:
103
124
 
104
125
  ### Next Steps
105
126
 
106
- - Configure your API to use the DATABASE_URL and REDIS_URL
107
- - Add OpenTelemetry SDK to your application
127
+ - Configure your API to use the connection strings from `.env`
128
+ - Add OpenTelemetry SDK to your application (if full observability was selected)
108
129
  - Create custom Grafana dashboards for your API metrics
109
- - Set up log forwarding to Loki