@fjall/generator 0.94.1 → 0.96.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.
Files changed (126) hide show
  1. package/dist/.minified +1 -1
  2. package/dist/src/ast/astCodeInjection.d.ts +9 -0
  3. package/dist/src/ast/astCodeInjection.js +8 -0
  4. package/dist/src/ast/astInfrastructureParser.d.ts +1 -1
  5. package/dist/src/ast/astStatementClassifier.d.ts +2 -2
  6. package/dist/src/ast/astStatementClassifier.js +1 -1
  7. package/dist/src/ast/astStatementQueries.d.ts +4 -4
  8. package/dist/src/ast/astStatementQueries.js +3 -3
  9. package/dist/src/ast/astSurgicalModification.d.ts +14 -12
  10. package/dist/src/ast/astSurgicalModification.js +6 -13
  11. package/dist/src/ast/astTestHelpers.d.ts +7 -7
  12. package/dist/src/ast/index.d.ts +3 -2
  13. package/dist/src/ast/index.js +1 -1
  14. package/dist/src/codemod/_internal.d.ts +6 -1
  15. package/dist/src/codemod/_internal.js +1 -1
  16. package/dist/src/codemod/drift/__tests__/fixtures.d.ts +55 -0
  17. package/dist/src/codemod/drift/__tests__/fixtures.js +2 -0
  18. package/dist/src/codemod/drift/detect.d.ts +11 -0
  19. package/dist/src/codemod/drift/detect.js +1 -0
  20. package/dist/src/codemod/drift/index.d.ts +4 -0
  21. package/dist/src/codemod/drift/index.js +1 -0
  22. package/dist/src/codemod/drift/merge.d.ts +19 -0
  23. package/dist/src/codemod/drift/merge.js +1 -0
  24. package/dist/src/codemod/drift/snapshot.d.ts +4 -0
  25. package/dist/src/codemod/drift/snapshot.js +1 -0
  26. package/dist/src/codemod/drift/types.d.ts +60 -0
  27. package/dist/src/codemod/drift/types.js +1 -0
  28. package/dist/src/codemod/edits/addResource/propertyBuilder.d.ts +1 -1
  29. package/dist/src/codemod/edits/addResource/propertyBuilder.js +1 -1
  30. package/dist/src/codemod/edits/addResource.d.ts +8 -3
  31. package/dist/src/codemod/edits/addResource.js +1 -1
  32. package/dist/src/codemod/edits/controlFlowPolicy.d.ts +19 -0
  33. package/dist/src/codemod/edits/controlFlowPolicy.js +1 -0
  34. package/dist/src/codemod/edits/crossPlanConnection.d.ts +24 -0
  35. package/dist/src/codemod/edits/crossPlanConnection.js +1 -0
  36. package/dist/src/codemod/edits/driftPolicy.d.ts +7 -0
  37. package/dist/src/codemod/edits/driftPolicy.js +1 -0
  38. package/dist/src/codemod/edits/findInsertionPosition.js +1 -1
  39. package/dist/src/codemod/edits/index.d.ts +3 -0
  40. package/dist/src/codemod/edits/index.js +1 -1
  41. package/dist/src/codemod/edits/modifyResource.d.ts +9 -3
  42. package/dist/src/codemod/edits/modifyResource.js +1 -1
  43. package/dist/src/codemod/edits/removeResource.d.ts +2 -2
  44. package/dist/src/codemod/edits/removeResource.js +1 -1
  45. package/dist/src/codemod/edits/vpcPeer.d.ts +28 -0
  46. package/dist/src/codemod/edits/vpcPeer.js +1 -0
  47. package/dist/src/codemod/edits/vpcPeerAccepter.d.ts +23 -0
  48. package/dist/src/codemod/edits/vpcPeerAccepter.js +1 -0
  49. package/dist/src/codemod/index.d.ts +16 -4
  50. package/dist/src/codemod/index.js +1 -1
  51. package/dist/src/codemod/llmFallback/__tests__/fixtures.d.ts +5 -0
  52. package/dist/src/codemod/llmFallback/__tests__/fixtures.js +7 -0
  53. package/dist/src/codemod/llmFallback/apply.d.ts +10 -0
  54. package/dist/src/codemod/llmFallback/apply.js +1 -0
  55. package/dist/src/codemod/llmFallback/claudeTier.d.ts +6 -0
  56. package/dist/src/codemod/llmFallback/claudeTier.js +1 -0
  57. package/dist/src/codemod/llmFallback/egressGate.d.ts +5 -0
  58. package/dist/src/codemod/llmFallback/egressGate.js +1 -0
  59. package/dist/src/codemod/llmFallback/egressGate.types.d.ts +9 -0
  60. package/dist/src/codemod/llmFallback/egressGate.types.js +0 -0
  61. package/dist/src/codemod/llmFallback/index.d.ts +6 -0
  62. package/dist/src/codemod/llmFallback/index.js +1 -0
  63. package/dist/src/codemod/llmFallback/morphTier.d.ts +2 -0
  64. package/dist/src/codemod/llmFallback/morphTier.js +3 -0
  65. package/dist/src/codemod/llmFallback/prompt.d.ts +12 -0
  66. package/dist/src/codemod/llmFallback/prompt.js +36 -0
  67. package/dist/src/codemod/llmFallback/runFallback.d.ts +13 -0
  68. package/dist/src/codemod/llmFallback/runFallback.js +1 -0
  69. package/dist/src/codemod/llmFallback/shouldTryFallback.d.ts +13 -0
  70. package/dist/src/codemod/llmFallback/shouldTryFallback.js +1 -0
  71. package/dist/src/codemod/llmFallback/signals.d.ts +4 -0
  72. package/dist/src/codemod/llmFallback/signals.js +1 -0
  73. package/dist/src/codemod/llmFallback/telemetryEvents.d.ts +141 -0
  74. package/dist/src/codemod/llmFallback/telemetryEvents.js +1 -0
  75. package/dist/src/codemod/llmFallback/tierRunner.d.ts +7 -0
  76. package/dist/src/codemod/llmFallback/tierRunner.js +1 -0
  77. package/dist/src/codemod/llmFallback/types.d.ts +104 -0
  78. package/dist/src/codemod/llmFallback/types.js +1 -0
  79. package/dist/src/codemod/registry.d.ts +4 -1
  80. package/dist/src/codemod/registry.js +1 -1
  81. package/dist/src/codemod/semanticIndex/classifyControlFlow.d.ts +2 -0
  82. package/dist/src/codemod/semanticIndex/classifyControlFlow.js +1 -0
  83. package/dist/src/codemod/semanticIndex/findReferences.js +2 -2
  84. package/dist/src/codemod/telemetry/__tests__/errorKinds.fixture.d.ts +1 -0
  85. package/dist/src/codemod/telemetry/__tests__/errorKinds.fixture.js +1 -0
  86. package/dist/src/codemod/telemetry/errorKinds.d.ts +2 -0
  87. package/dist/src/codemod/telemetry/errorKinds.js +1 -0
  88. package/dist/src/codemod/types.d.ts +105 -1
  89. package/dist/src/codemod/types.js +1 -1
  90. package/dist/src/codemod/validationGate/gates/classify.d.ts +2 -0
  91. package/dist/src/codemod/validationGate/gates/classify.js +1 -0
  92. package/dist/src/codemod/validationGate/gates/drift.d.ts +2 -0
  93. package/dist/src/codemod/validationGate/gates/drift.js +1 -0
  94. package/dist/src/codemod/validationGate/gates/locate.d.ts +7 -0
  95. package/dist/src/codemod/validationGate/gates/locate.js +1 -0
  96. package/dist/src/codemod/validationGate/gates/parse.d.ts +2 -0
  97. package/dist/src/codemod/validationGate/gates/parse.js +1 -0
  98. package/dist/src/codemod/validationGate/gates/schema.d.ts +2 -0
  99. package/dist/src/codemod/validationGate/gates/schema.js +1 -0
  100. package/dist/src/codemod/validationGate/index.d.ts +6 -0
  101. package/dist/src/codemod/validationGate/index.js +1 -0
  102. package/dist/src/codemod/validationGate/types.d.ts +35 -0
  103. package/dist/src/codemod/validationGate/types.js +1 -0
  104. package/dist/src/dns/domainFileGenerator.js +22 -183
  105. package/dist/src/index.js +1 -21
  106. package/dist/src/planning/index.d.ts +2 -1
  107. package/dist/src/planning/index.js +1 -1
  108. package/dist/src/planning/openNextPlanning.d.ts +38 -0
  109. package/dist/src/planning/openNextPlanning.js +1 -0
  110. package/dist/src/planning/resourcePlanning.d.ts +0 -46
  111. package/dist/src/planning/resourcePlanning.js +1 -1
  112. package/dist/src/schemas/applicationSchemas.d.ts +16 -0
  113. package/dist/src/schemas/applicationSchemas.js +1 -1
  114. package/dist/src/schemas/baseSchemas.d.ts +8 -5
  115. package/dist/src/schemas/baseSchemas.js +2 -2
  116. package/dist/src/schemas/networkSchemas.d.ts +119 -5
  117. package/dist/src/schemas/networkSchemas.js +1 -1
  118. package/dist/src/validation/patterns.d.ts +2 -318
  119. package/dist/src/validation/patterns.js +1 -1
  120. package/dist/src/validation/validationMessages.d.ts +314 -0
  121. package/dist/src/validation/validationMessages.js +1 -0
  122. package/dist/src/validation/validationPatterns.d.ts +20 -0
  123. package/dist/src/validation/validationPatterns.js +1 -0
  124. package/dist/src/version.d.ts +1 -1
  125. package/dist/src/version.js +1 -1
  126. package/package.json +3 -3
@@ -0,0 +1,19 @@
1
+ import type { ControlFlowClassifierError, NodeLocation, StatementType } from "../types.js";
2
+ export type ControlFlowPolicyOp = "add" | "remove" | "modify";
3
+ export interface ControlFlowPolicyInput {
4
+ ast: unknown;
5
+ target: NodeLocation;
6
+ resource: {
7
+ type: StatementType;
8
+ name: string;
9
+ };
10
+ op: ControlFlowPolicyOp;
11
+ }
12
+ export interface ControlFlowWarning {
13
+ message: string;
14
+ }
15
+ export interface ControlFlowPolicyResult {
16
+ refusal?: ControlFlowClassifierError;
17
+ warning?: ControlFlowWarning;
18
+ }
19
+ export declare function checkControlFlowPolicy(input: ControlFlowPolicyInput): ControlFlowPolicyResult;
@@ -0,0 +1 @@
1
+ import{isRecord as y}from"../_internal.js";const h=new Set(["loc","tokens","comments","original","range"]),p=new Set(["ForStatement","ForInStatement","ForOfStatement","WhileStatement","DoWhileStatement"]),m={"try-catch":"Move the resource declaration outside the try block.","switch-fall-through":"Add a break statement or convert to if/else.","nested-ternary":"Convert nested ternaries to if/else.",loop:"Extract the resource declaration before the loop.","generator-function":"Extract the resource declaration outside the generator.","async-iterator":"Extract the resource declaration outside the async iterator.","anonymous-helper":"Extract the resource to module scope.","decorator-return":"Extract the resource declaration outside the decorated function."};function g(e,r){if(!c(e))return;const n=[{node:e,ancestors:[]}];for(;n.length>0;){const s=n.pop();if(s===void 0)continue;const{node:o,ancestors:a}=s;if(o.type==="StringLiteral"&&typeof o.start=="number"&&o.start===r)return{node:o,ancestors:a};const t=[...a,o];for(const u of Object.keys(o)){if(h.has(u))continue;const f=o[u];if(Array.isArray(f))for(let d=f.length-1;d>=0;d-=1){const l=f[d];c(l)&&n.push({node:l,ancestors:t})}else c(f)&&n.push({node:f,ancestors:t})}}}function c(e){return typeof e=="object"&&e!==null&&typeof e.type=="string"}function i(e,r,n){return{kind:"ControlFlowClassifierError",reason:e,resource:r,location:S(n),remediation:m[e]}}function S(e){const r=e.loc;if(r?.start!==void 0&&typeof r.start.line=="number"&&typeof r.start.column=="number")return{line:r.start.line,column:r.start.column}}function F(e,r){const n=e.finalizer;return n!==void 0&&n===r}function E(e,r){const n=e.handler;return n!==void 0&&n===r}function b(e){const r=e.consequent;if(!Array.isArray(r)||r.length===0)return!0;const n=r[r.length-1];return c(n)?n.type!=="BreakStatement"&&n.type!=="ReturnStatement":!0}function k(e){const r=A(e.ast);if(r===void 0)return{};const n=g(r,e.target.start);if(n===void 0)return{};const{ancestors:s}=n;let o=n.node;for(let a=s.length-1;a>=0;a-=1){const t=s[a];if(t!==void 0){if(p.has(t.type))return{refusal:i("loop",e.resource,t)};if(t.type==="TryStatement"){if(E(t,o)||F(t,o))return{refusal:i("try-catch",e.resource,t)};o=t;continue}if(t.type==="CatchClause")return{refusal:i("try-catch",e.resource,t)};if(t.type==="SwitchCase"&&b(t))return{refusal:i("switch-fall-through",e.resource,t)};if(t.type==="ConditionalExpression"){const u=a-1;if((u>=0?s[u]:void 0)?.type==="ConditionalExpression")return{refusal:i("nested-ternary",e.resource,t)};if(e.op==="modify")return{warning:{message:`Modified property on resource "${e.resource.name}" declared in a ternary expression \u2014 consider converting to if/else.`}};if(e.op==="add"||e.op==="remove")return{refusal:i("nested-ternary",e.resource,t)}}if(t.type==="FunctionDeclaration"||t.type==="FunctionExpression"||t.type==="ArrowFunctionExpression"||t.type==="ObjectMethod"||t.type==="ClassMethod")return t.generator===!0?{refusal:i("generator-function",e.resource,t)}:t.async===!0&&w(t)?{refusal:i("async-iterator",e.resource,t)}:x(t)===void 0?{refusal:i("anonymous-helper",e.resource,t)}:{refusal:i("anonymous-helper",e.resource,t)};o=t}}return{}}function x(e){if(e.type==="FunctionDeclaration"){const r=e.id;if(c(r)&&typeof r.name=="string")return r.name}}function w(e){if(e.type!=="FunctionDeclaration"&&e.type!=="FunctionExpression")return!1;const r=e.body;if(!c(r)||r.type!=="BlockStatement")return!1;const n=r.body;return Array.isArray(n)?n.some(s=>c(s)&&s.type==="ForOfStatement"&&s.await===!0):!1}function A(e){if(!y(e))return;const r=e.program;if(y(r)&&typeof r.type=="string")return e}export{k as checkControlFlowPolicy};
@@ -0,0 +1,24 @@
1
+ import type { CrossPlanConnectionResourcePlan } from "../../schemas/applicationSchemas.js";
2
+ import { type Result } from "../../types/Result.js";
3
+ import type { CodemodError, LinesChanged } from "../types.js";
4
+ export type CrossPlanConnectionAddOptions = Omit<CrossPlanConnectionResourcePlan, "name"> & {
5
+ name: string;
6
+ filePath?: string;
7
+ };
8
+ export interface CrossPlanConnectionRemoveOptions {
9
+ name: string;
10
+ filePath?: string;
11
+ force?: boolean;
12
+ }
13
+ export type CrossPlanConnectionModifyOptions = Partial<Omit<CrossPlanConnectionResourcePlan, "name">> & {
14
+ name: string;
15
+ filePath?: string;
16
+ };
17
+ export interface CrossPlanConnectionOrchestratorSuccess {
18
+ content: string;
19
+ linesChanged: LinesChanged;
20
+ warnings?: string[];
21
+ }
22
+ export declare function addCrossPlanConnection(content: string, options: CrossPlanConnectionAddOptions): Result<CrossPlanConnectionOrchestratorSuccess, CodemodError>;
23
+ export declare function removeCrossPlanConnection(content: string, options: CrossPlanConnectionRemoveOptions): Result<CrossPlanConnectionOrchestratorSuccess, CodemodError>;
24
+ export declare function modifyCrossPlanConnection(content: string, options: CrossPlanConnectionModifyOptions): Result<CrossPlanConnectionOrchestratorSuccess, CodemodError>;
@@ -0,0 +1 @@
1
+ import{failure as i,success as d}from"../../types/Result.js";import{addResource as u}from"./addResource.js";import{modifyResource as f}from"./modifyResource.js";import{removeResource as l}from"./removeResource.js";function y(e,n){const{name:t,filePath:o,...s}=n,a={...s},r=u(e,{type:"cross-plan-connection",name:t,properties:a,...o!==void 0?{filePath:o}:{}});if(!r.success)return i(r.error);const c=m(n);return d({content:r.data.content,linesChanged:r.data.linesChanged,...c.length>0?{warnings:c}:{}})}function R(e,n){const t=l(e,{type:"cross-plan-connection",name:n.name,...n.filePath!==void 0?{filePath:n.filePath}:{},...n.force!==void 0?{force:n.force}:{}});return t.success?d({content:t.data.content,linesChanged:t.data.linesChanged}):i(t.error)}function A(e,n){const{name:t,filePath:o,...s}=n,a={...s},r=f(e,{type:"cross-plan-connection",name:t,properties:a,...o!==void 0?{filePath:o}:{}});if(!r.success)return i(r.error);const c=p(s);return d({content:r.data.content,linesChanged:r.data.linesChanged,...c.length>0?{warnings:c}:{}})}function m(e){return[`Cross-plan connection to "${e.remoteApp}/${e.remoteResource}" requires an accepter role granting ${e.permission} access on the remote plan.`]}function p(e){return e.remoteApp===void 0&&e.remoteResource===void 0&&e.permission===void 0?[]:["Updating remoteApp, remoteResource, or permission may require a corresponding change to the accepter role on the remote plan."]}export{y as addCrossPlanConnection,A as modifyCrossPlanConnection,R as removeCrossPlanConnection};
@@ -0,0 +1,7 @@
1
+ import type { DriftOp, DriftPolicy, DriftState } from "../drift/index.js";
2
+ export type DriftAction = "proceed" | "skip" | "reject";
3
+ export interface DriftDecision {
4
+ action: DriftAction;
5
+ driftState: DriftState;
6
+ }
7
+ export declare function resolveDriftPolicy(driftState: DriftState, op: DriftOp, policy: DriftPolicy | undefined): DriftDecision;
@@ -0,0 +1 @@
1
+ function t(e,o,n){const r=e.summary;return r==="clean"?{action:"proceed",driftState:e}:r==="no-op"?{action:"skip",driftState:e}:n?.force===!0?{action:"proceed",driftState:e}:r==="drifted-compatible"?{action:"proceed",driftState:e}:r==="drifted-conflict"?i(e,n)?{action:"proceed",driftState:e}:{action:"reject",driftState:e}:o==="add"?{action:"proceed",driftState:e}:{action:"reject",driftState:e}}function i(e,o){const n=o?.resolutionMap;if(n===void 0)return!1;const r=e.deltas.filter(c=>c.verdict==="conflict");return r.length===0?!1:r.every(c=>Object.prototype.hasOwnProperty.call(n,c.property))}export{t as resolveDriftPolicy};
@@ -1 +1 @@
1
- const s=["import","app-init","tags","database","storage","messaging","compute","network","cdn","pattern"];function d(i,a,c,r){const t=s.indexOf(c);if(t===-1)return r;let e;for(const n of i)s.indexOf("import")<=t&&(e=n.endPos);for(const n of a){const o=s.indexOf(n.type);o!==-1&&o<=t&&(e=n.endPos)}return e??r}export{d as findInsertionPosition};
1
+ const o=["import","app-init","tags","database","storage","messaging","compute","network","vpc-peer","vpc-peer-accepter","cross-plan-connection","cdn","pattern"];function d(c,i,p,r){const t=o.indexOf(p);if(t===-1)return r;let e;const a=o.indexOf("import");for(const n of c)a<=t&&(e=n.endPos);for(const n of i){const s=o.indexOf(n.type);s!==-1&&s<=t&&(e=n.endPos)}return e??r}export{d as findInsertionPosition};
@@ -3,3 +3,6 @@ export { findInsertionPosition, type ImportInfo, type InsertionStatementType, ty
3
3
  export { removeResource, type LinesChanged, type RemoveOptions, type RemoveResourceError, type RemoveResourceSuccess, } from "./removeResource.js";
4
4
  export { modifyResource, type ModifyOptions, type ModifyResourceError, type ModifyResourceSuccess, } from "./modifyResource.js";
5
5
  export { ensureImports, type EnsureImportsAddition, type EnsureImportsError, type EnsureImportsSuccess, } from "./ensureImports.js";
6
+ export { addVpcPeer, modifyVpcPeer, removeVpcPeer, type VpcPeerAddOptions, type VpcPeerModifyOptions, type VpcPeerOrchestratorSuccess, type VpcPeerRemoveOptions, } from "./vpcPeer.js";
7
+ export { addVpcPeerAccepter, modifyVpcPeerAccepter, removeVpcPeerAccepter, type VpcPeerAccepterAddOptions, type VpcPeerAccepterModifyOptions, type VpcPeerAccepterOrchestratorSuccess, type VpcPeerAccepterRemoveOptions, } from "./vpcPeerAccepter.js";
8
+ export { addCrossPlanConnection, modifyCrossPlanConnection, removeCrossPlanConnection, type CrossPlanConnectionAddOptions, type CrossPlanConnectionModifyOptions, type CrossPlanConnectionOrchestratorSuccess, type CrossPlanConnectionRemoveOptions, } from "./crossPlanConnection.js";
@@ -1 +1 @@
1
- import{addResource as e}from"./addResource.js";import{findInsertionPosition as t}from"./findInsertionPosition.js";import{removeResource as s}from"./removeResource.js";import{modifyResource as i}from"./modifyResource.js";import{ensureImports as x}from"./ensureImports.js";export{e as addResource,x as ensureImports,t as findInsertionPosition,i as modifyResource,s as removeResource};
1
+ import{addResource as r}from"./addResource.js";import{findInsertionPosition as p}from"./findInsertionPosition.js";import{removeResource as n}from"./removeResource.js";import{modifyResource as d}from"./modifyResource.js";import{ensureImports as s}from"./ensureImports.js";import{addVpcPeer as P,modifyVpcPeer as x,removeVpcPeer as a}from"./vpcPeer.js";import{addVpcPeerAccepter as V,modifyVpcPeerAccepter as u,removeVpcPeerAccepter as v}from"./vpcPeerAccepter.js";import{addCrossPlanConnection as l,modifyCrossPlanConnection as A,removeCrossPlanConnection as R}from"./crossPlanConnection.js";export{l as addCrossPlanConnection,r as addResource,P as addVpcPeer,V as addVpcPeerAccepter,s as ensureImports,p as findInsertionPosition,A as modifyCrossPlanConnection,d as modifyResource,x as modifyVpcPeer,u as modifyVpcPeerAccepter,R as removeCrossPlanConnection,n as removeResource,a as removeVpcPeer,v as removeVpcPeerAccepter};
@@ -1,9 +1,15 @@
1
1
  import { type Result } from "../../types/Result.js";
2
- import type { InvalidPropertyError, LinesChanged, ModifyOptions, ParseError, ResourceNotFoundError, SemanticQueryError, TemplateLiteralNameError } from "../types.js";
2
+ import { type ResourceSnapshot } from "../drift/index.js";
3
+ import type { ControlFlowClassifierError, DriftConflictError, InvalidPropertyError, LinesChanged, ModifyOptions, ParseError, ResourceNotFoundError, SemanticQueryError, TemplateLiteralNameError } from "../types.js";
3
4
  export type { LinesChanged, ModifyOptions } from "../types.js";
4
- export type ModifyResourceError = ParseError | ResourceNotFoundError | InvalidPropertyError | TemplateLiteralNameError | SemanticQueryError;
5
+ export type ModifyResourceError = ParseError | ResourceNotFoundError | InvalidPropertyError | TemplateLiteralNameError | SemanticQueryError | DriftConflictError | ControlFlowClassifierError;
5
6
  export interface ModifyResourceSuccess {
6
7
  content: string;
7
8
  linesChanged: LinesChanged;
9
+ skipped?: boolean;
10
+ warnings?: string[];
8
11
  }
9
- export declare function modifyResource(content: string, options: ModifyOptions): Result<ModifyResourceSuccess, ModifyResourceError>;
12
+ export interface ModifyResourceCallContext {
13
+ baseline?: ResourceSnapshot;
14
+ }
15
+ export declare function modifyResource(content: string, options: ModifyOptions, context?: ModifyResourceCallContext): Result<ModifyResourceSuccess, ModifyResourceError>;
@@ -1 +1 @@
1
- import{failure as u,success as y}from"../../types/Result.js";import{DEFAULT_FILE_PATH as g,computeLinesDelta as k,extractProgramBody as E,isRecord as d}from"../_internal.js";import{buildObjectProperty as b,detectQuoteStyle as P,parse as S,printFile as v}from"../fileRewriter/index.js";import{STATEMENT_REGISTRY as x}from"../registry.js";import{locateAllShapes as A,locateByShape as N}from"../semanticIndex/index.js";import{toAstValue as T}from"./addResource/propertyBuilder.js";import{buildMergedLiteral as C,isNodeShape as h,readKeyName as L}from"./modifyResource/literalConversion.js";function V(o,e){const t=e.filePath??g,n=S(o,t);if(!n.success)return u(n.error);const r=N(o,{type:e.type,name:e.name},t);if(!r.success)return r.error.kind==="TemplateLiteralNameError"?u(r.error):u({kind:"SemanticQueryError",reason:r.error.reason,cause:r.error.cause});if(r.data===void 0)return u({kind:"ResourceNotFoundError",type:e.type,name:e.name,knownNames:R(o,e.type,t)});const i=E(n.data);if(i===void 0)return u({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const s=j(i,r.data);if(s===void 0)return u({kind:"SemanticQueryError",reason:"Unable to resolve config ObjectExpression for the located resource."});const a=P(n.data),c=C(s,e.properties),l=x[e.type].schemaFragment.safeParse(c);if(!l.success){const f=l.error.issues[0];return u({kind:"InvalidPropertyError",property:f!==void 0&&f.path.length>0?String(f.path[0]):Object.keys(e.properties)[0]??"<unknown>",reason:f?.message??"Schema validation failed"})}const p=w(s,e.properties,a);if(!p.success)return u(p.error);const m=v(n.data,o);return y({content:m,linesChanged:k(o,m)})}function j(o,e){const t=e.start+e.length;let n;const r=i=>{if(n!==void 0||i.type!=="CallExpression")return;const s=i.arguments;if(!Array.isArray(s)||s.length<2)return;const a=s[0];if(!h(a)||a.type!=="StringLiteral"||a.start!==e.start||a.end!==t)return;const c=s[1];h(c)&&c.type==="ObjectExpression"&&(n=c)};for(const i of o)if(I(i,r),n!==void 0)break;return n}function w(o,e,t){const n=O(o);for(const[r,i]of Object.entries(e)){const s=T(i,t);if(s===void 0)return u({kind:"InvalidPropertyError",property:r,reason:`Unsupported property value for "${r}" (Phase 1 accepts string/number/boolean/null only).`});const a=F(o,r);if(a!==void 0){a.value=s;continue}const c=b(r,s,t);n&&(c.extra={...c.extra??{},trailingComma:!0}),o.properties.push(c)}return y(void 0)}function F(o,e){return o.properties.find(t=>(t.type==="Property"||t.type==="ObjectProperty")&&t.shorthand!==!0&&t.computed!==!0&&L(t.key)===e)}function O(o){return o.properties[o.properties.length-1]?.extra?.trailingComma===!0}function R(o,e,t){const n=A(o,t);return n.success?n.data.filter(r=>r.type===e).map(r=>r.symbolName):[]}function I(o,e){const t=[o];for(;t.length>0;){const n=t.pop();if(d(n)){typeof n.type=="string"&&e(n);for(const r of Object.keys(n)){if(r==="loc"||r==="comments"||r==="tokens")continue;const i=n[r];if(Array.isArray(i))for(const s of i)d(s)&&t.push(s);else d(i)&&t.push(i)}}}}export{V as modifyResource};
1
+ import{failure as c,success as l}from"../../types/Result.js";import{DEFAULT_FILE_PATH as P,computeLinesDelta as S,extractProgramBody as v,isRecord as p}from"../_internal.js";import{buildObjectProperty as w,detectQuoteStyle as C,parse as N,printFile as x}from"../fileRewriter/index.js";import{STATEMENT_REGISTRY as T}from"../registry.js";import{locateAllShapes as A,locateByShape as F}from"../semanticIndex/index.js";import{checkControlFlowPolicy as R}from"./controlFlowPolicy.js";import{driftGate as L,runPipeline as j,schemaGate as O}from"../validationGate/index.js";import{toAstValue as Q}from"./addResource/propertyBuilder.js";import{buildMergedLiteral as I,isNodeShape as h,readKeyName as G}from"./modifyResource/literalConversion.js";function ee(r,e,a={}){const i=e.filePath??P,t=N(r,i);if(!t.success)return c(t.error);const n=F(r,{type:e.type,name:e.name},i);if(!n.success)return n.error.kind==="TemplateLiteralNameError"?c(n.error):c({kind:"SemanticQueryError",reason:n.error.reason,cause:n.error.cause});if(n.data===void 0)return c({kind:"ResourceNotFoundError",type:e.type,name:e.name,knownNames:M(r,e.type,i)});const o=R({ast:t.data,target:n.data,resource:{type:e.type,name:e.name},op:"modify"});if(o.refusal!==void 0)return c(o.refusal);const s=j([O,L],{content:r,plan:{type:e.type,name:e.name,properties:e.properties,op:"modify"},baseline:a.baseline,policy:e.driftPolicy});if(!s.success)return c(U(s.error));if(s.data.action==="skip")return l({content:r,linesChanged:{added:0,removed:0},skipped:!0});const u=v(t.data);if(u===void 0)return c({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const f=B(u,n.data);if(f===void 0)return c({kind:"SemanticQueryError",reason:"Unable to resolve config ObjectExpression for the located resource."});const E=C(t.data),k=I(f,e.properties),m=T[e.type].schemaFragment.safeParse(k);if(!m.success){const d=m.error.issues[0];return c({kind:"InvalidPropertyError",property:d!==void 0&&d.path.length>0?String(d.path[0]):Object.keys(e.properties)[0]??"<unknown>",reason:d?.message??"Schema validation failed"})}const y=D(f,e.properties,E);if(!y.success)return c(y.error);const g=x(t.data,r),b=o.warning!==void 0?[o.warning.message]:void 0;return l({content:g,linesChanged:S(r,g),warnings:b})}function U(r){switch(r.kind){case"ParseError":case"ResourceNotFoundError":case"InvalidPropertyError":case"TemplateLiteralNameError":case"SemanticQueryError":case"DriftConflictError":case"ControlFlowClassifierError":return r;default:return{kind:"SemanticQueryError",reason:`Unexpected codemod error in validation-gate pipeline: ${r.kind}`}}}function B(r,e){const a=e.start+e.length;let i;const t=n=>{if(i!==void 0||n.type!=="CallExpression")return;const o=n.arguments;if(!Array.isArray(o)||o.length<2)return;const s=o[0];if(!h(s)||s.type!=="StringLiteral"||s.start!==e.start||s.end!==a)return;const u=o[1];h(u)&&u.type==="ObjectExpression"&&(i=u)};for(const n of r)if(V(n,t),i!==void 0)break;return i}function D(r,e,a){const i=_(r);for(const[t,n]of Object.entries(e)){const o=Q(n,a);if(o===void 0)return c({kind:"InvalidPropertyError",property:t,reason:`Unsupported property value for "${t}" (accepts string/number/boolean/null/array/object of the same).`});const s=K(r,t);if(s!==void 0){s.value=o;continue}const u=w(t,o,a);i&&(u.extra={...u.extra??{},trailingComma:!0}),r.properties.push(u)}return l(void 0)}function K(r,e){return r.properties.find(a=>(a.type==="Property"||a.type==="ObjectProperty")&&a.shorthand!==!0&&a.computed!==!0&&G(a.key)===e)}function _(r){return r.properties[r.properties.length-1]?.extra?.trailingComma===!0}function M(r,e,a){const i=A(r,a);return i.success?i.data.filter(t=>t.type===e).map(t=>t.symbolName):[]}function V(r,e){const a=[r];for(;a.length>0;){const i=a.pop();if(p(i)){typeof i.type=="string"&&e(i);for(const t of Object.keys(i)){if(t==="loc"||t==="comments"||t==="tokens")continue;const n=i[t];if(Array.isArray(n))for(const o of n)p(o)&&a.push(o);else p(n)&&a.push(n)}}}}export{ee as modifyResource};
@@ -1,7 +1,7 @@
1
1
  import { type Result } from "../../types/Result.js";
2
- import type { LinesChanged, ParseError, ReferenceLocation, ReferencesRemainError, RemoveOptions, ResourceNotFoundError, SemanticQueryError, TemplateLiteralNameError } from "../types.js";
2
+ import type { ControlFlowClassifierError, LinesChanged, ParseError, ReferenceLocation, ReferencesRemainError, RemoveOptions, ResourceNotFoundError, SemanticQueryError, TemplateLiteralNameError } from "../types.js";
3
3
  export type { LinesChanged, RemoveOptions } from "../types.js";
4
- export type RemoveResourceError = ParseError | TemplateLiteralNameError | ResourceNotFoundError | ReferencesRemainError | SemanticQueryError;
4
+ export type RemoveResourceError = ParseError | TemplateLiteralNameError | ResourceNotFoundError | ReferencesRemainError | SemanticQueryError | ControlFlowClassifierError;
5
5
  export interface RemoveResourceSuccess {
6
6
  content: string;
7
7
  linesChanged: LinesChanged;
@@ -1 +1 @@
1
- import{failure as c,success as u}from"../../types/Result.js";import{DEFAULT_FILE_PATH as l,computeLinesDelta as p,extractProgramBody as y,isRecord as d}from"../_internal.js";import{parse as g,printFile as h}from"../fileRewriter/index.js";import{findReferences as b,locateAllShapes as E,locateByShape as v}from"../semanticIndex/index.js";import{classifyLeadingComments as k}from"./removeResource/commentHeuristic.js";import{pruneUnusedImports as S}from"./removeResource/importPruning.js";function U(n,r){const a=r.filePath??l,t=g(n,a);if(!t.success)return c(t.error);const e=v(n,{type:r.type,name:r.name},a);if(!e.success)return e.error.kind==="TemplateLiteralNameError"?c(e.error):c({kind:"SemanticQueryError",reason:e.error.reason,cause:e.error.cause});if(e.data===void 0)return c({kind:"ResourceNotFoundError",type:r.type,name:r.name,knownNames:F(n,r.type,a)});const i=y(t.data);if(i===void 0)return c({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const o=N(i,e.data);if(o===void 0)return c({kind:"SemanticQueryError",reason:"Unable to resolve enclosing statement for the located resource."});const s=R(n,o.statement,a);if(!s.success)return c(s.error);if(s.data.locations.length>0&&r.force!==!0)return c({kind:"ReferencesRemainError",variable:s.data.variable??r.name,references:s.data.locations});A(i,o.index,n),S(i);const f=h(t.data,n),m=p(n,f);return u({content:f,linesChanged:m,references:s.data.locations})}function N(n,r){const a=r.start+r.length;for(let t=0;t<n.length;t+=1){const e=n[t];if(e!==void 0&&!(typeof e.start!="number"||typeof e.end!="number")&&e.start<=r.start&&e.end>=a)return{index:t,statement:e}}}function R(n,r,a){const t=D(r);if(t===void 0)return u({variable:void 0,locations:[]});const e=b(n,t.location,a);return e.success?u({variable:t.name,locations:e.data}):c({kind:"SemanticQueryError",reason:e.error.reason,cause:e.error.cause})}function D(n){let r=n;if(n.type==="ExportNamedDeclaration"){const f=n.declaration;if(!d(f)||f.type!=="VariableDeclaration")return;r=f}if(r.type!=="VariableDeclaration")return;const a=r.declarations;if(!Array.isArray(a)||a.length!==1)return;const t=a[0];if(!d(t))return;const e=t.id;if(!d(e)||e.type!=="Identifier")return;const i=e.name,o=e.start,s=e.end;if(!(typeof i!="string"||typeof o!="number"||typeof s!="number"))return{name:i,location:{filePath:l,start:o,length:s-o,symbolName:i}}}function A(n,r,a){const t=n[r];if(t===void 0)return;const{preserved:e}=k(t,a);if(e.length>0){const i=n[r+1];if(i!==void 0){const o=e.map(s=>({...s,leading:!0,trailing:!1}));i.comments=[...o,...i.comments??[]]}else{const o=n[r-1];if(o!==void 0){const s=e.map(f=>({...f,leading:!1,trailing:!0}));o.comments=[...o.comments??[],...s]}}}n.splice(r,1)}function F(n,r,a){const t=E(n,a);if(!t.success)return[];const e=[];for(const i of t.data)i.type===r&&e.push(i.symbolName);return e}export{U as removeResource};
1
+ import{failure as f,success as u}from"../../types/Result.js";import{DEFAULT_FILE_PATH as m,computeLinesDelta as y,extractProgramBody as g,isRecord as d}from"../_internal.js";import{parse as h,printFile as b}from"../fileRewriter/index.js";import{findReferences as E,locateAllShapes as v,locateByShape as k}from"../semanticIndex/index.js";import{checkControlFlowPolicy as R}from"./controlFlowPolicy.js";import{classifyLeadingComments as S}from"./removeResource/commentHeuristic.js";import{pruneUnusedImports as N}from"./removeResource/importPruning.js";function V(n,r){const a=r.filePath??m,t=h(n,a);if(!t.success)return f(t.error);const e=k(n,{type:r.type,name:r.name},a);if(!e.success)return e.error.kind==="TemplateLiteralNameError"?f(e.error):f({kind:"SemanticQueryError",reason:e.error.reason,cause:e.error.cause});if(e.data===void 0)return f({kind:"ResourceNotFoundError",type:r.type,name:r.name,knownNames:L(n,r.type,a)});const o=R({ast:t.data,target:e.data,resource:{type:r.type,name:r.name},op:"remove"});if(o.refusal!==void 0)return f(o.refusal);const i=g(t.data);if(i===void 0)return f({kind:"SemanticQueryError",reason:"recast File is missing program.body"});const c=D(i,e.data);if(c===void 0)return f({kind:"SemanticQueryError",reason:"Unable to resolve enclosing statement for the located resource."});const s=F(n,c.statement,a);if(!s.success)return f(s.error);if(s.data.locations.length>0&&r.force!==!0)return f({kind:"ReferencesRemainError",variable:s.data.variable??r.name,references:s.data.locations});A(i,c.index,n),N(i);const l=b(t.data,n),p=y(n,l);return u({content:l,linesChanged:p,references:s.data.locations})}function D(n,r){const a=r.start+r.length;for(let t=0;t<n.length;t+=1){const e=n[t];if(e!==void 0&&!(typeof e.start!="number"||typeof e.end!="number")&&e.start<=r.start&&e.end>=a)return{index:t,statement:e}}}function F(n,r,a){const t=P(r);if(t===void 0)return u({variable:void 0,locations:[]});const e=E(n,t.location,a);return e.success?u({variable:t.name,locations:e.data}):f({kind:"SemanticQueryError",reason:e.error.reason,cause:e.error.cause})}function P(n){let r=n;if(n.type==="ExportNamedDeclaration"){const s=n.declaration;if(!d(s)||s.type!=="VariableDeclaration")return;r=s}if(r.type!=="VariableDeclaration")return;const a=r.declarations;if(!Array.isArray(a)||a.length!==1)return;const t=a[0];if(!d(t))return;const e=t.id;if(!d(e)||e.type!=="Identifier")return;const o=e.name,i=e.start,c=e.end;if(!(typeof o!="string"||typeof i!="number"||typeof c!="number"))return{name:o,location:{filePath:m,start:i,length:c-i,symbolName:o}}}function A(n,r,a){const t=n[r];if(t===void 0)return;const{preserved:e}=S(t,a);if(e.length>0){const o=n[r+1];if(o!==void 0){const i=e.map(c=>({...c,leading:!0,trailing:!1}));o.comments=[...i,...o.comments??[]]}else{const i=n[r-1];if(i!==void 0){const c=e.map(s=>({...s,leading:!1,trailing:!0}));i.comments=[...i.comments??[],...c]}}}n.splice(r,1)}function L(n,r,a){const t=v(n,a);if(!t.success)return[];const e=[];for(const o of t.data)o.type===r&&e.push(o.symbolName);return e}export{V as removeResource};
@@ -0,0 +1,28 @@
1
+ import type { VpcPeerResourcePlan } from "../../schemas/networkSchemas.js";
2
+ import { type Result } from "../../types/Result.js";
3
+ import type { CodemodError, LinesChanged, PermissionError } from "../types.js";
4
+ export type VpcPeerAddOptions = Omit<VpcPeerResourcePlan, "name"> & {
5
+ name: string;
6
+ filePath?: string;
7
+ currentAccount?: string;
8
+ };
9
+ export interface VpcPeerRemoveOptions {
10
+ name: string;
11
+ filePath?: string;
12
+ force?: boolean;
13
+ }
14
+ export type VpcPeerModifyOptions = Partial<Omit<VpcPeerResourcePlan, "name">> & {
15
+ name: string;
16
+ filePath?: string;
17
+ currentAccount?: string;
18
+ };
19
+ export interface VpcPeerOrchestratorSuccess {
20
+ content: string;
21
+ linesChanged: LinesChanged;
22
+ warnings?: string[];
23
+ }
24
+ export declare function addVpcPeer(content: string, options: VpcPeerAddOptions): Result<VpcPeerOrchestratorSuccess, CodemodError>;
25
+ export declare function removeVpcPeer(content: string, options: VpcPeerRemoveOptions): Result<VpcPeerOrchestratorSuccess, CodemodError>;
26
+ export declare function modifyVpcPeer(content: string, options: VpcPeerModifyOptions): Result<VpcPeerOrchestratorSuccess, CodemodError>;
27
+ export declare function buildWildcardRejection(resourceType: string, planProperties: Record<string, unknown>, remediation: string): PermissionError | undefined;
28
+ export declare function findWildcardField(value: unknown, path?: string): string | undefined;
@@ -0,0 +1 @@
1
+ import{failure as o,success as l}from"../../types/Result.js";import{addResource as m}from"./addResource.js";import{modifyResource as P}from"./modifyResource.js";import{removeResource as A}from"./removeResource.js";const f="vpc-peer";function j(e,n){const t=g(n);if(t!==void 0)return o(t);const{name:r,filePath:c,currentAccount:d,...a}=n,s={...a},i=m(e,{type:f,name:r,properties:s,...c!==void 0?{filePath:c}:{}});if(!i.success)return o(i.error);const u=y(n);return l({content:i.data.content,linesChanged:i.data.linesChanged,...u.length>0?{warnings:u}:{}})}function w(e,n){const t=A(e,{type:f,name:n.name,...n.filePath!==void 0?{filePath:n.filePath}:{},...n.force!==void 0?{force:n.force}:{}});return t.success?l({content:t.data.content,linesChanged:t.data.linesChanged}):o(t.error)}function V(e,n){const t=g(n);if(t!==void 0)return o(t);const{name:r,filePath:c,currentAccount:d,...a}=n,s={...a},i=P(e,{type:f,name:r,properties:s,...c!==void 0?{filePath:c}:{}});if(!i.success)return o(i.error);const u=$(a,d);return l({content:i.data.content,linesChanged:i.data.linesChanged,...u.length>0?{warnings:u}:{}})}function y(e){return h(e.peerAppName,e.peerAccountId,e.currentAccount)}function $(e,n){return e.peerAccountId===void 0?[]:h(e.peerAppName,e.peerAccountId,n)}function h(e,n,t){if(t!==void 0&&n===t)return[];const r=e!==void 0?` (peer app ${e})`:"";return[`VPC peer targets AWS account ${n}${r}. Peer requires a VpcPeerAccepter in that account trusting the local account. Deploy the accepter stack first, then the requester.`]}function C(e,n,t){const r=p(n);if(r!==void 0)return{kind:"PermissionError",reason:"wildcard-principal-rejected",details:`Wildcard value detected in ${e} field "${r}". Fjall refuses to emit a ${e} statement that could map to a wildcard principal in the generated trust policy.`,remediation:t}}function g(e){const{name:n,filePath:t,currentAccount:r,...c}=e;return C(f,c,"Replace the wildcard with a concrete 12-digit AWS account id, region, or vpc-id.")}function p(e,n=""){if(typeof e=="string")return e.includes("*")?n:void 0;if(Array.isArray(e)){for(let t=0;t<e.length;t+=1){const r=p(e[t],`${n}[${t}]`);if(r!==void 0)return r}return}if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){const c=n.length>0?`${n}.${t}`:t,d=p(r,c);if(d!==void 0)return d}}export{j as addVpcPeer,C as buildWildcardRejection,p as findWildcardField,V as modifyVpcPeer,w as removeVpcPeer};
@@ -0,0 +1,23 @@
1
+ import type { VpcPeerAccepterResourcePlan } from "../../schemas/networkSchemas.js";
2
+ import { type Result } from "../../types/Result.js";
3
+ import type { CodemodError, LinesChanged } from "../types.js";
4
+ export type VpcPeerAccepterAddOptions = Omit<VpcPeerAccepterResourcePlan, "name"> & {
5
+ name: string;
6
+ filePath?: string;
7
+ };
8
+ export interface VpcPeerAccepterRemoveOptions {
9
+ name: string;
10
+ filePath?: string;
11
+ force?: boolean;
12
+ }
13
+ export type VpcPeerAccepterModifyOptions = Partial<Omit<VpcPeerAccepterResourcePlan, "name">> & {
14
+ name: string;
15
+ filePath?: string;
16
+ };
17
+ export interface VpcPeerAccepterOrchestratorSuccess {
18
+ content: string;
19
+ linesChanged: LinesChanged;
20
+ }
21
+ export declare function addVpcPeerAccepter(content: string, options: VpcPeerAccepterAddOptions): Result<VpcPeerAccepterOrchestratorSuccess, CodemodError>;
22
+ export declare function removeVpcPeerAccepter(content: string, options: VpcPeerAccepterRemoveOptions): Result<VpcPeerAccepterOrchestratorSuccess, CodemodError>;
23
+ export declare function modifyVpcPeerAccepter(content: string, options: VpcPeerAccepterModifyOptions): Result<VpcPeerAccepterOrchestratorSuccess, CodemodError>;
@@ -0,0 +1 @@
1
+ import{failure as i,success as u}from"../../types/Result.js";import{addResource as l}from"./addResource.js";import{modifyResource as p}from"./modifyResource.js";import{removeResource as m}from"./removeResource.js";import{buildWildcardRejection as h}from"./vpcPeer.js";const d="vpc-peer-accepter";function A(n,e){const r=f(e);if(r!==void 0)return i(r);const{name:c,filePath:a,...o}=e,s={...o},t=l(n,{type:d,name:c,properties:s,...a!==void 0?{filePath:a}:{}});return t.success?u({content:t.data.content,linesChanged:t.data.linesChanged}):i(t.error)}function v(n,e){const r=m(n,{type:d,name:e.name,...e.filePath!==void 0?{filePath:e.filePath}:{},...e.force!==void 0?{force:e.force}:{}});return r.success?u({content:r.data.content,linesChanged:r.data.linesChanged}):i(r.error)}function x(n,e){const r=f(e);if(r!==void 0)return i(r);const{name:c,filePath:a,...o}=e,s={...o},t=p(n,{type:d,name:c,properties:s,...a!==void 0?{filePath:a}:{}});return t.success?u({content:t.data.content,linesChanged:t.data.linesChanged}):i(t.error)}function f(n){const{name:e,filePath:r,...c}=n;return h(d,c,"Replace the wildcard with a concrete 12-digit AWS account id.")}export{A as addVpcPeerAccepter,x as modifyVpcPeerAccepter,v as removeVpcPeerAccepter};
@@ -1,7 +1,19 @@
1
- export { addResource, type AddResourceError, type AddResourceSuccess, } from "./edits/addResource.js";
1
+ export { addResource, type AddResourceCallContext, type AddResourceError, type AddResourceSuccess, } from "./edits/addResource.js";
2
2
  export { removeResource, type RemoveResourceError, type RemoveResourceSuccess, } from "./edits/removeResource.js";
3
- export { modifyResource, type ModifyResourceError, type ModifyResourceSuccess, } from "./edits/modifyResource.js";
3
+ export { modifyResource, type ModifyResourceCallContext, type ModifyResourceError, type ModifyResourceSuccess, } from "./edits/modifyResource.js";
4
+ export { addVpcPeer, modifyVpcPeer, removeVpcPeer, type VpcPeerAddOptions, type VpcPeerModifyOptions, type VpcPeerOrchestratorSuccess, type VpcPeerRemoveOptions, } from "./edits/vpcPeer.js";
5
+ export { addVpcPeerAccepter, modifyVpcPeerAccepter, removeVpcPeerAccepter, type VpcPeerAccepterAddOptions, type VpcPeerAccepterModifyOptions, type VpcPeerAccepterOrchestratorSuccess, type VpcPeerAccepterRemoveOptions, } from "./edits/vpcPeerAccepter.js";
6
+ export { addCrossPlanConnection, modifyCrossPlanConnection, removeCrossPlanConnection, type CrossPlanConnectionAddOptions, type CrossPlanConnectionModifyOptions, type CrossPlanConnectionOrchestratorSuccess, type CrossPlanConnectionRemoveOptions, } from "./edits/crossPlanConnection.js";
7
+ export { resolveDriftPolicy, type DriftAction, type DriftDecision, } from "./edits/driftPolicy.js";
4
8
  export { listResources, type ListResourcesError } from "./listResources.js";
5
9
  export { parse } from "./fileRewriter/parse.js";
6
- export { StatementTypeSchema } from "./types.js";
7
- export type { AddOptions, CodemodError, CodemodSuccess, DuplicateResourceError, InvalidPropertyError, LinesChanged, ModifyOptions, NodeLocation, ParseError, ReferenceLocation, ReferencesRemainError, RemoveOptions, ResourceListing, ResourceListingEntry, ResourceName, ResourceNotFoundError, SemanticQueryError, StatementType, TemplateLiteralNameError, } from "./types.js";
10
+ export { CrossPlanConnectionResourcePlanSchema, VpcPeerAccepterResourcePlanSchema, VpcPeerResourcePlanSchema, } from "../schemas/index.js";
11
+ export type { CrossPlanConnectionResourcePlan, VpcPeerAccepterResourcePlan, VpcPeerResourcePlan, } from "../schemas/index.js";
12
+ export { detectDrift, mergeProperties, snapshotProperties, type DriftOp, type DriftPlan, type DriftPolicy, type DriftState, type MergeResult, type PropertyDelta, type ResourceSnapshot, } from "./drift/index.js";
13
+ export { computeLinesDelta } from "./_internal.js";
14
+ export { ResourceNameSchema, StatementTypeSchema } from "./types.js";
15
+ export { CODEMOD_ERROR_KINDS } from "./telemetry/errorKinds.js";
16
+ export type { CodemodErrorKind } from "./telemetry/errorKinds.js";
17
+ export type { GateId } from "./validationGate/index.js";
18
+ export { buildEgressBlockedEvent, buildFiredEvent, buildGateFailedEvent, buildGatePassedEvent, buildRejectedEvent, buildSucceededEvent, buildTimeoutEvent, estimateCostUsd, FALLBACK_EVENTS, GATE_EVENTS, PARSE_GATE, RUNTIME_GATE, runFallback, shouldTryFallback, type AnthropicClientProvider, type FallbackClients, type FallbackDecision, type FallbackEgressBlockedEvent, type FallbackGuardConfig, type FallbackInput, type FallbackIntent, type FallbackOp, type FallbackOutput, type FallbackTelemetry, type FallbackTelemetryEvent, type MorphClientProvider, type RunFallbackInput, type TelemetrySource, type TriggerReason, } from "./llmFallback/index.js";
19
+ export type { AddOptions, CodemodError, CodemodSuccess, ControlFlowClassifierError, DriftConflictError, DriftUnmergeableError, DuplicateResourceError, InvalidPropertyError, LinesChanged, LlmFallbackRejectedError, LlmFallbackTimeoutError, LlmFallbackTier, LlmFallbackUnsafeInputError, ModifyOptions, NodeLocation, ParseError, PermissionError, ReferenceLocation, ReferencesRemainError, RemoveOptions, ResourceListing, ResourceListingEntry, ResourceName, ResourceNotFoundError, SemanticQueryError, StatementType, TemplateLiteralNameError, } from "./types.js";
@@ -1 +1 @@
1
- import{addResource as r}from"./edits/addResource.js";import{removeResource as t}from"./edits/removeResource.js";import{modifyResource as f}from"./edits/modifyResource.js";import{listResources as x}from"./listResources.js";import{parse as a}from"./fileRewriter/parse.js";import{StatementTypeSchema as R}from"./types.js";export{R as StatementTypeSchema,r as addResource,x as listResources,f as modifyResource,a as parse,t as removeResource};
1
+ import{addResource as o}from"./edits/addResource.js";import{removeResource as c}from"./edits/removeResource.js";import{modifyResource as p}from"./edits/modifyResource.js";import{addVpcPeer as a,modifyVpcPeer as n,removeVpcPeer as d}from"./edits/vpcPeer.js";import{addVpcPeerAccepter as l,modifyVpcPeerAccepter as f,removeVpcPeerAccepter as u}from"./edits/vpcPeerAccepter.js";import{addCrossPlanConnection as E,modifyCrossPlanConnection as x,removeCrossPlanConnection as R}from"./edits/crossPlanConnection.js";import{resolveDriftPolicy as C}from"./edits/driftPolicy.js";import{listResources as A}from"./listResources.js";import{parse as b}from"./fileRewriter/parse.js";import{CrossPlanConnectionResourcePlanSchema as h,VpcPeerAccepterResourcePlanSchema as y,VpcPeerResourcePlanSchema as D}from"../schemas/index.js";import{detectDrift as F,mergeProperties as G,snapshotProperties as N}from"./drift/index.js";import{computeLinesDelta as L}from"./_internal.js";import{ResourceNameSchema as g,StatementTypeSchema as B}from"./types.js";import{CODEMOD_ERROR_KINDS as K}from"./telemetry/errorKinds.js";import{buildEgressBlockedEvent as U,buildFiredEvent as j,buildGateFailedEvent as q,buildGatePassedEvent as w,buildRejectedEvent as z,buildSucceededEvent as H,buildTimeoutEvent as J,estimateCostUsd as Q,FALLBACK_EVENTS as W,GATE_EVENTS as X,PARSE_GATE as Y,RUNTIME_GATE as Z,runFallback as $,shouldTryFallback as ee}from"./llmFallback/index.js";export{K as CODEMOD_ERROR_KINDS,h as CrossPlanConnectionResourcePlanSchema,W as FALLBACK_EVENTS,X as GATE_EVENTS,Y as PARSE_GATE,Z as RUNTIME_GATE,g as ResourceNameSchema,B as StatementTypeSchema,y as VpcPeerAccepterResourcePlanSchema,D as VpcPeerResourcePlanSchema,E as addCrossPlanConnection,o as addResource,a as addVpcPeer,l as addVpcPeerAccepter,U as buildEgressBlockedEvent,j as buildFiredEvent,q as buildGateFailedEvent,w as buildGatePassedEvent,z as buildRejectedEvent,H as buildSucceededEvent,J as buildTimeoutEvent,L as computeLinesDelta,F as detectDrift,Q as estimateCostUsd,A as listResources,G as mergeProperties,x as modifyCrossPlanConnection,p as modifyResource,n as modifyVpcPeer,f as modifyVpcPeerAccepter,b as parse,R as removeCrossPlanConnection,c as removeResource,d as removeVpcPeer,u as removeVpcPeerAccepter,C as resolveDriftPolicy,$ as runFallback,ee as shouldTryFallback,N as snapshotProperties};
@@ -0,0 +1,5 @@
1
+ import type { FallbackIntent } from "../types.js";
2
+ export declare const TEST_MODEL_ID = "claude-sonnet-4-6";
3
+ export declare const TEST_INTENT: FallbackIntent;
4
+ export declare const SAFE_CONTENT = "import { StorageFactory } from \"@fjall/components-infrastructure\";\n\nStorageFactory.build(\"Photos\", { versioned: true });\n";
5
+ export declare const MODIFIED_CONTENT = "import { StorageFactory } from \"@fjall/components-infrastructure\";\n\nStorageFactory.build(\"Photos\", { versioned: false });\n";
@@ -0,0 +1,7 @@
1
+ const o="claude-sonnet-4-6",t={op:"modify",type:"storage",name:"Photos",properties:{versioned:!1}},r=`import { StorageFactory } from "@fjall/components-infrastructure";
2
+
3
+ StorageFactory.build("Photos", { versioned: true });
4
+ `,e=`import { StorageFactory } from "@fjall/components-infrastructure";
5
+
6
+ StorageFactory.build("Photos", { versioned: false });
7
+ `;export{e as MODIFIED_CONTENT,r as SAFE_CONTENT,t as TEST_INTENT,o as TEST_MODEL_ID};
@@ -0,0 +1,10 @@
1
+ import { type Result } from "../../types/Result.js";
2
+ import type { StrReplaceOp, ApplyResult } from "./types.js";
3
+ interface ApplyError {
4
+ kind: "ambiguous-str-replace";
5
+ opIndex: number;
6
+ old_str: string;
7
+ matchCount: number;
8
+ }
9
+ export declare function applyStrReplaceOps(content: string, ops: readonly StrReplaceOp[]): Result<ApplyResult, ApplyError>;
10
+ export {};
@@ -0,0 +1 @@
1
+ import{success as l,failure as d}from"../../types/Result.js";function x(c,r){let e=c,n=0,o=0;for(let i=0;i<r.length;i+=1){const t=r[i];if(t===void 0)continue;const s=e.indexOf(t.old_str);if(s===-1){o+=1;continue}if(e.indexOf(t.old_str,s+1)!==-1)return d({kind:"ambiguous-str-replace",opIndex:i,old_str:t.old_str,matchCount:u(e,t.old_str)});e=e.slice(0,s)+t.new_str+e.slice(s+t.old_str.length),n+=1}return l({content:e,appliedCount:n,skippedCount:o})}function u(c,r){let e=0,n=0;for(;;){const o=c.indexOf(r,n);if(o===-1)break;e+=1,n=o+1}return e}export{x as applyStrReplaceOps};
@@ -0,0 +1,6 @@
1
+ import { type AnthropicClientProvider, type FallbackInput, type FallbackOutput } from "./types.js";
2
+ export declare const TEXT_EDITOR_TOOL: {
3
+ name: "str_replace_based_edit_tool";
4
+ type: "text_editor_20250728";
5
+ };
6
+ export declare function runClaudeTier(input: FallbackInput, client: AnthropicClientProvider): Promise<FallbackOutput>;
@@ -0,0 +1 @@
1
+ import{gateEgress as p}from"./egressGate.js";import{buildPrompt as y}from"./prompt.js";import{applyStrReplaceOps as k}from"./apply.js";import{withTierTimeout as E}from"./tierRunner.js";import{PARSE_GATE as u}from"./types.js";const b=3e4,o="claude",m={name:"str_replace_based_edit_tool",type:"text_editor_20250728"};async function S(t,s){if(!t.orgAllowsFallback)return{state:"disabled",reason:"org-opt-out"};const r=p(t.content,o);if(r!==void 0)return r;const e=p(JSON.stringify(t.intent.properties),o);if(e!==void 0)return e;const{systemPrompt:i,userPrompt:c}=y({content:t.content,intent:t.intent,tier:o});return E(t.abortSignal,o,b,async({signal:f,started:_})=>{const a=await s.create({model:s.resolveModelId(),max_tokens:4096,system:i,messages:[{role:"user",content:c}],tools:[m],signal:f}),g=Date.now()-_,d=w(a.content);if(d.length===0)return{state:"rejected",tier:o,failedGate:u,diagnostics:"Model produced no str_replace operations"};const n=k(t.content,d);if(!n.success)return{state:"rejected",tier:o,failedGate:u,diagnostics:`Ambiguous str_replace at op ${n.error.opIndex}: "${n.error.old_str.slice(0,40)}\u2026" matched ${n.error.matchCount} times`};const l=p(n.data.content,o);if(l!==void 0)return l;const T={tier:o,elapsedMs:g,inputTokens:a.usage?.input_tokens??0,outputTokens:a.usage?.output_tokens??0,opsApplied:n.data.appliedCount};return{state:"applied",content:n.data.content,telemetry:T}})}function w(t){const s=[];for(const r of t){if(r.type!=="tool_use"||r.name!==m.name)continue;const e=r.input;if(!("command"in e)||e.command!=="str_replace"||!("old_str"in e)||!("new_str"in e))continue;const i=e.old_str,c=e.new_str;typeof i!="string"||typeof c!="string"||s.push({old_str:i,new_str:c})}return s}export{m as TEXT_EDITOR_TOOL,S as runClaudeTier};
@@ -0,0 +1,5 @@
1
+ import type { LlmFallbackTier } from "../types.js";
2
+ import type { EgressGateResult } from "./egressGate.types.js";
3
+ import type { FallbackOutput } from "./types.js";
4
+ export declare function scanForEgressRisk(content: string): EgressGateResult;
5
+ export declare function gateEgress(content: string, tier: LlmFallbackTier): FallbackOutput | undefined;
@@ -0,0 +1 @@
1
+ const E=32,l=4.5,T=8,c=/\barn:aws:[a-z0-9-]+:[a-z0-9-]*:[0-9]*:[^\s"']+/g,a=/(?<![A-Za-z0-9+/=_-])[A-Za-z0-9+/=_-]{32,}(?![A-Za-z0-9+/=_-])/g;function _(t){if(t.length===0)return 0;const e=new Map;for(const o of t)e.set(o,(e.get(o)??0)+1);let n=0;for(const o of e.values()){const s=o/t.length;n-=s*Math.log2(s)}return n}function r(t){return t.length<=8?t:`${t.slice(0,8)}\u2026`}function H(t){const e=[...t.matchAll(c)];if(e.length>0){const o=e[0]?.[0]??"";return{state:"block",reason:"arn-shape",count:e.length,sampleHint:r(o)}}const n=[];for(const o of t.matchAll(a)){const s=o[0]??"";s.length>=32&&_(s)>=4.5&&n.push(s)}return n.length>0?{state:"block",reason:"high-entropy",count:n.length,sampleHint:r(n[0]??"")}:{state:"pass"}}function h(t,e){const n=H(t);if(n.state==="block")return{state:"egress-blocked",tier:e,reason:n.reason,count:n.count}}export{h as gateEgress,H as scanForEgressRisk};
@@ -0,0 +1,9 @@
1
+ export type EgressRiskReason = "high-entropy" | "arn-shape";
2
+ export type EgressGateResult = {
3
+ state: "pass";
4
+ } | {
5
+ state: "block";
6
+ reason: EgressRiskReason;
7
+ count: number;
8
+ sampleHint: string;
9
+ };
@@ -0,0 +1,6 @@
1
+ export { runFallback, type FallbackClients, type RunFallbackInput, } from "./runFallback.js";
2
+ export { shouldTryFallback, type FallbackDecision, type FallbackGuardConfig, } from "./shouldTryFallback.js";
3
+ export { buildEgressBlockedEvent, buildFiredEvent, buildGateFailedEvent, buildGatePassedEvent, buildRejectedEvent, buildSucceededEvent, buildTimeoutEvent, estimateCostUsd, FALLBACK_EVENTS, GATE_EVENTS, type FallbackEgressBlockedEvent, type FallbackFiredEvent, type FallbackRejectedEvent, type FallbackSucceededEvent, type FallbackTelemetryEvent, type FallbackTimeoutEvent, type GateFailedEvent, type GatePassedEvent, type TelemetrySource, } from "./telemetryEvents.js";
4
+ export { PARSE_GATE, RUNTIME_GATE } from "./types.js";
5
+ export type { AnthropicClientProvider, AnthropicContentBlock, AnthropicResponse, ApplyResult, FallbackInput, FallbackIntent, FallbackOp, FallbackOutput, FallbackTelemetry, MorphClientProvider, MorphResponse, StrReplaceOp, TriggerReason, } from "./types.js";
6
+ export type { EgressGateResult, EgressRiskReason } from "./egressGate.types.js";
@@ -0,0 +1 @@
1
+ import{runFallback as E}from"./runFallback.js";import{shouldTryFallback as l}from"./shouldTryFallback.js";import{buildEgressBlockedEvent as r,buildFiredEvent as i,buildGateFailedEvent as u,buildGatePassedEvent as a,buildRejectedEvent as b,buildSucceededEvent as n,buildTimeoutEvent as s,estimateCostUsd as T,FALLBACK_EVENTS as v,GATE_EVENTS as c}from"./telemetryEvents.js";import{PARSE_GATE as A,RUNTIME_GATE as F}from"./types.js";export{v as FALLBACK_EVENTS,c as GATE_EVENTS,A as PARSE_GATE,F as RUNTIME_GATE,r as buildEgressBlockedEvent,i as buildFiredEvent,u as buildGateFailedEvent,a as buildGatePassedEvent,b as buildRejectedEvent,n as buildSucceededEvent,s as buildTimeoutEvent,T as estimateCostUsd,E as runFallback,l as shouldTryFallback};
@@ -0,0 +1,2 @@
1
+ import { type FallbackInput, type FallbackOutput, type MorphClientProvider } from "./types.js";
2
+ export declare function runMorphTier(input: FallbackInput, client: MorphClientProvider): Promise<FallbackOutput>;
@@ -0,0 +1,3 @@
1
+ import{gateEgress as o}from"./egressGate.js";import{buildPrompt as g}from"./prompt.js";import{withTierTimeout as m}from"./tierRunner.js";import{PARSE_GATE as T}from"./types.js";const k=15e3,t="morph";async function M(e,r){if(!e.orgAllowsFallback)return{state:"disabled",reason:"org-opt-out"};if(!r.isAvailable())return{state:"disabled",reason:"env-flag"};const s=o(e.content,t);if(s!==void 0)return s;const i=o(JSON.stringify(e.intent.properties),t);if(i!==void 0)return i;const{systemPrompt:c,userPrompt:p}=g({content:e.content,intent:e.intent,tier:t});return m(e.abortSignal,t,k,async({signal:u,started:l})=>{const n=await r.apply({originalFile:e.content,update:`${c}
2
+
3
+ ${p}`,signal:u}),d=Date.now()-l;if(n.content===e.content)return{state:"rejected",tier:t,failedGate:T,diagnostics:"Morph returned unchanged content"};const a=o(n.content,t);if(a!==void 0)return a;const f={tier:t,elapsedMs:d,inputTokens:n.usage?.inputTokens??0,outputTokens:n.usage?.outputTokens??0,opsApplied:1};return{state:"applied",content:n.content,telemetry:f}})}export{M as runMorphTier};
@@ -0,0 +1,12 @@
1
+ import type { LlmFallbackTier } from "../types.js";
2
+ import type { FallbackIntent } from "./types.js";
3
+ export interface BuildPromptInput {
4
+ content: string;
5
+ intent: FallbackIntent;
6
+ tier: LlmFallbackTier;
7
+ }
8
+ export interface BuiltPrompt {
9
+ systemPrompt: string;
10
+ userPrompt: string;
11
+ }
12
+ export declare function buildPrompt(input: BuildPromptInput): BuiltPrompt;
@@ -0,0 +1,36 @@
1
+ import{z as c}from"zod";import{STATEMENT_REGISTRY as o}from"../registry.js";const l=[...new Set(Object.values(o).map(e=>e.factoryIdentifier))].join(", "),s=`You are a Fjall infrastructure code editor. You modify TypeScript infrastructure files that use the Fjall CDK factory pattern.
2
+
3
+ Each resource is declared as a factory call:
4
+ \`XFactory.build("ResourceName", { ...properties })\`
5
+
6
+ where X is one of: ${l}.
7
+
8
+ ## Rules
9
+
10
+ 1. Use ONLY the str_replace command to make changes. Never rewrite the entire file.
11
+ 2. Each str_replace must match EXACTLY ONE location in the file. If the old_str appears more than once, include enough surrounding context to make it unique.
12
+ 3. Preserve all existing imports. Do not remove or reorder import statements.
13
+ 4. Preserve the quote style used in the file (single or double quotes).
14
+ 5. Do not move resource declarations into conditional blocks, loops, or function bodies. All factory calls must remain at module top level.
15
+ 6. If you cannot produce a valid edit, respond with an empty tool_use \u2014 do not guess.
16
+ 7. Properties must conform to the schema provided below. Do not invent property names.`;function u(e){return e==="morph"?`${s}
17
+
18
+ You are operating as a fast-apply tier. Produce minimal, precise edits only.`:s}function p(e){const t=o[e.type].factoryIdentifier;switch(e.op){case"add":return`Add a new ${e.type} resource named "${e.name}" using ${t}.build("${e.name}", { ... }) with the properties specified below.`;case"remove":return`Remove the ${e.type} resource named "${e.name}" (the ${t}.build("${e.name}", ...) call and any directly related code). Preserve all other resources.`;case"modify":return`Modify the ${e.type} resource named "${e.name}" by updating its properties to match the values specified below. Keep properties not mentioned in the update unchanged.`;case"resolve-drift-merge":return`Resolve a drift conflict on the ${e.type} resource named "${e.name}". The resource has been edited manually since Fjall last wrote it, and the requested properties conflict with the manual edits. Merge the two sets of changes: apply the requested properties below while preserving any manual edits to OTHER properties not listed in the update. Use ${t}.build("${e.name}", { ... }) with the merged property set.`}}function d(e){const r=o[e.type],t=c.toJSONSchema(r.schemaFragment,{io:"input"});return`## Property Schema for ${e.type}
19
+
20
+ \`\`\`json
21
+ ${JSON.stringify(t,null,2)}
22
+ \`\`\``}function m(e){if(e.op==="remove")return"";const r=Object.fromEntries(Object.entries(e.properties).filter(([,t])=>t!==void 0));return Object.keys(r).length===0?"":`## Target Properties
23
+
24
+ \`\`\`json
25
+ ${JSON.stringify(r,null,2)}
26
+ \`\`\``}function y(e){const r=u(e.tier),t=p(e.intent),n=d(e.intent),i=m(e.intent),a=`## Task
27
+
28
+ ${t}
29
+
30
+ ${n}
31
+ ${i}
32
+ ## Current File
33
+
34
+ \`\`\`typescript
35
+ ${e.content}
36
+ \`\`\``.trim();return{systemPrompt:r,userPrompt:a}}export{y as buildPrompt};
@@ -0,0 +1,13 @@
1
+ import type { AnthropicClientProvider, FallbackInput, FallbackOutput, MorphClientProvider } from "./types.js";
2
+ export interface FallbackClients {
3
+ claude: AnthropicClientProvider;
4
+ morph?: MorphClientProvider;
5
+ }
6
+ export interface RunFallbackInput {
7
+ content: string;
8
+ intent: FallbackInput["intent"];
9
+ orgAllowsFallback: boolean;
10
+ morphTierEnabled: boolean;
11
+ abortSignal?: AbortSignal;
12
+ }
13
+ export declare function runFallback(input: RunFallbackInput, clients: FallbackClients): Promise<FallbackOutput>;
@@ -0,0 +1 @@
1
+ import{runClaudeTier as n}from"./claudeTier.js";import{runMorphTier as a}from"./morphTier.js";function o(r,e){return{content:r.content,intent:r.intent,tier:e,orgAllowsFallback:r.orgAllowsFallback,abortSignal:r.abortSignal}}async function u(r,e){const t=await n(o(r,"claude"),e.claude);return!(t.state==="rejected"||t.state==="timeout")||!r.morphTierEnabled||e.morph===void 0?t:a(o(r,"morph"),e.morph)}export{u as runFallback};
@@ -0,0 +1,13 @@
1
+ import type { CodemodError } from "../types.js";
2
+ import type { TriggerReason } from "./types.js";
3
+ export interface FallbackGuardConfig {
4
+ envEnabled: boolean;
5
+ orgAllowsFallback: boolean;
6
+ }
7
+ export type FallbackDecision = {
8
+ shouldTry: true;
9
+ trigger: TriggerReason;
10
+ } | {
11
+ shouldTry: false;
12
+ };
13
+ export declare function shouldTryFallback(error: CodemodError, config: FallbackGuardConfig): FallbackDecision;
@@ -0,0 +1 @@
1
+ const e={shouldTry:!1};function o(r,n){if(!n.envEnabled||!n.orgAllowsFallback)return e;const t=l(r);return t===void 0?e:{shouldTry:!0,trigger:t}}function l(r){switch(r.kind){case"TemplateLiteralNameError":return"template-literal-name";case"ResourceNotFoundError":return"resource-not-found";case"ControlFlowClassifierError":return r.reason==="anonymous-helper"?"control-flow-unclassifiable":void 0;case"DriftUnmergeableError":return"drift-unmergeable";default:return}}export{o as shouldTryFallback};
@@ -0,0 +1,4 @@
1
+ export declare function linkAbortSignals(outer: AbortSignal | undefined, controller: AbortController): {
2
+ signal: AbortSignal;
3
+ cleanup: () => void;
4
+ };
@@ -0,0 +1 @@
1
+ function e(a,n){if(a===void 0)return{signal:n.signal,cleanup:()=>{}};if(a.aborted)return n.abort(),{signal:n.signal,cleanup:()=>{}};const i=()=>n.abort();return a.addEventListener("abort",i,{once:!0}),{signal:n.signal,cleanup:()=>a.removeEventListener("abort",i)}}export{e as linkAbortSignals};