@salte-common/terraflow 0.1.0-alpha.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 (131) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +278 -0
  3. package/RELEASE_SUMMARY.md +53 -0
  4. package/STANDARDS_COMPLIANCE.md +85 -0
  5. package/bin/terraflow.js +3 -0
  6. package/bin/tf.js +3 -0
  7. package/dist/commands/apply.d.ts +7 -0
  8. package/dist/commands/apply.js +12 -0
  9. package/dist/commands/base.d.ts +7 -0
  10. package/dist/commands/base.js +12 -0
  11. package/dist/commands/config.d.ts +25 -0
  12. package/dist/commands/config.js +354 -0
  13. package/dist/commands/destroy.d.ts +7 -0
  14. package/dist/commands/destroy.js +12 -0
  15. package/dist/commands/init.d.ts +68 -0
  16. package/dist/commands/init.js +131 -0
  17. package/dist/commands/plan.d.ts +7 -0
  18. package/dist/commands/plan.js +12 -0
  19. package/dist/core/backend-state.d.ts +25 -0
  20. package/dist/core/backend-state.js +77 -0
  21. package/dist/core/config.d.ts +83 -0
  22. package/dist/core/config.js +295 -0
  23. package/dist/core/context.d.ts +52 -0
  24. package/dist/core/context.js +192 -0
  25. package/dist/core/environment.d.ts +62 -0
  26. package/dist/core/environment.js +205 -0
  27. package/dist/core/errors.d.ts +22 -0
  28. package/dist/core/errors.js +36 -0
  29. package/dist/core/plugin-loader.d.ts +21 -0
  30. package/dist/core/plugin-loader.js +136 -0
  31. package/dist/core/terraform.d.ts +45 -0
  32. package/dist/core/terraform.js +247 -0
  33. package/dist/core/validator.d.ts +103 -0
  34. package/dist/core/validator.js +304 -0
  35. package/dist/index.d.ts +7 -0
  36. package/dist/index.js +184 -0
  37. package/dist/plugins/auth/aws-assume-role.d.ts +10 -0
  38. package/dist/plugins/auth/aws-assume-role.js +110 -0
  39. package/dist/plugins/auth/azure-service-principal.d.ts +10 -0
  40. package/dist/plugins/auth/azure-service-principal.js +99 -0
  41. package/dist/plugins/auth/gcp-service-account.d.ts +10 -0
  42. package/dist/plugins/auth/gcp-service-account.js +105 -0
  43. package/dist/plugins/backends/azurerm.d.ts +10 -0
  44. package/dist/plugins/backends/azurerm.js +117 -0
  45. package/dist/plugins/backends/gcs.d.ts +10 -0
  46. package/dist/plugins/backends/gcs.js +75 -0
  47. package/dist/plugins/backends/local.d.ts +11 -0
  48. package/dist/plugins/backends/local.js +37 -0
  49. package/dist/plugins/backends/s3.d.ts +10 -0
  50. package/dist/plugins/backends/s3.js +185 -0
  51. package/dist/plugins/secrets/aws-secrets.d.ts +12 -0
  52. package/dist/plugins/secrets/aws-secrets.js +125 -0
  53. package/dist/plugins/secrets/azure-keyvault.d.ts +12 -0
  54. package/dist/plugins/secrets/azure-keyvault.js +178 -0
  55. package/dist/plugins/secrets/env.d.ts +24 -0
  56. package/dist/plugins/secrets/env.js +62 -0
  57. package/dist/plugins/secrets/gcp-secret-manager.d.ts +12 -0
  58. package/dist/plugins/secrets/gcp-secret-manager.js +157 -0
  59. package/dist/templates/application/go/go.mod.template +4 -0
  60. package/dist/templates/application/go/main.template +8 -0
  61. package/dist/templates/application/go/test.template +11 -0
  62. package/dist/templates/application/javascript/main.template +14 -0
  63. package/dist/templates/application/javascript/test.template +8 -0
  64. package/dist/templates/application/python/main.template +13 -0
  65. package/dist/templates/application/python/requirements.txt.template +3 -0
  66. package/dist/templates/application/python/test.template +8 -0
  67. package/dist/templates/application/typescript/main.template +14 -0
  68. package/dist/templates/application/typescript/test.template +8 -0
  69. package/dist/templates/application/typescript/tsconfig.json.template +20 -0
  70. package/dist/templates/config/README.md.template +82 -0
  71. package/dist/templates/config/env.example.template +22 -0
  72. package/dist/templates/config/gitignore.template +40 -0
  73. package/dist/templates/config/tfwconfig.yml.template +69 -0
  74. package/dist/templates/templates/application/go/go.mod.template +4 -0
  75. package/dist/templates/templates/application/go/main.template +8 -0
  76. package/dist/templates/templates/application/go/test.template +11 -0
  77. package/dist/templates/templates/application/javascript/main.template +14 -0
  78. package/dist/templates/templates/application/javascript/test.template +8 -0
  79. package/dist/templates/templates/application/python/main.template +13 -0
  80. package/dist/templates/templates/application/python/requirements.txt.template +3 -0
  81. package/dist/templates/templates/application/python/test.template +8 -0
  82. package/dist/templates/templates/application/typescript/main.template +14 -0
  83. package/dist/templates/templates/application/typescript/test.template +8 -0
  84. package/dist/templates/templates/application/typescript/tsconfig.json.template +20 -0
  85. package/dist/templates/templates/config/README.md.template +82 -0
  86. package/dist/templates/templates/config/env.example.template +22 -0
  87. package/dist/templates/templates/config/gitignore.template +40 -0
  88. package/dist/templates/templates/config/tfwconfig.yml.template +69 -0
  89. package/dist/templates/templates/terraform/aws/_init.tf.template +24 -0
  90. package/dist/templates/templates/terraform/aws/inputs.tf.template +11 -0
  91. package/dist/templates/templates/terraform/azure/_init.tf.template +19 -0
  92. package/dist/templates/templates/terraform/azure/inputs.tf.template +11 -0
  93. package/dist/templates/templates/terraform/gcp/_init.tf.template +20 -0
  94. package/dist/templates/templates/terraform/gcp/inputs.tf.template +16 -0
  95. package/dist/templates/templates/terraform/locals.tf.template +9 -0
  96. package/dist/templates/templates/terraform/main.tf.template +8 -0
  97. package/dist/templates/templates/terraform/modules/inputs.tf.template +5 -0
  98. package/dist/templates/templates/terraform/modules/main.tf.template +2 -0
  99. package/dist/templates/templates/terraform/modules/outputs.tf.template +2 -0
  100. package/dist/templates/templates/terraform/outputs.tf.template +6 -0
  101. package/dist/templates/terraform/aws/_init.tf.template +24 -0
  102. package/dist/templates/terraform/aws/inputs.tf.template +11 -0
  103. package/dist/templates/terraform/azure/_init.tf.template +19 -0
  104. package/dist/templates/terraform/azure/inputs.tf.template +11 -0
  105. package/dist/templates/terraform/gcp/_init.tf.template +20 -0
  106. package/dist/templates/terraform/gcp/inputs.tf.template +16 -0
  107. package/dist/templates/terraform/locals.tf.template +9 -0
  108. package/dist/templates/terraform/main.tf.template +8 -0
  109. package/dist/templates/terraform/modules/inputs.tf.template +5 -0
  110. package/dist/templates/terraform/modules/main.tf.template +2 -0
  111. package/dist/templates/terraform/modules/outputs.tf.template +2 -0
  112. package/dist/templates/terraform/outputs.tf.template +6 -0
  113. package/dist/types/config.d.ts +92 -0
  114. package/dist/types/config.js +6 -0
  115. package/dist/types/context.d.ts +59 -0
  116. package/dist/types/context.js +6 -0
  117. package/dist/types/index.d.ts +7 -0
  118. package/dist/types/index.js +23 -0
  119. package/dist/types/plugins.d.ts +77 -0
  120. package/dist/types/plugins.js +6 -0
  121. package/dist/utils/cloud.d.ts +43 -0
  122. package/dist/utils/cloud.js +150 -0
  123. package/dist/utils/git.d.ts +88 -0
  124. package/dist/utils/git.js +258 -0
  125. package/dist/utils/logger.d.ts +67 -0
  126. package/dist/utils/logger.js +121 -0
  127. package/dist/utils/scaffolding.d.ts +92 -0
  128. package/dist/utils/scaffolding.js +338 -0
  129. package/dist/utils/templates.d.ts +25 -0
  130. package/dist/utils/templates.js +70 -0
  131. package/package.json +60 -0
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * Backend state management
4
+ * Stores previous backend configuration to detect migrations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.loadBackendState = loadBackendState;
8
+ exports.saveBackendState = saveBackendState;
9
+ exports.detectBackendMigration = detectBackendMigration;
10
+ const fs_1 = require("fs");
11
+ const path_1 = require("path");
12
+ /**
13
+ * Get the backend state file path
14
+ * @param workingDir - Working directory
15
+ * @returns Path to state file
16
+ */
17
+ function getStateFilePath(workingDir) {
18
+ const stateDir = (0, path_1.join)(workingDir, '.terraflow');
19
+ if (!(0, fs_1.existsSync)(stateDir)) {
20
+ (0, fs_1.mkdirSync)(stateDir, { recursive: true });
21
+ }
22
+ return (0, path_1.join)(stateDir, 'state.json');
23
+ }
24
+ /**
25
+ * Load previous backend state
26
+ * @param workingDir - Working directory
27
+ * @returns Previous backend configuration or null
28
+ */
29
+ function loadBackendState(workingDir) {
30
+ const statePath = getStateFilePath(workingDir);
31
+ if (!(0, fs_1.existsSync)(statePath)) {
32
+ return null;
33
+ }
34
+ try {
35
+ const stateContent = (0, fs_1.readFileSync)(statePath, 'utf8');
36
+ const state = JSON.parse(stateContent);
37
+ return state.backend || null;
38
+ }
39
+ catch (error) {
40
+ // If state file is invalid, treat as no previous state
41
+ return null;
42
+ }
43
+ }
44
+ /**
45
+ * Save backend state
46
+ * @param workingDir - Working directory
47
+ * @param backend - Backend configuration to save
48
+ */
49
+ function saveBackendState(workingDir, backend) {
50
+ const statePath = getStateFilePath(workingDir);
51
+ const state = {
52
+ backend,
53
+ lastUpdated: new Date().toISOString(),
54
+ };
55
+ (0, fs_1.writeFileSync)(statePath, JSON.stringify(state, null, 2), 'utf8');
56
+ }
57
+ /**
58
+ * Detect if backend has changed
59
+ * @param workingDir - Working directory
60
+ * @param currentBackend - Current backend configuration
61
+ * @returns Previous backend type if changed, null otherwise
62
+ */
63
+ function detectBackendMigration(workingDir, currentBackend) {
64
+ const previousBackend = loadBackendState(workingDir);
65
+ if (!previousBackend) {
66
+ // No previous state, this is first run
67
+ return null;
68
+ }
69
+ // Compare backend types
70
+ if (previousBackend.type !== currentBackend.type) {
71
+ return previousBackend.type;
72
+ }
73
+ // Backend types are the same, but config might have changed
74
+ // For now, we only detect type changes
75
+ return null;
76
+ }
77
+ //# sourceMappingURL=backend-state.js.map
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Configuration manager
3
+ * Loads and merges configuration from multiple sources
4
+ * Hierarchy: CLI > Env > Config File > Computed Defaults > Hard-coded Defaults
5
+ */
6
+ import type { TerraflowConfig } from '../types/config';
7
+ export interface CliOptions {
8
+ config?: string;
9
+ workspace?: string;
10
+ backend?: string;
11
+ secrets?: string;
12
+ skipCommitCheck?: boolean;
13
+ workingDir?: string;
14
+ assumeRole?: string;
15
+ verbose?: boolean;
16
+ debug?: boolean;
17
+ dryRun?: boolean;
18
+ noColor?: boolean;
19
+ }
20
+ /**
21
+ * Configuration manager for Terraflow
22
+ * Handles loading and merging configuration from multiple sources
23
+ */
24
+ export declare class ConfigManager {
25
+ /**
26
+ * Load and merge configuration from CLI args, env vars, and config file
27
+ * @param cliOptions - Command line options
28
+ * @param cwd - Current working directory
29
+ * @returns Merged configuration
30
+ */
31
+ static load(cliOptions?: CliOptions, cwd?: string): Promise<TerraflowConfig>;
32
+ /**
33
+ * Get the config file path
34
+ * @param cliOptions - CLI options
35
+ * @param cwd - Current working directory
36
+ * @returns Path to config file
37
+ */
38
+ private static getConfigFilePath;
39
+ /**
40
+ * Load configuration from file
41
+ * @param configPath - Path to config file
42
+ * @returns Configuration object or empty object if file doesn't exist
43
+ */
44
+ private static loadConfigFile;
45
+ /**
46
+ * Load configuration from environment variables
47
+ * @returns Configuration from environment
48
+ */
49
+ private static loadFromEnvironment;
50
+ /**
51
+ * Convert CLI options to configuration format
52
+ * @param cliOptions - CLI options
53
+ * @returns Configuration object
54
+ */
55
+ private static cliOptionsToConfig;
56
+ /**
57
+ * Parse boolean from string
58
+ * @param value - String value to parse
59
+ * @returns Boolean value
60
+ */
61
+ private static parseBoolean;
62
+ /**
63
+ * Deep merge configuration objects
64
+ * Later objects override earlier ones
65
+ * @param configs - Configuration objects to merge (in priority order)
66
+ * @returns Merged configuration
67
+ */
68
+ private static mergeConfigs;
69
+ /**
70
+ * Get resolved workspace name from configuration
71
+ * @param config - Configuration object
72
+ * @returns Workspace name or undefined
73
+ */
74
+ static getWorkspace(config: TerraflowConfig): string | undefined;
75
+ /**
76
+ * Get working directory path
77
+ * @param config - Configuration object
78
+ * @param cwd - Current working directory
79
+ * @returns Absolute path to working directory
80
+ */
81
+ static getWorkingDir(config: TerraflowConfig, cwd?: string): string;
82
+ }
83
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration manager
4
+ * Loads and merges configuration from multiple sources
5
+ * Hierarchy: CLI > Env > Config File > Computed Defaults > Hard-coded Defaults
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ConfigManager = void 0;
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const js_yaml_1 = __importDefault(require("js-yaml"));
15
+ const logger_1 = require("../utils/logger");
16
+ /**
17
+ * Configuration manager for Terraflow
18
+ * Handles loading and merging configuration from multiple sources
19
+ */
20
+ class ConfigManager {
21
+ /**
22
+ * Load and merge configuration from CLI args, env vars, and config file
23
+ * @param cliOptions - Command line options
24
+ * @param cwd - Current working directory
25
+ * @returns Merged configuration
26
+ */
27
+ static async load(cliOptions = {}, cwd = process.cwd()) {
28
+ // Start with hard-coded defaults (lowest priority)
29
+ const defaults = {
30
+ workspace: undefined,
31
+ 'working-dir': './terraform',
32
+ 'skip-commit-check': false,
33
+ backend: {
34
+ type: 'local',
35
+ },
36
+ logging: {
37
+ level: 'info',
38
+ terraform_log: false,
39
+ terraform_log_level: 'TRACE',
40
+ },
41
+ };
42
+ // Load config file (higher priority than defaults)
43
+ const configFile = ConfigManager.getConfigFilePath(cliOptions, cwd);
44
+ const fileConfig = ConfigManager.loadConfigFile(configFile);
45
+ // Load environment variables (higher priority than config file)
46
+ const envConfig = ConfigManager.loadFromEnvironment();
47
+ // Merge: defaults < fileConfig < envConfig < cliOptions
48
+ const merged = ConfigManager.mergeConfigs(defaults, fileConfig, envConfig, ConfigManager.cliOptionsToConfig(cliOptions));
49
+ return merged;
50
+ }
51
+ /**
52
+ * Get the config file path
53
+ * @param cliOptions - CLI options
54
+ * @param cwd - Current working directory
55
+ * @returns Path to config file
56
+ */
57
+ static getConfigFilePath(cliOptions, cwd) {
58
+ if (cliOptions.config) {
59
+ return path_1.default.isAbsolute(cliOptions.config)
60
+ ? cliOptions.config
61
+ : path_1.default.join(cwd, cliOptions.config);
62
+ }
63
+ const envConfig = process.env.TERRAFLOW_CONFIG;
64
+ if (envConfig) {
65
+ return path_1.default.isAbsolute(envConfig) ? envConfig : path_1.default.join(cwd, envConfig);
66
+ }
67
+ // Default: .tfwconfig.yml in working directory
68
+ return path_1.default.join(cwd, '.tfwconfig.yml');
69
+ }
70
+ /**
71
+ * Load configuration from file
72
+ * @param configPath - Path to config file
73
+ * @returns Configuration object or empty object if file doesn't exist
74
+ */
75
+ static loadConfigFile(configPath) {
76
+ if (!fs_1.default.existsSync(configPath)) {
77
+ return {};
78
+ }
79
+ try {
80
+ const content = fs_1.default.readFileSync(configPath, 'utf8');
81
+ const config = js_yaml_1.default.load(content);
82
+ logger_1.Logger.debug(`Loaded configuration from ${configPath}`);
83
+ return config || {};
84
+ }
85
+ catch (error) {
86
+ logger_1.Logger.warn(`Failed to load config file ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
87
+ return {};
88
+ }
89
+ }
90
+ /**
91
+ * Load configuration from environment variables
92
+ * @returns Configuration from environment
93
+ */
94
+ static loadFromEnvironment() {
95
+ const envConfig = {};
96
+ if (process.env.TERRAFLOW_WORKSPACE) {
97
+ envConfig.workspace = process.env.TERRAFLOW_WORKSPACE;
98
+ }
99
+ if (process.env.TERRAFLOW_WORKING_DIR) {
100
+ envConfig['working-dir'] = process.env.TERRAFLOW_WORKING_DIR;
101
+ }
102
+ if (process.env.TERRAFLOW_SKIP_COMMIT_CHECK) {
103
+ envConfig['skip-commit-check'] = ConfigManager.parseBoolean(process.env.TERRAFLOW_SKIP_COMMIT_CHECK);
104
+ }
105
+ if (process.env.TERRAFLOW_BACKEND) {
106
+ envConfig.backend = {
107
+ type: process.env.TERRAFLOW_BACKEND,
108
+ };
109
+ }
110
+ if (process.env.TERRAFLOW_SECRETS) {
111
+ envConfig.secrets = {
112
+ provider: process.env.TERRAFLOW_SECRETS,
113
+ };
114
+ }
115
+ if (process.env.TERRAFLOW_ASSUME_ROLE) {
116
+ envConfig.auth = {
117
+ assume_role: {
118
+ role_arn: process.env.TERRAFLOW_ASSUME_ROLE,
119
+ },
120
+ };
121
+ }
122
+ return envConfig;
123
+ }
124
+ /**
125
+ * Convert CLI options to configuration format
126
+ * @param cliOptions - CLI options
127
+ * @returns Configuration object
128
+ */
129
+ static cliOptionsToConfig(cliOptions) {
130
+ const config = {};
131
+ if (cliOptions.workspace !== undefined) {
132
+ config.workspace = cliOptions.workspace;
133
+ }
134
+ if (cliOptions.workingDir !== undefined) {
135
+ config['working-dir'] = cliOptions.workingDir;
136
+ }
137
+ if (cliOptions.skipCommitCheck !== undefined) {
138
+ config['skip-commit-check'] = cliOptions.skipCommitCheck;
139
+ }
140
+ if (cliOptions.backend !== undefined) {
141
+ config.backend = {
142
+ type: cliOptions.backend,
143
+ };
144
+ }
145
+ if (cliOptions.secrets !== undefined) {
146
+ config.secrets = {
147
+ provider: cliOptions.secrets,
148
+ };
149
+ }
150
+ if (cliOptions.assumeRole !== undefined) {
151
+ config.auth = {
152
+ assume_role: {
153
+ role_arn: cliOptions.assumeRole,
154
+ },
155
+ };
156
+ }
157
+ if (cliOptions.verbose || cliOptions.debug) {
158
+ config.logging = {
159
+ level: cliOptions.debug ? 'debug' : 'info',
160
+ };
161
+ }
162
+ if (cliOptions.noColor !== undefined) {
163
+ // no-color is handled by Logger, not config
164
+ }
165
+ return config;
166
+ }
167
+ /**
168
+ * Parse boolean from string
169
+ * @param value - String value to parse
170
+ * @returns Boolean value
171
+ */
172
+ static parseBoolean(value) {
173
+ const normalized = value.toLowerCase().trim();
174
+ return normalized === 'true' || normalized === '1' || normalized === 'yes';
175
+ }
176
+ /**
177
+ * Deep merge configuration objects
178
+ * Later objects override earlier ones
179
+ * @param configs - Configuration objects to merge (in priority order)
180
+ * @returns Merged configuration
181
+ */
182
+ static mergeConfigs(...configs) {
183
+ const result = {};
184
+ for (const config of configs) {
185
+ if (!config || typeof config !== 'object') {
186
+ continue;
187
+ }
188
+ // Merge workspace
189
+ if (config.workspace !== undefined) {
190
+ result.workspace = config.workspace;
191
+ }
192
+ // Merge working-dir
193
+ if (config['working-dir'] !== undefined) {
194
+ result['working-dir'] = config['working-dir'];
195
+ }
196
+ // Merge skip-commit-check
197
+ if (config['skip-commit-check'] !== undefined) {
198
+ result['skip-commit-check'] = config['skip-commit-check'];
199
+ }
200
+ // Merge backend
201
+ if (config.backend) {
202
+ result.backend = {
203
+ ...(result.backend || {}),
204
+ ...config.backend,
205
+ config: {
206
+ ...(result.backend?.config || {}),
207
+ ...(config.backend.config || {}),
208
+ },
209
+ };
210
+ }
211
+ // Merge secrets
212
+ if (config.secrets) {
213
+ result.secrets = {
214
+ ...(result.secrets || {}),
215
+ ...config.secrets,
216
+ config: {
217
+ ...(result.secrets?.config || {}),
218
+ ...(config.secrets.config || {}),
219
+ },
220
+ };
221
+ }
222
+ // Merge auth
223
+ if (config.auth) {
224
+ result.auth = {
225
+ ...(result.auth || {}),
226
+ ...config.auth,
227
+ assume_role: config.auth.assume_role
228
+ ? {
229
+ ...(result.auth?.assume_role || {}),
230
+ ...config.auth.assume_role,
231
+ }
232
+ : result.auth?.assume_role,
233
+ service_principal: config.auth.service_principal
234
+ ? {
235
+ ...(result.auth?.service_principal || {}),
236
+ ...config.auth.service_principal,
237
+ }
238
+ : result.auth?.service_principal,
239
+ service_account: config.auth.service_account
240
+ ? {
241
+ ...(result.auth?.service_account || {}),
242
+ ...config.auth.service_account,
243
+ }
244
+ : result.auth?.service_account,
245
+ };
246
+ }
247
+ // Merge variables
248
+ if (config.variables) {
249
+ result.variables = {
250
+ ...(result.variables || {}),
251
+ ...config.variables,
252
+ };
253
+ }
254
+ // Merge validations
255
+ if (config.validations) {
256
+ result.validations = {
257
+ ...(result.validations || {}),
258
+ ...config.validations,
259
+ };
260
+ }
261
+ // Merge logging
262
+ if (config.logging) {
263
+ result.logging = {
264
+ ...(result.logging || {}),
265
+ ...config.logging,
266
+ };
267
+ }
268
+ // Merge workspace_strategy
269
+ if (config.workspace_strategy) {
270
+ result.workspace_strategy = config.workspace_strategy;
271
+ }
272
+ }
273
+ return result;
274
+ }
275
+ /**
276
+ * Get resolved workspace name from configuration
277
+ * @param config - Configuration object
278
+ * @returns Workspace name or undefined
279
+ */
280
+ static getWorkspace(config) {
281
+ return config.workspace;
282
+ }
283
+ /**
284
+ * Get working directory path
285
+ * @param config - Configuration object
286
+ * @param cwd - Current working directory
287
+ * @returns Absolute path to working directory
288
+ */
289
+ static getWorkingDir(config, cwd = process.cwd()) {
290
+ const workingDir = config['working-dir'] || './terraform';
291
+ return path_1.default.isAbsolute(workingDir) ? workingDir : path_1.default.join(cwd, workingDir);
292
+ }
293
+ }
294
+ exports.ConfigManager = ConfigManager;
295
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Execution context builder
3
+ * Builds execution context from environment and configuration
4
+ */
5
+ import type { ExecutionContext } from '../types/context';
6
+ import type { TerraflowConfig } from '../types/config';
7
+ /**
8
+ * Execution context builder for Terraflow
9
+ * Collects runtime state for command execution
10
+ */
11
+ export declare class ContextBuilder {
12
+ /**
13
+ * Build execution context from configuration and environment
14
+ * @param config - Terraflow configuration
15
+ * @param cwd - Current working directory
16
+ * @returns Execution context
17
+ */
18
+ static build(config: TerraflowConfig, cwd?: string): Promise<ExecutionContext>;
19
+ /**
20
+ * Derive workspace name following priority strategy:
21
+ * 1. CLI parameter (--workspace)
22
+ * 2. Environment variable (TERRAFLOW_WORKSPACE)
23
+ * 3. Git tag (if on a tag)
24
+ * 4. Git branch (if not ephemeral)
25
+ * 5. Hostname
26
+ * @param config - Terraflow configuration
27
+ * @param cwd - Current working directory
28
+ * @returns Derived workspace name
29
+ */
30
+ private static deriveWorkspace;
31
+ /**
32
+ * Build cloud provider information
33
+ * @returns Cloud information
34
+ */
35
+ private static buildCloudInfo;
36
+ /**
37
+ * Build VCS information
38
+ * @param cwd - Current working directory
39
+ * @returns VCS information
40
+ */
41
+ private static buildVcsInfo;
42
+ /**
43
+ * Build template variables for config resolution
44
+ * @param cloud - Cloud information
45
+ * @param vcs - VCS information
46
+ * @param hostname - Machine hostname
47
+ * @param workspace - Workspace name
48
+ * @returns Template variables
49
+ */
50
+ private static buildTemplateVars;
51
+ }
52
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * Execution context builder
4
+ * Builds execution context from environment and configuration
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ContextBuilder = void 0;
11
+ const os_1 = __importDefault(require("os"));
12
+ const config_1 = require("./config");
13
+ const git_1 = require("../utils/git");
14
+ /**
15
+ * Execution context builder for Terraflow
16
+ * Collects runtime state for command execution
17
+ */
18
+ class ContextBuilder {
19
+ /**
20
+ * Build execution context from configuration and environment
21
+ * @param config - Terraflow configuration
22
+ * @param cwd - Current working directory
23
+ * @returns Execution context
24
+ */
25
+ static async build(config, cwd = process.cwd()) {
26
+ const workspace = await ContextBuilder.deriveWorkspace(config, cwd);
27
+ const workingDir = config_1.ConfigManager.getWorkingDir(config, cwd);
28
+ const cloud = await ContextBuilder.buildCloudInfo();
29
+ const vcs = await ContextBuilder.buildVcsInfo(cwd);
30
+ const hostname = os_1.default.hostname();
31
+ // Build template variables from environment and context
32
+ const templateVars = ContextBuilder.buildTemplateVars(cloud, vcs, hostname, workspace);
33
+ // Build environment variables (sanitized, no secrets)
34
+ const env = {};
35
+ for (const key in process.env) {
36
+ if (Object.prototype.hasOwnProperty.call(process.env, key)) {
37
+ const value = process.env[key];
38
+ if (value !== undefined) {
39
+ env[key] = value;
40
+ }
41
+ }
42
+ }
43
+ return {
44
+ workspace,
45
+ workingDir,
46
+ cloud,
47
+ vcs,
48
+ hostname,
49
+ env,
50
+ templateVars,
51
+ };
52
+ }
53
+ /**
54
+ * Derive workspace name following priority strategy:
55
+ * 1. CLI parameter (--workspace)
56
+ * 2. Environment variable (TERRAFLOW_WORKSPACE)
57
+ * 3. Git tag (if on a tag)
58
+ * 4. Git branch (if not ephemeral)
59
+ * 5. Hostname
60
+ * @param config - Terraflow configuration
61
+ * @param cwd - Current working directory
62
+ * @returns Derived workspace name
63
+ */
64
+ static async deriveWorkspace(config, cwd) {
65
+ // 1. CLI parameter (highest priority) - already in config via ConfigManager
66
+ const cliWorkspace = config_1.ConfigManager.getWorkspace(config);
67
+ if (cliWorkspace) {
68
+ return git_1.GitUtils.sanitizeWorkspaceName(cliWorkspace);
69
+ }
70
+ // 2. Environment variable
71
+ const envWorkspace = process.env.TERRAFLOW_WORKSPACE;
72
+ if (envWorkspace) {
73
+ return git_1.GitUtils.sanitizeWorkspaceName(envWorkspace);
74
+ }
75
+ // Check if workspace_strategy is specified in config
76
+ const strategy = config.workspace_strategy || ['cli', 'env', 'tag', 'branch', 'hostname'];
77
+ // 3. Git tag (if on a tag)
78
+ if (strategy.includes('tag')) {
79
+ const tag = await git_1.GitUtils.getTag(cwd);
80
+ if (tag) {
81
+ return git_1.GitUtils.sanitizeWorkspaceName(tag);
82
+ }
83
+ }
84
+ // 4. Git branch (if not ephemeral)
85
+ if (strategy.includes('branch')) {
86
+ const branch = await git_1.GitUtils.getBranch(cwd);
87
+ if (branch && !git_1.GitUtils.isEphemeralBranch(branch)) {
88
+ return git_1.GitUtils.sanitizeWorkspaceName(branch);
89
+ }
90
+ }
91
+ // 5. Hostname (fallback)
92
+ if (strategy.includes('hostname')) {
93
+ const hostname = os_1.default.hostname();
94
+ return git_1.GitUtils.sanitizeWorkspaceName(hostname);
95
+ }
96
+ // Final fallback
97
+ return 'default';
98
+ }
99
+ /**
100
+ * Build cloud provider information
101
+ * @returns Cloud information
102
+ */
103
+ static async buildCloudInfo() {
104
+ // TODO: Implement cloud detection (AWS, Azure, GCP)
105
+ // For now, return default
106
+ return {
107
+ provider: 'none',
108
+ };
109
+ }
110
+ /**
111
+ * Build VCS information
112
+ * @param cwd - Current working directory
113
+ * @returns VCS information
114
+ */
115
+ static async buildVcsInfo(cwd = process.cwd()) {
116
+ if (!git_1.GitUtils.isGitRepository(cwd)) {
117
+ return {};
118
+ }
119
+ const branch = await git_1.GitUtils.getBranch(cwd);
120
+ const tag = await git_1.GitUtils.getTag(cwd);
121
+ const commitSha = await git_1.GitUtils.getCommitSha(cwd);
122
+ const shortSha = commitSha ? commitSha.substring(0, 7) : await git_1.GitUtils.getShortSha(cwd);
123
+ const isClean = await git_1.GitUtils.isClean(cwd);
124
+ const githubRepository = await git_1.GitUtils.getGithubRepository(cwd);
125
+ const gitlabProjectPath = await git_1.GitUtils.getGitlabProjectPath(cwd);
126
+ return {
127
+ branch,
128
+ tag,
129
+ commitSha,
130
+ shortSha,
131
+ isClean,
132
+ githubRepository,
133
+ gitlabProjectPath,
134
+ };
135
+ }
136
+ /**
137
+ * Build template variables for config resolution
138
+ * @param cloud - Cloud information
139
+ * @param vcs - VCS information
140
+ * @param hostname - Machine hostname
141
+ * @param workspace - Workspace name
142
+ * @returns Template variables
143
+ */
144
+ static buildTemplateVars(cloud, vcs, hostname, workspace) {
145
+ const vars = {
146
+ HOSTNAME: hostname,
147
+ WORKSPACE: workspace,
148
+ };
149
+ // Add all environment variables
150
+ for (const key in process.env) {
151
+ if (Object.prototype.hasOwnProperty.call(process.env, key)) {
152
+ const value = process.env[key];
153
+ if (value !== undefined) {
154
+ vars[key] = value;
155
+ }
156
+ }
157
+ }
158
+ // Add cloud-specific variables
159
+ if (cloud.awsAccountId) {
160
+ vars.AWS_ACCOUNT_ID = cloud.awsAccountId;
161
+ }
162
+ if (cloud.awsRegion) {
163
+ vars.AWS_REGION = cloud.awsRegion;
164
+ }
165
+ if (cloud.azureSubscriptionId) {
166
+ vars.AZURE_SUBSCRIPTION_ID = cloud.azureSubscriptionId;
167
+ }
168
+ if (cloud.gcpProjectId) {
169
+ vars.GCP_PROJECT_ID = cloud.gcpProjectId;
170
+ }
171
+ // Add VCS-specific variables
172
+ if (vcs.branch) {
173
+ vars.GIT_BRANCH = vcs.branch;
174
+ }
175
+ if (vcs.tag) {
176
+ vars.GIT_TAG = vcs.tag;
177
+ }
178
+ if (vcs.commitSha) {
179
+ vars.GIT_COMMIT_SHA = vcs.commitSha;
180
+ vars.GIT_SHORT_SHA = vcs.shortSha || vcs.commitSha.substring(0, 7);
181
+ }
182
+ if (vcs.githubRepository) {
183
+ vars.GITHUB_REPOSITORY = vcs.githubRepository;
184
+ }
185
+ if (vcs.gitlabProjectPath) {
186
+ vars.GITLAB_PROJECT_PATH = vcs.gitlabProjectPath;
187
+ }
188
+ return vars;
189
+ }
190
+ }
191
+ exports.ContextBuilder = ContextBuilder;
192
+ //# sourceMappingURL=context.js.map