@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,338 @@
1
+ "use strict";
2
+ /**
3
+ * Scaffolding utilities for project initialization
4
+ * Handles template processing and file generation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.loadTemplate = loadTemplate;
8
+ exports.processTemplate = processTemplate;
9
+ exports.generateTerraformFiles = generateTerraformFiles;
10
+ exports.generateApplicationFiles = generateApplicationFiles;
11
+ exports.generateConfigFiles = generateConfigFiles;
12
+ exports.createProjectStructure = createProjectStructure;
13
+ exports.validateProjectName = validateProjectName;
14
+ exports.validateProvider = validateProvider;
15
+ exports.validateLanguage = validateLanguage;
16
+ exports.isDirectoryEmpty = isDirectoryEmpty;
17
+ exports.buildTemplateVariables = buildTemplateVariables;
18
+ const fs_1 = require("fs");
19
+ const path_1 = require("path");
20
+ const logger_1 = require("./logger");
21
+ const errors_1 = require("../core/errors");
22
+ /**
23
+ * Template processing functions
24
+ */
25
+ /**
26
+ * Load a template file from the templates directory
27
+ * @param templatePath - Path to template file relative to templates directory
28
+ * @returns Template content as string
29
+ */
30
+ function loadTemplate(templatePath) {
31
+ // Get template directory (works in both source and built code)
32
+ const templatesDir = (0, path_1.join)(__dirname, '..', 'templates');
33
+ // Prevent path traversal attacks
34
+ // Reject any path that contains path traversal sequences
35
+ if (templatePath.includes('..') || templatePath.includes('~')) {
36
+ throw new errors_1.ConfigError(`Invalid template path: ${templatePath}`);
37
+ }
38
+ // Join and resolve to get absolute path, then verify it's within templates directory
39
+ const fullPath = (0, path_1.join)(templatesDir, templatePath);
40
+ // Additional safety: verify the resolved path is within templates directory
41
+ // by checking that it starts with the templates directory path
42
+ if (!fullPath.startsWith(templatesDir)) {
43
+ throw new errors_1.ConfigError(`Invalid template path: ${templatePath}`);
44
+ }
45
+ try {
46
+ return (0, fs_1.readFileSync)(fullPath, 'utf8');
47
+ }
48
+ catch (error) {
49
+ logger_1.Logger.error(`Failed to load template ${templatePath}: ${error instanceof Error ? error.message : String(error)}`);
50
+ throw new errors_1.ConfigError(`Template file not found: ${templatePath}.\n` +
51
+ `This may indicate a corrupted installation. Try reinstalling terraflow.`);
52
+ }
53
+ }
54
+ /**
55
+ * Process a template string by replacing variable placeholders
56
+ * @param template - Template content with placeholders
57
+ * @param variables - Object mapping variable names to values
58
+ * @returns Processed template with variables replaced
59
+ */
60
+ function processTemplate(template, variables) {
61
+ let result = template;
62
+ for (const [key, value] of Object.entries(variables)) {
63
+ const regex = new RegExp(`<${key}>`, 'g');
64
+ result = result.replace(regex, value);
65
+ }
66
+ return result;
67
+ }
68
+ /**
69
+ * File generation functions
70
+ */
71
+ /**
72
+ * Generate Terraform files for the project
73
+ * @param projectDir - Root directory of the project
74
+ * @param provider - Cloud provider (aws, azure, gcp)
75
+ * @param projectName - Name of the project
76
+ */
77
+ async function generateTerraformFiles(projectDir, provider, projectName) {
78
+ const terraformDir = (0, path_1.join)(projectDir, 'terraform');
79
+ const templatesDir = 'terraform';
80
+ logger_1.Logger.debug(`Generating Terraform files for provider: ${provider}`);
81
+ // Create terraform directory if it doesn't exist
82
+ (0, fs_1.mkdirSync)(terraformDir, { recursive: true });
83
+ // _init.tf - provider-specific
84
+ const initTemplate = loadTemplate((0, path_1.join)(templatesDir, provider, '_init.tf.template'));
85
+ (0, fs_1.writeFileSync)((0, path_1.join)(terraformDir, '_init.tf'), initTemplate);
86
+ // inputs.tf - provider-specific
87
+ const inputsTemplate = loadTemplate((0, path_1.join)(templatesDir, provider, 'inputs.tf.template'));
88
+ (0, fs_1.writeFileSync)((0, path_1.join)(terraformDir, 'inputs.tf'), inputsTemplate);
89
+ // locals.tf - common with project name replacement
90
+ const localsTemplate = loadTemplate((0, path_1.join)(templatesDir, 'locals.tf.template'));
91
+ const localsContent = processTemplate(localsTemplate, { 'project-name': projectName });
92
+ (0, fs_1.writeFileSync)((0, path_1.join)(terraformDir, 'locals.tf'), localsContent);
93
+ // main.tf - common
94
+ const mainTemplate = loadTemplate((0, path_1.join)(templatesDir, 'main.tf.template'));
95
+ (0, fs_1.writeFileSync)((0, path_1.join)(terraformDir, 'main.tf'), mainTemplate);
96
+ // outputs.tf - common
97
+ const outputsTemplate = loadTemplate((0, path_1.join)(templatesDir, 'outputs.tf.template'));
98
+ (0, fs_1.writeFileSync)((0, path_1.join)(terraformDir, 'outputs.tf'), outputsTemplate);
99
+ // Create modules directory
100
+ const modulesDir = (0, path_1.join)(terraformDir, 'modules');
101
+ (0, fs_1.mkdirSync)(modulesDir, { recursive: true });
102
+ // modules/inputs.tf
103
+ const moduleInputsTemplate = loadTemplate((0, path_1.join)(templatesDir, 'modules', 'inputs.tf.template'));
104
+ (0, fs_1.writeFileSync)((0, path_1.join)(modulesDir, 'inputs.tf'), moduleInputsTemplate);
105
+ // modules/main.tf
106
+ const moduleMainTemplate = loadTemplate((0, path_1.join)(templatesDir, 'modules', 'main.tf.template'));
107
+ (0, fs_1.writeFileSync)((0, path_1.join)(modulesDir, 'main.tf'), moduleMainTemplate);
108
+ // modules/outputs.tf
109
+ const moduleOutputsTemplate = loadTemplate((0, path_1.join)(templatesDir, 'modules', 'outputs.tf.template'));
110
+ (0, fs_1.writeFileSync)((0, path_1.join)(modulesDir, 'outputs.tf'), moduleOutputsTemplate);
111
+ logger_1.Logger.debug('Terraform files generated successfully');
112
+ }
113
+ /**
114
+ * Get file extension for main file based on language
115
+ * @param language - Programming language (javascript, typescript, python, go)
116
+ * @returns File extension (e.g., '.js', '.ts', '.py', '.go')
117
+ * @example
118
+ * getMainExtension('typescript') // returns '.ts'
119
+ * getMainExtension('python') // returns '.py'
120
+ */
121
+ function getMainExtension(language) {
122
+ switch (language) {
123
+ case 'typescript':
124
+ return '.ts';
125
+ case 'python':
126
+ return '.py';
127
+ case 'go':
128
+ return '.go';
129
+ default:
130
+ return '.js';
131
+ }
132
+ }
133
+ /**
134
+ * Get test file name based on language
135
+ * @param language - Programming language (javascript, typescript, python, go)
136
+ * @returns Test file name (e.g., 'index.spec.js', 'test_main.py', 'main_test.go')
137
+ * @example
138
+ * getTestFileName('python') // returns 'test_main.py'
139
+ * getTestFileName('go') // returns 'main_test.go'
140
+ */
141
+ function getTestFileName(language) {
142
+ switch (language) {
143
+ case 'python':
144
+ return 'test_main.py';
145
+ case 'go':
146
+ return 'main_test.go';
147
+ case 'typescript':
148
+ return 'index.spec.ts';
149
+ default:
150
+ return 'index.spec.js';
151
+ }
152
+ }
153
+ /**
154
+ * Generate application files for the project
155
+ * @param projectDir - Root directory of the project
156
+ * @param language - Programming language (javascript, typescript, python, go)
157
+ * @param projectName - Name of the project
158
+ */
159
+ async function generateApplicationFiles(projectDir, language, projectName) {
160
+ const srcDir = (0, path_1.join)(projectDir, 'src');
161
+ const templatesDir = 'application';
162
+ logger_1.Logger.debug(`Generating application files for language: ${language}`);
163
+ // Create src directories
164
+ (0, fs_1.mkdirSync)((0, path_1.join)(srcDir, 'main'), { recursive: true });
165
+ (0, fs_1.mkdirSync)((0, path_1.join)(srcDir, 'test'), { recursive: true });
166
+ // Main file
167
+ const mainTemplate = loadTemplate((0, path_1.join)(templatesDir, language, 'main.template'));
168
+ const mainContent = processTemplate(mainTemplate, { 'project-name': projectName });
169
+ const mainExt = getMainExtension(language);
170
+ (0, fs_1.writeFileSync)((0, path_1.join)(srcDir, 'main', `index${mainExt}`), mainContent);
171
+ // Test file
172
+ const testTemplate = loadTemplate((0, path_1.join)(templatesDir, language, 'test.template'));
173
+ const testContent = processTemplate(testTemplate, { 'project-name': projectName });
174
+ const testFileName = getTestFileName(language);
175
+ (0, fs_1.writeFileSync)((0, path_1.join)(srcDir, 'test', testFileName), testContent);
176
+ // Language-specific config files
177
+ if (language === 'typescript') {
178
+ const tsconfigTemplate = loadTemplate((0, path_1.join)(templatesDir, language, 'tsconfig.json.template'));
179
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, 'tsconfig.json'), tsconfigTemplate);
180
+ }
181
+ else if (language === 'python') {
182
+ const requirementsTemplate = loadTemplate((0, path_1.join)(templatesDir, language, 'requirements.txt.template'));
183
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, 'requirements.txt'), requirementsTemplate);
184
+ }
185
+ else if (language === 'go') {
186
+ const goModTemplate = loadTemplate((0, path_1.join)(templatesDir, language, 'go.mod.template'));
187
+ const goModContent = processTemplate(goModTemplate, { 'project-name': projectName });
188
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, 'go.mod'), goModContent);
189
+ }
190
+ logger_1.Logger.debug('Application files generated successfully');
191
+ }
192
+ /**
193
+ * Map cloud provider to Terraform backend type
194
+ * @param provider - Cloud provider name (aws, azure, gcp)
195
+ * @returns Backend type (s3, azurerm, gcs, or local)
196
+ * @example
197
+ * getBackendType('aws') // returns 's3'
198
+ * getBackendType('azure') // returns 'azurerm'
199
+ * getBackendType('gcp') // returns 'gcs'
200
+ */
201
+ function getBackendType(provider) {
202
+ switch (provider) {
203
+ case 'aws':
204
+ return 's3';
205
+ case 'azure':
206
+ return 'azurerm';
207
+ case 'gcp':
208
+ return 'gcs';
209
+ default:
210
+ return 'local';
211
+ }
212
+ }
213
+ /**
214
+ * Generate configuration files for the project
215
+ * @param projectDir - Root directory of the project
216
+ * @param provider - Cloud provider (aws, azure, gcp)
217
+ * @param language - Programming language (javascript, typescript, python, go)
218
+ * @param projectName - Name of the project
219
+ */
220
+ async function generateConfigFiles(projectDir, provider, language, projectName) {
221
+ const templatesDir = 'config';
222
+ logger_1.Logger.debug(`Generating configuration files for provider: ${provider}, language: ${language}`);
223
+ // .tfwconfig.yml
224
+ const tfwconfigTemplate = loadTemplate((0, path_1.join)(templatesDir, 'tfwconfig.yml.template'));
225
+ const backendType = getBackendType(provider);
226
+ const tfwconfigContent = processTemplate(tfwconfigTemplate, {
227
+ 'project-name': projectName,
228
+ provider: backendType,
229
+ });
230
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, '.tfwconfig.yml'), tfwconfigContent);
231
+ // .env.example
232
+ const envExampleTemplate = loadTemplate((0, path_1.join)(templatesDir, 'env.example.template'));
233
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, '.env.example'), envExampleTemplate);
234
+ // .gitignore
235
+ const gitignoreTemplate = loadTemplate((0, path_1.join)(templatesDir, 'gitignore.template'));
236
+ // gitignore template already includes all languages, no processing needed
237
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, '.gitignore'), gitignoreTemplate);
238
+ // README.md
239
+ const readmeTemplate = loadTemplate((0, path_1.join)(templatesDir, 'README.md.template'));
240
+ const readmeContent = processTemplate(readmeTemplate, {
241
+ 'project-name': projectName,
242
+ provider: provider, // Use original provider name for README
243
+ });
244
+ (0, fs_1.writeFileSync)((0, path_1.join)(projectDir, 'README.md'), readmeContent);
245
+ logger_1.Logger.debug('Configuration files generated successfully');
246
+ }
247
+ /**
248
+ * Project structure creation
249
+ */
250
+ /**
251
+ * Create the complete project directory structure
252
+ * @param projectDir - Root directory of the project
253
+ */
254
+ async function createProjectStructure(projectDir) {
255
+ logger_1.Logger.debug(`Creating project structure in: ${projectDir}`);
256
+ const dirs = [
257
+ (0, path_1.join)(projectDir, 'src', 'main'),
258
+ (0, path_1.join)(projectDir, 'src', 'test'),
259
+ (0, path_1.join)(projectDir, 'terraform', 'modules'),
260
+ ];
261
+ for (const dir of dirs) {
262
+ try {
263
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
264
+ }
265
+ catch (error) {
266
+ logger_1.Logger.error(`Failed to create directory ${dir}: ${error instanceof Error ? error.message : String(error)}`);
267
+ throw new errors_1.ConfigError(`Failed to create directory: ${dir}`);
268
+ }
269
+ }
270
+ logger_1.Logger.debug('Project structure created successfully');
271
+ }
272
+ /**
273
+ * Validation helpers
274
+ */
275
+ /**
276
+ * Validate project name format
277
+ * @param name - Project name to validate
278
+ * @returns true if valid, false otherwise
279
+ */
280
+ function validateProjectName(name) {
281
+ const PROJECT_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
282
+ return PROJECT_NAME_REGEX.test(name);
283
+ }
284
+ /**
285
+ * Validate cloud provider
286
+ * @param provider - Provider name to validate
287
+ * @returns true if valid, false otherwise
288
+ */
289
+ function validateProvider(provider) {
290
+ const VALID_PROVIDERS = ['aws', 'azure', 'gcp'];
291
+ return VALID_PROVIDERS.includes(provider);
292
+ }
293
+ /**
294
+ * Validate programming language
295
+ * @param language - Language name to validate
296
+ * @returns true if valid, false otherwise
297
+ */
298
+ function validateLanguage(language) {
299
+ const VALID_LANGUAGES = ['javascript', 'typescript', 'python', 'go'];
300
+ return VALID_LANGUAGES.includes(language);
301
+ }
302
+ /**
303
+ * Check if a directory is empty
304
+ * @param dir - Directory path to check
305
+ * @returns true if directory is empty or doesn't exist, false otherwise
306
+ */
307
+ async function isDirectoryEmpty(dir) {
308
+ if (!(0, fs_1.existsSync)(dir)) {
309
+ return true;
310
+ }
311
+ try {
312
+ const files = (0, fs_1.readdirSync)(dir);
313
+ return files.length === 0;
314
+ }
315
+ catch (error) {
316
+ logger_1.Logger.error(`Failed to read directory ${dir}: ${error instanceof Error ? error.message : String(error)}`);
317
+ throw new errors_1.ConfigError(`Failed to read directory: ${dir}`);
318
+ }
319
+ }
320
+ /**
321
+ * Template variable builder
322
+ */
323
+ /**
324
+ * Build template variables object from project parameters
325
+ * @param projectName - Name of the project
326
+ * @param provider - Cloud provider (aws, azure, gcp)
327
+ * @param language - Programming language (javascript, typescript, python, go)
328
+ * @returns Object with all template variable mappings
329
+ */
330
+ function buildTemplateVariables(projectName, provider, _language) {
331
+ const backendType = getBackendType(provider);
332
+ return {
333
+ 'project-name': projectName,
334
+ provider: backendType,
335
+ 'provider-name': provider, // Keep original provider name for README
336
+ };
337
+ }
338
+ //# sourceMappingURL=scaffolding.js.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Variable templating utility
3
+ * Resolves template variables in configuration
4
+ */
5
+ /**
6
+ * Template resolution utility
7
+ */
8
+ export declare class TemplateUtils {
9
+ /**
10
+ * Resolve template variables in a string
11
+ * Supports ${VAR} syntax
12
+ * @param template - Template string with ${VAR} placeholders
13
+ * @param vars - Variables to substitute
14
+ * @returns Resolved string
15
+ */
16
+ static resolve(template: string, vars: Record<string, string>): string;
17
+ /**
18
+ * Resolve all template variables in an object recursively
19
+ * @param obj - Object to resolve templates in
20
+ * @param vars - Variables to substitute
21
+ * @returns Object with templates resolved
22
+ */
23
+ static resolveObject<T extends Record<string, unknown>>(obj: T, vars: Record<string, string>): T;
24
+ }
25
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * Variable templating utility
4
+ * Resolves template variables in configuration
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.TemplateUtils = void 0;
8
+ /**
9
+ * Template resolution utility
10
+ */
11
+ class TemplateUtils {
12
+ /**
13
+ * Resolve template variables in a string
14
+ * Supports ${VAR} syntax
15
+ * @param template - Template string with ${VAR} placeholders
16
+ * @param vars - Variables to substitute
17
+ * @returns Resolved string
18
+ */
19
+ static resolve(template, vars) {
20
+ if (typeof template !== 'string') {
21
+ return template;
22
+ }
23
+ return template.replace(/\$\{([^}]+)\}/g, (match, varName) => {
24
+ const trimmedVarName = varName.trim();
25
+ if (vars[trimmedVarName] !== undefined) {
26
+ return vars[trimmedVarName];
27
+ }
28
+ // If variable not found, return the original placeholder
29
+ return match;
30
+ });
31
+ }
32
+ /**
33
+ * Resolve all template variables in an object recursively
34
+ * @param obj - Object to resolve templates in
35
+ * @param vars - Variables to substitute
36
+ * @returns Object with templates resolved
37
+ */
38
+ static resolveObject(obj, vars) {
39
+ if (obj === null || obj === undefined) {
40
+ return obj;
41
+ }
42
+ if (typeof obj === 'string') {
43
+ return TemplateUtils.resolve(obj, vars);
44
+ }
45
+ if (Array.isArray(obj)) {
46
+ return obj.map((item) => TemplateUtils.resolveObject(item, vars));
47
+ }
48
+ if (typeof obj === 'object') {
49
+ const resolved = {};
50
+ for (const key in obj) {
51
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
52
+ const value = obj[key];
53
+ if (typeof value === 'string') {
54
+ resolved[key] = TemplateUtils.resolve(value, vars);
55
+ }
56
+ else if (typeof value === 'object' && value !== null) {
57
+ resolved[key] = TemplateUtils.resolveObject(value, vars);
58
+ }
59
+ else {
60
+ resolved[key] = value;
61
+ }
62
+ }
63
+ }
64
+ return resolved;
65
+ }
66
+ return obj;
67
+ }
68
+ }
69
+ exports.TemplateUtils = TemplateUtils;
70
+ //# sourceMappingURL=templates.js.map
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@salte-common/terraflow",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "Opinionated Terraform workflow CLI with multi-cloud support",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "terraflow": "./bin/terraflow.js",
9
+ "tf": "./bin/tf.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc && npm run copy-templates",
13
+ "copy-templates": "cp -r src/templates dist/templates",
14
+ "test": "jest",
15
+ "test:coverage": "jest --coverage",
16
+ "lint": "eslint src --ext .ts",
17
+ "format": "prettier --write \"src/**/*.ts\"",
18
+ "prepublishOnly": "npm run build && npm test"
19
+ },
20
+ "keywords": [
21
+ "terraform",
22
+ "infrastructure",
23
+ "iac",
24
+ "devops",
25
+ "cli",
26
+ "aws",
27
+ "azure",
28
+ "gcp"
29
+ ],
30
+ "author": "Dave Sibiski",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/salte-common/terraflow.git"
35
+ },
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ },
39
+ "dependencies": {
40
+ "@aws-sdk/client-secrets-manager": "^3.956.0",
41
+ "@aws-sdk/client-sts": "^3.956.0",
42
+ "commander": "^11.0.0",
43
+ "dotenv": "^16.0.0",
44
+ "js-yaml": "^4.1.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/jest": "^29.0.0",
48
+ "@types/js-yaml": "^4.0.5",
49
+ "@types/node": "^20.0.0",
50
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
51
+ "@typescript-eslint/parser": "^6.0.0",
52
+ "eslint": "^8.0.0",
53
+ "eslint-config-prettier": "^9.0.0",
54
+ "eslint-plugin-prettier": "^5.0.0",
55
+ "jest": "^29.0.0",
56
+ "prettier": "^3.0.0",
57
+ "ts-jest": "^29.0.0",
58
+ "typescript": "^5.0.0"
59
+ }
60
+ }