composable.env 0.1.3 → 0.2.1

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 (47) hide show
  1. package/dist/cli/commands/build.d.ts +3 -0
  2. package/dist/cli/commands/build.d.ts.map +1 -0
  3. package/dist/cli/commands/build.js +37 -0
  4. package/dist/cli/commands/build.js.map +1 -0
  5. package/dist/cli/commands/init.d.ts +3 -0
  6. package/dist/cli/commands/init.d.ts.map +1 -0
  7. package/dist/cli/commands/init.js +195 -0
  8. package/dist/cli/commands/init.js.map +1 -0
  9. package/dist/cli/commands/list.d.ts +3 -0
  10. package/dist/cli/commands/list.d.ts.map +1 -0
  11. package/dist/cli/commands/list.js +21 -0
  12. package/dist/cli/commands/list.js.map +1 -0
  13. package/dist/cli/commands/run.d.ts +3 -0
  14. package/dist/cli/commands/run.d.ts.map +1 -0
  15. package/dist/cli/commands/run.js +35 -0
  16. package/dist/cli/commands/run.js.map +1 -0
  17. package/dist/cli/commands/script.d.ts +3 -0
  18. package/dist/cli/commands/script.d.ts.map +1 -0
  19. package/dist/cli/commands/script.js +47 -0
  20. package/dist/cli/commands/script.js.map +1 -0
  21. package/dist/cli/commands/uninstall.d.ts +3 -0
  22. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  23. package/dist/cli/commands/uninstall.js +141 -0
  24. package/dist/cli/commands/uninstall.js.map +1 -0
  25. package/dist/cli/index.js +14 -214
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/src/builder.d.ts.map +1 -1
  28. package/dist/src/builder.js +7 -3
  29. package/dist/src/builder.js.map +1 -1
  30. package/dist/src/contracts.d.ts.map +1 -1
  31. package/dist/src/contracts.js +27 -7
  32. package/dist/src/contracts.js.map +1 -1
  33. package/dist/src/index.d.ts +2 -0
  34. package/dist/src/index.d.ts.map +1 -1
  35. package/dist/src/index.js +1 -0
  36. package/dist/src/index.js.map +1 -1
  37. package/dist/src/markers.d.ts +19 -0
  38. package/dist/src/markers.d.ts.map +1 -0
  39. package/dist/src/markers.js +76 -0
  40. package/dist/src/markers.js.map +1 -0
  41. package/examples/fullstack/env/contracts/api.contract.json +17 -0
  42. package/examples/fullstack/env/contracts/web.contract.json +15 -0
  43. package/examples/fullstack/env/contracts/worker.contract.json +21 -0
  44. package/package.json +2 -1
  45. package/examples/fullstack/env/contracts/api.contract.ts +0 -24
  46. package/examples/fullstack/env/contracts/web.contract.ts +0 -20
  47. package/examples/fullstack/env/contracts/worker.contract.ts +0 -28
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerBuildCommand(program: Command): void;
3
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../cli/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiC3D"}
@@ -0,0 +1,37 @@
1
+ import chalk from 'chalk';
2
+ import { EnvironmentBuilder } from '../../src/index.js';
3
+ export function registerBuildCommand(program) {
4
+ program
5
+ .command('build')
6
+ .description('Build .cenv files from a profile')
7
+ .requiredOption('-p, --profile <name>', 'Profile name (e.g., production, staging)')
8
+ .option('-o, --output <path>', 'Output path for single-file builds', '.env')
9
+ .action(async (options) => {
10
+ const configDir = process.cwd();
11
+ const builder = new EnvironmentBuilder(configDir, options.output, options.profile);
12
+ try {
13
+ console.log(chalk.blue(`Building from profile: ${options.profile}`));
14
+ const result = await builder.buildFromProfile(options.profile);
15
+ if (result.success) {
16
+ console.log(chalk.green(`\u2705 Environment built successfully`));
17
+ if (result.warnings?.length) {
18
+ result.warnings.forEach(w => console.log(chalk.yellow(` ${w}`)));
19
+ }
20
+ console.log(chalk.gray(` Files: ${result.envPath}`));
21
+ }
22
+ else {
23
+ console.error(chalk.red('\u274c Build failed:'));
24
+ result.errors?.forEach(e => console.error(chalk.red(` ${e}`)));
25
+ if (result.warnings?.length) {
26
+ result.warnings.forEach(w => console.log(chalk.yellow(` ${w}`)));
27
+ }
28
+ process.exit(1);
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error(chalk.red(`\u274c Unexpected error: ${error}`));
33
+ process.exit(1);
34
+ }
35
+ });
36
+ }
37
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../cli/commands/build.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,cAAc,CAAC,sBAAsB,EAAE,0CAA0C,CAAC;SAClF,MAAM,CAAC,qBAAqB,EAAE,oCAAoC,EAAE,MAAM,CAAC;SAC3E,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAEnF,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAE/D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;gBAClE,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC5B,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACrE,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;gBACjD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACjE,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC5B,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACrE,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerInitCommand(program: Command): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../cli/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsH1D"}
@@ -0,0 +1,195 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import chalk from 'chalk';
4
+ import { ManagedJsonRegistry, wrapWithMarkers, hasMarkerBlock, replaceMarkerBlock, } from '../../src/index.js';
5
+ export function registerInitCommand(program) {
6
+ program
7
+ .command('init')
8
+ .description('Scaffold a new composable.env directory structure')
9
+ .option('--examples', 'Include example files for all parts of the system')
10
+ .action(async (options) => {
11
+ const cwd = process.cwd();
12
+ const registry = new ManagedJsonRegistry(cwd);
13
+ const dirs = [
14
+ 'env/components',
15
+ 'env/profiles',
16
+ 'env/contracts',
17
+ ];
18
+ for (const dir of dirs) {
19
+ const fullPath = path.join(cwd, dir);
20
+ if (!fs.existsSync(fullPath)) {
21
+ fs.mkdirSync(fullPath, { recursive: true });
22
+ console.log(chalk.green(` created ${dir}/`));
23
+ }
24
+ }
25
+ // Scaffold default.json
26
+ const defaultPath = path.join(cwd, 'env/profiles/default.json');
27
+ if (!fs.existsSync(defaultPath)) {
28
+ fs.writeFileSync(defaultPath, JSON.stringify({
29
+ name: 'Default',
30
+ description: 'All available components',
31
+ components: [],
32
+ }, null, 2) + '\n');
33
+ console.log(chalk.green(' created env/profiles/default.json'));
34
+ }
35
+ // Scaffold .env.shared
36
+ const sharedPath = path.join(cwd, 'env/.env.shared');
37
+ if (!fs.existsSync(sharedPath)) {
38
+ fs.writeFileSync(sharedPath, '# Shared team values — commit this file to version control\n' +
39
+ '# Applied AFTER components, BEFORE .env.local\n' +
40
+ '# No secrets here — use .env.local or a secrets manager for those\n');
41
+ console.log(chalk.green(' created env/.env.shared'));
42
+ }
43
+ // Scaffold .env.local
44
+ const localPath = path.join(cwd, 'env/.env.local');
45
+ if (!fs.existsSync(localPath)) {
46
+ fs.writeFileSync(localPath, '# Personal overrides — DO NOT commit this file (gitignored)\n' +
47
+ '# Applied last, overrides everything else\n');
48
+ console.log(chalk.green(' created env/.env.local'));
49
+ }
50
+ // Scaffold .gitignore with markers
51
+ const gitignorePath = path.join(cwd, '.gitignore');
52
+ const gitignoreEntries = '.cenv.*\nenv/.env.local';
53
+ if (fs.existsSync(gitignorePath)) {
54
+ let content = fs.readFileSync(gitignorePath, 'utf8');
55
+ if (hasMarkerBlock(content)) {
56
+ content = replaceMarkerBlock(content, gitignoreEntries);
57
+ }
58
+ else {
59
+ content += '\n' + wrapWithMarkers(gitignoreEntries);
60
+ }
61
+ fs.writeFileSync(gitignorePath, content);
62
+ console.log(chalk.green(' updated .gitignore'));
63
+ }
64
+ else {
65
+ fs.writeFileSync(gitignorePath, wrapWithMarkers(gitignoreEntries));
66
+ console.log(chalk.green(' created .gitignore'));
67
+ }
68
+ // Detect turbo.json and add globalDependencies
69
+ const turboPath = path.join(cwd, 'turbo.json');
70
+ if (fs.existsSync(turboPath)) {
71
+ const turbo = JSON.parse(fs.readFileSync(turboPath, 'utf8'));
72
+ const deps = turbo.globalDependencies || [];
73
+ const toAdd = ['env/**', '.cenv.*'];
74
+ let changed = false;
75
+ for (const entry of toAdd) {
76
+ if (!deps.includes(entry)) {
77
+ deps.push(entry);
78
+ changed = true;
79
+ }
80
+ }
81
+ if (changed) {
82
+ turbo.globalDependencies = deps;
83
+ fs.writeFileSync(turboPath, JSON.stringify(turbo, null, 2) + '\n');
84
+ registry.register('turbo.json', 'globalDependencies', toAdd);
85
+ console.log(chalk.green(' updated turbo.json globalDependencies'));
86
+ }
87
+ }
88
+ // Scaffold example files when --examples is passed
89
+ if (options.examples) {
90
+ scaffoldExamples(cwd, defaultPath, sharedPath, localPath);
91
+ }
92
+ console.log('');
93
+ console.log(chalk.blue('Next steps:'));
94
+ console.log(' 1. Add component files to env/components/');
95
+ console.log(' 2. Define profiles in env/profiles/');
96
+ console.log(' 3. Add contract files to env/contracts/ (optional)');
97
+ console.log(' 4. Add shared values to env/.env.shared (commit this)');
98
+ console.log(' 5. Add local overrides to env/.env.local (gitignored)');
99
+ console.log(' 6. Run: cenv build --profile <name>');
100
+ });
101
+ }
102
+ function scaffoldExamples(cwd, defaultPath, sharedPath, localPath) {
103
+ console.log('');
104
+ console.log(chalk.blue('Scaffolding examples...'));
105
+ const exampleComponents = {
106
+ 'database.env': 'NAMESPACE=DATABASE\n\n' +
107
+ '[default]\n' +
108
+ 'HOST=localhost\nPORT=5432\nNAME=myapp_dev\nUSER=postgres\nPASSWORD=postgres\n\n' +
109
+ '[staging]\n' +
110
+ 'HOST=${DATABASE_STAGING_HOST}\nNAME=myapp_staging\nUSER=${DATABASE_STAGING_USER}\nPASSWORD=${DATABASE_STAGING_PASSWORD}\n\n' +
111
+ '[production]\n' +
112
+ 'HOST=${DATABASE_PROD_HOST}\nPORT=5432\nNAME=myapp\nUSER=${DATABASE_PROD_USER}\nPASSWORD=${DATABASE_PROD_PASSWORD}\n',
113
+ 'redis.env': 'NAMESPACE=REDIS\n\n' +
114
+ '[default]\n' +
115
+ 'HOST=localhost\nPORT=6379\nURL=redis://localhost:6379\nDB=0\n\n' +
116
+ '[staging]\n' +
117
+ 'HOST=${REDIS_STAGING_HOST}\nPORT=6379\nURL=redis://${REDIS_STAGING_HOST}:6379\nDB=0\n\n' +
118
+ '[production]\n' +
119
+ 'HOST=${REDIS_PROD_HOST}\nPORT=6379\nURL=redis://${REDIS_PROD_HOST}:6379\nDB=0\n',
120
+ };
121
+ const exampleProfiles = {
122
+ 'production.json': {
123
+ name: 'Production',
124
+ description: 'Production environment with remote services',
125
+ },
126
+ 'staging.json': {
127
+ name: 'Staging',
128
+ description: 'Staging environment — extends production',
129
+ extends: 'production',
130
+ },
131
+ };
132
+ const exampleContract = {
133
+ name: 'api',
134
+ location: 'apps/api',
135
+ required: {
136
+ DATABASE_URL: 'postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}',
137
+ REDIS_URL: 'REDIS_URL',
138
+ },
139
+ optional: {
140
+ LOG_LEVEL: 'LOG_LEVEL',
141
+ },
142
+ defaults: {
143
+ LOG_LEVEL: 'info',
144
+ },
145
+ };
146
+ const exampleShared = '# Shared team values — commit this file\n\n' +
147
+ '# Staging hosts\n' +
148
+ 'DATABASE_STAGING_HOST=db-staging.example.com\n' +
149
+ 'DATABASE_STAGING_USER=app_staging\n' +
150
+ 'REDIS_STAGING_HOST=redis-staging.example.com\n\n' +
151
+ '# Production hosts\n' +
152
+ 'DATABASE_PROD_HOST=db.example.com\n' +
153
+ 'DATABASE_PROD_USER=app_prod\n' +
154
+ 'REDIS_PROD_HOST=redis.example.com\n';
155
+ const exampleLocal = '# Personal overrides — DO NOT commit this file (gitignored)\n\n' +
156
+ '# Use a custom local database port\n' +
157
+ 'DATABASE_PORT=5433\n\n' +
158
+ '# Verbose logging during development\n' +
159
+ 'LOG_LEVEL=debug\n';
160
+ // Write components
161
+ for (const [filename, content] of Object.entries(exampleComponents)) {
162
+ const filePath = path.join(cwd, 'env/components', filename);
163
+ if (!fs.existsSync(filePath)) {
164
+ fs.writeFileSync(filePath, content);
165
+ console.log(chalk.green(` created env/components/${filename}`));
166
+ }
167
+ }
168
+ // Update default.json with example components
169
+ const defaultData = JSON.parse(fs.readFileSync(defaultPath, 'utf8'));
170
+ if (Array.isArray(defaultData.components) && defaultData.components.length === 0) {
171
+ defaultData.components = ['database', 'redis'];
172
+ fs.writeFileSync(defaultPath, JSON.stringify(defaultData, null, 2) + '\n');
173
+ console.log(chalk.green(' updated env/profiles/default.json with example components'));
174
+ }
175
+ // Write profiles
176
+ for (const [filename, data] of Object.entries(exampleProfiles)) {
177
+ const filePath = path.join(cwd, 'env/profiles', filename);
178
+ if (!fs.existsSync(filePath)) {
179
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
180
+ console.log(chalk.green(` created env/profiles/${filename}`));
181
+ }
182
+ }
183
+ // Write contract
184
+ const contractPath = path.join(cwd, 'env/contracts/api.contract.json');
185
+ if (!fs.existsSync(contractPath)) {
186
+ fs.writeFileSync(contractPath, JSON.stringify(exampleContract, null, 2) + '\n');
187
+ console.log(chalk.green(' created env/contracts/api.contract.json'));
188
+ }
189
+ // Write shared/local with example content
190
+ fs.writeFileSync(sharedPath, exampleShared);
191
+ console.log(chalk.green(' updated env/.env.shared with example values'));
192
+ fs.writeFileSync(localPath, exampleLocal);
193
+ console.log(chalk.green(' updated env/.env.local with example overrides'));
194
+ }
195
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerListCommand(program: Command): void;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../cli/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmB1D"}
@@ -0,0 +1,21 @@
1
+ import chalk from 'chalk';
2
+ import { EnvironmentBuilder } from '../../src/index.js';
3
+ export function registerListCommand(program) {
4
+ program
5
+ .command('list')
6
+ .description('List available profiles')
7
+ .action(() => {
8
+ const builder = new EnvironmentBuilder(process.cwd(), '');
9
+ const profiles = builder.listProfiles();
10
+ if (profiles.length === 0) {
11
+ console.log(chalk.yellow('No profiles found in env/profiles/'));
12
+ return;
13
+ }
14
+ console.log(chalk.blue('Available profiles:'));
15
+ profiles.forEach(({ name, description }) => {
16
+ console.log(` ${chalk.green(name)}`);
17
+ console.log(chalk.gray(` ${description}`));
18
+ });
19
+ });
20
+ }
21
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../cli/commands/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QACxC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oCAAoC,CAAC,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC/C,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE;YACzC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,WAAW,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerRunCommand(program: Command): void;
3
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../cli/commands/run.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkCzD"}
@@ -0,0 +1,35 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { spawn } from 'child_process';
4
+ import chalk from 'chalk';
5
+ import dotenv from 'dotenv';
6
+ export function registerRunCommand(program) {
7
+ program
8
+ .command('run')
9
+ .description('Load a .cenv profile and run a command')
10
+ .requiredOption('-p, --profile <name>', 'Profile name')
11
+ .argument('<command...>', 'Command to execute (use -- before the command)')
12
+ .passThroughOptions()
13
+ .action((commandArgs, options) => {
14
+ const cwd = process.cwd();
15
+ const envFile = path.join(cwd, `.cenv.${options.profile}`);
16
+ if (!fs.existsSync(envFile)) {
17
+ console.error(chalk.red(`\u274c .cenv.${options.profile} not found in ${cwd}\n` +
18
+ ` Run "cenv build --profile ${options.profile}" first.`));
19
+ process.exit(1);
20
+ }
21
+ dotenv.config({ path: envFile, override: true });
22
+ const [cmd, ...args] = commandArgs;
23
+ const child = spawn(cmd, args, {
24
+ stdio: 'inherit',
25
+ env: process.env,
26
+ shell: true,
27
+ });
28
+ child.on('close', (code) => process.exit(code ?? 1));
29
+ child.on('error', (err) => {
30
+ console.error(chalk.red(`\u274c Failed to start command: ${err.message}`));
31
+ process.exit(1);
32
+ });
33
+ });
34
+ }
35
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../cli/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,wCAAwC,CAAC;SACrD,cAAc,CAAC,sBAAsB,EAAE,cAAc,CAAC;SACtD,QAAQ,CAAC,cAAc,EAAE,gDAAgD,CAAC;SAC1E,kBAAkB,EAAE;SACpB,MAAM,CAAC,CAAC,WAAqB,EAAE,OAA4B,EAAE,EAAE;QAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAE3D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CACrB,gBAAgB,OAAO,CAAC,OAAO,iBAAiB,GAAG,IAAI;gBACvD,gCAAgC,OAAO,CAAC,OAAO,UAAU,CAC1D,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;YAC7B,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACrD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerScriptCommand(program: Command): void;
3
+ //# sourceMappingURL=script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../cli/commands/script.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgD5D"}
@@ -0,0 +1,47 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import chalk from 'chalk';
4
+ import { EnvironmentBuilder, ManagedJsonRegistry } from '../../src/index.js';
5
+ export function registerScriptCommand(program) {
6
+ program
7
+ .command('script')
8
+ .description('Inject profile-aware scripts into package.json')
9
+ .argument('<name>', 'Script name (e.g., "dev", "build")')
10
+ .requiredOption('-c, --command <cmd>', 'Command to wrap (e.g., "turbo dev")')
11
+ .action((name, options) => {
12
+ const cwd = process.cwd();
13
+ const builder = new EnvironmentBuilder(cwd, '');
14
+ const profiles = builder.listProfiles();
15
+ if (profiles.length === 0) {
16
+ console.error(chalk.red('\u274c No profiles found in env/profiles/'));
17
+ process.exit(1);
18
+ }
19
+ const scripts = {};
20
+ // Default profile gets the base name
21
+ scripts[name] = `cenv run --profile default -- ${options.command}`;
22
+ // Every other profile gets name:profile
23
+ for (const profile of profiles) {
24
+ if (profile.name === 'default')
25
+ continue;
26
+ scripts[`${name}:${profile.name}`] =
27
+ `cenv run --profile ${profile.name} -- ${options.command}`;
28
+ }
29
+ // Read package.json, merge scripts
30
+ const pkgPath = path.join(cwd, 'package.json');
31
+ if (!fs.existsSync(pkgPath)) {
32
+ console.error(chalk.red('\u274c package.json not found'));
33
+ process.exit(1);
34
+ }
35
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
36
+ pkg.scripts = { ...pkg.scripts, ...scripts };
37
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
38
+ // Track managed keys
39
+ const registry = new ManagedJsonRegistry(cwd);
40
+ registry.register('package.json', 'scripts', Object.keys(scripts));
41
+ console.log(chalk.green(`\u2705 Injected ${Object.keys(scripts).length} scripts into package.json:`));
42
+ for (const [scriptName, scriptCmd] of Object.entries(scripts)) {
43
+ console.log(` ${chalk.blue(scriptName)} ${chalk.gray('\u2192')} ${chalk.gray(scriptCmd)}`);
44
+ }
45
+ });
46
+ }
47
+ //# sourceMappingURL=script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script.js","sourceRoot":"","sources":["../../../cli/commands/script.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerUninstallCommand(program: Command): void;
3
+ //# sourceMappingURL=uninstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../cli/commands/uninstall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoH/D"}
@@ -0,0 +1,141 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import chalk from 'chalk';
4
+ import { ManagedJsonRegistry, hasMarkerBlock, removeMarkerBlock } from '../../src/index.js';
5
+ export function registerUninstallCommand(program) {
6
+ program
7
+ .command('uninstall')
8
+ .description('Remove all composable.env managed content and generated files')
9
+ .option('--all', 'Also remove the env/ configuration directory')
10
+ .option('--dry-run', 'Show what would be removed without actually removing')
11
+ .action((options) => {
12
+ const cwd = process.cwd();
13
+ const removed = [];
14
+ const dryRun = options.dryRun ?? false;
15
+ if (dryRun) {
16
+ console.log(chalk.blue('Dry run — no files will be modified:\n'));
17
+ }
18
+ // 1. Remove marker blocks from .gitignore
19
+ const gitignorePath = path.join(cwd, '.gitignore');
20
+ if (fs.existsSync(gitignorePath)) {
21
+ const content = fs.readFileSync(gitignorePath, 'utf8');
22
+ if (hasMarkerBlock(content)) {
23
+ if (!dryRun) {
24
+ fs.writeFileSync(gitignorePath, removeMarkerBlock(content));
25
+ }
26
+ removed.push('.gitignore (removed cenv markers)');
27
+ }
28
+ }
29
+ // 2. Remove tracked JSON keys via registry
30
+ const registry = new ManagedJsonRegistry(cwd);
31
+ const entries = registry.load();
32
+ for (const entry of entries) {
33
+ const filePath = path.join(cwd, entry.file);
34
+ if (!fs.existsSync(filePath))
35
+ continue;
36
+ const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
37
+ let changed = false;
38
+ for (const [jsonPath, keys] of Object.entries(entry.keys)) {
39
+ const target = json[jsonPath];
40
+ if (target && typeof target === 'object') {
41
+ for (const key of keys) {
42
+ if (key in target) {
43
+ if (!dryRun)
44
+ delete target[key];
45
+ changed = true;
46
+ }
47
+ }
48
+ }
49
+ }
50
+ if (changed) {
51
+ if (!dryRun) {
52
+ fs.writeFileSync(filePath, JSON.stringify(json, null, 2) + '\n');
53
+ }
54
+ removed.push(`${entry.file} (removed managed keys)`);
55
+ }
56
+ }
57
+ // 3. Find and delete all .cenv.* files recursively
58
+ const cenvFiles = findCenvFiles(cwd);
59
+ for (const file of cenvFiles) {
60
+ const rel = path.relative(cwd, file);
61
+ if (!dryRun)
62
+ fs.unlinkSync(file);
63
+ removed.push(rel);
64
+ }
65
+ // 4. Optionally remove env/ directory
66
+ if (options.all) {
67
+ const envDir = path.join(cwd, 'env');
68
+ if (fs.existsSync(envDir)) {
69
+ if (!dryRun)
70
+ fs.rmSync(envDir, { recursive: true });
71
+ removed.push('env/ (configuration directory)');
72
+ }
73
+ }
74
+ // 5. Remove composable.env from package.json dependencies
75
+ const pkgPath = path.join(cwd, 'package.json');
76
+ if (fs.existsSync(pkgPath)) {
77
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
78
+ let pkgChanged = false;
79
+ if (pkg.devDependencies?.['composable.env']) {
80
+ if (!dryRun)
81
+ delete pkg.devDependencies['composable.env'];
82
+ pkgChanged = true;
83
+ }
84
+ if (pkg.dependencies?.['composable.env']) {
85
+ if (!dryRun)
86
+ delete pkg.dependencies['composable.env'];
87
+ pkgChanged = true;
88
+ }
89
+ if (pkgChanged) {
90
+ if (!dryRun) {
91
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
92
+ }
93
+ removed.push('package.json (removed composable.env dependency)');
94
+ }
95
+ }
96
+ // 6. Remove .cenv-managed.json
97
+ const managedPath = path.join(cwd, '.cenv-managed.json');
98
+ if (fs.existsSync(managedPath)) {
99
+ if (!dryRun)
100
+ registry.remove();
101
+ removed.push('.cenv-managed.json');
102
+ }
103
+ // Summary
104
+ if (removed.length === 0) {
105
+ console.log(chalk.yellow('Nothing to remove — no composable.env artifacts found.'));
106
+ }
107
+ else {
108
+ const verb = dryRun ? 'Would remove' : 'Removed';
109
+ console.log(chalk.green(`${verb} ${removed.length} item(s):`));
110
+ for (const item of removed) {
111
+ console.log(` ${chalk.gray('-')} ${item}`);
112
+ }
113
+ }
114
+ });
115
+ }
116
+ function findCenvFiles(dir) {
117
+ const results = [];
118
+ function walk(current) {
119
+ let entries;
120
+ try {
121
+ entries = fs.readdirSync(current, { withFileTypes: true });
122
+ }
123
+ catch {
124
+ return;
125
+ }
126
+ for (const entry of entries) {
127
+ if (entry.name === 'node_modules' || entry.name === '.git')
128
+ continue;
129
+ const fullPath = path.join(current, entry.name);
130
+ if (entry.isDirectory()) {
131
+ walk(fullPath);
132
+ }
133
+ else if (entry.name.startsWith('.cenv.')) {
134
+ results.push(fullPath);
135
+ }
136
+ }
137
+ }
138
+ walk(dir);
139
+ return results;
140
+ }
141
+ //# sourceMappingURL=uninstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../../cli/commands/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5F,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,+DAA+D,CAAC;SAC5E,MAAM,CAAC,OAAO,EAAE,8CAA8C,CAAC;SAC/D,MAAM,CAAC,WAAW,EAAE,sDAAsD,CAAC;SAC3E,MAAM,CAAC,CAAC,OAA4C,EAAE,EAAE;QACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;QAEvC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,0CAA0C;QAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACnD,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YACvD,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC9D,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEhC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAAE,SAAS;YAEvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;YAC3D,IAAI,OAAO,GAAG,KAAK,CAAC;YAEpB,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC9B,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACzC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;wBACvB,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;4BAClB,IAAI,CAAC,MAAM;gCAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;4BAChC,OAAO,GAAG,IAAI,CAAC;wBACjB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBACnE,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,yBAAyB,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,mDAAmD;QACnD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM;gBAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QAED,sCAAsC;QACtC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACrC,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM;oBAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAED,0DAA0D;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YACzD,IAAI,UAAU,GAAG,KAAK,CAAC;YAEvB,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,MAAM;oBAAE,OAAO,GAAG,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;gBAC1D,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;YACD,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACzC,IAAI,CAAC,MAAM;oBAAE,OAAO,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;gBACvD,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBACjE,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;QACzD,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM;gBAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACrC,CAAC;QAED,UAAU;QACV,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,wDAAwD,CAAC,CAAC,CAAC;QACtF,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC;YAC/D,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,SAAS,IAAI,CAAC,OAAe;QAC3B,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YAErE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,OAAO,CAAC;AACjB,CAAC"}