parse-hcl 0.1.0
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.
- package/LICENSE +201 -0
- package/README.md +749 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +91 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +74 -0
- package/dist/parsers/genericParser.d.ts +167 -0
- package/dist/parsers/genericParser.js +268 -0
- package/dist/parsers/localsParser.d.ts +30 -0
- package/dist/parsers/localsParser.js +43 -0
- package/dist/parsers/outputParser.d.ts +25 -0
- package/dist/parsers/outputParser.js +44 -0
- package/dist/parsers/variableParser.d.ts +62 -0
- package/dist/parsers/variableParser.js +249 -0
- package/dist/services/artifactParsers.d.ts +12 -0
- package/dist/services/artifactParsers.js +157 -0
- package/dist/services/terraformJsonParser.d.ts +16 -0
- package/dist/services/terraformJsonParser.js +212 -0
- package/dist/services/terraformParser.d.ts +91 -0
- package/dist/services/terraformParser.js +191 -0
- package/dist/types/artifacts.d.ts +210 -0
- package/dist/types/artifacts.js +5 -0
- package/dist/types/blocks.d.ts +419 -0
- package/dist/types/blocks.js +28 -0
- package/dist/utils/common/errors.d.ts +46 -0
- package/dist/utils/common/errors.js +54 -0
- package/dist/utils/common/fs.d.ts +5 -0
- package/dist/utils/common/fs.js +48 -0
- package/dist/utils/common/logger.d.ts +5 -0
- package/dist/utils/common/logger.js +17 -0
- package/dist/utils/common/valueHelpers.d.ts +4 -0
- package/dist/utils/common/valueHelpers.js +23 -0
- package/dist/utils/graph/graphBuilder.d.ts +33 -0
- package/dist/utils/graph/graphBuilder.js +373 -0
- package/dist/utils/lexer/blockScanner.d.ts +36 -0
- package/dist/utils/lexer/blockScanner.js +143 -0
- package/dist/utils/lexer/hclLexer.d.ts +119 -0
- package/dist/utils/lexer/hclLexer.js +525 -0
- package/dist/utils/parser/bodyParser.d.ts +26 -0
- package/dist/utils/parser/bodyParser.js +81 -0
- package/dist/utils/parser/valueClassifier.d.ts +21 -0
- package/dist/utils/parser/valueClassifier.js +434 -0
- package/dist/utils/serialization/serializer.d.ts +9 -0
- package/dist/utils/serialization/serializer.js +63 -0
- package/dist/utils/serialization/yaml.d.ts +1 -0
- package/dist/utils/serialization/yaml.js +81 -0
- package/package.json +66 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Terraform HCL block structures.
|
|
3
|
+
* Provides comprehensive type coverage for all Terraform configuration elements.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Known Terraform block types.
|
|
7
|
+
* - `terraform`: Terraform settings and required providers
|
|
8
|
+
* - `provider`: Provider configuration
|
|
9
|
+
* - `variable`: Input variable declarations
|
|
10
|
+
* - `output`: Output value declarations
|
|
11
|
+
* - `module`: Module calls
|
|
12
|
+
* - `resource`: Managed resource definitions
|
|
13
|
+
* - `data`: Data source definitions
|
|
14
|
+
* - `locals`: Local value definitions
|
|
15
|
+
* - `moved`: Resource move declarations
|
|
16
|
+
* - `import`: Import declarations
|
|
17
|
+
* - `check`: Check assertions
|
|
18
|
+
* - `terraform_data`: Terraform data resources
|
|
19
|
+
* - `unknown`: Unrecognized block types
|
|
20
|
+
*/
|
|
21
|
+
export type BlockKind = 'terraform' | 'provider' | 'variable' | 'output' | 'module' | 'resource' | 'data' | 'locals' | 'moved' | 'import' | 'check' | 'terraform_data' | 'unknown';
|
|
22
|
+
/**
|
|
23
|
+
* Types of expressions in HCL.
|
|
24
|
+
* - `traversal`: Attribute access (e.g., `var.name`, `local.value`)
|
|
25
|
+
* - `function_call`: Function invocation (e.g., `length(var.list)`)
|
|
26
|
+
* - `template`: String interpolation (e.g., `"${var.name}"`)
|
|
27
|
+
* - `for_expr`: For expressions/comprehensions
|
|
28
|
+
* - `conditional`: Ternary conditional (e.g., `var.enabled ? "yes" : "no"`)
|
|
29
|
+
* - `splat`: Splat expressions (e.g., `aws_instance.web[*].id`)
|
|
30
|
+
* - `unknown`: Unrecognized expression type
|
|
31
|
+
*/
|
|
32
|
+
export type ExpressionKind = 'traversal' | 'function_call' | 'template' | 'for_expr' | 'conditional' | 'splat' | 'unknown';
|
|
33
|
+
/**
|
|
34
|
+
* Reference to a Terraform configuration element.
|
|
35
|
+
* Used for dependency tracking and graph building.
|
|
36
|
+
*/
|
|
37
|
+
export type Reference = {
|
|
38
|
+
kind: 'variable';
|
|
39
|
+
name: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'local';
|
|
42
|
+
name: string;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'module_output';
|
|
45
|
+
module: string;
|
|
46
|
+
name: string;
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'data';
|
|
49
|
+
data_type: string;
|
|
50
|
+
name: string;
|
|
51
|
+
attribute?: string;
|
|
52
|
+
splat?: boolean;
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'resource';
|
|
55
|
+
resource_type: string;
|
|
56
|
+
name: string;
|
|
57
|
+
attribute?: string;
|
|
58
|
+
splat?: boolean;
|
|
59
|
+
} | {
|
|
60
|
+
kind: 'path';
|
|
61
|
+
name: string;
|
|
62
|
+
} | {
|
|
63
|
+
kind: 'each';
|
|
64
|
+
property: 'key' | 'value';
|
|
65
|
+
} | {
|
|
66
|
+
kind: 'count';
|
|
67
|
+
property: 'index';
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'self';
|
|
70
|
+
attribute: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* A literal value (string, number, boolean, or null).
|
|
74
|
+
*/
|
|
75
|
+
export interface LiteralValue {
|
|
76
|
+
type: 'literal';
|
|
77
|
+
/** The parsed literal value */
|
|
78
|
+
value: string | number | boolean | null;
|
|
79
|
+
/** The original raw text */
|
|
80
|
+
raw: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* An object/map value with key-value pairs.
|
|
84
|
+
*/
|
|
85
|
+
export interface ObjectValue {
|
|
86
|
+
type: 'object';
|
|
87
|
+
/** Parsed object entries (if successfully parsed) */
|
|
88
|
+
value?: Record<string, Value>;
|
|
89
|
+
/** The original raw text */
|
|
90
|
+
raw: string;
|
|
91
|
+
/** References found within the object */
|
|
92
|
+
references?: Reference[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* An array/list value with elements.
|
|
96
|
+
*/
|
|
97
|
+
export interface ArrayValue {
|
|
98
|
+
type: 'array';
|
|
99
|
+
/** Parsed array elements (if successfully parsed) */
|
|
100
|
+
value?: Value[];
|
|
101
|
+
/** The original raw text */
|
|
102
|
+
raw: string;
|
|
103
|
+
/** References found within the array */
|
|
104
|
+
references?: Reference[];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* An expression value (traversals, function calls, templates, etc.).
|
|
108
|
+
*/
|
|
109
|
+
export interface ExpressionValue {
|
|
110
|
+
type: 'expression';
|
|
111
|
+
/** The kind of expression */
|
|
112
|
+
kind: ExpressionKind;
|
|
113
|
+
/** The original raw text */
|
|
114
|
+
raw: string;
|
|
115
|
+
/** References found within the expression */
|
|
116
|
+
references?: Reference[];
|
|
117
|
+
/** Additional parsed data (for specific expression types) */
|
|
118
|
+
parsed?: Record<string, unknown>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Union type for all possible HCL values.
|
|
122
|
+
*/
|
|
123
|
+
export type Value = LiteralValue | ObjectValue | ArrayValue | ExpressionValue;
|
|
124
|
+
/**
|
|
125
|
+
* Parsed body of an HCL block containing attributes and nested blocks.
|
|
126
|
+
*/
|
|
127
|
+
export interface ParsedBody {
|
|
128
|
+
/** Key-value attribute assignments */
|
|
129
|
+
attributes: Record<string, Value>;
|
|
130
|
+
/** Nested block definitions */
|
|
131
|
+
blocks: NestedBlock[];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A nested block within a parent block.
|
|
135
|
+
*/
|
|
136
|
+
export interface NestedBlock {
|
|
137
|
+
/** The block type identifier */
|
|
138
|
+
type: string;
|
|
139
|
+
/** Block labels (e.g., for provisioner blocks) */
|
|
140
|
+
labels: string[];
|
|
141
|
+
/** Attribute assignments within the block */
|
|
142
|
+
attributes: Record<string, Value>;
|
|
143
|
+
/** Further nested blocks */
|
|
144
|
+
blocks: NestedBlock[];
|
|
145
|
+
/** The original raw text */
|
|
146
|
+
raw: string;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* A raw HCL block as extracted by the scanner.
|
|
150
|
+
*/
|
|
151
|
+
export interface HclBlock {
|
|
152
|
+
/** The classified block kind */
|
|
153
|
+
kind: BlockKind;
|
|
154
|
+
/** The original keyword used */
|
|
155
|
+
keyword: string;
|
|
156
|
+
/** Block labels (e.g., resource type and name) */
|
|
157
|
+
labels: string[];
|
|
158
|
+
/** The block body content (without braces) */
|
|
159
|
+
body: string;
|
|
160
|
+
/** The complete raw block text */
|
|
161
|
+
raw: string;
|
|
162
|
+
/** Source file path */
|
|
163
|
+
source: string;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Terraform settings block (terraform { ... }).
|
|
167
|
+
*/
|
|
168
|
+
export interface TerraformSettingsBlock {
|
|
169
|
+
/** All properties defined in the block */
|
|
170
|
+
properties: Record<string, Value>;
|
|
171
|
+
/** The original raw text */
|
|
172
|
+
raw: string;
|
|
173
|
+
/** Source file path */
|
|
174
|
+
source: string;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Provider configuration block.
|
|
178
|
+
*/
|
|
179
|
+
export interface ProviderBlock {
|
|
180
|
+
/** Provider name (e.g., "aws", "google") */
|
|
181
|
+
name: string;
|
|
182
|
+
/** Provider alias (for multiple provider configurations) */
|
|
183
|
+
alias?: string;
|
|
184
|
+
/** All properties defined in the block */
|
|
185
|
+
properties: Record<string, Value>;
|
|
186
|
+
/** The original raw text */
|
|
187
|
+
raw: string;
|
|
188
|
+
/** Source file path */
|
|
189
|
+
source: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Module call block.
|
|
193
|
+
*/
|
|
194
|
+
export interface ModuleBlock {
|
|
195
|
+
/** Module name (the label) */
|
|
196
|
+
name: string;
|
|
197
|
+
/** All properties defined in the block (including source, version, etc.) */
|
|
198
|
+
properties: Record<string, Value>;
|
|
199
|
+
/** The original raw text */
|
|
200
|
+
raw: string;
|
|
201
|
+
/** Source file path */
|
|
202
|
+
source: string;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Resource definition block.
|
|
206
|
+
*/
|
|
207
|
+
export interface ResourceBlock {
|
|
208
|
+
/** Resource type (e.g., "aws_instance", "google_compute_instance") */
|
|
209
|
+
type: string;
|
|
210
|
+
/** Resource name (the second label) */
|
|
211
|
+
name: string;
|
|
212
|
+
/** Resource properties (excluding meta-arguments) */
|
|
213
|
+
properties: Record<string, Value>;
|
|
214
|
+
/** Nested blocks within the resource */
|
|
215
|
+
blocks: NestedBlock[];
|
|
216
|
+
/** Dynamic blocks within the resource */
|
|
217
|
+
dynamic_blocks: DynamicBlock[];
|
|
218
|
+
/** Meta-arguments (count, for_each, provider, depends_on, lifecycle) */
|
|
219
|
+
meta: Record<string, Value>;
|
|
220
|
+
/** The original raw text */
|
|
221
|
+
raw: string;
|
|
222
|
+
/** Source file path */
|
|
223
|
+
source: string;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Dynamic block definition within a resource.
|
|
227
|
+
*/
|
|
228
|
+
export interface DynamicBlock {
|
|
229
|
+
/** The label (block type being generated) */
|
|
230
|
+
label: string;
|
|
231
|
+
/** The for_each expression */
|
|
232
|
+
for_each?: Value;
|
|
233
|
+
/** The iterator variable name */
|
|
234
|
+
iterator?: string;
|
|
235
|
+
/** The content block attributes */
|
|
236
|
+
content: Record<string, Value>;
|
|
237
|
+
/** The original raw text */
|
|
238
|
+
raw: string;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Data source definition block.
|
|
242
|
+
*/
|
|
243
|
+
export interface DataBlock {
|
|
244
|
+
/** Data source type (e.g., "aws_ami", "google_compute_image") */
|
|
245
|
+
dataType: string;
|
|
246
|
+
/** Data source name (the second label) */
|
|
247
|
+
name: string;
|
|
248
|
+
/** Data source properties */
|
|
249
|
+
properties: Record<string, Value>;
|
|
250
|
+
/** Nested blocks within the data source */
|
|
251
|
+
blocks: NestedBlock[];
|
|
252
|
+
/** The original raw text */
|
|
253
|
+
raw: string;
|
|
254
|
+
/** Source file path */
|
|
255
|
+
source: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Parsed type constraint for a variable.
|
|
259
|
+
*/
|
|
260
|
+
export interface TypeConstraint {
|
|
261
|
+
/** The base type name (string, number, bool, list, map, object, set, tuple, any) */
|
|
262
|
+
base: string;
|
|
263
|
+
/** Element type for collection types */
|
|
264
|
+
element?: TypeConstraint;
|
|
265
|
+
/** Element types for tuple types */
|
|
266
|
+
elements?: TypeConstraint[];
|
|
267
|
+
/** Attribute types for object types */
|
|
268
|
+
attributes?: Record<string, TypeConstraint>;
|
|
269
|
+
/** Whether the type is optional (for object attributes) */
|
|
270
|
+
optional?: boolean;
|
|
271
|
+
/** The original raw type expression */
|
|
272
|
+
raw: string;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Validation rule for a variable.
|
|
276
|
+
*/
|
|
277
|
+
export interface VariableValidation {
|
|
278
|
+
/** The condition expression (must evaluate to true) */
|
|
279
|
+
condition?: Value;
|
|
280
|
+
/** The error message to display when condition is false */
|
|
281
|
+
error_message?: Value;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Variable definition block.
|
|
285
|
+
*/
|
|
286
|
+
export interface VariableBlock {
|
|
287
|
+
/** Variable name */
|
|
288
|
+
name: string;
|
|
289
|
+
/** Variable description */
|
|
290
|
+
description?: string;
|
|
291
|
+
/** Type constraint expression */
|
|
292
|
+
type?: string;
|
|
293
|
+
/** Parsed type constraint (if type is provided) */
|
|
294
|
+
typeConstraint?: TypeConstraint;
|
|
295
|
+
/** Default value */
|
|
296
|
+
default?: Value;
|
|
297
|
+
/** Validation rules */
|
|
298
|
+
validation?: VariableValidation;
|
|
299
|
+
/** Whether the variable is sensitive */
|
|
300
|
+
sensitive?: boolean;
|
|
301
|
+
/** Whether the variable is nullable */
|
|
302
|
+
nullable?: boolean;
|
|
303
|
+
/** The original raw text */
|
|
304
|
+
raw: string;
|
|
305
|
+
/** Source file path */
|
|
306
|
+
source: string;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Output definition block.
|
|
310
|
+
*/
|
|
311
|
+
export interface OutputBlock {
|
|
312
|
+
/** Output name */
|
|
313
|
+
name: string;
|
|
314
|
+
/** Output description */
|
|
315
|
+
description?: string;
|
|
316
|
+
/** The output value expression */
|
|
317
|
+
value?: Value;
|
|
318
|
+
/** Whether the output is sensitive */
|
|
319
|
+
sensitive?: boolean;
|
|
320
|
+
/** The original raw text */
|
|
321
|
+
raw: string;
|
|
322
|
+
/** Source file path */
|
|
323
|
+
source: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* A single local value definition.
|
|
327
|
+
*/
|
|
328
|
+
export interface LocalValue {
|
|
329
|
+
/** Local value name */
|
|
330
|
+
name: string;
|
|
331
|
+
/** The value type classification */
|
|
332
|
+
type: Value['type'];
|
|
333
|
+
/** The parsed value */
|
|
334
|
+
value: Value;
|
|
335
|
+
/** The original raw text */
|
|
336
|
+
raw: string;
|
|
337
|
+
/** Source file path */
|
|
338
|
+
source: string;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* A generic block for less common block types (moved, import, check, etc.).
|
|
342
|
+
*/
|
|
343
|
+
export interface GenericBlock {
|
|
344
|
+
/** The block type */
|
|
345
|
+
type: string;
|
|
346
|
+
/** Block labels */
|
|
347
|
+
labels: string[];
|
|
348
|
+
/** Block properties */
|
|
349
|
+
properties: Record<string, Value>;
|
|
350
|
+
/** Nested blocks */
|
|
351
|
+
blocks: NestedBlock[];
|
|
352
|
+
/** The original raw text */
|
|
353
|
+
raw: string;
|
|
354
|
+
/** Source file path */
|
|
355
|
+
source: string;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Complete Terraform document containing all parsed blocks.
|
|
359
|
+
*/
|
|
360
|
+
export interface TerraformDocument {
|
|
361
|
+
/** Terraform settings blocks */
|
|
362
|
+
terraform: TerraformSettingsBlock[];
|
|
363
|
+
/** Provider configurations */
|
|
364
|
+
provider: ProviderBlock[];
|
|
365
|
+
/** Variable declarations */
|
|
366
|
+
variable: VariableBlock[];
|
|
367
|
+
/** Output declarations */
|
|
368
|
+
output: OutputBlock[];
|
|
369
|
+
/** Module calls */
|
|
370
|
+
module: ModuleBlock[];
|
|
371
|
+
/** Resource definitions */
|
|
372
|
+
resource: ResourceBlock[];
|
|
373
|
+
/** Data source definitions */
|
|
374
|
+
data: DataBlock[];
|
|
375
|
+
/** Local value definitions */
|
|
376
|
+
locals: LocalValue[];
|
|
377
|
+
/** Moved declarations */
|
|
378
|
+
moved: GenericBlock[];
|
|
379
|
+
/** Import declarations */
|
|
380
|
+
import: GenericBlock[];
|
|
381
|
+
/** Check assertions */
|
|
382
|
+
check: GenericBlock[];
|
|
383
|
+
/** Terraform data resources */
|
|
384
|
+
terraform_data: GenericBlock[];
|
|
385
|
+
/** Unrecognized blocks */
|
|
386
|
+
unknown: GenericBlock[];
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Creates an empty TerraformDocument with all arrays initialized.
|
|
390
|
+
* @returns A new empty TerraformDocument
|
|
391
|
+
*/
|
|
392
|
+
export declare function createEmptyDocument(): TerraformDocument;
|
|
393
|
+
/**
|
|
394
|
+
* Result of parsing a single file.
|
|
395
|
+
*/
|
|
396
|
+
export interface FileParseResult {
|
|
397
|
+
/** The file path */
|
|
398
|
+
path: string;
|
|
399
|
+
/** The parsed document */
|
|
400
|
+
document: TerraformDocument;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Options for directory parsing.
|
|
404
|
+
*/
|
|
405
|
+
export interface DirectoryParseOptions {
|
|
406
|
+
/** Whether to aggregate all files into a combined document (default: true) */
|
|
407
|
+
aggregate?: boolean;
|
|
408
|
+
/** Whether to include per-file results (default: true) */
|
|
409
|
+
includePerFile?: boolean;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Result of parsing a directory.
|
|
413
|
+
*/
|
|
414
|
+
export interface DirectoryParseResult {
|
|
415
|
+
/** Combined document from all files (if aggregate is true) */
|
|
416
|
+
combined?: TerraformDocument;
|
|
417
|
+
/** Per-file parsing results (if includePerFile is true) */
|
|
418
|
+
files: FileParseResult[];
|
|
419
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Type definitions for Terraform HCL block structures.
|
|
4
|
+
* Provides comprehensive type coverage for all Terraform configuration elements.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.createEmptyDocument = createEmptyDocument;
|
|
8
|
+
/**
|
|
9
|
+
* Creates an empty TerraformDocument with all arrays initialized.
|
|
10
|
+
* @returns A new empty TerraformDocument
|
|
11
|
+
*/
|
|
12
|
+
function createEmptyDocument() {
|
|
13
|
+
return {
|
|
14
|
+
terraform: [],
|
|
15
|
+
provider: [],
|
|
16
|
+
variable: [],
|
|
17
|
+
output: [],
|
|
18
|
+
module: [],
|
|
19
|
+
resource: [],
|
|
20
|
+
data: [],
|
|
21
|
+
locals: [],
|
|
22
|
+
moved: [],
|
|
23
|
+
import: [],
|
|
24
|
+
check: [],
|
|
25
|
+
terraform_data: [],
|
|
26
|
+
unknown: []
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a location in source code with line, column, and absolute offset.
|
|
3
|
+
*/
|
|
4
|
+
export interface SourceLocation {
|
|
5
|
+
/** 1-based line number */
|
|
6
|
+
line: number;
|
|
7
|
+
/** 1-based column number */
|
|
8
|
+
column: number;
|
|
9
|
+
/** 0-based character offset from start of content */
|
|
10
|
+
offset: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Represents a range in source code from start to end positions.
|
|
14
|
+
*/
|
|
15
|
+
export interface SourceRange {
|
|
16
|
+
start: SourceLocation;
|
|
17
|
+
end: SourceLocation;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when HCL parsing fails.
|
|
21
|
+
* Contains location information for debugging.
|
|
22
|
+
*/
|
|
23
|
+
export declare class ParseError extends Error {
|
|
24
|
+
/** The source file path where the error occurred */
|
|
25
|
+
readonly source: string;
|
|
26
|
+
/** The location in the source where the error occurred */
|
|
27
|
+
readonly location: SourceLocation;
|
|
28
|
+
/** Optional end location for range-based errors */
|
|
29
|
+
readonly endLocation?: SourceLocation;
|
|
30
|
+
constructor(message: string, source: string, location: SourceLocation, endLocation?: SourceLocation);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Calculates line and column numbers from a character offset.
|
|
34
|
+
* @param content - The full source content
|
|
35
|
+
* @param offset - The 0-based character offset
|
|
36
|
+
* @returns The source location with line, column, and offset
|
|
37
|
+
*/
|
|
38
|
+
export declare function offsetToLocation(content: string, offset: number): SourceLocation;
|
|
39
|
+
/**
|
|
40
|
+
* Creates a SourceRange from start and end offsets.
|
|
41
|
+
* @param content - The full source content
|
|
42
|
+
* @param startOffset - The 0-based start offset
|
|
43
|
+
* @param endOffset - The 0-based end offset
|
|
44
|
+
* @returns The source range
|
|
45
|
+
*/
|
|
46
|
+
export declare function offsetsToRange(content: string, startOffset: number, endOffset: number): SourceRange;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ParseError = void 0;
|
|
4
|
+
exports.offsetToLocation = offsetToLocation;
|
|
5
|
+
exports.offsetsToRange = offsetsToRange;
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when HCL parsing fails.
|
|
8
|
+
* Contains location information for debugging.
|
|
9
|
+
*/
|
|
10
|
+
class ParseError extends Error {
|
|
11
|
+
constructor(message, source, location, endLocation) {
|
|
12
|
+
const locationStr = `${source}:${location.line}:${location.column}`;
|
|
13
|
+
super(`${message} at ${locationStr}`);
|
|
14
|
+
this.name = 'ParseError';
|
|
15
|
+
this.source = source;
|
|
16
|
+
this.location = location;
|
|
17
|
+
this.endLocation = endLocation;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.ParseError = ParseError;
|
|
21
|
+
/**
|
|
22
|
+
* Calculates line and column numbers from a character offset.
|
|
23
|
+
* @param content - The full source content
|
|
24
|
+
* @param offset - The 0-based character offset
|
|
25
|
+
* @returns The source location with line, column, and offset
|
|
26
|
+
*/
|
|
27
|
+
function offsetToLocation(content, offset) {
|
|
28
|
+
let line = 1;
|
|
29
|
+
let column = 1;
|
|
30
|
+
const safeOffset = Math.min(offset, content.length);
|
|
31
|
+
for (let i = 0; i < safeOffset; i++) {
|
|
32
|
+
if (content[i] === '\n') {
|
|
33
|
+
line++;
|
|
34
|
+
column = 1;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
column++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { line, column, offset: safeOffset };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a SourceRange from start and end offsets.
|
|
44
|
+
* @param content - The full source content
|
|
45
|
+
* @param startOffset - The 0-based start offset
|
|
46
|
+
* @param endOffset - The 0-based end offset
|
|
47
|
+
* @returns The source range
|
|
48
|
+
*/
|
|
49
|
+
function offsetsToRange(content, startOffset, endOffset) {
|
|
50
|
+
return {
|
|
51
|
+
start: offsetToLocation(content, startOffset),
|
|
52
|
+
end: offsetToLocation(content, endOffset)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function readTextFile(filePath: string): string;
|
|
2
|
+
export declare function readJsonFile<T = unknown>(filePath: string): T;
|
|
3
|
+
export declare function listTerraformFiles(dirPath: string): string[];
|
|
4
|
+
export declare function pathExists(targetPath: string): boolean;
|
|
5
|
+
export declare function isDirectory(targetPath: string): boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readTextFile = readTextFile;
|
|
7
|
+
exports.readJsonFile = readJsonFile;
|
|
8
|
+
exports.listTerraformFiles = listTerraformFiles;
|
|
9
|
+
exports.pathExists = pathExists;
|
|
10
|
+
exports.isDirectory = isDirectory;
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const IGNORED_DIRS = new Set(['.terraform', '.git', 'node_modules']);
|
|
14
|
+
function readTextFile(filePath) {
|
|
15
|
+
return fs_1.default.readFileSync(filePath, 'utf-8');
|
|
16
|
+
}
|
|
17
|
+
function readJsonFile(filePath) {
|
|
18
|
+
return JSON.parse(readTextFile(filePath));
|
|
19
|
+
}
|
|
20
|
+
function listTerraformFiles(dirPath) {
|
|
21
|
+
const files = [];
|
|
22
|
+
const stack = [dirPath];
|
|
23
|
+
while (stack.length > 0) {
|
|
24
|
+
const current = stack.pop();
|
|
25
|
+
const entries = fs_1.default.readdirSync(current, { withFileTypes: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const fullPath = path_1.default.join(current, entry.name);
|
|
28
|
+
if (entry.isDirectory()) {
|
|
29
|
+
if (IGNORED_DIRS.has(entry.name)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
stack.push(fullPath);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (entry.isFile() &&
|
|
36
|
+
(entry.name.endsWith('.tf') || entry.name.endsWith('.tf.json'))) {
|
|
37
|
+
files.push(fullPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return files.sort();
|
|
42
|
+
}
|
|
43
|
+
function pathExists(targetPath) {
|
|
44
|
+
return fs_1.default.existsSync(targetPath);
|
|
45
|
+
}
|
|
46
|
+
function isDirectory(targetPath) {
|
|
47
|
+
return fs_1.default.existsSync(targetPath) && fs_1.default.statSync(targetPath).isDirectory();
|
|
48
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
/* Simple logger used inside the parser. */
|
|
5
|
+
exports.logger = {
|
|
6
|
+
debug: (...args) => {
|
|
7
|
+
if (process.env.TF_PARSER_DEBUG) {
|
|
8
|
+
console.debug('[parser:debug]', ...args);
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
info: (...args) => {
|
|
12
|
+
console.info('[parser:info]', ...args);
|
|
13
|
+
},
|
|
14
|
+
warn: (...args) => {
|
|
15
|
+
console.warn('[parser:warn]', ...args);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.literalString = literalString;
|
|
4
|
+
exports.literalBoolean = literalBoolean;
|
|
5
|
+
exports.literalNumber = literalNumber;
|
|
6
|
+
function literalString(value) {
|
|
7
|
+
if (value?.type === 'literal' && typeof value.value === 'string') {
|
|
8
|
+
return value.value;
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
function literalBoolean(value) {
|
|
13
|
+
if (value?.type === 'literal' && typeof value.value === 'boolean') {
|
|
14
|
+
return value.value;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
function literalNumber(value) {
|
|
19
|
+
if (value?.type === 'literal' && typeof value.value === 'number') {
|
|
20
|
+
return value.value;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency graph builder for Terraform documents.
|
|
3
|
+
* Creates a directed graph of dependencies between Terraform elements.
|
|
4
|
+
*/
|
|
5
|
+
import { DependencyGraph, TerraformExport } from '../../types/artifacts';
|
|
6
|
+
import { TerraformDocument } from '../../types/blocks';
|
|
7
|
+
/**
|
|
8
|
+
* Builds a dependency graph from a parsed Terraform document.
|
|
9
|
+
* Analyzes all blocks and their references to construct nodes and edges.
|
|
10
|
+
*
|
|
11
|
+
* @param document - The parsed Terraform document
|
|
12
|
+
* @returns A complete dependency graph with nodes, edges, and orphan references
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const parser = new TerraformParser();
|
|
17
|
+
* const doc = parser.parseFile('main.tf');
|
|
18
|
+
* const graph = buildDependencyGraph(doc);
|
|
19
|
+
*
|
|
20
|
+
* // Visualize dependencies
|
|
21
|
+
* for (const edge of graph.edges) {
|
|
22
|
+
* console.log(`${edge.from} -> ${edge.to}`);
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildDependencyGraph(document: TerraformDocument): DependencyGraph;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a complete export containing the document and its dependency graph.
|
|
29
|
+
*
|
|
30
|
+
* @param document - The parsed Terraform document
|
|
31
|
+
* @returns TerraformExport with version, document, and graph
|
|
32
|
+
*/
|
|
33
|
+
export declare function createExport(document: TerraformDocument): TerraformExport;
|