@fjall/generator 0.89.5 → 0.89.6
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 +50 -21
- package/README.md +28 -0
- package/dist/.minified +1 -0
- package/dist/src/ast/astCdnParser.d.ts +5 -0
- package/dist/src/ast/astCdnParser.js +1 -114
- package/dist/src/ast/astCommonParser.d.ts +6 -17
- package/dist/src/ast/astCommonParser.js +1 -351
- package/dist/src/ast/astComputeConnectionParser.d.ts +18 -0
- package/dist/src/ast/astComputeConnectionParser.js +1 -0
- package/dist/src/ast/astComputeParser.d.ts +6 -0
- package/dist/src/ast/astComputeParser.js +1 -473
- package/dist/src/ast/astComputeParserHelpers.d.ts +21 -0
- package/dist/src/ast/astComputeParserHelpers.js +1 -0
- package/dist/src/ast/astDatabaseParser.d.ts +9 -24
- package/dist/src/ast/astDatabaseParser.js +1 -275
- package/dist/src/ast/astDomainParser.d.ts +139 -0
- package/dist/src/ast/astDomainParser.js +1 -0
- package/dist/src/ast/astDynamoDBParser.d.ts +35 -0
- package/dist/src/ast/astDynamoDBParser.js +1 -0
- package/dist/src/ast/astExpressionEvaluator.d.ts +23 -0
- package/dist/src/ast/astExpressionEvaluator.js +1 -0
- package/dist/src/ast/astInfrastructureParser.d.ts +12 -49
- package/dist/src/ast/astInfrastructureParser.js +1 -552
- package/dist/src/ast/astMessagingParser.d.ts +5 -0
- package/dist/src/ast/astMessagingParser.js +1 -78
- package/dist/src/ast/astNetworkParser.d.ts +6 -0
- package/dist/src/ast/astNetworkParser.js +1 -219
- package/dist/src/ast/astPatternParser.d.ts +6 -0
- package/dist/src/ast/astPatternParser.js +1 -155
- package/dist/src/ast/astPlanConverter.d.ts +11 -0
- package/dist/src/ast/astPlanConverter.js +2 -0
- package/dist/src/ast/astStatementClassifier.d.ts +24 -0
- package/dist/src/ast/astStatementClassifier.js +1 -0
- package/dist/src/ast/astStatementQueries.d.ts +21 -0
- package/dist/src/ast/astStatementQueries.js +3 -0
- package/dist/src/ast/astStorageParser.d.ts +5 -0
- package/dist/src/ast/astStorageParser.js +1 -164
- package/dist/src/ast/astSurgicalModification.js +19 -400
- package/dist/src/ast/astTestHelpers.d.ts +635 -0
- package/dist/src/ast/astTestHelpers.js +1 -0
- package/dist/src/ast/index.d.ts +1 -0
- package/dist/src/ast/index.js +1 -6
- package/dist/src/aws/regions.js +1 -254
- package/dist/src/codemod/_internal.d.ts +12 -0
- package/dist/src/codemod/_internal.js +1 -0
- package/dist/src/codemod/edits/addResource/bodyIndex.d.ts +34 -0
- package/dist/src/codemod/edits/addResource/bodyIndex.js +1 -0
- package/dist/src/codemod/edits/addResource/propertyBuilder.d.ts +7 -0
- package/dist/src/codemod/edits/addResource/propertyBuilder.js +1 -0
- package/dist/src/codemod/edits/addResource.d.ts +9 -0
- package/dist/src/codemod/edits/addResource.js +1 -0
- package/dist/src/codemod/edits/ensureImports.d.ts +26 -0
- package/dist/src/codemod/edits/ensureImports.js +1 -0
- package/dist/src/codemod/edits/findInsertionPosition.d.ts +39 -0
- package/dist/src/codemod/edits/findInsertionPosition.js +1 -0
- package/dist/src/codemod/edits/index.d.ts +6 -0
- package/dist/src/codemod/edits/index.js +1 -0
- package/dist/src/codemod/edits/modifyResource/literalConversion.d.ts +37 -0
- package/dist/src/codemod/edits/modifyResource/literalConversion.js +1 -0
- package/dist/src/codemod/edits/modifyResource.d.ts +9 -0
- package/dist/src/codemod/edits/modifyResource.js +1 -0
- package/dist/src/codemod/edits/removeResource/commentHeuristic.d.ts +31 -0
- package/dist/src/codemod/edits/removeResource/commentHeuristic.js +1 -0
- package/dist/src/codemod/edits/removeResource/importPruning.d.ts +8 -0
- package/dist/src/codemod/edits/removeResource/importPruning.js +1 -0
- package/dist/src/codemod/edits/removeResource.d.ts +10 -0
- package/dist/src/codemod/edits/removeResource.js +1 -0
- package/dist/src/codemod/edits/schemaFragments.d.ts +9 -0
- package/dist/src/codemod/edits/schemaFragments.js +1 -0
- package/dist/src/codemod/fileRewriter/builders.d.ts +57 -0
- package/dist/src/codemod/fileRewriter/builders.js +1 -0
- package/dist/src/codemod/fileRewriter/index.d.ts +4 -0
- package/dist/src/codemod/fileRewriter/index.js +1 -0
- package/dist/src/codemod/fileRewriter/locateByRange.d.ts +65 -0
- package/dist/src/codemod/fileRewriter/locateByRange.js +1 -0
- package/dist/src/codemod/fileRewriter/parse.d.ts +18 -0
- package/dist/src/codemod/fileRewriter/parse.js +2 -0
- package/dist/src/codemod/fileRewriter/print.d.ts +46 -0
- package/dist/src/codemod/fileRewriter/print.js +4 -0
- package/dist/src/codemod/historyPaths.d.ts +2 -0
- package/dist/src/codemod/historyPaths.js +1 -0
- package/dist/src/codemod/index.d.ts +7 -0
- package/dist/src/codemod/index.js +1 -0
- package/dist/src/codemod/listResources.d.ts +4 -0
- package/dist/src/codemod/listResources.js +1 -0
- package/dist/src/codemod/semanticIndex/findReferences.d.ts +15 -0
- package/dist/src/codemod/semanticIndex/findReferences.js +2 -0
- package/dist/src/codemod/semanticIndex/index.d.ts +4 -0
- package/dist/src/codemod/semanticIndex/index.js +1 -0
- package/dist/src/codemod/semanticIndex/listImports.d.ts +24 -0
- package/dist/src/codemod/semanticIndex/listImports.js +1 -0
- package/dist/src/codemod/semanticIndex/locateByShape.d.ts +28 -0
- package/dist/src/codemod/semanticIndex/locateByShape.js +1 -0
- package/dist/src/codemod/semanticIndex/projectCache.d.ts +14 -0
- package/dist/src/codemod/semanticIndex/projectCache.js +1 -0
- package/dist/src/codemod/types.d.ts +172 -0
- package/dist/src/codemod/types.js +1 -0
- package/dist/src/dns/bindParser.js +2 -224
- package/dist/src/dns/bindWriter.js +3 -52
- package/dist/src/dns/domainFileGenerator.d.ts +20 -0
- package/dist/src/dns/domainFileGenerator.js +207 -0
- package/dist/src/dns/domainRecords.d.ts +164 -0
- package/dist/src/dns/domainRecords.js +1 -0
- package/dist/src/dns/index.d.ts +2 -1
- package/dist/src/dns/index.js +1 -4
- package/dist/src/dns/types.js +1 -52
- package/dist/src/generation/common.js +6 -161
- package/dist/src/generation/compute.js +82 -590
- package/dist/src/generation/database.js +12 -198
- package/dist/src/generation/generatePatternCode.d.ts +58 -0
- package/dist/src/generation/generatePatternCode.js +33 -0
- package/dist/src/generation/index.js +1 -20
- package/dist/src/generation/infrastructure.d.ts +1 -5
- package/dist/src/generation/infrastructure.js +35 -377
- package/dist/src/generation/messagingConnections.js +1 -73
- package/dist/src/generation/storage.d.ts +0 -15
- package/dist/src/generation/storage.js +35 -168
- package/dist/src/generation/storageConnections.js +1 -75
- package/dist/src/planning/generateResourceChange.d.ts +21 -0
- package/dist/src/planning/generateResourceChange.js +1 -0
- package/dist/src/planning/index.d.ts +3 -0
- package/dist/src/planning/index.js +1 -1
- package/dist/src/planning/resourceAddition.d.ts +154 -0
- package/dist/src/planning/resourceAddition.js +1 -0
- package/dist/src/planning/resourceConnections.d.ts +19 -0
- package/dist/src/planning/resourceConnections.js +1 -0
- package/dist/src/planning/resourcePlanning.js +1 -214
- package/dist/src/presets/index.js +1 -3
- package/dist/src/presets/patternTierPresets.js +1 -131
- package/dist/src/presets/storagePresets.js +1 -36
- package/dist/src/presets/tierPresets.d.ts +5 -8
- package/dist/src/presets/tierPresets.js +1 -384
- package/dist/src/presets/tierTypes.d.ts +1 -1
- package/dist/src/presets/tierTypes.js +0 -7
- package/dist/src/schemas/alarmSchemas.d.ts +19 -0
- package/dist/src/schemas/alarmSchemas.js +1 -0
- package/dist/src/schemas/applicationSchemas.d.ts +22 -6
- package/dist/src/schemas/applicationSchemas.js +1 -80
- package/dist/src/schemas/baseSchemas.d.ts +8 -3
- package/dist/src/schemas/baseSchemas.js +2 -248
- package/dist/src/schemas/cdnSchemas.js +1 -62
- package/dist/src/schemas/computeSchemas.d.ts +25 -3
- package/dist/src/schemas/computeSchemas.js +1 -727
- package/dist/src/schemas/constants.d.ts +5 -7
- package/dist/src/schemas/constants.js +1 -218
- package/dist/src/schemas/databaseSchemas.d.ts +6 -1
- package/dist/src/schemas/databaseSchemas.js +1 -366
- package/dist/src/schemas/index.js +1 -3
- package/dist/src/schemas/instanceTypeArchitecture.js +1 -75
- package/dist/src/schemas/messagingSchemas.js +1 -29
- package/dist/src/schemas/networkSchemas.js +1 -125
- package/dist/src/schemas/patternSchemas.d.ts +1 -1
- package/dist/src/schemas/patternSchemas.js +1 -294
- package/dist/src/schemas/resourceSchemas.d.ts +1 -0
- package/dist/src/schemas/resourceSchemas.js +1 -28
- package/dist/src/schemas/sharedTypes.d.ts +18 -0
- package/dist/src/schemas/sharedTypes.js +1 -0
- package/dist/src/schemas/storageSchemas.d.ts +1 -0
- package/dist/src/schemas/storageSchemas.js +1 -119
- package/dist/src/types/Result.js +1 -31
- package/dist/src/util/errorUtils.js +1 -1
- package/dist/src/validation/patterns.d.ts +9 -0
- package/dist/src/validation/patterns.js +1 -369
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +29 -9
- package/dist/src/dns/infrastructureWriter.d.ts +0 -2
- package/dist/src/dns/infrastructureWriter.js +0 -58
package/LICENSE
CHANGED
|
@@ -1,21 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Fjall
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
to
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
Fjall Proprietary Software Licence
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fjall. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software, including all source, object, bundled, and minified forms
|
|
6
|
+
("the Software"), is the proprietary and confidential property of Fjall.
|
|
7
|
+
|
|
8
|
+
1. Permitted Use. Subject to the terms of this Licence, Fjall grants you
|
|
9
|
+
a non-exclusive, non-transferable, revocable licence to install the
|
|
10
|
+
Software via the npm registry and to execute it solely for the purpose
|
|
11
|
+
of deploying, operating, and managing your own applications and
|
|
12
|
+
infrastructure on cloud providers.
|
|
13
|
+
|
|
14
|
+
2. Restrictions. You may NOT, and may not permit any third party to:
|
|
15
|
+
(a) copy, redistribute, sublicense, sell, rent, lease, or otherwise
|
|
16
|
+
transfer the Software;
|
|
17
|
+
(b) modify, adapt, translate, or create derivative works of the Software;
|
|
18
|
+
(c) reverse engineer, decompile, disassemble, deminify, or otherwise
|
|
19
|
+
attempt to derive the source code, structure, or organisation of
|
|
20
|
+
the Software, except to the minimum extent expressly permitted by
|
|
21
|
+
applicable mandatory law;
|
|
22
|
+
(d) use the Software, or any portion of it, to develop, train, or
|
|
23
|
+
improve any product or service that competes with Fjall;
|
|
24
|
+
(e) remove, alter, or obscure any proprietary notices contained in
|
|
25
|
+
the Software;
|
|
26
|
+
(f) publish, share, or otherwise disclose the Software or its contents
|
|
27
|
+
to any third party.
|
|
28
|
+
|
|
29
|
+
3. Ownership. All right, title, and interest in and to the Software,
|
|
30
|
+
including all intellectual property rights, remain with Fjall. No
|
|
31
|
+
rights are granted except as expressly set out in this Licence.
|
|
32
|
+
|
|
33
|
+
4. Termination. This Licence terminates automatically if you breach any
|
|
34
|
+
of its terms. Upon termination you must cease all use of the Software
|
|
35
|
+
and destroy all copies in your possession.
|
|
36
|
+
|
|
37
|
+
5. Disclaimer of Warranty. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT
|
|
38
|
+
WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
|
39
|
+
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
|
40
|
+
AND NON-INFRINGEMENT.
|
|
41
|
+
|
|
42
|
+
6. Limitation of Liability. IN NO EVENT SHALL FJALL BE LIABLE FOR ANY
|
|
43
|
+
INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES
|
|
44
|
+
ARISING OUT OF OR RELATED TO THE SOFTWARE, EVEN IF ADVISED OF THE
|
|
45
|
+
POSSIBILITY OF SUCH DAMAGES.
|
|
46
|
+
|
|
47
|
+
7. Governing Law. This Licence is governed by the laws of England and
|
|
48
|
+
Wales, without regard to conflict of laws principles.
|
|
49
|
+
|
|
50
|
+
For commercial licensing enquiries, contact: contact@fjall.io
|
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @fjall/generator
|
|
2
|
+
|
|
3
|
+
Pure infrastructure generation logic for Fjall. Detects application patterns (Next.js, Payload CMS, Remix, etc.) and generates the AWS CDK resources, IAM policies, and config required to deploy them.
|
|
4
|
+
|
|
5
|
+
This package contains no AWS SDK calls — it is a deterministic transformer from application source + config to a resource plan. Consumed by `@fjall/cli` and the Fjall webapp deployment worker.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @fjall/generator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { generateResourcePlan } from "@fjall/generator";
|
|
17
|
+
|
|
18
|
+
const plan = generateResourcePlan({
|
|
19
|
+
appPath: "./my-app",
|
|
20
|
+
config: fjallConfig,
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
See [docs.fjall.io](https://docs.fjall.io) for full usage.
|
|
25
|
+
|
|
26
|
+
## Licence
|
|
27
|
+
|
|
28
|
+
Proprietary — see [LICENSE](./LICENSE).
|
package/dist/.minified
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
93 files minified at 2026-04-20T23:47:43.752Z
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only AST parser for the CDN section of infrastructure.ts. Used by
|
|
3
|
+
* fjall list and by the deploy-worker's convertToResourcePlan. Write paths
|
|
4
|
+
* live in src/codemod/. Do not add mutation helpers here.
|
|
5
|
+
*/
|
|
1
6
|
import * as ts from "typescript";
|
|
2
7
|
import type { ApplicationResourcePlan } from "../schemas/resourceSchemas.js";
|
|
3
8
|
import { type ParsedObject } from "./astCommonParser.js";
|
|
@@ -1,114 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { asString, asStringArray, asStringUnion, captureExtraProperties, findFirstInAst, isFactoryBuildCall, isFactoryMethodCall, isIdentifierRef, isParsedObject, parseObjectLiteral, } from "./astCommonParser.js";
|
|
3
|
-
// ---- Extraction helpers ----
|
|
4
|
-
function extractCDNResource(buildCall) {
|
|
5
|
-
if (buildCall.arguments.length < 2)
|
|
6
|
-
return null;
|
|
7
|
-
const nameArg = buildCall.arguments[0];
|
|
8
|
-
const configArg = buildCall.arguments[1];
|
|
9
|
-
if (!ts.isStringLiteral(nameArg) ||
|
|
10
|
-
!ts.isObjectLiteralExpression(configArg)) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
return {
|
|
14
|
-
resourceName: nameArg.text,
|
|
15
|
-
config: parseObjectLiteral(configArg),
|
|
16
|
-
node: buildCall,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/** Resolve a CDN origin identifier back to its resource name */
|
|
20
|
-
function resolveOriginIdentifier(identifier, s3Resources, computeResources) {
|
|
21
|
-
const s3Match = s3Resources.find((s3) => s3.variableName === identifier);
|
|
22
|
-
if (s3Match)
|
|
23
|
-
return s3Match.resourceName;
|
|
24
|
-
const computeMatch = computeResources.find((c) => c.variableName === identifier ||
|
|
25
|
-
c.resourceName.charAt(0).toLowerCase() + c.resourceName.slice(1) ===
|
|
26
|
-
identifier);
|
|
27
|
-
if (computeMatch)
|
|
28
|
-
return computeMatch.resourceName;
|
|
29
|
-
return identifier;
|
|
30
|
-
}
|
|
31
|
-
const CDN_CACHE_POLICIES = ["CACHING_OPTIMIZED", "CACHING_DISABLED"];
|
|
32
|
-
// ---- Public API ----
|
|
33
|
-
/** Find CDN resource from addCdn call */
|
|
34
|
-
export function findCDNResource(sourceFile) {
|
|
35
|
-
return findFirstInAst(sourceFile, (node) => {
|
|
36
|
-
if (!ts.isCallExpression(node) || !isFactoryMethodCall(node, "addCdn"))
|
|
37
|
-
return undefined;
|
|
38
|
-
const cdnArg = node.arguments[0];
|
|
39
|
-
if (!isFactoryBuildCall(cdnArg, "CdnFactory"))
|
|
40
|
-
return undefined;
|
|
41
|
-
return extractCDNResource(cdnArg) ?? undefined;
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
/** Convert parsed CDN resource to plan format */
|
|
45
|
-
export function convertCDNResource(cdnResource, s3Resources, computeResources) {
|
|
46
|
-
if (!cdnResource)
|
|
47
|
-
return undefined;
|
|
48
|
-
const cdn = cdnResource;
|
|
49
|
-
const config = cdn.config;
|
|
50
|
-
const resolveOrigin = (val) => {
|
|
51
|
-
if (isIdentifierRef(val)) {
|
|
52
|
-
return resolveOriginIdentifier(val.__identifier, s3Resources, computeResources);
|
|
53
|
-
}
|
|
54
|
-
return asString(val) ?? "";
|
|
55
|
-
};
|
|
56
|
-
const defaultOriginRef = resolveOrigin(config.origin);
|
|
57
|
-
const result = {
|
|
58
|
-
name: cdn.resourceName,
|
|
59
|
-
defaultOriginRef,
|
|
60
|
-
};
|
|
61
|
-
if (Array.isArray(config.behaviours)) {
|
|
62
|
-
const behaviours = config.behaviours.filter(isParsedObject).map((b) => ({
|
|
63
|
-
pathPattern: asString(b.pathPattern) ?? "",
|
|
64
|
-
originRef: resolveOrigin(b.origin),
|
|
65
|
-
...{
|
|
66
|
-
...(asStringUnion(b.cachePolicy, CDN_CACHE_POLICIES) !== undefined && {
|
|
67
|
-
cachePolicy: asStringUnion(b.cachePolicy, CDN_CACHE_POLICIES),
|
|
68
|
-
}),
|
|
69
|
-
},
|
|
70
|
-
}));
|
|
71
|
-
if (behaviours.length > 0)
|
|
72
|
-
result.behaviours = behaviours;
|
|
73
|
-
}
|
|
74
|
-
const customDomain = asString(config.customDomain);
|
|
75
|
-
if (customDomain) {
|
|
76
|
-
result.customDomain = customDomain;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
const domainNames = asStringArray(config.domainNames);
|
|
80
|
-
if (domainNames && domainNames.length > 0) {
|
|
81
|
-
result.customDomain = domainNames[0];
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
const certificateArn = asString(config.certificateArn);
|
|
85
|
-
if (certificateArn)
|
|
86
|
-
result.certificateArn = certificateArn;
|
|
87
|
-
if (config.accessGate !== undefined) {
|
|
88
|
-
if (config.accessGate === false) {
|
|
89
|
-
result.accessGate = false;
|
|
90
|
-
}
|
|
91
|
-
else if (isParsedObject(config.accessGate)) {
|
|
92
|
-
const gate = config.accessGate;
|
|
93
|
-
const gateType = asString(gate.type);
|
|
94
|
-
const username = asString(gate.username);
|
|
95
|
-
const password = asString(gate.password);
|
|
96
|
-
if (gateType === "basic-auth" && username && password) {
|
|
97
|
-
result.accessGate = { type: "basic-auth", username, password };
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
const CDN_KNOWN_KEYS = new Set([
|
|
102
|
-
"originType",
|
|
103
|
-
"origin",
|
|
104
|
-
"behaviours",
|
|
105
|
-
"customDomain",
|
|
106
|
-
"domainNames",
|
|
107
|
-
"certificateArn",
|
|
108
|
-
"accessGate",
|
|
109
|
-
]);
|
|
110
|
-
const extras = captureExtraProperties(config, CDN_KNOWN_KEYS);
|
|
111
|
-
if (extras.length > 0)
|
|
112
|
-
result.extraProperties = extras;
|
|
113
|
-
return result;
|
|
114
|
-
}
|
|
1
|
+
import*as f from"typescript";import{asString as c,asStringArray as D,asStringUnion as h,captureExtraProperties as y,findFirstInAst as I,isFactoryBuildCall as O,isFactoryMethodCall as P,isIdentifierRef as _,isParsedObject as p,parseObjectLiteral as x}from"./astCommonParser.js";function E(e){if(e.arguments.length<2)return null;const n=e.arguments[0],s=e.arguments[1];return!f.isStringLiteral(n)||!f.isObjectLiteralExpression(s)?null:{resourceName:n.text,config:x(s),node:e}}function G(e,n,s){const u=n.find(i=>i.variableName===e);if(u)return u.resourceName;const r=s.find(i=>i.variableName===e||i.resourceName.charAt(0).toLowerCase()+i.resourceName.slice(1)===e);return r?r.resourceName:e}const A=["CACHING_OPTIMIZED","CACHING_DISABLED"];function b(e){return I(e,n=>{if(!f.isCallExpression(n)||!P(n,"addCdn"))return;const s=n.arguments[0];if(O(s,"CdnFactory"))return E(s)??void 0})}function L(e,n,s){if(!e)return;const u=e,r=u.config,i=t=>_(t)?G(t.__identifier,n,s):c(t)??"",C=i(r.origin),a={name:u.resourceName,defaultOriginRef:C};if(Array.isArray(r.behaviours)){const t=r.behaviours.filter(p).map(o=>({pathPattern:c(o.pathPattern)??"",originRef:i(o.origin),...h(o.cachePolicy,A)!==void 0&&{cachePolicy:h(o.cachePolicy,A)}}));t.length>0&&(a.behaviours=t)}const m=c(r.customDomain);if(m)a.customDomain=m;else{const t=D(r.domainNames);t&&t.length>0&&(a.customDomain=t[0])}const g=c(r.certificateArn);if(g&&(a.certificateArn=g),r.accessGate!==void 0){if(r.accessGate===!1)a.accessGate=!1;else if(p(r.accessGate)){const t=r.accessGate,o=c(t.type),N=c(t.username),l=c(t.password);o==="basic-auth"&&N&&l&&(a.accessGate={type:"basic-auth",username:N,password:l})}}const d=y(r,new Set(["originType","origin","behaviours","customDomain","domainNames","certificateArn","accessGate"]));return d.length>0&&(a.extraProperties=d),a}export{L as convertCDNResource,b as findCDNResource};
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only AST parser utilities shared across the other ast*Parser.ts files.
|
|
3
|
+
* Used by fjall list and by the deploy-worker's convertToResourcePlan. Write
|
|
4
|
+
* paths live in src/codemod/. Do not add mutation helpers here.
|
|
5
|
+
*/
|
|
1
6
|
import * as ts from "typescript";
|
|
2
7
|
import type { ExtraProperty } from "../schemas/resourceSchemas.js";
|
|
3
8
|
/** Special marker for identifier references in parsed AST */
|
|
@@ -71,20 +76,4 @@ export declare function parseBooleanOrConfig<T>(value: ParsedValue | undefined,
|
|
|
71
76
|
export declare function parseOptionalConfig<T>(value: ParsedValue | undefined, parser: (obj: ParsedObject) => T): T | undefined;
|
|
72
77
|
/** Extract a named sub-object from a config, returning undefined if not a plain object */
|
|
73
78
|
export declare function extractSubConfig<T>(rawConfig: ParsedObject, field: string, transform: (obj: ParsedObject) => T): T | undefined;
|
|
74
|
-
|
|
75
|
-
export declare function parseObjectLiteral(node: ts.ObjectLiteralExpression): ParsedObject;
|
|
76
|
-
/** Evaluate a TypeScript AST expression to a ParsedValue */
|
|
77
|
-
export declare function evaluateExpression(node: ts.Expression): ParsedValue;
|
|
78
|
-
/** Find a string variable value by name */
|
|
79
|
-
export declare function findVariableValue(sourceFile: ts.SourceFile, varName: string): string | undefined;
|
|
80
|
-
/** Find an object variable declaration by name */
|
|
81
|
-
export declare function findObjectDeclaration(sourceFile: ts.SourceFile, objName: string): ParsedObject | undefined;
|
|
82
|
-
/** Evaluate a property access expression to a string */
|
|
83
|
-
export declare function evaluatePropertyAccess(sourceFile: ts.SourceFile, node: ts.PropertyAccessExpression): string | undefined;
|
|
84
|
-
/**
|
|
85
|
-
* Resolve a template literal expression to its string value.
|
|
86
|
-
* Walks spans: head.text + resolve each span.expression + span.literal.text.
|
|
87
|
-
* Falls back to stripping backticks from getText() if resolution fails.
|
|
88
|
-
*/
|
|
89
|
-
export declare function resolveTemplateLiteral(sourceFile: ts.SourceFile, templateExpr: ts.TemplateExpression): string;
|
|
90
|
-
export {};
|
|
79
|
+
export { parseObjectLiteral, evaluateExpression, findVariableValue, findObjectDeclaration, evaluatePropertyAccess, resolveTemplateLiteral, } from "./astExpressionEvaluator.js";
|
|
@@ -1,351 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { constIncludes } from "../schemas/constants.js";
|
|
3
|
-
/** Base check for non-null, non-array objects */
|
|
4
|
-
export function isPlainObject(value) {
|
|
5
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
|
-
/** Type guard for identifier references */
|
|
8
|
-
export function isIdentifierRef(value) {
|
|
9
|
-
return isPlainObject(value) && "__identifier" in value;
|
|
10
|
-
}
|
|
11
|
-
/** Type guard for expression references */
|
|
12
|
-
export function isExpressionRef(value) {
|
|
13
|
-
return isPlainObject(value) && "__expression" in value;
|
|
14
|
-
}
|
|
15
|
-
/** Type guard for call references */
|
|
16
|
-
export function isCallRef(value) {
|
|
17
|
-
return isPlainObject(value) && "__call" in value;
|
|
18
|
-
}
|
|
19
|
-
/** Type guard for parsed objects */
|
|
20
|
-
export function isParsedObject(value) {
|
|
21
|
-
return (isPlainObject(value) &&
|
|
22
|
-
!("__identifier" in value) &&
|
|
23
|
-
!("__expression" in value) &&
|
|
24
|
-
!("__call" in value) &&
|
|
25
|
-
!("__unknown" in value));
|
|
26
|
-
}
|
|
27
|
-
/** Safely extract a string from ParsedValue */
|
|
28
|
-
export function asString(value) {
|
|
29
|
-
return typeof value === "string" ? value : undefined;
|
|
30
|
-
}
|
|
31
|
-
/** Safely extract a number from ParsedValue */
|
|
32
|
-
export function asNumber(value) {
|
|
33
|
-
return typeof value === "number" ? value : undefined;
|
|
34
|
-
}
|
|
35
|
-
/** Safely extract a boolean from ParsedValue */
|
|
36
|
-
export function asBoolean(value) {
|
|
37
|
-
return typeof value === "boolean" ? value : undefined;
|
|
38
|
-
}
|
|
39
|
-
/** Safely extract a string array from ParsedValue */
|
|
40
|
-
export function asStringArray(value) {
|
|
41
|
-
if (!Array.isArray(value))
|
|
42
|
-
return undefined;
|
|
43
|
-
const result = [];
|
|
44
|
-
for (const item of value) {
|
|
45
|
-
if (typeof item === "string")
|
|
46
|
-
result.push(item);
|
|
47
|
-
}
|
|
48
|
-
return result.length > 0 ? result : undefined;
|
|
49
|
-
}
|
|
50
|
-
/** Narrow a string to a union member, returning undefined if not a valid member */
|
|
51
|
-
export function asStringUnion(value, validValues) {
|
|
52
|
-
const str = asString(value);
|
|
53
|
-
if (str === undefined)
|
|
54
|
-
return undefined;
|
|
55
|
-
return constIncludes(validValues, str) ? str : undefined;
|
|
56
|
-
}
|
|
57
|
-
/** Returns a shallow copy with all undefined-valued properties removed */
|
|
58
|
-
export function omitUndefined(obj) {
|
|
59
|
-
const result = {};
|
|
60
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
61
|
-
if (value !== undefined) {
|
|
62
|
-
result[key] = value;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
/** Reconstruct source text from a parsed AST value for round-trip preservation */
|
|
68
|
-
export function parsedValueToSourceText(value) {
|
|
69
|
-
if (value === null)
|
|
70
|
-
return "null";
|
|
71
|
-
if (value === undefined)
|
|
72
|
-
return "undefined";
|
|
73
|
-
if (typeof value === "string")
|
|
74
|
-
return JSON.stringify(value);
|
|
75
|
-
if (typeof value === "number" || typeof value === "boolean")
|
|
76
|
-
return String(value);
|
|
77
|
-
if (Array.isArray(value)) {
|
|
78
|
-
return `[${value.map(parsedValueToSourceText).join(", ")}]`;
|
|
79
|
-
}
|
|
80
|
-
if (!isPlainObject(value))
|
|
81
|
-
return String(value);
|
|
82
|
-
if (isIdentifierRef(value))
|
|
83
|
-
return value.__identifier;
|
|
84
|
-
if (isExpressionRef(value))
|
|
85
|
-
return value.__expression;
|
|
86
|
-
if (isCallRef(value))
|
|
87
|
-
return value.__call;
|
|
88
|
-
if ("__unknown" in value && typeof value.__unknown === "string")
|
|
89
|
-
return value.__unknown;
|
|
90
|
-
const entries = Object.entries(value);
|
|
91
|
-
if (entries.length === 0)
|
|
92
|
-
return "{}";
|
|
93
|
-
const inner = entries
|
|
94
|
-
.map(([k, v]) => `${k}: ${parsedValueToSourceText(v)}`)
|
|
95
|
-
.join(", ");
|
|
96
|
-
return `{ ${inner} }`;
|
|
97
|
-
}
|
|
98
|
-
/** Capture properties from a parsed config that are NOT in the known keys set */
|
|
99
|
-
export function captureExtraProperties(config, knownKeys) {
|
|
100
|
-
const extras = [];
|
|
101
|
-
for (const [key, value] of Object.entries(config)) {
|
|
102
|
-
if (knownKeys.has(key) || value === undefined)
|
|
103
|
-
continue;
|
|
104
|
-
extras.push({ key, sourceText: parsedValueToSourceText(value) });
|
|
105
|
-
}
|
|
106
|
-
return extras;
|
|
107
|
-
}
|
|
108
|
-
/** Check if an object literal property is a named property assignment */
|
|
109
|
-
export function isNamedProperty(prop, name) {
|
|
110
|
-
return (ts.isPropertyAssignment(prop) &&
|
|
111
|
-
ts.isIdentifier(prop.name) &&
|
|
112
|
-
prop.name.text === name);
|
|
113
|
-
}
|
|
114
|
-
/** Check if a node is an App.getApp() call expression */
|
|
115
|
-
export function isAppGetAppCall(node) {
|
|
116
|
-
return (ts.isCallExpression(node) &&
|
|
117
|
-
ts.isPropertyAccessExpression(node.expression) &&
|
|
118
|
-
node.expression.name.text === "getApp" &&
|
|
119
|
-
ts.isIdentifier(node.expression.expression) &&
|
|
120
|
-
node.expression.expression.text === "App");
|
|
121
|
-
}
|
|
122
|
-
/** Check if a node is a chained factory method call (e.g., app.addDatabase(...)) */
|
|
123
|
-
export function isFactoryMethodCall(node, methodName) {
|
|
124
|
-
const { expression } = node;
|
|
125
|
-
return (ts.isPropertyAccessExpression(expression) &&
|
|
126
|
-
expression.name.text === methodName &&
|
|
127
|
-
node.arguments.length > 0);
|
|
128
|
-
}
|
|
129
|
-
/** Traverse AST and return the first non-undefined result from the finder. */
|
|
130
|
-
export function findFirstInAst(sourceFile, finder) {
|
|
131
|
-
let result;
|
|
132
|
-
const visit = (node) => {
|
|
133
|
-
if (result !== undefined)
|
|
134
|
-
return;
|
|
135
|
-
result = finder(node);
|
|
136
|
-
if (result === undefined)
|
|
137
|
-
ts.forEachChild(node, visit);
|
|
138
|
-
};
|
|
139
|
-
visit(sourceFile);
|
|
140
|
-
return result;
|
|
141
|
-
}
|
|
142
|
-
/** Traverse AST and collect all non-null results from the collector. */
|
|
143
|
-
export function collectFromAst(sourceFile, collector) {
|
|
144
|
-
const results = [];
|
|
145
|
-
const visit = (node) => {
|
|
146
|
-
const item = collector(node);
|
|
147
|
-
if (item !== null)
|
|
148
|
-
results.push(item);
|
|
149
|
-
ts.forEachChild(node, visit);
|
|
150
|
-
};
|
|
151
|
-
visit(sourceFile);
|
|
152
|
-
return results;
|
|
153
|
-
}
|
|
154
|
-
/** Type guard for Factory.build() call expressions */
|
|
155
|
-
export function isFactoryBuildCall(node, factoryName) {
|
|
156
|
-
return (ts.isCallExpression(node) &&
|
|
157
|
-
ts.isPropertyAccessExpression(node.expression) &&
|
|
158
|
-
node.expression.name.text === "build" &&
|
|
159
|
-
ts.isIdentifier(node.expression.expression) &&
|
|
160
|
-
node.expression.expression.text === factoryName);
|
|
161
|
-
}
|
|
162
|
-
/** Extract variable name from the parent declaration of a node */
|
|
163
|
-
export function extractVariableName(node) {
|
|
164
|
-
const parent = node.parent;
|
|
165
|
-
if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
|
|
166
|
-
return parent.name.text;
|
|
167
|
-
}
|
|
168
|
-
return undefined;
|
|
169
|
-
}
|
|
170
|
-
/** Identity cast - trusts that parsed CDK output matches the expected shape.
|
|
171
|
-
* Safe because input is always generated CDK code that was originally validated by Zod schemas. */
|
|
172
|
-
export const typed = () => (v) => v;
|
|
173
|
-
/** Safely extract an object or false from ParsedValue */
|
|
174
|
-
export function asObjectOrFalse(value) {
|
|
175
|
-
if (value === undefined || value === null)
|
|
176
|
-
return undefined;
|
|
177
|
-
if (value === false)
|
|
178
|
-
return false;
|
|
179
|
-
if (typeof value === "object" && !Array.isArray(value))
|
|
180
|
-
return value;
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
export function parseBooleanOrConfig(value, cast) {
|
|
184
|
-
if (value === false)
|
|
185
|
-
return false;
|
|
186
|
-
return isParsedObject(value) ? cast(value) : undefined;
|
|
187
|
-
}
|
|
188
|
-
export function parseOptionalConfig(value, parser) {
|
|
189
|
-
return isParsedObject(value) ? parser(value) : undefined;
|
|
190
|
-
}
|
|
191
|
-
/** Extract a named sub-object from a config, returning undefined if not a plain object */
|
|
192
|
-
export function extractSubConfig(rawConfig, field, transform) {
|
|
193
|
-
const value = rawConfig[field];
|
|
194
|
-
return isParsedObject(value) ? transform(value) : undefined;
|
|
195
|
-
}
|
|
196
|
-
/** Parse an object literal expression into a ParsedObject */
|
|
197
|
-
export function parseObjectLiteral(node) {
|
|
198
|
-
const result = {};
|
|
199
|
-
for (const prop of node.properties) {
|
|
200
|
-
if (!ts.isPropertyAssignment(prop))
|
|
201
|
-
continue;
|
|
202
|
-
const key = ts.isIdentifier(prop.name)
|
|
203
|
-
? prop.name.text
|
|
204
|
-
: ts.isStringLiteral(prop.name)
|
|
205
|
-
? prop.name.text
|
|
206
|
-
: undefined;
|
|
207
|
-
if (key === undefined)
|
|
208
|
-
continue;
|
|
209
|
-
result[key] = evaluateExpression(prop.initializer);
|
|
210
|
-
}
|
|
211
|
-
return result;
|
|
212
|
-
}
|
|
213
|
-
/** Evaluate a TypeScript AST expression to a ParsedValue */
|
|
214
|
-
export function evaluateExpression(node) {
|
|
215
|
-
if (ts.isStringLiteral(node)) {
|
|
216
|
-
return node.text;
|
|
217
|
-
}
|
|
218
|
-
else if (ts.isNumericLiteral(node)) {
|
|
219
|
-
return Number(node.text);
|
|
220
|
-
}
|
|
221
|
-
else if (node.kind === ts.SyntaxKind.TrueKeyword) {
|
|
222
|
-
return true;
|
|
223
|
-
}
|
|
224
|
-
else if (node.kind === ts.SyntaxKind.FalseKeyword) {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
else if (ts.isArrayLiteralExpression(node)) {
|
|
228
|
-
return node.elements.map((element) => evaluateExpression(element));
|
|
229
|
-
}
|
|
230
|
-
else if (ts.isObjectLiteralExpression(node)) {
|
|
231
|
-
return parseObjectLiteral(node);
|
|
232
|
-
}
|
|
233
|
-
else if (ts.isIdentifier(node)) {
|
|
234
|
-
return { __identifier: node.text };
|
|
235
|
-
}
|
|
236
|
-
else if (ts.isPropertyAccessExpression(node)) {
|
|
237
|
-
return { __expression: node.getText() };
|
|
238
|
-
}
|
|
239
|
-
else if (ts.isCallExpression(node)) {
|
|
240
|
-
return { __call: node.getText() };
|
|
241
|
-
}
|
|
242
|
-
else if (ts.isBinaryExpression(node) &&
|
|
243
|
-
node.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
|
|
244
|
-
// Handle || operator - return the left side if it's a literal
|
|
245
|
-
const left = evaluateExpression(node.left);
|
|
246
|
-
const right = evaluateExpression(node.right);
|
|
247
|
-
// For simplicity, prefer string literals from the right side for defaults
|
|
248
|
-
if (typeof right === "string") {
|
|
249
|
-
return right;
|
|
250
|
-
}
|
|
251
|
-
return left;
|
|
252
|
-
}
|
|
253
|
-
else if (ts.isConditionalExpression(node)) {
|
|
254
|
-
// Handle ternary operator - for simplicity, try to evaluate the branches
|
|
255
|
-
const whenTrue = evaluateExpression(node.whenTrue);
|
|
256
|
-
const whenFalse = evaluateExpression(node.whenFalse);
|
|
257
|
-
// Default to the false branch for simplicity
|
|
258
|
-
if (typeof whenFalse === "string" || typeof whenFalse === "number") {
|
|
259
|
-
return whenFalse;
|
|
260
|
-
}
|
|
261
|
-
return whenTrue;
|
|
262
|
-
}
|
|
263
|
-
else if (ts.isTemplateExpression(node) ||
|
|
264
|
-
ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
265
|
-
// Handle template literals to preserve them as expressions during round-trip parsing
|
|
266
|
-
return { __expression: node.getText() };
|
|
267
|
-
}
|
|
268
|
-
return { __unknown: node.getText() };
|
|
269
|
-
}
|
|
270
|
-
/** Find a string variable value by name */
|
|
271
|
-
export function findVariableValue(sourceFile, varName) {
|
|
272
|
-
return findFirstInAst(sourceFile, (node) => {
|
|
273
|
-
if (!ts.isVariableStatement(node))
|
|
274
|
-
return undefined;
|
|
275
|
-
for (const declaration of node.declarationList.declarations) {
|
|
276
|
-
if (ts.isIdentifier(declaration.name) &&
|
|
277
|
-
declaration.name.text === varName &&
|
|
278
|
-
declaration.initializer) {
|
|
279
|
-
if (ts.isStringLiteral(declaration.initializer)) {
|
|
280
|
-
return declaration.initializer.text;
|
|
281
|
-
}
|
|
282
|
-
if (ts.isObjectLiteralExpression(declaration.initializer)) {
|
|
283
|
-
const obj = parseObjectLiteral(declaration.initializer);
|
|
284
|
-
return JSON.stringify(obj);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
return undefined;
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
/** Find an object variable declaration by name */
|
|
292
|
-
export function findObjectDeclaration(sourceFile, objName) {
|
|
293
|
-
return findFirstInAst(sourceFile, (node) => {
|
|
294
|
-
if (!ts.isVariableStatement(node))
|
|
295
|
-
return undefined;
|
|
296
|
-
for (const declaration of node.declarationList.declarations) {
|
|
297
|
-
if (ts.isIdentifier(declaration.name) &&
|
|
298
|
-
declaration.name.text === objName &&
|
|
299
|
-
declaration.initializer &&
|
|
300
|
-
ts.isObjectLiteralExpression(declaration.initializer)) {
|
|
301
|
-
return parseObjectLiteral(declaration.initializer);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return undefined;
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
/** Evaluate a property access expression to a string */
|
|
308
|
-
export function evaluatePropertyAccess(sourceFile, node) {
|
|
309
|
-
if (!ts.isIdentifier(node.expression))
|
|
310
|
-
return undefined;
|
|
311
|
-
const objValue = findObjectDeclaration(sourceFile, node.expression.text);
|
|
312
|
-
const propName = node.name.text;
|
|
313
|
-
if (objValue && objValue[propName] !== undefined) {
|
|
314
|
-
return String(objValue[propName]);
|
|
315
|
-
}
|
|
316
|
-
return undefined;
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Resolve a template literal expression to its string value.
|
|
320
|
-
* Walks spans: head.text + resolve each span.expression + span.literal.text.
|
|
321
|
-
* Falls back to stripping backticks from getText() if resolution fails.
|
|
322
|
-
*/
|
|
323
|
-
export function resolveTemplateLiteral(sourceFile, templateExpr) {
|
|
324
|
-
let result = templateExpr.head.text;
|
|
325
|
-
for (const span of templateExpr.templateSpans) {
|
|
326
|
-
if (ts.isIdentifier(span.expression)) {
|
|
327
|
-
const resolved = findVariableValue(sourceFile, span.expression.text);
|
|
328
|
-
if (resolved) {
|
|
329
|
-
result += resolved;
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
// Can't resolve -- fall back to raw getText()
|
|
333
|
-
return templateExpr.getText(sourceFile).replace(/^`|`$/g, "");
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
else if (ts.isPropertyAccessExpression(span.expression)) {
|
|
337
|
-
const resolved = evaluatePropertyAccess(sourceFile, span.expression);
|
|
338
|
-
if (resolved) {
|
|
339
|
-
result += resolved;
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
return templateExpr.getText(sourceFile).replace(/^`|`$/g, "");
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
return templateExpr.getText(sourceFile).replace(/^`|`$/g, "");
|
|
347
|
-
}
|
|
348
|
-
result += span.literal.text;
|
|
349
|
-
}
|
|
350
|
-
return result;
|
|
351
|
-
}
|
|
1
|
+
import*as i from"typescript";import{constIncludes as c}from"../schemas/constants.js";function o(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function x(n){return o(n)&&"__identifier"in n}function d(n){return o(n)&&"__expression"in n}function a(n){return o(n)&&"__call"in n}function f(n){return o(n)&&!("__identifier"in n)&&!("__expression"in n)&&!("__call"in n)&&!("__unknown"in n)}function y(n){return typeof n=="string"?n:void 0}function m(n){return typeof n=="number"?n:void 0}function _(n){return typeof n=="boolean"?n:void 0}function b(n){if(!Array.isArray(n))return;const e=[];for(const r of n)typeof r=="string"&&e.push(r);return e.length>0?e:void 0}function A(n,e){const r=y(n);if(r!==void 0)return c(e,r)?r:void 0}function g(n){const e={};for(const[r,t]of Object.entries(n))t!==void 0&&(e[r]=t);return e}function p(n){if(n===null)return"null";if(n===void 0)return"undefined";if(typeof n=="string")return JSON.stringify(n);if(typeof n=="number"||typeof n=="boolean")return String(n);if(Array.isArray(n))return`[${n.map(p).join(", ")}]`;if(!o(n))return String(n);if(x(n))return n.__identifier;if(d(n))return n.__expression;if(a(n))return n.__call;if("__unknown"in n&&typeof n.__unknown=="string")return n.__unknown;const e=Object.entries(n);return e.length===0?"{}":`{ ${e.map(([t,s])=>`${t}: ${p(s)}`).join(", ")} }`}function h(n,e){const r=[];for(const[t,s]of Object.entries(n))e.has(t)||s===void 0||r.push({key:t,sourceText:p(s)});return r}function j(n,e){return i.isPropertyAssignment(n)&&i.isIdentifier(n.name)&&n.name.text===e}function O(n){return i.isCallExpression(n)&&i.isPropertyAccessExpression(n.expression)&&n.expression.name.text==="getApp"&&i.isIdentifier(n.expression.expression)&&n.expression.expression.text==="App"}function C(n,e){const{expression:r}=n;return i.isPropertyAccessExpression(r)&&r.name.text===e&&n.arguments.length>0}function E(n,e){let r;const t=s=>{r===void 0&&(r=e(s),r===void 0&&i.forEachChild(s,t))};return t(n),r}function P(n,e){const r=[],t=s=>{const u=e(s);u!==null&&r.push(u),i.forEachChild(s,t)};return t(n),r}function S(n,e){return i.isCallExpression(n)&&i.isPropertyAccessExpression(n.expression)&&n.expression.name.text==="build"&&i.isIdentifier(n.expression.expression)&&n.expression.expression.text===e}function I(n){const e=n.parent;if(i.isVariableDeclaration(e)&&i.isIdentifier(e.name))return e.name.text}const k=()=>n=>n;function F(n){if(n!=null){if(n===!1)return!1;if(typeof n=="object"&&!Array.isArray(n))return n}}function V(n,e){return n===!1?!1:f(n)?e(n):void 0}function w(n,e){return f(n)?e(n):void 0}function N(n,e,r){const t=n[e];return f(t)?r(t):void 0}import{parseObjectLiteral as B,evaluateExpression as R,findVariableValue as D,findObjectDeclaration as L,evaluatePropertyAccess as U,resolveTemplateLiteral as G}from"./astExpressionEvaluator.js";export{_ as asBoolean,m as asNumber,F as asObjectOrFalse,y as asString,b as asStringArray,A as asStringUnion,h as captureExtraProperties,P as collectFromAst,R as evaluateExpression,U as evaluatePropertyAccess,N as extractSubConfig,I as extractVariableName,E as findFirstInAst,L as findObjectDeclaration,D as findVariableValue,O as isAppGetAppCall,a as isCallRef,d as isExpressionRef,S as isFactoryBuildCall,C as isFactoryMethodCall,x as isIdentifierRef,j as isNamedProperty,f as isParsedObject,o as isPlainObject,g as omitUndefined,V as parseBooleanOrConfig,B as parseObjectLiteral,w as parseOptionalConfig,p as parsedValueToSourceText,G as resolveTemplateLiteral,k as typed};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only AST helpers that resolve compute→database/storage connections
|
|
3
|
+
* and infer them from environment variables. Split out of
|
|
4
|
+
* astComputeParserHelpers.ts to keep both files within the 400-line budget.
|
|
5
|
+
* Write paths live in src/codemod/. Do not add mutation helpers here.
|
|
6
|
+
*/
|
|
7
|
+
import { type ParsedValue } from "./astCommonParser.js";
|
|
8
|
+
import type { ComputeResourcePlan, ApplicationResourcePlan } from "../schemas/resourceSchemas.js";
|
|
9
|
+
import type { ParsedDatabaseResource } from "./astDatabaseParser.js";
|
|
10
|
+
import type { ParsedS3Resource } from "./astStorageParser.js";
|
|
11
|
+
/** Resolve connected database names from AST connection references */
|
|
12
|
+
export declare function resolveConnectedDatabaseNames(connections: ParsedValue, databaseResources: ParsedDatabaseResource[]): string[];
|
|
13
|
+
/** Resolve connected storage names from AST connection references */
|
|
14
|
+
export declare function resolveConnectedStorageNames(connections: ParsedValue, s3Resources: ParsedS3Resource[]): string[];
|
|
15
|
+
/** Infer database connections from environment variables in ECS containers */
|
|
16
|
+
export declare function inferDatabaseConnectionsFromEnv(computePlan: ComputeResourcePlan, servicesVal: ParsedValue, databasePlans: ApplicationResourcePlan["database"]): void;
|
|
17
|
+
/** Infer storage connections from environment variables in ECS containers */
|
|
18
|
+
export declare function inferStorageConnectionsFromEnv(computePlan: ComputeResourcePlan, servicesVal: ParsedValue, s3Plans: ApplicationResourcePlan["s3"]): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isIdentifierRef as s,isParsedObject as f}from"./astCommonParser.js";const c=10;function d(n,r){return Array.isArray(n)?n.filter(s).map(e=>r.find(t=>t.variableName===e.__identifier)).filter(e=>e!==void 0).map(e=>e.resourceName):[]}function _(n,r){return Array.isArray(n)?n.filter(s).map(e=>r.find(t=>t.variableName===e.__identifier)).filter(e=>e!==void 0).map(e=>e.resourceName):[]}function m(n,r,e){if(!Array.isArray(r)||r.length===0)return;const t=r[0];if(!f(t))return;const i=t.containers;if(!Array.isArray(i)||i.length===0)return;const o=i[0];if(!f(o)||!f(o.environment))return;const a=o.environment;(a.DATABASE_HOST||a.DATABASE_PORT||a.DATABASE_NAME)&&(n.needsConnection=!0,e.length>0&&(n.connectedDatabase??[]).length===0&&(n.connectedDatabase=[e[0].name]));for(let A=1;A<=c;A++)(a[`DATABASE_HOST_${A}`]||a[`DATABASE_PORT_${A}`]||a[`DATABASE_NAME_${A}`])&&(n.needsConnection=!0)}function S(n,r,e){if(!Array.isArray(r)||r.length===0)return;const t=r[0];if(!f(t))return;const i=t.containers;if(!Array.isArray(i)||i.length===0)return;const o=i[0];if(!f(o)||!f(o.environment))return;o.environment.BUCKET_NAME&&e.length>0&&(n.connectedStorage??[]).length===0&&(n.connectedStorage=[e[0].name])}export{m as inferDatabaseConnectionsFromEnv,S as inferStorageConnectionsFromEnv,d as resolveConnectedDatabaseNames,_ as resolveConnectedStorageNames};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only AST parser for the compute section of infrastructure.ts (ECS,
|
|
3
|
+
* Lambda, EC2). Used by fjall list and by the deploy-worker's
|
|
4
|
+
* convertToResourcePlan. Write paths live in src/codemod/. Do not add
|
|
5
|
+
* mutation helpers here.
|
|
6
|
+
*/
|
|
1
7
|
import * as ts from "typescript";
|
|
2
8
|
import { type ParsedObject } from "./astCommonParser.js";
|
|
3
9
|
import { type ApplicationResourcePlan } from "../schemas/resourceSchemas.js";
|