@fjall/generator 2.15.0 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/.minified CHANGED
@@ -1 +1 @@
1
- 138 files minified at 2026-06-12T02:44:59.912Z
1
+ 139 files minified at 2026-06-14T08:04:20.305Z
@@ -109,6 +109,14 @@ export declare function parseAndConvert(code: string): {
109
109
  } | undefined;
110
110
  } | undefined;
111
111
  retain?: boolean | undefined;
112
+ resourcePolicyStatements?: {
113
+ effect: "Allow" | "Deny";
114
+ principals: string[];
115
+ actions: string[];
116
+ sid?: string | undefined;
117
+ resources?: string[] | undefined;
118
+ conditions?: Record<string, Record<string, string | string[]>> | undefined;
119
+ }[] | undefined;
112
120
  stackPlacement?: "storage" | "compute" | "cdn" | undefined;
113
121
  variableName?: string | undefined;
114
122
  extraProperties?: {
@@ -1,5 +1,5 @@
1
1
  import { type RegionInfo } from "@fjall/util";
2
- export { AWS_REGIONS_METADATA, DEFAULT_REGION, getRegionInfo, regions, suggestRegionForTimezone, type RegionCode, type RegionInfo, } from "@fjall/util";
2
+ export { AWS_REGIONS_METADATA, DEFAULT_REGION, getRegionInfo, OPT_IN_REGION_CODES, optInRegionWarning, regions, suggestRegionForTimezone, type RegionCode, type RegionInfo, } from "@fjall/util";
3
3
  export declare const topRegions: readonly RegionInfo[];
4
4
  export declare const commonRegions: readonly ["us-east-2", "us-west-2", "us-east-1", "eu-west-1", "ap-southeast-1"];
5
5
  export declare function parseRegionList(value: string): string[];
@@ -1 +1 @@
1
- import{AWS_REGIONS_METADATA as s,getRegionInfo as f,regions as c}from"@fjall/util";import{AWS_REGIONS_METADATA as y,DEFAULT_REGION as S,getRegionInfo as $,regions as z,suggestRegionForTimezone as D}from"@fjall/util";const g=["us-east-2","us-west-2","us-east-1","eu-west-1","eu-central-1","ap-southeast-1"],O=Object.freeze(g.flatMap(t=>{const e=f(t);return e?[e]:[]})),u=Object.freeze(["us-east-2","us-west-2","us-east-1","eu-west-1","ap-southeast-1"]);function a(t){return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}function p(t){return c.includes(t)}function l(t){return/^[a-z]{2}-[a-z]+-[1-9]$/.test(t)}function R(t){if(!t)return u.slice(0,3);const e=t.toLowerCase().split("-"),n=e[0],o=e.length>1?e[1]:"";let r=[];return n&&o&&(r=c.filter(i=>i.startsWith(`${n}-${o}`))),r.length===0&&n&&(r=c.filter(i=>i.startsWith(`${n}-`))),r.length>0?r.slice(0,3):u.slice(0,3)}function d(t){if(p(t))return!0;const e=R(t);return l(t)?`Unknown region. Try: ${e.join(", ")}`:`Invalid format. Try: ${e.join(", ")}`}function A(t){if(!t||t.trim()==="")return!0;const e=a(t);for(const n of e){const o=d(n);if(o!==!0)return o}return!0}function x(t,e){return t.filter(n=>n!==e)}function E(){return s.map(t=>({label:t.city,value:t.code,description:t.code}))}function T(t){return s.filter(e=>e.code!==t).map(e=>({label:e.city,value:e.code,description:e.code}))}function h(t){const e=s.find(n=>n.code===t);return e?e.city:t}function I(t){return e=>{const n=a(e);return x(n,t)}}export{y as AWS_REGIONS_METADATA,S as DEFAULT_REGION,u as commonRegions,I as createRegionFormatter,x as filterDuplicateRegions,$ as getRegionInfo,h as getRegionName,E as getRegionOptions,T as getRegionOptionsExcluding,R as getSuggestions,p as isValidRegion,l as isValidRegionFormat,a as parseRegionList,z as regions,D as suggestRegionForTimezone,O as topRegions,d as validateRegion,A as validateRegionList};
1
+ import{AWS_REGIONS_METADATA as s,getRegionInfo as f,regions as u}from"@fjall/util";import{AWS_REGIONS_METADATA as $,DEFAULT_REGION as w,getRegionInfo as D,OPT_IN_REGION_CODES as y,optInRegionWarning as z,regions as G,suggestRegionForTimezone as L}from"@fjall/util";const p=["us-east-2","us-west-2","us-east-1","eu-west-1","eu-central-1","ap-southeast-1"],E=Object.freeze(p.flatMap(t=>{const e=f(t);return e?[e]:[]})),c=Object.freeze(["us-east-2","us-west-2","us-east-1","eu-west-1","ap-southeast-1"]);function g(t){return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}function l(t){return u.includes(t)}function R(t){return/^[a-z]{2}-[a-z]+-[1-9]$/.test(t)}function x(t){if(!t)return c.slice(0,3);const e=t.toLowerCase().split("-"),n=e[0],o=e.length>1?e[1]:"";let r=[];return n&&o&&(r=u.filter(i=>i.startsWith(`${n}-${o}`))),r.length===0&&n&&(r=u.filter(i=>i.startsWith(`${n}-`))),r.length>0?r.slice(0,3):c.slice(0,3)}function d(t){if(l(t))return!0;const e=x(t);return R(t)?`Unknown region. Try: ${e.join(", ")}`:`Invalid format. Try: ${e.join(", ")}`}function I(t){if(!t||t.trim()==="")return!0;const e=g(t);for(const n of e){const o=d(n);if(o!==!0)return o}return!0}function m(t,e){return t.filter(n=>n!==e)}function a(t){return{label:t.city,value:t.code,description:t.optIn?`${t.code} \u2014 opt-in required`:t.code}}function T(){return s.map(a)}function _(t){return s.filter(e=>e.code!==t).map(a)}function A(t){const e=s.find(n=>n.code===t);return e?e.city:t}function h(t){return e=>{const n=g(e);return m(n,t)}}export{$ as AWS_REGIONS_METADATA,w as DEFAULT_REGION,y as OPT_IN_REGION_CODES,c as commonRegions,h as createRegionFormatter,m as filterDuplicateRegions,D as getRegionInfo,A as getRegionName,T as getRegionOptions,_ as getRegionOptionsExcluding,x as getSuggestions,l as isValidRegion,R as isValidRegionFormat,z as optInRegionWarning,g as parseRegionList,G as regions,L as suggestRegionForTimezone,E as topRegions,d as validateRegion,I as validateRegionList};
@@ -7,6 +7,7 @@ export { addVpcPeerAccepter, modifyVpcPeerAccepter, removeVpcPeerAccepter, type
7
7
  export { addCrossPlanConnection, modifyCrossPlanConnection, removeCrossPlanConnection, type CrossPlanConnectionAddOptions, type CrossPlanConnectionModifyOptions, type CrossPlanConnectionOrchestratorSuccess, type CrossPlanConnectionRemoveOptions, } from "./edits/crossPlanConnection.js";
8
8
  export { resolveDriftPolicy, type DriftAction, type DriftDecision, } from "./edits/driftPolicy.js";
9
9
  export { listResources, type ListResourcesError } from "./listResources.js";
10
+ export { resolveConstructByLiteralProperty, type ConstructResolution, type ConstructResolutionFailureReason, type ResolveConstructQuery, type ResolvedConstruct, } from "./semanticIndex/index.js";
10
11
  export { parse } from "./fileRewriter/parse.js";
11
12
  export { CrossPlanConnectionResourcePlanSchema, VpcPeerAccepterResourcePlanSchema, VpcPeerResourcePlanSchema, } from "../schemas/index.js";
12
13
  export type { CrossPlanConnectionResourcePlan, VpcPeerAccepterResourcePlan, VpcPeerResourcePlan, } from "../schemas/index.js";
@@ -1 +1 @@
1
- import{addResource as o}from"./edits/addResource.js";import{removeResource as c}from"./edits/removeResource.js";import{modifyResource as m}from"./edits/modifyResource.js";import{appendAccountToStage as a}from"./edits/appendAccountToStage.js";import{addVpcPeer as d,modifyVpcPeer as i,removeVpcPeer as l}from"./edits/vpcPeer.js";import{addVpcPeerAccepter as u,modifyVpcPeerAccepter as P,removeVpcPeerAccepter as E}from"./edits/vpcPeerAccepter.js";import{addCrossPlanConnection as R,modifyCrossPlanConnection as v,removeCrossPlanConnection as S}from"./edits/crossPlanConnection.js";import{resolveDriftPolicy as C}from"./edits/driftPolicy.js";import{listResources as V}from"./listResources.js";import{parse as h}from"./fileRewriter/parse.js";import{CrossPlanConnectionResourcePlanSchema as D,VpcPeerAccepterResourcePlanSchema as _,VpcPeerResourcePlanSchema as F}from"../schemas/index.js";import{detectDrift as N,mergeProperties as g,snapshotProperties as k}from"./drift/index.js";import{computeLinesDelta as O}from"./_internal.js";import{ResourceNameSchema as I,StatementTypeSchema as K}from"./types.js";import{CODEMOD_ERROR_KINDS as U}from"./telemetry/errorKinds.js";import{buildEgressBlockedEvent as q,buildFiredEvent as w,buildGateFailedEvent as z,buildGatePassedEvent as H,buildRejectedEvent as J,buildSucceededEvent as Q,buildTimeoutEvent as W,estimateCostUsd as X,FALLBACK_EVENTS as Y,GATE_EVENTS as Z,PARSE_GATE as $,RUNTIME_GATE as ee,runFallback as re,shouldTryFallback as oe}from"./llmFallback/index.js";export{U as CODEMOD_ERROR_KINDS,D as CrossPlanConnectionResourcePlanSchema,Y as FALLBACK_EVENTS,Z as GATE_EVENTS,$ as PARSE_GATE,ee as RUNTIME_GATE,I as ResourceNameSchema,K as StatementTypeSchema,_ as VpcPeerAccepterResourcePlanSchema,F as VpcPeerResourcePlanSchema,R as addCrossPlanConnection,o as addResource,d as addVpcPeer,u as addVpcPeerAccepter,a as appendAccountToStage,q as buildEgressBlockedEvent,w as buildFiredEvent,z as buildGateFailedEvent,H as buildGatePassedEvent,J as buildRejectedEvent,Q as buildSucceededEvent,W as buildTimeoutEvent,O as computeLinesDelta,N as detectDrift,X as estimateCostUsd,V as listResources,g as mergeProperties,v as modifyCrossPlanConnection,m as modifyResource,i as modifyVpcPeer,P as modifyVpcPeerAccepter,h as parse,S as removeCrossPlanConnection,c as removeResource,l as removeVpcPeer,E as removeVpcPeerAccepter,C as resolveDriftPolicy,re as runFallback,oe as shouldTryFallback,k as snapshotProperties};
1
+ import{addResource as o}from"./edits/addResource.js";import{removeResource as c}from"./edits/removeResource.js";import{modifyResource as m}from"./edits/modifyResource.js";import{appendAccountToStage as a}from"./edits/appendAccountToStage.js";import{addVpcPeer as d,modifyVpcPeer as i,removeVpcPeer as l}from"./edits/vpcPeer.js";import{addVpcPeerAccepter as u,modifyVpcPeerAccepter as P,removeVpcPeerAccepter as E}from"./edits/vpcPeerAccepter.js";import{addCrossPlanConnection as R,modifyCrossPlanConnection as v,removeCrossPlanConnection as C}from"./edits/crossPlanConnection.js";import{resolveDriftPolicy as A}from"./edits/driftPolicy.js";import{listResources as V}from"./listResources.js";import{resolveConstructByLiteralProperty as y}from"./semanticIndex/index.js";import{parse as D}from"./fileRewriter/parse.js";import{CrossPlanConnectionResourcePlanSchema as F,VpcPeerAccepterResourcePlanSchema as G,VpcPeerResourcePlanSchema as N}from"../schemas/index.js";import{detectDrift as g,mergeProperties as k,snapshotProperties as B}from"./drift/index.js";import{computeLinesDelta as I}from"./_internal.js";import{ResourceNameSchema as M,StatementTypeSchema as U}from"./types.js";import{CODEMOD_ERROR_KINDS as q}from"./telemetry/errorKinds.js";import{buildEgressBlockedEvent as z,buildFiredEvent as H,buildGateFailedEvent as J,buildGatePassedEvent as Q,buildRejectedEvent as W,buildSucceededEvent as X,buildTimeoutEvent as Y,estimateCostUsd as Z,FALLBACK_EVENTS as $,GATE_EVENTS as ee,PARSE_GATE as re,RUNTIME_GATE as oe,runFallback as te,shouldTryFallback as ce}from"./llmFallback/index.js";export{q as CODEMOD_ERROR_KINDS,F as CrossPlanConnectionResourcePlanSchema,$ as FALLBACK_EVENTS,ee as GATE_EVENTS,re as PARSE_GATE,oe as RUNTIME_GATE,M as ResourceNameSchema,U as StatementTypeSchema,G as VpcPeerAccepterResourcePlanSchema,N as VpcPeerResourcePlanSchema,R as addCrossPlanConnection,o as addResource,d as addVpcPeer,u as addVpcPeerAccepter,a as appendAccountToStage,z as buildEgressBlockedEvent,H as buildFiredEvent,J as buildGateFailedEvent,Q as buildGatePassedEvent,W as buildRejectedEvent,X as buildSucceededEvent,Y as buildTimeoutEvent,I as computeLinesDelta,g as detectDrift,Z as estimateCostUsd,V as listResources,k as mergeProperties,v as modifyCrossPlanConnection,m as modifyResource,i as modifyVpcPeer,P as modifyVpcPeerAccepter,D as parse,C as removeCrossPlanConnection,c as removeResource,l as removeVpcPeer,E as removeVpcPeerAccepter,y as resolveConstructByLiteralProperty,A as resolveDriftPolicy,te as runFallback,ce as shouldTryFallback,B as snapshotProperties};
@@ -1,4 +1,5 @@
1
- export { locateByShape, locateAllShapes, type NodeLocation, type StatementType, type LocateByShapeError, } from "./locateByShape.js";
1
+ export { locateByShape, locateAllShapes, forEachFactoryMatch, type FactoryCallMatch, type NodeLocation, type StatementType, type LocateByShapeError, } from "./locateByShape.js";
2
+ export { resolveConstructByLiteralProperty, type ConstructResolution, type ConstructResolutionFailureReason, type ResolveConstructQuery, type ResolvedConstruct, } from "./resolveConstructByLiteralProperty.js";
2
3
  export { findReferences, type ReferenceLocation, type FindReferencesError, } from "./findReferences.js";
3
4
  export { getProject, resetProjectForTest } from "./projectCache.js";
4
5
  export { listImports, type ImportInfo, type ListImportsError, } from "./listImports.js";
@@ -1 +1 @@
1
- import{locateByShape as r,locateAllShapes as t}from"./locateByShape.js";import{findReferences as f}from"./findReferences.js";import{getProject as c,resetProjectForTest as l}from"./projectCache.js";import{listImports as a}from"./listImports.js";export{f as findReferences,c as getProject,a as listImports,t as locateAllShapes,r as locateByShape,l as resetProjectForTest};
1
+ import{locateByShape as o,locateAllShapes as t,forEachFactoryMatch as c}from"./locateByShape.js";import{resolveConstructByLiteralProperty as a}from"./resolveConstructByLiteralProperty.js";import{findReferences as s}from"./findReferences.js";import{getProject as m,resetProjectForTest as x}from"./projectCache.js";import{listImports as y}from"./listImports.js";export{s as findReferences,c as forEachFactoryMatch,m as getProject,y as listImports,t as locateAllShapes,o as locateByShape,x as resetProjectForTest,a as resolveConstructByLiteralProperty};
@@ -1,3 +1,4 @@
1
+ import { type CallExpression } from "ts-morph";
1
2
  import { type Result } from "../../types/Result.js";
2
3
  import type { NodeLocation, StatementType, TemplateLiteralNameError, SemanticQueryError } from "../types.js";
3
4
  export type { NodeLocation, StatementType } from "../types.js";
@@ -13,6 +14,16 @@ export declare function locateByShape(content: string, query: {
13
14
  type: StatementType;
14
15
  name: string;
15
16
  }, filePath?: string): Result<NodeLocation | undefined, LocateByShapeError>;
17
+ /**
18
+ * A `XFactory.build("Name", ...)` call whose name is a plain string
19
+ * literal. `nameStart`/`nameLength` anchor the name token (ADR §4(a)).
20
+ */
21
+ export interface FactoryCallMatch {
22
+ type: StatementType;
23
+ name: string;
24
+ nameStart: number;
25
+ nameLength: number;
26
+ }
16
27
  /**
17
28
  * Walks every call expression in the source and returns a
18
29
  * `NodeLocation & { type }` for each `XFactory.build("Name", ...)`
@@ -26,3 +37,15 @@ export declare function locateByShape(content: string, query: {
26
37
  export declare function locateAllShapes(content: string, filePath?: string): Result<Array<NodeLocation & {
27
38
  type: StatementType;
28
39
  }>, LocateByShapeError>;
40
+ /**
41
+ * Shared walk over every `XFactory.build("Name", ...)` call with a
42
+ * plain string-literal name. Invokes `onMatch(match, call)` for each —
43
+ * `match` carries the resolved name + token span, while `call` is the
44
+ * live ts-morph node so callers can read further arguments (e.g. the
45
+ * second-argument config object literal).
46
+ *
47
+ * Binding-pattern and type-space calls are skipped (parity with the
48
+ * `locateByShape` contract); the first template-literal name aborts the
49
+ * walk as a `TemplateLiteralNameError` failure.
50
+ */
51
+ export declare function forEachFactoryMatch(content: string, filePath: string, onMatch: (match: FactoryCallMatch, call: CallExpression) => void): Result<void, LocateByShapeError>;
@@ -1 +1 @@
1
- import{Node as s,SyntaxKind as a}from"ts-morph";import{failure as c,success as l}from"../../types/Result.js";import{DEFAULT_FILE_PATH as u}from"../_internal.js";import{findTypeByIdentifier as p}from"../registry.js";import{getProject as m}from"./projectCache.js";function b(n,t,e=u){const o=g(n,e);if(!o.success)return o;const r=o.data.find(i=>i.type===t.type&&i.symbolName===t.name);return l(r)}function g(n,t=u){let e;try{e=m().createSourceFile(t,n,{overwrite:!0})}catch(r){return c({kind:"SemanticQueryError",reason:"Failed to create source file",cause:r})}const o=[];try{e.forEachDescendant(r=>{if(!s.isCallExpression(r))return;const i=y(r);if(i!=="not-factory-call"&&i.kind!=="binding-pattern-declared"){if(i.kind==="template-literal-name")throw new f(r,i.type);o.push({filePath:t,start:i.nameStart,length:i.nameLength,symbolName:i.name,type:i.type})}})}catch(r){return r instanceof f?c(r.toError(t)):c({kind:"SemanticQueryError",reason:"forEachDescendant traversal failed",cause:r})}return l(o)}function y(n){const t=n.getExpression();if(!s.isPropertyAccessExpression(t))return"not-factory-call";const e=h(t);if(e===void 0||E(n))return"not-factory-call";if(S(n))return{kind:"binding-pattern-declared"};const r=n.getArguments()[0];return r===void 0?"not-factory-call":s.isTemplateExpression(r)||s.isNoSubstitutionTemplateLiteral(r)?{kind:"template-literal-name",type:e}:s.isStringLiteral(r)?{kind:"match",type:e,name:r.getLiteralValue(),nameStart:r.getStart(),nameLength:r.getWidth()}:"not-factory-call"}function h(n){const t=n.getExpression();if(s.isIdentifier(t)&&n.getName()==="build")return p(t.getText())}function E(n){let t=n.getParent();for(;t!==void 0;){const e=t.getKind();if(e===a.TypeReference||e===a.TypeQuery||e===a.TypeLiteral||e===a.TypeAliasDeclaration||e===a.InterfaceDeclaration||e===a.TypeParameter||e===a.PropertySignature||e===a.MethodSignature||e===a.JsxOpeningElement||e===a.JsxClosingElement||e===a.JsxSelfClosingElement||e===a.JsxAttribute)return!0;t=t.getParent()}return!1}function S(n){const t=n.getFirstAncestorByKind(a.VariableDeclaration);if(t===void 0)return!1;const o=t.getNameNode().getKind();return o===a.ObjectBindingPattern||o===a.ArrayBindingPattern}class f extends Error{call;type;constructor(t,e){super("Template-literal factory name detected"),this.call=t,this.type=e,this.name="TemplateLiteralMarker"}toError(t){const o=this.call.getArguments()[0]?.getStart()??this.call.getStart(),r=this.call.getSourceFile(),{line:i,column:d}=r.getLineAndColumnAtPos(o);return{kind:"TemplateLiteralNameError",file:t,line:i,column:d,suggestion:"Replace the template literal with a plain string literal so the resource name can be resolved statically."}}}export{g as locateAllShapes,b as locateByShape};
1
+ import{Node as s,SyntaxKind as i}from"ts-morph";import{failure as c,success as l}from"../../types/Result.js";import{DEFAULT_FILE_PATH as u}from"../_internal.js";import{findTypeByIdentifier as d}from"../registry.js";import{getProject as m}from"./projectCache.js";function b(n,r,t=u){const a=g(n,t);if(!a.success)return a;const e=a.data.find(o=>o.type===r.type&&o.symbolName===r.name);return l(e)}function g(n,r=u){const t=[],a=y(n,r,e=>{t.push({filePath:r,start:e.nameStart,length:e.nameLength,symbolName:e.name,type:e.type})});return a.success?l(t):a}function y(n,r,t){let a;try{a=m().createSourceFile(r,n,{overwrite:!0})}catch(e){return c({kind:"SemanticQueryError",reason:"Failed to create source file",cause:e})}try{a.forEachDescendant(e=>{if(!s.isCallExpression(e))return;const o=h(e);if(o!=="not-factory-call"&&o.kind!=="binding-pattern-declared"){if(o.kind==="template-literal-name")throw new f(e,o.type);t({type:o.type,name:o.name,nameStart:o.nameStart,nameLength:o.nameLength},e)}})}catch(e){return e instanceof f?c(e.toError(r)):c({kind:"SemanticQueryError",reason:"forEachDescendant traversal failed",cause:e})}return l(void 0)}function h(n){const r=n.getExpression();if(!s.isPropertyAccessExpression(r))return"not-factory-call";const t=S(r);if(t===void 0||E(n))return"not-factory-call";if(T(n))return{kind:"binding-pattern-declared"};const e=n.getArguments()[0];return e===void 0?"not-factory-call":s.isTemplateExpression(e)||s.isNoSubstitutionTemplateLiteral(e)?{kind:"template-literal-name",type:t}:s.isStringLiteral(e)?{kind:"match",type:t,name:e.getLiteralValue(),nameStart:e.getStart(),nameLength:e.getWidth()}:"not-factory-call"}function S(n){const r=n.getExpression();if(s.isIdentifier(r)&&n.getName()==="build")return d(r.getText())}function E(n){let r=n.getParent();for(;r!==void 0;){const t=r.getKind();if(t===i.TypeReference||t===i.TypeQuery||t===i.TypeLiteral||t===i.TypeAliasDeclaration||t===i.InterfaceDeclaration||t===i.TypeParameter||t===i.PropertySignature||t===i.MethodSignature||t===i.JsxOpeningElement||t===i.JsxClosingElement||t===i.JsxSelfClosingElement||t===i.JsxAttribute)return!0;r=r.getParent()}return!1}function T(n){const r=n.getFirstAncestorByKind(i.VariableDeclaration);if(r===void 0)return!1;const a=r.getNameNode().getKind();return a===i.ObjectBindingPattern||a===i.ArrayBindingPattern}class f extends Error{call;type;constructor(r,t){super("Template-literal factory name detected"),this.call=r,this.type=t,this.name="TemplateLiteralMarker"}toError(r){const a=this.call.getArguments()[0]?.getStart()??this.call.getStart(),e=this.call.getSourceFile(),{line:o,column:p}=e.getLineAndColumnAtPos(a);return{kind:"TemplateLiteralNameError",file:r,line:o,column:p,suggestion:"Replace the template literal with a plain string literal so the resource name can be resolved statically."}}}export{y as forEachFactoryMatch,g as locateAllShapes,b as locateByShape};
@@ -0,0 +1,48 @@
1
+ import { type Result } from "../../types/Result.js";
2
+ import type { StatementType } from "../types.js";
3
+ import { type LocateByShapeError } from "./locateByShape.js";
4
+ export type { LocateByShapeError } from "./locateByShape.js";
5
+ /**
6
+ * A `XFactory.build("constructId", …)` construct of a given statement type.
7
+ */
8
+ export interface ResolvedConstruct {
9
+ type: StatementType;
10
+ constructId: string;
11
+ filePath: string;
12
+ }
13
+ /**
14
+ * Why a literal-property resolution did not yield a single construct.
15
+ * - `no-literal-match`: no construct of the queried type carries the property
16
+ * as a string literal equal to `value`. `candidates` lists every construct
17
+ * of that type so the caller can report what it did find.
18
+ * - `ambiguous`: more than one construct's literal property equalled `value`.
19
+ * `candidates` lists the colliding constructs.
20
+ */
21
+ export type ConstructResolutionFailureReason = "no-literal-match" | "ambiguous";
22
+ export type ConstructResolution = {
23
+ resolved: true;
24
+ construct: ResolvedConstruct;
25
+ } | {
26
+ resolved: false;
27
+ reason: ConstructResolutionFailureReason;
28
+ candidates: ResolvedConstruct[];
29
+ };
30
+ export interface ResolveConstructQuery {
31
+ /** Restrict the search to constructs of this factory statement type. */
32
+ type: StatementType;
33
+ /** Config-object property whose literal value to match (e.g. `bucketName`). */
34
+ property: string;
35
+ /** The physical value to match against (e.g. the quarantined bucket name). */
36
+ value: string;
37
+ }
38
+ /**
39
+ * Resolves the construct id whose factory-call config object sets
40
+ * `query.property` to the string literal `query.value`.
41
+ *
42
+ * Returns `failure(...)` only for a genuine parse / semantic-query error or a
43
+ * template-literal factory name (the engine cannot statically locate those).
44
+ * A clean run that simply finds no unique match returns
45
+ * `success({ resolved: false, … })` — the caller decides whether to degrade to
46
+ * report-only.
47
+ */
48
+ export declare function resolveConstructByLiteralProperty(content: string, query: ResolveConstructQuery, filePath?: string): Result<ConstructResolution, LocateByShapeError>;
@@ -0,0 +1 @@
1
+ import{Node as s}from"ts-morph";import{success as u}from"../../types/Result.js";import{DEFAULT_FILE_PATH as p}from"../_internal.js";import{forEachFactoryMatch as g}from"./locateByShape.js";function A(i,n,t=p){const r=[],e=[],c=g(i,t,(o,l)=>{if(o.type!==n.type)return;const a={type:o.type,constructId:o.name,filePath:t};r.push(a);const f=m(l,n.property);f!==void 0&&f===n.value&&e.push(a)});if(!c.success)return c;const[d]=e;return e.length===1&&d!==void 0?u({resolved:!0,construct:d}):e.length===0?u({resolved:!1,reason:"no-literal-match",candidates:r}):u({resolved:!1,reason:"ambiguous",candidates:e})}function m(i,n){const t=i.getArguments()[1];if(t===void 0||!s.isObjectLiteralExpression(t))return;const r=t.getProperty(n);if(r===void 0||!s.isPropertyAssignment(r))return;const e=r.getInitializer();if(!(e===void 0||!s.isStringLiteral(e)))return e.getLiteralValue()}export{A as resolveConstructByLiteralProperty};
@@ -1,7 +1,7 @@
1
1
  export { normaliseError, getErrorMessage } from "./util/errorUtils.js";
2
2
  export { type Result, isSuccess, isFailure, success, failure, tryAsync, trySync, } from "./types/Result.js";
3
3
  export { VALIDATION_PATTERNS, VALIDATION_MESSAGES, parseRateExpression, type ValidationPatternKey, type ValidationMessageKey, } from "./validation/patterns.js";
4
- export { type RegionCode, type RegionInfo, DEFAULT_REGION, regions, AWS_REGIONS_METADATA, getRegionInfo, suggestRegionForTimezone, topRegions, commonRegions, parseRegionList, isValidRegion, isValidRegionFormat, getSuggestions, validateRegion, validateRegionList, filterDuplicateRegions, getRegionOptions, getRegionOptionsExcluding, getRegionName, createRegionFormatter, } from "./aws/regions.js";
4
+ export { type RegionCode, type RegionInfo, DEFAULT_REGION, regions, AWS_REGIONS_METADATA, getRegionInfo, OPT_IN_REGION_CODES, optInRegionWarning, suggestRegionForTimezone, topRegions, commonRegions, parseRegionList, isValidRegion, isValidRegionFormat, getSuggestions, validateRegion, validateRegionList, filterDuplicateRegions, getRegionOptions, getRegionOptionsExcluding, getRegionName, createRegionFormatter, } from "./aws/regions.js";
5
5
  export { GENERATOR_VERSION } from "./version.js";
6
6
  export * from "./schemas/index.js";
7
7
  export * from "./generation/index.js";
package/dist/src/index.js CHANGED
@@ -1 +1 @@
1
- import{normaliseError as r,getErrorMessage as i}from"./util/errorUtils.js";import{isSuccess as s,isFailure as g,success as n,failure as R,tryAsync as a,trySync as m}from"./types/Result.js";import{VALIDATION_PATTERNS as f,VALIDATION_MESSAGES as E,parseRateExpression as x}from"./validation/patterns.js";import{DEFAULT_REGION as c,regions as l,AWS_REGIONS_METADATA as S,getRegionInfo as T,suggestRegionForTimezone as u,topRegions as I,commonRegions as N,parseRegionList as O,isValidRegion as _,isValidRegionFormat as d,getSuggestions as D,validateRegion as F,validateRegionList as L,filterDuplicateRegions as V,getRegionOptions as y,getRegionOptionsExcluding as G,getRegionName as M,createRegionFormatter as v}from"./aws/regions.js";import{GENERATOR_VERSION as P}from"./version.js";export*from"./schemas/index.js";export*from"./generation/index.js";export*from"./presets/index.js";export*from"./ast/index.js";export*from"./planning/index.js";export*from"./dns/index.js";export{S as AWS_REGIONS_METADATA,c as DEFAULT_REGION,P as GENERATOR_VERSION,E as VALIDATION_MESSAGES,f as VALIDATION_PATTERNS,N as commonRegions,v as createRegionFormatter,R as failure,V as filterDuplicateRegions,i as getErrorMessage,T as getRegionInfo,M as getRegionName,y as getRegionOptions,G as getRegionOptionsExcluding,D as getSuggestions,g as isFailure,s as isSuccess,_ as isValidRegion,d as isValidRegionFormat,r as normaliseError,x as parseRateExpression,O as parseRegionList,l as regions,n as success,u as suggestRegionForTimezone,I as topRegions,a as tryAsync,m as trySync,F as validateRegion,L as validateRegionList};
1
+ import{normaliseError as r,getErrorMessage as i}from"./util/errorUtils.js";import{isSuccess as n,isFailure as g,success as s,failure as R,tryAsync as a,trySync as p}from"./types/Result.js";import{VALIDATION_PATTERNS as E,VALIDATION_MESSAGES as f,parseRateExpression as x}from"./validation/patterns.js";import{DEFAULT_REGION as I,regions as O,AWS_REGIONS_METADATA as S,getRegionInfo as c,OPT_IN_REGION_CODES as l,optInRegionWarning as N,suggestRegionForTimezone as T,topRegions as _,commonRegions as u,parseRegionList as D,isValidRegion as d,isValidRegionFormat as F,getSuggestions as G,validateRegion as L,validateRegionList as V,filterDuplicateRegions as y,getRegionOptions as M,getRegionOptionsExcluding as v,getRegionName as P,createRegionFormatter as W}from"./aws/regions.js";import{GENERATOR_VERSION as C}from"./version.js";export*from"./schemas/index.js";export*from"./generation/index.js";export*from"./presets/index.js";export*from"./ast/index.js";export*from"./planning/index.js";export*from"./dns/index.js";export{S as AWS_REGIONS_METADATA,I as DEFAULT_REGION,C as GENERATOR_VERSION,l as OPT_IN_REGION_CODES,f as VALIDATION_MESSAGES,E as VALIDATION_PATTERNS,u as commonRegions,W as createRegionFormatter,R as failure,y as filterDuplicateRegions,i as getErrorMessage,c as getRegionInfo,P as getRegionName,M as getRegionOptions,v as getRegionOptionsExcluding,G as getSuggestions,g as isFailure,n as isSuccess,d as isValidRegion,F as isValidRegionFormat,r as normaliseError,N as optInRegionWarning,x as parseRateExpression,D as parseRegionList,O as regions,s as success,T as suggestRegionForTimezone,_ as topRegions,a as tryAsync,p as trySync,L as validateRegion,V as validateRegionList};
@@ -465,6 +465,17 @@ export declare const ApplicationResourcePlanSchema: z.ZodObject<{
465
465
  }, z.core.$strict>>;
466
466
  }, z.core.$strict>>;
467
467
  retain: z.ZodOptional<z.ZodBoolean>;
468
+ resourcePolicyStatements: z.ZodOptional<z.ZodArray<z.ZodObject<{
469
+ sid: z.ZodOptional<z.ZodString>;
470
+ effect: z.ZodEnum<{
471
+ Allow: "Allow";
472
+ Deny: "Deny";
473
+ }>;
474
+ principals: z.ZodArray<z.ZodString>;
475
+ actions: z.ZodArray<z.ZodString>;
476
+ resources: z.ZodOptional<z.ZodArray<z.ZodString>>;
477
+ conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
478
+ }, z.core.$strict>>>;
468
479
  stackPlacement: z.ZodOptional<z.ZodEnum<{
469
480
  storage: "storage";
470
481
  compute: "compute";
@@ -6,6 +6,25 @@ import { z } from "zod";
6
6
  * - "compute": Created in Compute stack for Lambda-consumed buckets
7
7
  */
8
8
  export declare const S3_STACK_PLACEMENTS: readonly ["storage", "cdn", "compute"];
9
+ /**
10
+ * A declarative bucket-policy statement. Mirrors the `ResourcePolicyStatement`
11
+ * interface on the `S3Bucket` construct in `@fjall/components-infrastructure` —
12
+ * the two shapes must move together. The codemod sets this as a typed prop on an
13
+ * existing `StorageFactory.build("Name", { … })` call; the construct turns each
14
+ * entry into an `addToResourcePolicy` call at synth.
15
+ */
16
+ export declare const ResourcePolicyStatementSchema: z.ZodObject<{
17
+ sid: z.ZodOptional<z.ZodString>;
18
+ effect: z.ZodEnum<{
19
+ Allow: "Allow";
20
+ Deny: "Deny";
21
+ }>;
22
+ principals: z.ZodArray<z.ZodString>;
23
+ actions: z.ZodArray<z.ZodString>;
24
+ resources: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
26
+ }, z.core.$strict>;
27
+ export type ResourcePolicyStatement = z.infer<typeof ResourcePolicyStatementSchema>;
9
28
  export declare const S3ResourcePlanSchema: z.ZodObject<{
10
29
  name: z.ZodString;
11
30
  bucketName: z.ZodOptional<z.ZodString>;
@@ -41,6 +60,17 @@ export declare const S3ResourcePlanSchema: z.ZodObject<{
41
60
  }, z.core.$strict>>;
42
61
  }, z.core.$strict>>;
43
62
  retain: z.ZodOptional<z.ZodBoolean>;
63
+ resourcePolicyStatements: z.ZodOptional<z.ZodArray<z.ZodObject<{
64
+ sid: z.ZodOptional<z.ZodString>;
65
+ effect: z.ZodEnum<{
66
+ Allow: "Allow";
67
+ Deny: "Deny";
68
+ }>;
69
+ principals: z.ZodArray<z.ZodString>;
70
+ actions: z.ZodArray<z.ZodString>;
71
+ resources: z.ZodOptional<z.ZodArray<z.ZodString>>;
72
+ conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
73
+ }, z.core.$strict>>>;
44
74
  stackPlacement: z.ZodOptional<z.ZodEnum<{
45
75
  storage: "storage";
46
76
  compute: "compute";
@@ -1 +1 @@
1
- import{z as o}from"zod";import{VALIDATION_MESSAGES as t}from"../validation/patterns.js";import{BACKUP_VAULT_TIERS as n,S3_ENCRYPTION_TYPES as a,STORAGE_PRESET_TYPES as r}from"./constants.js";import{ResourceNameSchema as i,BucketNameSchema as s,AppNameSchema as l,ExtraPropertySchema as p}from"./baseSchemas.js";const c=["storage","cdn","compute"],y=o.object({name:i,bucketName:o.string().optional(),publicReadAccess:o.boolean().optional(),websiteHosting:o.object({indexDocument:o.string(),errorDocument:o.string().optional()}).strict().optional(),backupVaultTier:o.enum(n).optional(),versioned:o.boolean().optional(),encryption:o.enum(a).optional(),kmsKeyArn:o.string().optional(),cors:o.array(o.object({allowedOrigins:o.array(o.string()),allowedMethods:o.array(o.string()),allowedHeaders:o.array(o.string()).optional(),exposedHeaders:o.array(o.string()).optional(),maxAge:o.number().optional()}).strict()).optional(),deployment:o.object({source:o.string(),prune:o.boolean().optional(),cacheControl:o.object({maxAge:o.number().optional(),immutable:o.boolean().optional()}).strict().optional()}).strict().optional(),retain:o.boolean().optional(),stackPlacement:o.enum(c).optional(),variableName:o.string().optional(),extraProperties:o.array(p).optional()}).strict().refine(e=>e.encryption!=="KMS"||!!e.kmsKeyArn,{message:t.KMS.KEY_REQUIRED}),S=o.object({appName:l,bucketName:s,nameProvidedByFlag:o.boolean().optional(),storagePreset:o.enum(r).optional(),publicReadAccess:o.boolean().optional(),websiteHosting:o.object({indexDocument:o.string(),errorDocument:o.string().optional()}).strict().optional(),backupVaultTier:o.enum(n).optional(),versioned:o.boolean().optional(),encryption:o.enum(a).optional(),kmsKeyArn:o.string().optional(),cors:o.array(o.object({allowedOrigins:o.array(o.string()),allowedMethods:o.array(o.string()),allowedHeaders:o.array(o.string()).optional(),exposedHeaders:o.array(o.string()).optional(),maxAge:o.number().optional()}).strict()).optional(),connectionConfig:o.object({connectToCompute:o.array(o.string()).optional(),connectToServices:o.array(o.string()).optional()}).strict().optional()}).strict().refine(e=>e.encryption!=="KMS"||!!e.kmsKeyArn,{message:t.KMS.KEY_REQUIRED,path:["kmsKeyArn"]});export{S as S3GeneratorSchema,y as S3ResourcePlanSchema,c as S3_STACK_PLACEMENTS};
1
+ import{z as o}from"zod";import{VALIDATION_MESSAGES as t}from"../validation/patterns.js";import{BACKUP_VAULT_TIERS as r,S3_ENCRYPTION_TYPES as n,STORAGE_PRESET_TYPES as a}from"./constants.js";import{ResourceNameSchema as i,BucketNameSchema as s,AppNameSchema as c,ExtraPropertySchema as l}from"./baseSchemas.js";const p=["storage","cdn","compute"],m=o.object({sid:o.string().optional(),effect:o.enum(["Allow","Deny"]),principals:o.array(o.string()),actions:o.array(o.string()),resources:o.array(o.string()).optional(),conditions:o.record(o.string(),o.record(o.string(),o.union([o.string(),o.array(o.string())]))).optional()}).strict(),S=o.object({name:i,bucketName:o.string().optional(),publicReadAccess:o.boolean().optional(),websiteHosting:o.object({indexDocument:o.string(),errorDocument:o.string().optional()}).strict().optional(),backupVaultTier:o.enum(r).optional(),versioned:o.boolean().optional(),encryption:o.enum(n).optional(),kmsKeyArn:o.string().optional(),cors:o.array(o.object({allowedOrigins:o.array(o.string()),allowedMethods:o.array(o.string()),allowedHeaders:o.array(o.string()).optional(),exposedHeaders:o.array(o.string()).optional(),maxAge:o.number().optional()}).strict()).optional(),deployment:o.object({source:o.string(),prune:o.boolean().optional(),cacheControl:o.object({maxAge:o.number().optional(),immutable:o.boolean().optional()}).strict().optional()}).strict().optional(),retain:o.boolean().optional(),resourcePolicyStatements:o.array(m).optional(),stackPlacement:o.enum(p).optional(),variableName:o.string().optional(),extraProperties:o.array(l).optional()}).strict().refine(e=>e.encryption!=="KMS"||!!e.kmsKeyArn,{message:t.KMS.KEY_REQUIRED}),d=o.object({appName:c,bucketName:s,nameProvidedByFlag:o.boolean().optional(),storagePreset:o.enum(a).optional(),publicReadAccess:o.boolean().optional(),websiteHosting:o.object({indexDocument:o.string(),errorDocument:o.string().optional()}).strict().optional(),backupVaultTier:o.enum(r).optional(),versioned:o.boolean().optional(),encryption:o.enum(n).optional(),kmsKeyArn:o.string().optional(),cors:o.array(o.object({allowedOrigins:o.array(o.string()),allowedMethods:o.array(o.string()),allowedHeaders:o.array(o.string()).optional(),exposedHeaders:o.array(o.string()).optional(),maxAge:o.number().optional()}).strict()).optional(),connectionConfig:o.object({connectToCompute:o.array(o.string()).optional(),connectToServices:o.array(o.string()).optional()}).strict().optional()}).strict().refine(e=>e.encryption!=="KMS"||!!e.kmsKeyArn,{message:t.KMS.KEY_REQUIRED,path:["kmsKeyArn"]});export{m as ResourcePolicyStatementSchema,d as S3GeneratorSchema,S as S3ResourcePlanSchema,p as S3_STACK_PLACEMENTS};
@@ -1 +1 @@
1
- export declare const GENERATOR_VERSION = "2.14.0";
1
+ export declare const GENERATOR_VERSION = "2.15.0";
@@ -1 +1 @@
1
- const E="2.14.0";export{E as GENERATOR_VERSION};
1
+ const E="2.15.0";export{E as GENERATOR_VERSION};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/generator",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "Pure infrastructure generation logic for Fjall",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "license": "SEE LICENSE IN LICENSE",
45
45
  "dependencies": {
46
- "@fjall/util": "^2.15.0",
46
+ "@fjall/util": "^2.16.0",
47
47
  "ast-types": "^0.16.1",
48
48
  "recast": "^0.23.11",
49
49
  "ts-morph": "^28.0.0",
@@ -59,5 +59,5 @@
59
59
  "typescript-eslint": "^8.59.1",
60
60
  "vitest": "^4.1.5"
61
61
  },
62
- "gitHead": "b2223855907cb6d467e47df073b2a5b28c684ede"
62
+ "gitHead": "2383b19f1e7db980ae603a6c75dca2c61b7a1d42"
63
63
  }