container-superposition 0.1.1 → 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 (178) hide show
  1. package/README.md +569 -8
  2. package/dist/scripts/init.js +436 -254
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/commands/doctor.d.ts +15 -0
  5. package/dist/tool/commands/doctor.d.ts.map +1 -0
  6. package/dist/tool/commands/doctor.js +862 -0
  7. package/dist/tool/commands/doctor.js.map +1 -0
  8. package/dist/tool/commands/explain.d.ts +13 -0
  9. package/dist/tool/commands/explain.d.ts.map +1 -0
  10. package/dist/tool/commands/explain.js +299 -0
  11. package/dist/tool/commands/explain.js.map +1 -0
  12. package/dist/tool/commands/list.d.ts +16 -0
  13. package/dist/tool/commands/list.d.ts.map +1 -0
  14. package/dist/tool/commands/list.js +121 -0
  15. package/dist/tool/commands/list.js.map +1 -0
  16. package/dist/tool/commands/plan.d.ts +67 -0
  17. package/dist/tool/commands/plan.d.ts.map +1 -0
  18. package/dist/tool/commands/plan.js +851 -0
  19. package/dist/tool/commands/plan.js.map +1 -0
  20. package/dist/tool/questionnaire/composer.d.ts +16 -2
  21. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  22. package/dist/tool/questionnaire/composer.js +411 -200
  23. package/dist/tool/questionnaire/composer.js.map +1 -1
  24. package/dist/tool/readme/markdown-parser.d.ts.map +1 -1
  25. package/dist/tool/readme/markdown-parser.js.map +1 -1
  26. package/dist/tool/readme/readme-generator.d.ts.map +1 -1
  27. package/dist/tool/readme/readme-generator.js +11 -6
  28. package/dist/tool/readme/readme-generator.js.map +1 -1
  29. package/dist/tool/schema/deployment-targets.d.ts +77 -0
  30. package/dist/tool/schema/deployment-targets.d.ts.map +1 -0
  31. package/dist/tool/schema/deployment-targets.js +91 -0
  32. package/dist/tool/schema/deployment-targets.js.map +1 -0
  33. package/dist/tool/schema/manifest-migrations.d.ts +51 -0
  34. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -0
  35. package/dist/tool/schema/manifest-migrations.js +159 -0
  36. package/dist/tool/schema/manifest-migrations.js.map +1 -0
  37. package/dist/tool/schema/overlay-loader.d.ts +1 -1
  38. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  39. package/dist/tool/schema/overlay-loader.js +42 -14
  40. package/dist/tool/schema/overlay-loader.js.map +1 -1
  41. package/dist/tool/schema/types.d.ts +62 -2
  42. package/dist/tool/schema/types.d.ts.map +1 -1
  43. package/dist/tool/utils/gitignore.d.ts +15 -0
  44. package/dist/tool/utils/gitignore.d.ts.map +1 -0
  45. package/dist/tool/utils/gitignore.js +41 -0
  46. package/dist/tool/utils/gitignore.js.map +1 -0
  47. package/dist/tool/utils/merge.d.ts +134 -0
  48. package/dist/tool/utils/merge.d.ts.map +1 -0
  49. package/dist/tool/utils/merge.js +277 -0
  50. package/dist/tool/utils/merge.js.map +1 -0
  51. package/dist/tool/utils/port-utils.d.ts +29 -0
  52. package/dist/tool/utils/port-utils.d.ts.map +1 -0
  53. package/dist/tool/utils/port-utils.js +128 -0
  54. package/dist/tool/utils/port-utils.js.map +1 -0
  55. package/dist/tool/utils/services-export.d.ts +14 -0
  56. package/dist/tool/utils/services-export.d.ts.map +1 -0
  57. package/dist/tool/utils/services-export.js +478 -0
  58. package/dist/tool/utils/services-export.js.map +1 -0
  59. package/dist/tool/utils/summary.d.ts +69 -0
  60. package/dist/tool/utils/summary.d.ts.map +1 -0
  61. package/dist/tool/utils/summary.js +260 -0
  62. package/dist/tool/utils/summary.js.map +1 -0
  63. package/dist/tool/utils/version.d.ts +9 -0
  64. package/dist/tool/utils/version.d.ts.map +1 -0
  65. package/dist/tool/utils/version.js +32 -0
  66. package/dist/tool/utils/version.js.map +1 -0
  67. package/docs/architecture.md +25 -21
  68. package/docs/deployment-targets.md +150 -0
  69. package/docs/discovery-commands.md +442 -0
  70. package/docs/merge-strategy.md +700 -0
  71. package/docs/minimal-and-editor.md +265 -0
  72. package/docs/overlay-imports.md +209 -0
  73. package/docs/overlay-manifest-refactoring.md +2 -2
  74. package/docs/overlay-metadata-archive.md +1 -1
  75. package/docs/overlays.md +139 -28
  76. package/docs/presets-architecture.md +3 -3
  77. package/docs/presets.md +1 -1
  78. package/docs/publishing.md +36 -35
  79. package/docs/team-workflow.md +540 -0
  80. package/overlays/.presets/data-engineering.yml +392 -0
  81. package/overlays/.presets/event-sourced-service.yml +262 -0
  82. package/overlays/.presets/frontend.yml +287 -0
  83. package/overlays/.presets/k8s-operator-dev.yml +462 -0
  84. package/overlays/{presets → .presets}/microservice.yml +32 -6
  85. package/overlays/.presets/web-api.yml +129 -0
  86. package/overlays/.registry/README.md +1 -1
  87. package/overlays/.registry/deployment-targets.yml +54 -0
  88. package/overlays/.shared/README.md +43 -0
  89. package/overlays/.shared/compose/common-healthchecks.yml +38 -0
  90. package/overlays/.shared/otel/instrumentation.env +20 -0
  91. package/overlays/.shared/otel/otel-base-config.yaml +30 -0
  92. package/overlays/.shared/vscode/recommended-extensions.json +14 -0
  93. package/overlays/README.md +1 -1
  94. package/overlays/cloudflared/README.md +190 -0
  95. package/overlays/cloudflared/devcontainer.patch.json +3 -0
  96. package/overlays/cloudflared/overlay.yml +15 -0
  97. package/overlays/cloudflared/setup.sh +49 -0
  98. package/overlays/cloudflared/verify.sh +21 -0
  99. package/overlays/codex/overlay.yml +1 -0
  100. package/overlays/direnv/README.md +6 -4
  101. package/overlays/direnv/setup.sh +0 -12
  102. package/overlays/duckdb/README.md +274 -0
  103. package/overlays/duckdb/devcontainer.patch.json +10 -0
  104. package/overlays/duckdb/overlay.yml +17 -0
  105. package/overlays/duckdb/setup.sh +45 -0
  106. package/overlays/duckdb/verify.sh +32 -0
  107. package/overlays/git-helpers/overlay.yml +1 -0
  108. package/overlays/grafana/README.md +5 -5
  109. package/overlays/grafana/dashboard-provider.yml +1 -1
  110. package/overlays/grafana/docker-compose.yml +2 -2
  111. package/overlays/grafana/overlay.yml +6 -1
  112. package/overlays/grpc-tools/README.md +242 -0
  113. package/overlays/grpc-tools/devcontainer.patch.json +14 -0
  114. package/overlays/grpc-tools/overlay.yml +14 -0
  115. package/overlays/grpc-tools/setup.sh +57 -0
  116. package/overlays/grpc-tools/verify.sh +47 -0
  117. package/overlays/jaeger/overlay.yml +16 -3
  118. package/overlays/jupyter/.env.example +6 -0
  119. package/overlays/jupyter/README.md +210 -0
  120. package/overlays/jupyter/devcontainer.patch.json +14 -0
  121. package/overlays/jupyter/docker-compose.yml +23 -0
  122. package/overlays/jupyter/overlay.yml +18 -0
  123. package/overlays/jupyter/verify.sh +35 -0
  124. package/overlays/keycloak/.env.example +5 -0
  125. package/overlays/keycloak/README.md +238 -0
  126. package/overlays/keycloak/devcontainer.patch.json +17 -0
  127. package/overlays/keycloak/docker-compose.yml +32 -0
  128. package/overlays/keycloak/overlay.yml +23 -0
  129. package/overlays/keycloak/verify.sh +54 -0
  130. package/overlays/kind/README.md +221 -0
  131. package/overlays/kind/devcontainer.patch.json +10 -0
  132. package/overlays/kind/overlay.yml +18 -0
  133. package/overlays/kind/setup.sh +43 -0
  134. package/overlays/kind/verify.sh +40 -0
  135. package/overlays/localstack/.env.example +6 -0
  136. package/overlays/localstack/README.md +188 -0
  137. package/overlays/localstack/devcontainer.patch.json +21 -0
  138. package/overlays/localstack/docker-compose.yml +25 -0
  139. package/overlays/localstack/overlay.yml +18 -0
  140. package/overlays/localstack/verify.sh +47 -0
  141. package/overlays/loki/overlay.yml +6 -1
  142. package/overlays/mailpit/.env.example +4 -0
  143. package/overlays/mailpit/README.md +191 -0
  144. package/overlays/mailpit/devcontainer.patch.json +20 -0
  145. package/overlays/mailpit/docker-compose.yml +17 -0
  146. package/overlays/mailpit/overlay.yml +26 -0
  147. package/overlays/mailpit/verify.sh +52 -0
  148. package/overlays/modern-cli-tools/overlay.yml +1 -0
  149. package/overlays/mongodb/overlay.yml +12 -2
  150. package/overlays/mysql/overlay.yml +12 -2
  151. package/overlays/nats/overlay.yml +12 -2
  152. package/overlays/ngrok/overlay.yml +2 -1
  153. package/overlays/openapi-tools/README.md +243 -0
  154. package/overlays/openapi-tools/devcontainer.patch.json +10 -0
  155. package/overlays/openapi-tools/overlay.yml +16 -0
  156. package/overlays/openapi-tools/setup.sh +45 -0
  157. package/overlays/openapi-tools/verify.sh +51 -0
  158. package/overlays/otel-collector/overlay.yml.example +26 -0
  159. package/overlays/postgres/overlay.yml +6 -1
  160. package/overlays/prometheus/overlay.yml +6 -1
  161. package/overlays/python/README.md +51 -35
  162. package/overlays/python/devcontainer.patch.json +7 -4
  163. package/overlays/python/setup.sh +50 -23
  164. package/overlays/python/verify.sh +29 -1
  165. package/overlays/rabbitmq/overlay.yml +12 -2
  166. package/overlays/redis/overlay.yml +6 -1
  167. package/overlays/tilt/README.md +259 -0
  168. package/overlays/tilt/devcontainer.patch.json +17 -0
  169. package/overlays/tilt/overlay.yml +19 -0
  170. package/overlays/tilt/setup.sh +25 -0
  171. package/overlays/tilt/verify.sh +24 -0
  172. package/package.json +8 -6
  173. package/tool/README.md +12 -16
  174. package/tool/schema/overlay-manifest.schema.json +64 -4
  175. package/tool/schema/superposition-manifest.schema.json +104 -0
  176. package/overlays/presets/web-api.yml +0 -109
  177. /package/overlays/{presets → .presets}/docs-site.yml +0 -0
  178. /package/overlays/{presets → .presets}/fullstack.yml +0 -0
@@ -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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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Utility functions for version management
3
+ */
4
+ /**
5
+ * Get the current tool version from package.json
6
+ * Works in both source (TypeScript) and compiled (JavaScript) contexts
7
+ */
8
+ export declare function getToolVersion(): string;
9
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../tool/utils/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAmBvC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Utility functions for version management
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ // Get __dirname equivalent in ESM
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ /**
11
+ * Get the current tool version from package.json
12
+ * Works in both source (TypeScript) and compiled (JavaScript) contexts
13
+ */
14
+ export function getToolVersion() {
15
+ try {
16
+ // Try multiple paths to handle different execution contexts
17
+ const packageJsonCandidates = [
18
+ // From tool/utils/ (source)
19
+ path.join(__dirname, '..', '..', 'package.json'),
20
+ // From dist/tool/utils/ (compiled)
21
+ path.join(__dirname, '..', '..', '..', 'package.json'),
22
+ ];
23
+ const packageJsonPath = packageJsonCandidates.find((candidate) => fs.existsSync(candidate)) ??
24
+ packageJsonCandidates[0];
25
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
26
+ return packageJson.version || 'unknown';
27
+ }
28
+ catch (error) {
29
+ return 'unknown';
30
+ }
31
+ }
32
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../tool/utils/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,kCAAkC;AAClC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC1B,IAAI,CAAC;QACD,4DAA4D;QAC5D,MAAM,qBAAqB,GAAG;YAC1B,4BAA4B;YAC5B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;YAChD,mCAAmC;YACnC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;SACzD,CAAC;QAEF,MAAM,eAAe,GACjB,qBAAqB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACnE,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1E,OAAO,WAAW,CAAC,OAAO,IAAI,SAAS,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC"}
@@ -74,29 +74,33 @@ scripts/
74
74
  5. **Merge .env.example** files from all selected overlays
75
75
  6. **Write merged configuration** to output path
76
76
 
77
- ### Deep Merge Logic
78
-
79
- ```typescript
80
- function deepMerge(base, overlay) {
81
- for each key in overlay:
82
- if key exists in base and both are objects:
83
- if both are arrays:
84
- concatenate and deduplicate
85
- else:
86
- recursively merge
87
- else:
88
- use overlay value
89
- return merged
90
- }
91
- ```
77
+ ### Merge Strategy
78
+
79
+ Container-superposition uses a **formal, deterministic merge strategy** for combining configurations from base templates and overlays.
80
+
81
+ **Core principles:**
82
+
83
+ - **Deterministic**: Same inputs always produce same output
84
+ - **Deep merge**: Objects are recursively merged, not replaced
85
+ - **Union by default**: Arrays and collections are merged (unioned), not replaced
86
+ - **Last writer wins**: For conflicting primitive values
87
+
88
+ **Key behaviors:**
89
+
90
+ - **Objects**: Recursively merged
91
+ - **Arrays**: Concatenated and deduplicated (union strategy)
92
+ - **Features**: Deep merged by feature key
93
+ - **remoteEnv**: Intelligent PATH variable merging
94
+ - **Package lists**: Space-separated strings merged with deduplication
95
+ - **depends_on**: Filtered to only existing services
96
+
97
+ For the complete specification with examples, see **[Merge Strategy Specification](merge-strategy.md)**.
92
98
 
93
- Special handling:
99
+ Implementation details:
94
100
 
95
- - **Arrays**: Concatenate and deduplicate (ports, packages)
96
- - **apt-get packages**: Merge space-separated lists
97
- - **Features**: Deep merge feature configs
98
- - **Environment variables**: Merge key-value pairs
99
- - **Port attributes**: Merge labeled port configurations
101
+ - Merge utilities: `tool/utils/merge.ts`
102
+ - Integration: `tool/questionnaire/composer.ts`
103
+ - Tests: `tool/__tests__/merge-strategy.test.ts`
100
104
 
101
105
  ### File Handling per Overlay
102
106
 
@@ -0,0 +1,150 @@
1
+ # Deployment Target Support
2
+
3
+ Container Superposition validates overlay compatibility with different deployment environments using the `--target` flag.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Specify deployment target
9
+ npx container-superposition init --target codespaces
10
+ npx container-superposition init --target gitpod
11
+ npx container-superposition init --target local # default
12
+
13
+ # With specific configuration
14
+ npx container-superposition init \
15
+ --stack compose \
16
+ --language nodejs \
17
+ --database postgres \
18
+ --dev-tools docker-in-docker \
19
+ --target codespaces
20
+ ```
21
+
22
+ ## Supported Deployment Targets
23
+
24
+ | Target | Description | Docker Support | Auto Port Forward |
25
+ | -------------- | --------------------------------- | -------------- | ----------------- |
26
+ | **local** | Local machine with Docker Desktop | ✅ Host Docker | No |
27
+ | **codespaces** | GitHub Codespaces (cloud IDE) | ⚠️ DinD only | Yes |
28
+ | **gitpod** | Gitpod workspaces | ⚠️ DinD only | Yes |
29
+ | **devpod** | DevPod client-only environments | ✅ Host Docker | No |
30
+
31
+ ## How It Works
32
+
33
+ ### Interactive Mode
34
+
35
+ If you select incompatible overlays (e.g., `docker-sock` for Codespaces), the tool will:
36
+
37
+ - Show which overlays won't work in your target environment
38
+ - Suggest compatible alternatives
39
+ - Let you choose your deployment target with informed guidance
40
+
41
+ **Example interaction:**
42
+
43
+ ```
44
+ ⚠️ Deployment Target Compatibility Check:
45
+
46
+ Some selected overlays may not work in all environments.
47
+
48
+ • Docker (host socket)
49
+ Not compatible with: GitHub Codespaces, Gitpod
50
+ Alternatives: Docker-in-Docker
51
+
52
+ Which environment are you targeting?
53
+ ❯ 🖥️ Local Development (Docker Desktop)
54
+ ☁️ GitHub Codespaces
55
+ 🌐 Gitpod
56
+ 📦 DevPod
57
+ ```
58
+
59
+ ### CLI Mode
60
+
61
+ The target validates your selection and generates the configuration:
62
+
63
+ - Incompatibilities are allowed (you know what you're doing)
64
+ - Generated documentation notes any compatibility issues
65
+
66
+ ## Example Configurations
67
+
68
+ ### Optimized for GitHub Codespaces
69
+
70
+ ```bash
71
+ npx container-superposition init \
72
+ --stack compose \
73
+ --language nodejs \
74
+ --database postgres \
75
+ --dev-tools docker-in-docker \
76
+ --target codespaces
77
+ ```
78
+
79
+ ### Local Development
80
+
81
+ ```bash
82
+ npx container-superposition init \
83
+ --stack compose \
84
+ --language nodejs \
85
+ --database postgres \
86
+ --dev-tools docker-sock \
87
+ --target local
88
+ ```
89
+
90
+ ## Key Compatibility Rules
91
+
92
+ - ⚠️ **docker-sock** requires host Docker → Use in `local` or `devpod` only
93
+ - ✅ **docker-in-docker** works everywhere → Recommended for `codespaces` and `gitpod`
94
+ - 🔄 Cloud targets auto-forward ports → No manual forwarding needed
95
+
96
+ ## Environment Differences
97
+
98
+ Different environments have different capabilities:
99
+
100
+ ### Codespaces/Gitpod
101
+
102
+ - **No access to host Docker daemon** - Must use docker-in-docker
103
+ - **Auto-forward ports** - Ports are automatically accessible
104
+ - **Cloud-based** - Resources may be constrained
105
+
106
+ ### Local
107
+
108
+ - **Full access to host Docker** - Can use docker-sock for better performance
109
+ - **Faster builds** - Shared cache with host
110
+ - **Manual port forwarding** - Need to expose ports explicitly
111
+
112
+ ### DevPod
113
+
114
+ - **Client-managed** - Runs on your infrastructure
115
+ - **Can access host Docker** - Depending on setup
116
+ - **Flexible** - Configure based on your needs
117
+
118
+ ## Why Deployment Targets?
119
+
120
+ The target system ensures you get warnings about incompatibilities before deploying. This prevents:
121
+
122
+ - Wasted time debugging environment-specific issues
123
+ - Confusion about why overlays don't work in cloud IDEs
124
+ - Having to manually research compatibility
125
+
126
+ ## Configuration
127
+
128
+ Target configurations are stored in `overlays/.registry/deployment-targets.yml`. To add a new target, simply add an entry to this file:
129
+
130
+ ```yaml
131
+ - id: new-target
132
+ name: New Target
133
+ description: Description of the target
134
+ incompatibleOverlays:
135
+ - docker-sock
136
+ recommendations:
137
+ docker-sock:
138
+ - docker-in-docker
139
+ portForwarding:
140
+ defaultBehavior: notify
141
+ autoForward: true
142
+ constraints:
143
+ hasHostDocker: false
144
+ supportsPrivileged: true
145
+ ```
146
+
147
+ ## See Also
148
+
149
+ - [Discovery Commands](discovery-commands.md) - Explore overlays before generating
150
+ - [Overlays Documentation](overlays.md) - Complete overlay reference