@fjall/util 2.27.0 → 2.29.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
- 77 files minified at 2026-07-07T01:04:04.313Z
1
+ 79 files minified at 2026-07-13T22:21:40.141Z
@@ -1,4 +1,5 @@
1
1
  import { type ResourceEvent } from "./cloudformationTypes.js";
2
+ import { type DriftSuspectEvent } from "./driftSuspects.js";
2
3
  export interface RootCause {
3
4
  resource: ResourceEvent;
4
5
  reason: string;
@@ -12,6 +13,13 @@ export interface FailureAnalysis {
12
13
  summary: string;
13
14
  remediation: string[];
14
15
  errorPattern?: string;
16
+ /**
17
+ * Resources whose failure carries the out-of-band-deletion shape (Class 1
18
+ * drift): CloudFormation still tracks them but the service reported
19
+ * NotFound. Suspects only — confirmation requires the deploy-core drift
20
+ * probe. Absent when no failure event matches the NotFound anchors.
21
+ */
22
+ driftSuspects?: DriftSuspectEvent[];
15
23
  }
16
24
  /**
17
25
  * CloudFormationFailureAnalyser provides intelligent analysis of deployment failures
@@ -19,7 +27,25 @@ export interface FailureAnalysis {
19
27
  */
20
28
  export declare class CloudFormationFailureAnalyser {
21
29
  private knownErrorPatterns;
22
- analyseFailure(eventHistory: Map<string, ResourceEvent[]>): FailureAnalysis | null;
30
+ /**
31
+ * `stackName` opts the drift scan into current-operation bounding: the
32
+ * monitor's event history is seeded with the stack's FULL retained event
33
+ * history (~90 days), so an unbounded scan would resurrect suspects from
34
+ * long-past operations that were since cured. Callers whose history is
35
+ * already operation-scoped (callback-fed collections) omit it.
36
+ */
37
+ analyseFailure(eventHistory: Map<string, ResourceEvent[]>, stackName?: string): FailureAnalysis | null;
38
+ /**
39
+ * Scans EVERY failed event, not failedResources: a wedged resource's
40
+ * UPDATE_FAILED is superseded by its rollback event, so latest-per-resource
41
+ * semantics would drop exactly the wedge. When `stackName` is given, the
42
+ * scan is bounded to events at/after the current operation's opening event;
43
+ * if no opening event is visible the scan yields nothing rather than risk
44
+ * classifying a stale prior-operation failure (fail-safe: a missed hint is
45
+ * recoverable via `fjall drift detect`, a stale suspect self-reinforces
46
+ * through the journal).
47
+ */
48
+ private classifyDriftSuspects;
23
49
  private findFailedResources;
24
50
  private findRootCause;
25
51
  private categoriseError;
@@ -1 +1 @@
1
- class a{knownErrorPatterns=[{pattern:/AccessDenied|UnauthorizedOperation|Forbidden/i,category:"permissions",remediation:["Check IAM permissions for the deployment role","Ensure the role has necessary CloudFormation permissions","Verify service-linked roles are created if needed"]},{pattern:/Invalid.*Parameter|ValidationError|Invalid.*Value/i,category:"validation",remediation:["Review parameter values in your CDK code","Check for typos in resource names or ARNs","Ensure all required parameters are provided"]},{pattern:/Limit.*Exceeded|Quota.*Exceeded|Maximum.*reached/i,category:"limit",remediation:["Check AWS service quotas in the Service Quotas console","Request a quota increase if needed","Consider using a different region with available capacity"]},{pattern:/Timeout|Connection.*refused|Network.*unreachable/i,category:"network",remediation:["Check network connectivity and VPC settings","Verify security groups and NACLs","Ensure endpoints are accessible"]},{pattern:/already exists|Duplicate|ConflictException/i,category:"validation",remediation:["Resource with this name already exists","Consider using a different name or deleting the existing resource","Check if you are deploying to the correct account/region"]},{pattern:/Role.*not.*found|Role.*does.*not.*exist/i,category:"dependency",remediation:["Ensure IAM roles are created before dependent resources","Check role names and ARNs are correct","Verify cross-stack references are properly configured"]}];analyseFailure(e){const r=this.findFailedResources(e);if(r.length===0)return null;const s=this.findRootCause(r,e),n=this.buildDependencyChain(s.resource,r),i=this.generateRemediation(s),t=this.generateSummary(s,r);return{rootCause:s,affectedResources:r,dependencyChain:n,summary:t,remediation:i,errorPattern:s.category}}findFailedResources(e){const r=[];for(const[s,n]of e){const i=n[n.length-1];i&&this.isFailedStatus(i.status)&&r.push(i)}return r.sort((s,n)=>s.timestamp.getTime()-n.timestamp.getTime())}findRootCause(e,r){if(e.length===0)return{resource:{logicalId:"Unknown",resourceType:"Unknown",status:"FAILED",timestamp:new Date},reason:"No failed resources found",category:"unknown",isDirectCause:!1};const s=e[0],n=this.categoriseError(s.statusReason||""),i=this.isDirectCause(s,r);return{resource:s,reason:s.statusReason||"Unknown error",category:n,isDirectCause:i}}categoriseError(e){for(const r of this.knownErrorPatterns)if(r.pattern.test(e))return r.category;return"unknown"}isDirectCause(e,r){const s=e.statusReason||"";return s.includes("depends on")||s.includes("referenced by")||s.includes("required by")?!1:!(r.get(e.logicalId)||[]).some(t=>t.status.includes("COMPLETE")&&!t.status.includes("ROLLBACK"))}buildDependencyChain(e,r){const s=[];s.push(`${e.logicalId} (${e.resourceType}) - ROOT CAUSE`);for(const n of r)n.logicalId!==e.logicalId&&((n.statusReason||"").toLowerCase().includes(e.logicalId.toLowerCase())?s.push(` \u2192 ${n.logicalId} (${n.resourceType}) - Failed due to ${e.logicalId}`):s.push(` \u2192 ${n.logicalId} (${n.resourceType})`));return s}generateRemediation(e){const r=[];for(const s of this.knownErrorPatterns)if(s.category===e.category){r.push(...s.remediation);break}return e.resource.resourceType.includes("IAM")?r.push("Review IAM policies and trust relationships"):e.resource.resourceType.includes("Lambda")?r.push("Check Lambda function configuration and runtime"):e.resource.resourceType.includes("ECS")&&r.push("Verify ECS task definition and container configuration"),r.length===0&&r.push("Review the CloudFormation console for detailed error messages","Check the resource configuration in your CDK code","Ensure all dependencies are properly defined"),r}generateSummary(e,r){const s=this.simplifyResourceType(e.resource.resourceType),n=r.length;let i=`Deployment failed: ${s} "${e.resource.logicalId}" `;switch(e.category){case"permissions":i+="failed due to insufficient permissions";break;case"validation":i+="failed validation";break;case"dependency":i+="has missing or invalid dependencies";break;case"limit":i+="exceeded AWS service limits";break;case"network":i+="encountered network issues";break;default:i+="failed to create"}return n>1&&(i+=` (${n-1} dependent resources also failed)`),i}simplifyResourceType(e){return e.replace("AWS::","").replace("::"," ")}isFailedStatus(e){return e.includes("FAILED")}}export{a as CloudFormationFailureAnalyser};
1
+ import{classifyDriftSuspectEvents as c,findCurrentOperationStart as d}from"./driftSuspects.js";class f{knownErrorPatterns=[{pattern:/AccessDenied|UnauthorizedOperation|Forbidden/i,category:"permissions",remediation:["Check IAM permissions for the deployment role","Ensure the role has necessary CloudFormation permissions","Verify service-linked roles are created if needed"]},{pattern:/Invalid.*Parameter|ValidationError|Invalid.*Value/i,category:"validation",remediation:["Review parameter values in your CDK code","Check for typos in resource names or ARNs","Ensure all required parameters are provided"]},{pattern:/Limit.*Exceeded|Quota.*Exceeded|Maximum.*reached/i,category:"limit",remediation:["Check AWS service quotas in the Service Quotas console","Request a quota increase if needed","Consider using a different region with available capacity"]},{pattern:/Timeout|Connection.*refused|Network.*unreachable/i,category:"network",remediation:["Check network connectivity and VPC settings","Verify security groups and NACLs","Ensure endpoints are accessible"]},{pattern:/already exists|Duplicate|ConflictException/i,category:"validation",remediation:["Resource with this name already exists","Consider using a different name or deleting the existing resource","Check if you are deploying to the correct account/region"]},{pattern:/Role.*not.*found|Role.*does.*not.*exist/i,category:"dependency",remediation:["Ensure IAM roles are created before dependent resources","Check role names and ARNs are correct","Verify cross-stack references are properly configured"]}];analyseFailure(e,t){const r=this.findFailedResources(e);if(r.length===0)return null;const s=this.findRootCause(r,e),n=this.buildDependencyChain(s.resource,r),i=this.classifyDriftSuspects(e,t),o=this.generateRemediation(s);i.length>0&&o.unshift("One or more resources CloudFormation still tracks appear to have been deleted outside CloudFormation","Run 'fjall drift detect' to confirm the deletion; confirmed deletions are remediated with 'fjall drift repair'");const a=this.generateSummary(s,r);return{rootCause:s,affectedResources:r,dependencyChain:n,summary:a,remediation:o,errorPattern:s.category,...i.length>0?{driftSuspects:i}:{}}}classifyDriftSuspects(e,t){const r=t!==void 0?d(e.get(t)??[],t):null;if(t!==void 0&&r===null)return[];const s=[];for(const n of e.values())for(const i of n)this.isFailedStatus(i.status)&&(r!==null&&i.timestamp.getTime()<r.getTime()||s.push(i));return c(s)}findFailedResources(e){const t=[];for(const[r,s]of e){const n=s[s.length-1];n&&this.isFailedStatus(n.status)&&t.push(n)}return t.sort((r,s)=>r.timestamp.getTime()-s.timestamp.getTime())}findRootCause(e,t){if(e.length===0)return{resource:{logicalId:"Unknown",resourceType:"Unknown",status:"FAILED",timestamp:new Date},reason:"No failed resources found",category:"unknown",isDirectCause:!1};const r=e[0],s=this.categoriseError(r.statusReason||""),n=this.isDirectCause(r,t);return{resource:r,reason:r.statusReason||"Unknown error",category:s,isDirectCause:n}}categoriseError(e){for(const t of this.knownErrorPatterns)if(t.pattern.test(e))return t.category;return"unknown"}isDirectCause(e,t){const r=e.statusReason||"";return r.includes("depends on")||r.includes("referenced by")||r.includes("required by")?!1:!(t.get(e.logicalId)||[]).some(i=>i.status.includes("COMPLETE")&&!i.status.includes("ROLLBACK"))}buildDependencyChain(e,t){const r=[];r.push(`${e.logicalId} (${e.resourceType}) - ROOT CAUSE`);for(const s of t)s.logicalId!==e.logicalId&&((s.statusReason||"").toLowerCase().includes(e.logicalId.toLowerCase())?r.push(` \u2192 ${s.logicalId} (${s.resourceType}) - Failed due to ${e.logicalId}`):r.push(` \u2192 ${s.logicalId} (${s.resourceType})`));return r}generateRemediation(e){const t=[];for(const r of this.knownErrorPatterns)if(r.category===e.category){t.push(...r.remediation);break}return e.resource.resourceType.includes("IAM")?t.push("Review IAM policies and trust relationships"):e.resource.resourceType.includes("Lambda")?t.push("Check Lambda function configuration and runtime"):e.resource.resourceType.includes("ECS")&&t.push("Verify ECS task definition and container configuration"),t.length===0&&t.push("Review the CloudFormation console for detailed error messages","Check the resource configuration in your CDK code","Ensure all dependencies are properly defined"),t}generateSummary(e,t){const r=this.simplifyResourceType(e.resource.resourceType),s=t.length;let n=`Deployment failed: ${r} "${e.resource.logicalId}" `;switch(e.category){case"permissions":n+="failed due to insufficient permissions";break;case"validation":n+="failed validation";break;case"dependency":n+="has missing or invalid dependencies";break;case"limit":n+="exceeded AWS service limits";break;case"network":n+="encountered network issues";break;default:n+="failed to create"}return s>1&&(n+=` (${s-1} dependent resources also failed)`),n}simplifyResourceType(e){return e.replace("AWS::","").replace("::"," ")}isFailedStatus(e){return e.includes("FAILED")}}export{f as CloudFormationFailureAnalyser};
@@ -13,5 +13,11 @@ export interface ResourceEvent {
13
13
  group?: string;
14
14
  /** CDK construct path (e.g., "/Account/CloudTrail/trail/Resource"). */
15
15
  constructPath?: string;
16
+ /**
17
+ * CloudFormation ClientRequestToken for the operation that emitted this event
18
+ * (§5.9 capture-not-stamp). Lets a reconciler correlate an orphaned CFN
19
+ * operation back to its deployment row. Absent on synthetic/initial events.
20
+ */
21
+ clientRequestToken?: string;
16
22
  }
17
23
  export declare function isResourceEvent(event: unknown): event is ResourceEvent;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Class 1 drift classification — out-of-band deletion suspects.
3
+ *
4
+ * A resource CloudFormation still tracks but which was deleted outside
5
+ * CloudFormation wedges every subsequent update: the service handler returns
6
+ * NotFound and the stack rolls back (the BusinessContinuity CMK incident,
7
+ * account 913524923178). The patterns here are derived from the Phase 0
8
+ * empirical fixtures (`fjall/deploy-core/src/orchestration/drift/__tests__/
9
+ * fixtures/bc-stack-events.json`, captured 2026-07-07): the stable anchors are
10
+ * the registry handler contract marker `HandlerErrorCode: NotFound` and the
11
+ * service message shape `does not exist (Service: …`.
12
+ *
13
+ * Classification is SUSPECTS ONLY — never a confirmed verdict. Confirmation
14
+ * requires a direct per-type probe (deploy-core `driftProbe.ts`); a suspect
15
+ * that cannot be probed stays UNCONFIRMED and remediation is refused
16
+ * (fail-closed: never surgery on a resource not proven dead).
17
+ */
18
+ import type { ResourceEvent } from "./cloudformationTypes.js";
19
+ /**
20
+ * A resource whose failure event carries the out-of-band-deletion shape.
21
+ * `statusReason` is raw here — the analyser's `maskFailureAnalysis` boundary
22
+ * (or the sink) masks before display/persistence.
23
+ */
24
+ export interface DriftSuspectEvent {
25
+ logicalId: string;
26
+ resourceType: string;
27
+ physicalId?: string;
28
+ /** The failed status that carried the NotFound shape (e.g. UPDATE_FAILED). */
29
+ failedStatus: string;
30
+ statusReason: string;
31
+ }
32
+ /** True when a failure reason carries the out-of-band-deletion shape. */
33
+ export declare function isDriftSuspectReason(statusReason: string): boolean;
34
+ /**
35
+ * True for the stack-level event that opens a CloudFormation operation —
36
+ * the shared boundary for "current operation only" scans (the deploy-core
37
+ * last-operation event walk and the failure analyser's drift scan).
38
+ */
39
+ export declare function isOperationOpeningEvent(event: ResourceEvent, stackName: string): boolean;
40
+ /**
41
+ * Timestamp of the most recent operation-opening event for `stackName`, or
42
+ * null when none is visible. Server-clock consistent with event timestamps,
43
+ * so callers can bound scans without local-clock skew.
44
+ */
45
+ export declare function findCurrentOperationStart(events: readonly ResourceEvent[], stackName: string): Date | null;
46
+ /**
47
+ * Extract out-of-band-deletion suspects from failure events. Callers pass
48
+ * EVERY failed event in the operation, not just each resource's latest — a
49
+ * wedged resource's UPDATE_FAILED is typically superseded by a later
50
+ * UPDATE_ROLLBACK_* event, so latest-event-per-resource semantics would drop
51
+ * exactly the suspects this classifier exists to find. Deduplicated by
52
+ * logicalId (first match wins).
53
+ */
54
+ export declare function classifyDriftSuspectEvents(events: readonly ResourceEvent[]): DriftSuspectEvent[];
@@ -0,0 +1 @@
1
+ const o=new Set(["UPDATE_FAILED","DELETE_FAILED"]),i=[/HandlerErrorCode:\s*NotFound\b/,/does not exist \(Service:/i,/\b(?:ResourceNotFoundException|NotFoundException|NoSuchBucket|NoSuchEntity)\b/],c=/Resource (?:creation|update) cancelled/i;function u(e){return c.test(e)?!1:i.some(s=>s.test(e))}const a="AWS::CloudFormation::Stack",r=new Set(["CREATE_IN_PROGRESS","UPDATE_IN_PROGRESS","DELETE_IN_PROGRESS","IMPORT_IN_PROGRESS"]),E="User Initiated";function S(e,s){return e.resourceType===a&&e.logicalId===s&&r.has(e.status)&&e.statusReason!==void 0&&e.statusReason.includes(E)}function d(e,s){let n=null;for(const t of e)S(t,s)&&(n===null||t.timestamp.getTime()>n.getTime())&&(n=t.timestamp);return n}function R(e){const s=[],n=new Set;for(const t of e)n.has(t.logicalId)||o.has(t.status)&&(t.statusReason===void 0||t.statusReason===""||u(t.statusReason)&&(n.add(t.logicalId),s.push({logicalId:t.logicalId,resourceType:t.resourceType,...t.physicalId!==void 0&&t.physicalId!==""?{physicalId:t.physicalId}:{},failedStatus:t.status,statusReason:t.statusReason})));return s}export{R as classifyDriftSuspectEvents,d as findCurrentOperationStart,u as isDriftSuspectReason,S as isOperationOpeningEvent};
@@ -3,6 +3,7 @@ export { STACK_NOT_FOUND_PATTERN, CDK_NO_STACKS_MATCH, type ResourceEvent, isRes
3
3
  export { type ResourceProgressCounts, countResourceProgress, formatElapsed } from "./deployProgress.js";
4
4
  export { CloudFormationFailureAnalyser, type RootCause, type FailureAnalysis } from "./CloudFormationFailureAnalyser.js";
5
5
  export { maskFailureAnalysis } from "./maskFailureAnalysis.js";
6
+ export { classifyDriftSuspectEvents, findCurrentOperationStart, isDriftSuspectReason, isOperationOpeningEvent, type DriftSuspectEvent } from "./driftSuspects.js";
6
7
  export { IPAM_OPERATIONS_POOL_TAG_KEY, formatIpamPairTagValue } from "./ipamTags.js";
7
8
  export { SDK_PRE_EMPTY_TAG_KEY } from "./infraTags.js";
8
9
  export { ACCOUNT_MONITORING_ROLE_NAME } from "./monitoringRole.js";
package/dist/aws/index.js CHANGED
@@ -1 +1 @@
1
- import{AWSError as e,NoRolesFoundError as E,InvalidCredentialsError as s,SSOTokenExpiredError as a,MissingRegionError as i,ProfileNotFoundError as _,CommandError as t,isAWSError as m,isNoRolesFoundError as n,isSSOUnauthorizedError as A}from"./errors.js";import{STACK_NOT_FOUND_PATTERN as O,CDK_NO_STACKS_MATCH as l,isResourceEvent as N}from"./cloudformationTypes.js";import{countResourceProgress as p,formatElapsed as u}from"./deployProgress.js";import{CloudFormationFailureAnalyser as d}from"./CloudFormationFailureAnalyser.js";import{maskFailureAnalysis as x}from"./maskFailureAnalysis.js";import{IPAM_OPERATIONS_POOL_TAG_KEY as P,formatIpamPairTagValue as F}from"./ipamTags.js";import{SDK_PRE_EMPTY_TAG_KEY as K}from"./infraTags.js";import{ACCOUNT_MONITORING_ROLE_NAME as g}from"./monitoringRole.js";export{g as ACCOUNT_MONITORING_ROLE_NAME,e as AWSError,l as CDK_NO_STACKS_MATCH,d as CloudFormationFailureAnalyser,t as CommandError,P as IPAM_OPERATIONS_POOL_TAG_KEY,s as InvalidCredentialsError,i as MissingRegionError,E as NoRolesFoundError,_ as ProfileNotFoundError,K as SDK_PRE_EMPTY_TAG_KEY,a as SSOTokenExpiredError,O as STACK_NOT_FOUND_PATTERN,p as countResourceProgress,u as formatElapsed,F as formatIpamPairTagValue,m as isAWSError,n as isNoRolesFoundError,N as isResourceEvent,A as isSSOUnauthorizedError,x as maskFailureAnalysis};
1
+ import{AWSError as e,NoRolesFoundError as t,InvalidCredentialsError as i,SSOTokenExpiredError as s,MissingRegionError as n,ProfileNotFoundError as E,CommandError as a,isAWSError as p,isNoRolesFoundError as _,isSSOUnauthorizedError as f}from"./errors.js";import{STACK_NOT_FOUND_PATTERN as O,CDK_NO_STACKS_MATCH as u,isResourceEvent as A}from"./cloudformationTypes.js";import{countResourceProgress as T,formatElapsed as l}from"./deployProgress.js";import{CloudFormationFailureAnalyser as d}from"./CloudFormationFailureAnalyser.js";import{maskFailureAnalysis as x}from"./maskFailureAnalysis.js";import{classifyDriftSuspectEvents as P,findCurrentOperationStart as F,isDriftSuspectReason as c,isOperationOpeningEvent as I}from"./driftSuspects.js";import{IPAM_OPERATIONS_POOL_TAG_KEY as M,formatIpamPairTagValue as g}from"./ipamTags.js";import{SDK_PRE_EMPTY_TAG_KEY as v}from"./infraTags.js";import{ACCOUNT_MONITORING_ROLE_NAME as G}from"./monitoringRole.js";export{G as ACCOUNT_MONITORING_ROLE_NAME,e as AWSError,u as CDK_NO_STACKS_MATCH,d as CloudFormationFailureAnalyser,a as CommandError,M as IPAM_OPERATIONS_POOL_TAG_KEY,i as InvalidCredentialsError,n as MissingRegionError,t as NoRolesFoundError,E as ProfileNotFoundError,v as SDK_PRE_EMPTY_TAG_KEY,s as SSOTokenExpiredError,O as STACK_NOT_FOUND_PATTERN,P as classifyDriftSuspectEvents,T as countResourceProgress,F as findCurrentOperationStart,l as formatElapsed,g as formatIpamPairTagValue,p as isAWSError,c as isDriftSuspectReason,_ as isNoRolesFoundError,I as isOperationOpeningEvent,A as isResourceEvent,f as isSSOUnauthorizedError,x as maskFailureAnalysis};
@@ -1 +1 @@
1
- import{maskSensitiveOutput as o}from"../securityHelpers.js";function r(e){return e.statusReason===void 0?e:{...e,statusReason:o(e.statusReason)}}function u(e){const s={...e.rootCause,reason:o(e.rootCause.reason),resource:r(e.rootCause.resource)};return{...e,rootCause:s,affectedResources:e.affectedResources.map(r)}}export{u as maskFailureAnalysis};
1
+ import{maskSensitiveOutput as t}from"../securityHelpers.js";function r(e){return e.statusReason===void 0?e:{...e,statusReason:t(e.statusReason)}}function u(e){return{...e,statusReason:t(e.statusReason)}}function n(e){const s={...e.rootCause,reason:t(e.rootCause.reason),resource:r(e.rootCause.resource)};return{...e,rootCause:s,affectedResources:e.affectedResources.map(r),...e.driftSuspects!==void 0?{driftSuspects:e.driftSuspects.map(u)}:{}}}export{n as maskFailureAnalysis};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fallback map for pinned-name detection: CloudFormation resource types whose
3
+ * user-settable NAMING property cannot be derived from the registry schema's
4
+ * `primaryIdentifier` — the identifier is a generated attribute (ARN, URL, ID)
5
+ * that never appears in a template's Properties.
6
+ *
7
+ * Consulted by @fjall/deploy-core's pinned-name detector AFTER the
8
+ * primaryIdentifier derivation fails to yield a template property. Keep this
9
+ * map small: types whose primaryIdentifier IS the naming property
10
+ * (DBInstanceIdentifier, TableName, BucketName, RepositoryName, …) must NOT be
11
+ * added here.
12
+ */
13
+ export declare const PHYSICAL_NAME_FALLBACK_PROPERTIES: Readonly<Record<string, string>>;
@@ -0,0 +1 @@
1
+ const e={"AWS::SecretsManager::Secret":"Name","AWS::SQS::Queue":"QueueName","AWS::SNS::Topic":"TopicName"};export{e as PHYSICAL_NAME_FALLBACK_PROPERTIES};
package/dist/index.d.ts CHANGED
@@ -26,3 +26,4 @@ export { RESERVED_APP_NAMES, type ReservedAppName, RESERVED_APP_NAME_MESSAGE, is
26
26
  export { deriveContentHashTag, CONTENT_HASH_TAG_PATTERN } from "./infra/deriveContentHashTag.js";
27
27
  export { DEPLOY_MODES, DeployModeSchema, type DeployMode, IMAGE_TAG_PATTERN, ImageTagSchema, type ImageTag, ServiceArtefactSchema, type ServiceArtefact, ServiceArtefactsSchema, type ServiceArtefacts, ARTEFACT_OUTPUT_FIELDS, type ArtefactOutputField, artefactOutputKey } from "./infra/deployArtefacts.js";
28
28
  export { MIGRATION_SNAPSHOT_NAME_PREFIX, EXPECTED_SCHEMA_VERSION_ENV, EXPECTED_SCHEMA_VERSION_TOOL_ENV, EXPECTED_CH_SCHEMA_VERSION_ENV, SCHEMA_ADMIN_USER_ENV, SCHEMA_ADMIN_PASSWORD_ENV, PRISMA_MIGRATION_DIR_RE, CLICKHOUSE_MIGRATION_SKIP_RE } from "./migration/constants.js";
29
+ export { PHYSICAL_NAME_FALLBACK_PROPERTIES } from "./cfn/physicalNameProperties.js";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{DNS_APEX as o,getDomainExportNames as E}from"./infra/domainExports.js";import{BACKUP_VAULT_NAME as a}from"./infra/backupVault.js";import{APPROVAL_TOKEN_OUTPUT_PREFIX as _,TOKEN_STDERR_PREFIX as A}from"./deploy/approvalTokenOutput.js";import{imageTagParameterName as i}from"./infra/imageTags.js";import{toPascalCase as T,toKebab as N,toValidDatabaseName as m,toScreamingSnake as s,capitalise as O,getSafeZoneName as C,accountConstructKey as c,hasAsciiStableConstructKey as f}from"./naming/caseConversion.js";import{findAccountNameCollision as P}from"./naming/accountNameCollision.js";import{defaultConnectedAccountName as I,suffixedAccountName as M,REGION_SHORT_CODES as u,findTrailingRegionShortCode as x,regionSuffixRejectionMessage as D}from"./naming/connectedAccountName.js";import{normaliseError as l,getErrorMessage as U,hasErrorCode as V,getErrorCode as h,getErrorStack as G,formatErrorString as v}from"./errorUtils.js";import{singleton as F}from"./async/singleton.js";import{DANGEROUS_ENV_VARS as X,filterDangerousEnvVars as b,maskSensitiveOutput as K,parseShellArgs as y,SCOPED_TOKEN_REGEX as W}from"./securityHelpers.js";import{sleep as Y}from"./async/sleep.js";import{mapSettledWithConcurrency as j}from"./async/concurrency.js";import{ACCOUNT_STAGES_WITH_ROOT as Z,STRUCTURAL_ENVIRONMENTS as q,ACCOUNT_STAGES as w,ACCOUNT_STAGE_LABELS as J,isAccountStage as Q,ACCOUNT_TIERS as $,AccountTierSchema as ee,isAccountTier as re,environmentToTier as oe,stageFromWireEnvironment as Ee,accountTier as te,getEnvironmentLabel as ae,ACCOUNT_ROLES as Se}from"./environments.js";import{RESOURCE_CATEGORIES as Ae,categoriseResource as ne,getExpectedDuration as ie,getFriendlyResourceType as Re}from"./resourceCategorisation.js";import{parseGitRemoteUrl as Ne}from"./repo/gitRemoteParser.js";import{abbreviateRegion as se,AWS_REGIONS_METADATA as Oe,DEFAULT_REGION as Ce,getRegionInfo as ce,MAX_SECONDARY_REGIONS as fe,OPT_IN_REGION_CODES as pe,optInRegionWarning as Pe,regions as ge,suggestRegionForTimezone as Ie}from"./infra/regions.js";import{SCOPE_VALUES as ue,MACHINE_ONLY_SCOPES as xe,USER_GRANTABLE_SCOPES as De}from"./infra/tokenScopes.js";import{SECRET_NAME_PATTERN as le,SECRET_NAME_ERROR as Ue,SSM_COMPONENT_PATTERN as Ve,SSM_COMPONENT_ERROR as he,SSM_STANDARD_MAX_VALUE_BYTES as Ge,SecretNamespaceSchema as ve,buildNamespaceParts as Le,buildParameterPath as Fe,parseParameterPath as He,isManageablePath as Xe,parseDotEnv as be,escapeDotEnvValue as Ke}from"./secrets.js";import{ConnectionWireSchema as We,ConnectionsListResponseSchema as Be}from"./infra/connectionsWire.js";import{deriveRegionsFromOrgConfig as ke,deriveTargets as je,deriveAllTargets as ze,environmentOrTier as Ze,findTarget as qe,generateTargetName as we}from"./targets.js";import{buildAppConfigPath as Qe}from"./repo/appPath.js";import{findInfrastructurePaths as er,findBoundaryPath as rr,isInfrastructureFile as or}from"./repo/findInfrastructurePaths.js";import{inferContainerFromCandidates as tr}from"./repo/inferContainerFromCandidates.js";import{RESERVED_APP_NAMES as Sr,RESERVED_APP_NAME_MESSAGE as _r,isReservedAppName as Ar,RESERVED_APP_NAME_SUFFIX as nr,RESERVED_APP_NAME_SUFFIX_MESSAGE as ir,hasReservedAppNameSuffix as Rr}from"./naming/reservedAppNames.js";import{deriveContentHashTag as Nr,CONTENT_HASH_TAG_PATTERN as mr}from"./infra/deriveContentHashTag.js";import{DEPLOY_MODES as Or,DeployModeSchema as Cr,IMAGE_TAG_PATTERN as cr,ImageTagSchema as fr,ServiceArtefactSchema as pr,ServiceArtefactsSchema as Pr,ARTEFACT_OUTPUT_FIELDS as gr,artefactOutputKey as Ir}from"./infra/deployArtefacts.js";import{MIGRATION_SNAPSHOT_NAME_PREFIX as ur,EXPECTED_SCHEMA_VERSION_ENV as xr,EXPECTED_SCHEMA_VERSION_TOOL_ENV as Dr,EXPECTED_CH_SCHEMA_VERSION_ENV as dr,SCHEMA_ADMIN_USER_ENV as lr,SCHEMA_ADMIN_PASSWORD_ENV as Ur,PRISMA_MIGRATION_DIR_RE as Vr,CLICKHOUSE_MIGRATION_SKIP_RE as hr}from"./migration/constants.js";export{Se as ACCOUNT_ROLES,w as ACCOUNT_STAGES,Z as ACCOUNT_STAGES_WITH_ROOT,J as ACCOUNT_STAGE_LABELS,$ as ACCOUNT_TIERS,_ as APPROVAL_TOKEN_OUTPUT_PREFIX,gr as ARTEFACT_OUTPUT_FIELDS,Oe as AWS_REGIONS_METADATA,ee as AccountTierSchema,a as BACKUP_VAULT_NAME,hr as CLICKHOUSE_MIGRATION_SKIP_RE,mr as CONTENT_HASH_TAG_PATTERN,We as ConnectionWireSchema,Be as ConnectionsListResponseSchema,X as DANGEROUS_ENV_VARS,Ce as DEFAULT_REGION,Or as DEPLOY_MODES,o as DNS_APEX,Cr as DeployModeSchema,dr as EXPECTED_CH_SCHEMA_VERSION_ENV,xr as EXPECTED_SCHEMA_VERSION_ENV,Dr as EXPECTED_SCHEMA_VERSION_TOOL_ENV,cr as IMAGE_TAG_PATTERN,fr as ImageTagSchema,xe as MACHINE_ONLY_SCOPES,fe as MAX_SECONDARY_REGIONS,ur as MIGRATION_SNAPSHOT_NAME_PREFIX,pe as OPT_IN_REGION_CODES,Vr as PRISMA_MIGRATION_DIR_RE,u as REGION_SHORT_CODES,Sr as RESERVED_APP_NAMES,_r as RESERVED_APP_NAME_MESSAGE,nr as RESERVED_APP_NAME_SUFFIX,ir as RESERVED_APP_NAME_SUFFIX_MESSAGE,Ae as RESOURCE_CATEGORIES,Ur as SCHEMA_ADMIN_PASSWORD_ENV,lr as SCHEMA_ADMIN_USER_ENV,W as SCOPED_TOKEN_REGEX,ue as SCOPE_VALUES,Ue as SECRET_NAME_ERROR,le as SECRET_NAME_PATTERN,he as SSM_COMPONENT_ERROR,Ve as SSM_COMPONENT_PATTERN,Ge as SSM_STANDARD_MAX_VALUE_BYTES,q as STRUCTURAL_ENVIRONMENTS,ve as SecretNamespaceSchema,pr as ServiceArtefactSchema,Pr as ServiceArtefactsSchema,A as TOKEN_STDERR_PREFIX,De as USER_GRANTABLE_SCOPES,se as abbreviateRegion,c as accountConstructKey,te as accountTier,Ir as artefactOutputKey,Qe as buildAppConfigPath,Le as buildNamespaceParts,Fe as buildParameterPath,O as capitalise,ne as categoriseResource,I as defaultConnectedAccountName,ze as deriveAllTargets,Nr as deriveContentHashTag,ke as deriveRegionsFromOrgConfig,je as deriveTargets,Ze as environmentOrTier,oe as environmentToTier,Ke as escapeDotEnvValue,b as filterDangerousEnvVars,P as findAccountNameCollision,rr as findBoundaryPath,er as findInfrastructurePaths,qe as findTarget,x as findTrailingRegionShortCode,v as formatErrorString,we as generateTargetName,E as getDomainExportNames,ae as getEnvironmentLabel,h as getErrorCode,U as getErrorMessage,G as getErrorStack,ie as getExpectedDuration,Re as getFriendlyResourceType,ce as getRegionInfo,C as getSafeZoneName,f as hasAsciiStableConstructKey,V as hasErrorCode,Rr as hasReservedAppNameSuffix,i as imageTagParameterName,tr as inferContainerFromCandidates,Q as isAccountStage,re as isAccountTier,or as isInfrastructureFile,Xe as isManageablePath,Ar as isReservedAppName,j as mapSettledWithConcurrency,K as maskSensitiveOutput,l as normaliseError,Pe as optInRegionWarning,be as parseDotEnv,Ne as parseGitRemoteUrl,He as parseParameterPath,y as parseShellArgs,D as regionSuffixRejectionMessage,ge as regions,F as singleton,Y as sleep,Ee as stageFromWireEnvironment,M as suffixedAccountName,Ie as suggestRegionForTimezone,N as toKebab,T as toPascalCase,s as toScreamingSnake,m as toValidDatabaseName};
1
+ import{DNS_APEX as o,getDomainExportNames as E}from"./infra/domainExports.js";import{BACKUP_VAULT_NAME as a}from"./infra/backupVault.js";import{APPROVAL_TOKEN_OUTPUT_PREFIX as S,TOKEN_STDERR_PREFIX as A}from"./deploy/approvalTokenOutput.js";import{imageTagParameterName as i}from"./infra/imageTags.js";import{toPascalCase as T,toKebab as N,toValidDatabaseName as m,toScreamingSnake as s,capitalise as O,getSafeZoneName as C,accountConstructKey as c,hasAsciiStableConstructKey as f}from"./naming/caseConversion.js";import{findAccountNameCollision as P}from"./naming/accountNameCollision.js";import{defaultConnectedAccountName as I,suffixedAccountName as M,REGION_SHORT_CODES as u,findTrailingRegionShortCode as x,regionSuffixRejectionMessage as D}from"./naming/connectedAccountName.js";import{normaliseError as l,getErrorMessage as U,hasErrorCode as V,getErrorCode as h,getErrorStack as G,formatErrorString as L}from"./errorUtils.js";import{singleton as F}from"./async/singleton.js";import{DANGEROUS_ENV_VARS as X,filterDangerousEnvVars as b,maskSensitiveOutput as K,parseShellArgs as y,SCOPED_TOKEN_REGEX as W}from"./securityHelpers.js";import{sleep as Y}from"./async/sleep.js";import{mapSettledWithConcurrency as j}from"./async/concurrency.js";import{ACCOUNT_STAGES_WITH_ROOT as Z,STRUCTURAL_ENVIRONMENTS as q,ACCOUNT_STAGES as w,ACCOUNT_STAGE_LABELS as J,isAccountStage as Q,ACCOUNT_TIERS as $,AccountTierSchema as ee,isAccountTier as re,environmentToTier as oe,stageFromWireEnvironment as Ee,accountTier as te,getEnvironmentLabel as ae,ACCOUNT_ROLES as _e}from"./environments.js";import{RESOURCE_CATEGORIES as Ae,categoriseResource as ne,getExpectedDuration as ie,getFriendlyResourceType as Re}from"./resourceCategorisation.js";import{parseGitRemoteUrl as Ne}from"./repo/gitRemoteParser.js";import{abbreviateRegion as se,AWS_REGIONS_METADATA as Oe,DEFAULT_REGION as Ce,getRegionInfo as ce,MAX_SECONDARY_REGIONS as fe,OPT_IN_REGION_CODES as pe,optInRegionWarning as Pe,regions as ge,suggestRegionForTimezone as Ie}from"./infra/regions.js";import{SCOPE_VALUES as ue,MACHINE_ONLY_SCOPES as xe,USER_GRANTABLE_SCOPES as De}from"./infra/tokenScopes.js";import{SECRET_NAME_PATTERN as le,SECRET_NAME_ERROR as Ue,SSM_COMPONENT_PATTERN as Ve,SSM_COMPONENT_ERROR as he,SSM_STANDARD_MAX_VALUE_BYTES as Ge,SecretNamespaceSchema as Le,buildNamespaceParts as ve,buildParameterPath as Fe,parseParameterPath as He,isManageablePath as Xe,parseDotEnv as be,escapeDotEnvValue as Ke}from"./secrets.js";import{ConnectionWireSchema as We,ConnectionsListResponseSchema as Be}from"./infra/connectionsWire.js";import{deriveRegionsFromOrgConfig as ke,deriveTargets as je,deriveAllTargets as ze,environmentOrTier as Ze,findTarget as qe,generateTargetName as we}from"./targets.js";import{buildAppConfigPath as Qe}from"./repo/appPath.js";import{findInfrastructurePaths as er,findBoundaryPath as rr,isInfrastructureFile as or}from"./repo/findInfrastructurePaths.js";import{inferContainerFromCandidates as tr}from"./repo/inferContainerFromCandidates.js";import{RESERVED_APP_NAMES as _r,RESERVED_APP_NAME_MESSAGE as Sr,isReservedAppName as Ar,RESERVED_APP_NAME_SUFFIX as nr,RESERVED_APP_NAME_SUFFIX_MESSAGE as ir,hasReservedAppNameSuffix as Rr}from"./naming/reservedAppNames.js";import{deriveContentHashTag as Nr,CONTENT_HASH_TAG_PATTERN as mr}from"./infra/deriveContentHashTag.js";import{DEPLOY_MODES as Or,DeployModeSchema as Cr,IMAGE_TAG_PATTERN as cr,ImageTagSchema as fr,ServiceArtefactSchema as pr,ServiceArtefactsSchema as Pr,ARTEFACT_OUTPUT_FIELDS as gr,artefactOutputKey as Ir}from"./infra/deployArtefacts.js";import{MIGRATION_SNAPSHOT_NAME_PREFIX as ur,EXPECTED_SCHEMA_VERSION_ENV as xr,EXPECTED_SCHEMA_VERSION_TOOL_ENV as Dr,EXPECTED_CH_SCHEMA_VERSION_ENV as dr,SCHEMA_ADMIN_USER_ENV as lr,SCHEMA_ADMIN_PASSWORD_ENV as Ur,PRISMA_MIGRATION_DIR_RE as Vr,CLICKHOUSE_MIGRATION_SKIP_RE as hr}from"./migration/constants.js";import{PHYSICAL_NAME_FALLBACK_PROPERTIES as Lr}from"./cfn/physicalNameProperties.js";export{_e as ACCOUNT_ROLES,w as ACCOUNT_STAGES,Z as ACCOUNT_STAGES_WITH_ROOT,J as ACCOUNT_STAGE_LABELS,$ as ACCOUNT_TIERS,S as APPROVAL_TOKEN_OUTPUT_PREFIX,gr as ARTEFACT_OUTPUT_FIELDS,Oe as AWS_REGIONS_METADATA,ee as AccountTierSchema,a as BACKUP_VAULT_NAME,hr as CLICKHOUSE_MIGRATION_SKIP_RE,mr as CONTENT_HASH_TAG_PATTERN,We as ConnectionWireSchema,Be as ConnectionsListResponseSchema,X as DANGEROUS_ENV_VARS,Ce as DEFAULT_REGION,Or as DEPLOY_MODES,o as DNS_APEX,Cr as DeployModeSchema,dr as EXPECTED_CH_SCHEMA_VERSION_ENV,xr as EXPECTED_SCHEMA_VERSION_ENV,Dr as EXPECTED_SCHEMA_VERSION_TOOL_ENV,cr as IMAGE_TAG_PATTERN,fr as ImageTagSchema,xe as MACHINE_ONLY_SCOPES,fe as MAX_SECONDARY_REGIONS,ur as MIGRATION_SNAPSHOT_NAME_PREFIX,pe as OPT_IN_REGION_CODES,Lr as PHYSICAL_NAME_FALLBACK_PROPERTIES,Vr as PRISMA_MIGRATION_DIR_RE,u as REGION_SHORT_CODES,_r as RESERVED_APP_NAMES,Sr as RESERVED_APP_NAME_MESSAGE,nr as RESERVED_APP_NAME_SUFFIX,ir as RESERVED_APP_NAME_SUFFIX_MESSAGE,Ae as RESOURCE_CATEGORIES,Ur as SCHEMA_ADMIN_PASSWORD_ENV,lr as SCHEMA_ADMIN_USER_ENV,W as SCOPED_TOKEN_REGEX,ue as SCOPE_VALUES,Ue as SECRET_NAME_ERROR,le as SECRET_NAME_PATTERN,he as SSM_COMPONENT_ERROR,Ve as SSM_COMPONENT_PATTERN,Ge as SSM_STANDARD_MAX_VALUE_BYTES,q as STRUCTURAL_ENVIRONMENTS,Le as SecretNamespaceSchema,pr as ServiceArtefactSchema,Pr as ServiceArtefactsSchema,A as TOKEN_STDERR_PREFIX,De as USER_GRANTABLE_SCOPES,se as abbreviateRegion,c as accountConstructKey,te as accountTier,Ir as artefactOutputKey,Qe as buildAppConfigPath,ve as buildNamespaceParts,Fe as buildParameterPath,O as capitalise,ne as categoriseResource,I as defaultConnectedAccountName,ze as deriveAllTargets,Nr as deriveContentHashTag,ke as deriveRegionsFromOrgConfig,je as deriveTargets,Ze as environmentOrTier,oe as environmentToTier,Ke as escapeDotEnvValue,b as filterDangerousEnvVars,P as findAccountNameCollision,rr as findBoundaryPath,er as findInfrastructurePaths,qe as findTarget,x as findTrailingRegionShortCode,L as formatErrorString,we as generateTargetName,E as getDomainExportNames,ae as getEnvironmentLabel,h as getErrorCode,U as getErrorMessage,G as getErrorStack,ie as getExpectedDuration,Re as getFriendlyResourceType,ce as getRegionInfo,C as getSafeZoneName,f as hasAsciiStableConstructKey,V as hasErrorCode,Rr as hasReservedAppNameSuffix,i as imageTagParameterName,tr as inferContainerFromCandidates,Q as isAccountStage,re as isAccountTier,or as isInfrastructureFile,Xe as isManageablePath,Ar as isReservedAppName,j as mapSettledWithConcurrency,K as maskSensitiveOutput,l as normaliseError,Pe as optInRegionWarning,be as parseDotEnv,Ne as parseGitRemoteUrl,He as parseParameterPath,y as parseShellArgs,D as regionSuffixRejectionMessage,ge as regions,F as singleton,Y as sleep,Ee as stageFromWireEnvironment,M as suffixedAccountName,Ie as suggestRegionForTimezone,N as toKebab,T as toPascalCase,s as toScreamingSnake,m as toValidDatabaseName};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/util",
3
- "version": "2.27.0",
3
+ "version": "2.29.0",
4
4
  "description": "Common utility methods",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -129,5 +129,5 @@
129
129
  "engines": {
130
130
  "node": ">=22.0.0"
131
131
  },
132
- "gitHead": "921ecd4f65f52c17037a8a24834d7e4c196b9347"
132
+ "gitHead": "c40ea0e1435400f3f42faaad5bcbf50e4400c1d4"
133
133
  }