@fjall/util 7.3.0 → 9.0.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.
@@ -9,7 +9,7 @@
9
9
  "package.json",
10
10
  "tsconfig.json"
11
11
  ],
12
- "hash": "dd4b6f4216f4e2a95fadfd0b75bff3b3c60bcde2293836647a4b358194e9d1b8",
12
+ "hash": "45c0c260a70c536ef2d05997781c8ccc49866ce559e8d6940f58f9f092c5f250",
13
13
  "files": {
14
14
  "src/async/concurrency.ts": "3c7ebe0222a720f9",
15
15
  "src/async/singleton.ts": "7bcc21b0fb920561",
@@ -56,11 +56,11 @@
56
56
  "src/docker/rawjsonParser.ts": "b9e5218abc326fa5",
57
57
  "src/docker/rawjsonToVertexEvent.ts": "a356190727f0d1a4",
58
58
  "src/docker/result.ts": "2ff0d59a3add8b06",
59
- "src/environments.ts": "13d583ce2ce37454",
59
+ "src/environments.ts": "b3d2f2493554cd0f",
60
60
  "src/errorUtils.ts": "c601f2905c74b8d0",
61
61
  "src/fsHelpers.ts": "0869d9739d523572",
62
62
  "src/fsScan.ts": "feb187758481443f",
63
- "src/index.ts": "b53459f372672363",
63
+ "src/index.ts": "79929947a329af6f",
64
64
  "src/infra/backupVault.ts": "661678a6dfb0b648",
65
65
  "src/infra/connectionsWire.ts": "125c099da0e17ac1",
66
66
  "src/infra/deployArtefacts.ts": "235ac21dd3ccf0b2",
@@ -81,11 +81,12 @@
81
81
  "src/migration/index.ts": "de586c9d775b3174",
82
82
  "src/migration/pickLatestClickHouseMigration.ts": "a5b4a00ba63522cb",
83
83
  "src/migration/pickLatestPrismaMigration.ts": "cbddc2950f4d4c85",
84
- "src/migration/verifyExpectedSchemaVersion.ts": "f2a9c63023ffb3d2",
84
+ "src/migration/verifyExpectedSchemaVersion.ts": "cd583329d771a047",
85
85
  "src/naming/accountNameCollision.ts": "2dc8b278ff039220",
86
86
  "src/naming/caseConversion.ts": "8b8984f2b58b8ab7",
87
87
  "src/naming/connectedAccountName.ts": "3cd3bc7dba0a2f0b",
88
88
  "src/naming/reservedAppNames.ts": "7f63dd0b84c1972e",
89
+ "src/naming/targetExportNames.ts": "82447463310e43c8",
89
90
  "src/patterns/index.ts": "6e8b1b7a4a7db24c",
90
91
  "src/patterns/patternTypes.ts": "c64758645bc88702",
91
92
  "src/patterns/staticSiteForms.ts": "86ffcf142d9a8eac",
@@ -102,9 +103,9 @@
102
103
  "src/securityHelpers.ts": "ee2ab9ffd53119fb",
103
104
  "src/targets.ts": "126280f0a5762e21",
104
105
  "../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
105
- "package.json": "3a8f986a81a80c42",
106
+ "package.json": "de20bfd9ecd3a130",
106
107
  "tsconfig.json": "db759831ad95f396"
107
108
  },
108
- "outputHash": "6f5fc5d5e93c66a4396906af84d0afea9a4ab6b6eae10c7993e6dca435150b04",
109
- "outputFileCount": 187
109
+ "outputHash": "d92d1ce1a95c7c760cdd03cefa7cd594c041bb5c0768c96a6806c9d703b6456b",
110
+ "outputFileCount": 189
110
111
  }
package/dist/.minified CHANGED
@@ -1 +1 @@
1
- 93 files minified at 2026-08-06T23:10:24.976Z
1
+ 94 files minified at 2026-08-09T10:16:53.310Z
@@ -112,3 +112,25 @@ export declare function accountTier(acc: {
112
112
  tier?: AccountTier | null;
113
113
  environment?: string | null;
114
114
  }): AccountTier;
115
+ /**
116
+ * Resolve a provider account's synth-time environment — the value that reaches
117
+ * a CDK synth as `-c environment=` and that `envAwareRemovalPolicyDefault()`
118
+ * turns into RETAIN or DESTROY.
119
+ *
120
+ * The tier/stage separation (decisions/2026-06-07-account-tier-vs-stage-separation.md)
121
+ * nulls the wire `environment` for organisation-tier accounts, but scaffolded
122
+ * org entry points gate on `config.environment === "root"` — decode the tier
123
+ * back to the historical "root" marker via the sanctioned `accountTier()`
124
+ * decoder. Workload stages pass through verbatim; a null stage on any other
125
+ * tier stays unresolved.
126
+ *
127
+ * Lives here, not in the constructs package, because deploy-core resolves the
128
+ * environment BEFORE synth (to pass it explicitly) while
129
+ * `components/infrastructure` resolves it DURING synth (when no explicit
130
+ * signal arrived). Two derivations that disagree would put a stack's removal
131
+ * policies on the wrong side of production — so there is only one.
132
+ */
133
+ export declare function resolveSynthEnvironment(acc: {
134
+ tier?: AccountTier | null;
135
+ environment?: string | null;
136
+ }): string | undefined;
@@ -1 +1 @@
1
- var O=Object.defineProperty;var o=(t,i)=>O(t,"name",{value:i,configurable:!0});import{z as u}from"zod";const e=["production","staging","development","platform","compliance"],a={production:"Production",staging:"Staging",development:"Development",platform:"Platform",compliance:"Compliance"},p=new Set(e);function T(t){return p.has(t)}o(T,"isAccountStage");const r={ROOT:"root",PLATFORM:"platform"},l=[...e,r.ROOT];function f(t){return T(t)?a[t]:t.charAt(0).toUpperCase()+t.slice(1)}o(f,"getEnvironmentLabel");const c=["organisation","platform","account"],_=u.enum(c),n={ORGANISATION:"organisation",PLATFORM:"platform",ACCOUNT:"account"},A={[n.ORGANISATION]:!0,[n.PLATFORM]:!0,[n.ACCOUNT]:!0},C=new Set(Object.keys(A));function m(t){return C.has(t)}o(m,"isAccountTier");const s=c.filter(t=>t!==n.ACCOUNT),E=new Set(s);function x(t){return E.has(t)}o(x,"isGovernanceTier");function N(t){return t===r.ROOT?"organisation":t===r.PLATFORM?"platform":"account"}o(N,"environmentToTier");function U(t){return t==null||t===""||t===r.ROOT?null:T(t)?t:null}o(U,"stageFromWireEnvironment");function g(t){return t.tier??N(t.environment)}o(g,"accountTier");export{n as ACCOUNT_ROLES,e as ACCOUNT_STAGES,l as ACCOUNT_STAGES_WITH_ROOT,a as ACCOUNT_STAGE_LABELS,c as ACCOUNT_TIERS,_ as AccountTierSchema,s as GOVERNANCE_ACCOUNT_TIERS,r as STRUCTURAL_ENVIRONMENTS,g as accountTier,N as environmentToTier,f as getEnvironmentLabel,T as isAccountStage,m as isAccountTier,x as isGovernanceTier,U as stageFromWireEnvironment};
1
+ var u=Object.defineProperty;var n=(t,c)=>u(t,"name",{value:c,configurable:!0});import{z as O}from"zod";const e=["production","staging","development","platform","compliance"],a={production:"Production",staging:"Staging",development:"Development",platform:"Platform",compliance:"Compliance"},p=new Set(e);function T(t){return p.has(t)}n(T,"isAccountStage");const o={ROOT:"root",PLATFORM:"platform"},l=[...e,o.ROOT];function _(t){return T(t)?a[t]:t.charAt(0).toUpperCase()+t.slice(1)}n(_,"getEnvironmentLabel");const i=["organisation","platform","account"],m=O.enum(i),r={ORGANISATION:"organisation",PLATFORM:"platform",ACCOUNT:"account"},A={[r.ORGANISATION]:!0,[r.PLATFORM]:!0,[r.ACCOUNT]:!0},C=new Set(Object.keys(A));function x(t){return C.has(t)}n(x,"isAccountTier");const s=i.filter(t=>t!==r.ACCOUNT),E=new Set(s);function U(t){return E.has(t)}n(U,"isGovernanceTier");function R(t){return t===o.ROOT?"organisation":t===o.PLATFORM?"platform":"account"}n(R,"environmentToTier");function g(t){return t==null||t===""||t===o.ROOT?null:T(t)?t:null}n(g,"stageFromWireEnvironment");function S(t){return t.tier??R(t.environment)}n(S,"accountTier");function I(t){return S(t)==="organisation"?o.ROOT:t.environment??void 0}n(I,"resolveSynthEnvironment");export{r as ACCOUNT_ROLES,e as ACCOUNT_STAGES,l as ACCOUNT_STAGES_WITH_ROOT,a as ACCOUNT_STAGE_LABELS,i as ACCOUNT_TIERS,m as AccountTierSchema,s as GOVERNANCE_ACCOUNT_TIERS,o as STRUCTURAL_ENVIRONMENTS,S as accountTier,R as environmentToTier,_ as getEnvironmentLabel,T as isAccountStage,x as isAccountTier,U as isGovernanceTier,I as resolveSynthEnvironment,g as stageFromWireEnvironment};
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { BACKUP_VAULT_NAME } from "./infra/backupVault.js";
3
3
  export { APPROVAL_TOKEN_OUTPUT_PREFIX, TOKEN_STDERR_PREFIX } from "./deploy/approvalTokenOutput.js";
4
4
  export { imageTagParameterName } from "./infra/imageTags.js";
5
5
  export { toPascalCase, toKebab, toValidDatabaseName, toScreamingSnake, capitalise, getSafeZoneName, accountConstructKey, hasAsciiStableConstructKey } from "./naming/caseConversion.js";
6
+ export { albDnsExportName, albHostedZoneIdExportName, cdnDomainExportName, bucketWebsiteEndpointExportName, bucketWebsiteHostedZoneIdExportName } from "./naming/targetExportNames.js";
6
7
  export { CAPACITY_SLOT_PATTERN, CAPACITY_SLOT_MAX_LENGTH, DEFAULT_CAPACITY_SLOT, CAPACITY_ANCHOR_PATTERN, CAPACITY_ANCHOR_MAX_LENGTH, CAPACITY_IDENTITY_CONTEXT_KEY, CapacityIdentityPinSchema, type CapacityIdentityPin, CapacityIdentityWireSchema, type CapacityIdentityWire, CapacityIdentityConfigSchema, type CapacityIdentityConfig, projectCapacityIdentityToTarget } from "./capacityIdentity.js";
7
8
  export { findAccountNameCollision, type AccountNameCollision } from "./naming/accountNameCollision.js";
8
9
  export { defaultConnectedAccountName, suffixedAccountName, REGION_SHORT_CODES, findTrailingRegionShortCode, regionSuffixRejectionMessage } from "./naming/connectedAccountName.js";
@@ -11,7 +12,7 @@ export { singleton } from "./async/singleton.js";
11
12
  export { DANGEROUS_ENV_VARS, filterDangerousEnvVars, MASKED_VALUE_MARKER, maskSensitiveOutput, parseShellArgs, REDACTED_KEY_SENTINEL, SCOPED_TOKEN_REGEX } from "./securityHelpers.js";
12
13
  export { sleep } from "./async/sleep.js";
13
14
  export { mapSettledWithConcurrency } from "./async/concurrency.js";
14
- export { ACCOUNT_STAGES_WITH_ROOT, STRUCTURAL_ENVIRONMENTS, ACCOUNT_STAGES, ACCOUNT_STAGE_LABELS, isAccountStage, ACCOUNT_TIERS, type AccountTier, AccountTierSchema, isAccountTier, GOVERNANCE_ACCOUNT_TIERS, isGovernanceTier, environmentToTier, stageFromWireEnvironment, accountTier, type AccountStageWithRoot, type AccountStage, getEnvironmentLabel, ACCOUNT_ROLES } from "./environments.js";
15
+ export { ACCOUNT_STAGES_WITH_ROOT, STRUCTURAL_ENVIRONMENTS, ACCOUNT_STAGES, ACCOUNT_STAGE_LABELS, isAccountStage, ACCOUNT_TIERS, type AccountTier, AccountTierSchema, isAccountTier, GOVERNANCE_ACCOUNT_TIERS, isGovernanceTier, environmentToTier, stageFromWireEnvironment, accountTier, resolveSynthEnvironment, type AccountStageWithRoot, type AccountStage, getEnvironmentLabel, ACCOUNT_ROLES } from "./environments.js";
15
16
  export { RESOURCE_CATEGORIES, type ResourceCategory, categoriseResource, getExpectedDuration, getFriendlyResourceType } from "./resourceCategorisation.js";
16
17
  export { parseGitRemoteUrl, type GitProvider, type ParsedGitRemote } from "./repo/gitRemoteParser.js";
17
18
  export { abbreviateRegion, AWS_REGIONS_METADATA, DEFAULT_REGION, getRegionInfo, MAX_SECONDARY_REGIONS, OPT_IN_REGION_CODES, optInRegionWarning, regions, suggestRegionForTimezone, type RegionCode, type RegionInfo } from "./infra/regions.js";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{DNS_APEX as r,getDomainExportNames as t,getDomainStackName as o,getDomainUsEast1CertificatesStackName as _,isManagedDomainBinding as A,DOMAIN_DEPLOY_DEFAULT_PHASE as a}from"./infra/domainExports.js";import{BACKUP_VAULT_NAME as T}from"./infra/backupVault.js";import{APPROVAL_TOKEN_OUTPUT_PREFIX as i,TOKEN_STDERR_PREFIX as n}from"./deploy/approvalTokenOutput.js";import{imageTagParameterName as C}from"./infra/imageTags.js";import{toPascalCase as O,toKebab as P,toValidDatabaseName as s,toScreamingSnake as c,capitalise as p,getSafeZoneName as I,accountConstructKey as f,hasAsciiStableConstructKey as D}from"./naming/caseConversion.js";import{CAPACITY_SLOT_PATTERN as M,CAPACITY_SLOT_MAX_LENGTH as d,DEFAULT_CAPACITY_SLOT as x,CAPACITY_ANCHOR_PATTERN as L,CAPACITY_ANCHOR_MAX_LENGTH as U,CAPACITY_IDENTITY_CONTEXT_KEY as u,CapacityIdentityPinSchema as V,CapacityIdentityWireSchema as l,CapacityIdentityConfigSchema as G,projectCapacityIdentityToTarget as h}from"./capacityIdentity.js";import{findAccountNameCollision as Y}from"./naming/accountNameCollision.js";import{defaultConnectedAccountName as v,suffixedAccountName as y,REGION_SHORT_CODES as X,findTrailingRegionShortCode as K,regionSuffixRejectionMessage as b}from"./naming/connectedAccountName.js";import{normaliseError as W,getErrorMessage as k,hasErrorCode as j,getErrorCode as z,getErrorStack as Q,formatErrorString as Z}from"./errorUtils.js";import{singleton as w}from"./async/singleton.js";import{DANGEROUS_ENV_VARS as $,filterDangerousEnvVars as ee,MASKED_VALUE_MARKER as Ee,maskSensitiveOutput as re,parseShellArgs as te,REDACTED_KEY_SENTINEL as oe,SCOPED_TOKEN_REGEX as _e}from"./securityHelpers.js";import{sleep as ae}from"./async/sleep.js";import{mapSettledWithConcurrency as Te}from"./async/concurrency.js";import{ACCOUNT_STAGES_WITH_ROOT as ie,STRUCTURAL_ENVIRONMENTS as ne,ACCOUNT_STAGES as Ne,ACCOUNT_STAGE_LABELS as Ce,isAccountStage as me,ACCOUNT_TIERS as Oe,AccountTierSchema as Pe,isAccountTier as se,GOVERNANCE_ACCOUNT_TIERS as ce,isGovernanceTier as pe,environmentToTier as Ie,stageFromWireEnvironment as fe,accountTier as De,getEnvironmentLabel as ge,ACCOUNT_ROLES as Me}from"./environments.js";import{RESOURCE_CATEGORIES as xe,categoriseResource as Le,getExpectedDuration as Ue,getFriendlyResourceType as ue}from"./resourceCategorisation.js";import{parseGitRemoteUrl as le}from"./repo/gitRemoteParser.js";import{abbreviateRegion as he,AWS_REGIONS_METADATA as Fe,DEFAULT_REGION as Ye,getRegionInfo as He,MAX_SECONDARY_REGIONS as ve,OPT_IN_REGION_CODES as ye,optInRegionWarning as Xe,regions as Ke,suggestRegionForTimezone as be}from"./infra/regions.js";import{SCOPE_VALUES as We,MACHINE_ONLY_SCOPES as ke,USER_GRANTABLE_SCOPES as je,GOVERNANCE_SCOPE_REQUIRED_CODE as ze}from"./infra/tokenScopes.js";import{SECRET_NAME_PATTERN as Ze,SECRET_NAME_ERROR as qe,SSM_COMPONENT_PATTERN as we,SSM_COMPONENT_ERROR as Je,SSM_STANDARD_MAX_VALUE_BYTES as $e,SecretNamespaceSchema as eE,buildNamespaceParts as EE,buildParameterPath as rE,parseParameterPath as tE,isManageablePath as oE,parseDotEnv as _E,escapeDotEnvValue as AE}from"./secrets.js";import{ConnectionWireSchema as SE,ConnectionsListResponseSchema as TE}from"./infra/connectionsWire.js";import{deriveRegionsFromOrgConfig as iE,deriveTargets as nE,deriveAllTargets as NE,environmentOrTier as CE,findTarget as mE,generateTargetName as OE}from"./targets.js";import{buildAppConfigPath as sE}from"./repo/appPath.js";import{findInfrastructurePaths as pE,findBoundaryPath as IE,isInfrastructureFile as fE}from"./repo/findInfrastructurePaths.js";import{inferContainerFromCandidates as gE}from"./repo/inferContainerFromCandidates.js";import{RESERVED_APP_NAMES as dE,RESERVED_APP_NAME_MESSAGE as xE,isReservedAppName as LE,RESERVED_APP_NAME_SUFFIX as UE,RESERVED_APP_NAME_SUFFIX_MESSAGE as uE,hasReservedAppNameSuffix as VE}from"./naming/reservedAppNames.js";import{deriveContentHashTag as GE,CONTENT_HASH_TAG_PATTERN as hE}from"./infra/deriveContentHashTag.js";import{DEPLOY_MODES as YE,DeployModeSchema as HE,IMAGE_TAG_PATTERN as vE,ImageTagSchema as yE,ServiceArtefactSchema as XE,ServiceArtefactsSchema as KE,ARTEFACT_OUTPUT_FIELDS as bE,artefactOutputKey as BE}from"./infra/deployArtefacts.js";import{MIGRATION_SNAPSHOT_NAME_PREFIX as kE,EXPECTED_SCHEMA_VERSION_ENV as jE,EXPECTED_SCHEMA_VERSION_TOOL_ENV as zE,EXPECTED_CH_SCHEMA_VERSION_ENV as QE,SCHEMA_ADMIN_USER_ENV as ZE,SCHEMA_ADMIN_PASSWORD_ENV as qE,PRISMA_MIGRATION_DIR_RE as wE,CLICKHOUSE_MIGRATION_SKIP_RE as JE}from"./migration/constants.js";import{PHYSICAL_NAME_FALLBACK_PROPERTIES as er}from"./cfn/physicalNameProperties.js";import{PATTERN_TYPE_VALUES as rr,PATTERN_TYPES as tr,isPatternType as or,PATTERN_REGISTRY as _r,DEPLOYABLE_PATTERN_TYPES as Ar,OPENNEXT_PATTERN_TYPES as ar,isOpenNextPatternType as Sr,STATIC_SITE_ROUTING_VALUES as Tr}from"./patterns/patternTypes.js";import{DEFAULT_FORMS_FROM_LOCAL_PART as ir,defaultFormsFromAddress as nr,defaultFormsCorsOrigin as Nr,isAddressAtDomain as Cr}from"./patterns/staticSiteForms.js";import{DEV_SUBSTRATE_PARAMS_SCHEMA_VERSION as Or,DEV_SUBSTRATE_PARAMS_FILENAME as Pr,DevSubstrateSynthPropsSchema as sr,DevSubstrateParamsSchema as cr}from"./devSubstrate/params.js";import{DEV_SUBSTRATE_ENTRYPOINT_SOURCE as Ir}from"./devSubstrate/entrypoint.js";export{Me as ACCOUNT_ROLES,Ne as ACCOUNT_STAGES,ie as ACCOUNT_STAGES_WITH_ROOT,Ce as ACCOUNT_STAGE_LABELS,Oe as ACCOUNT_TIERS,i as APPROVAL_TOKEN_OUTPUT_PREFIX,bE as ARTEFACT_OUTPUT_FIELDS,Fe as AWS_REGIONS_METADATA,Pe as AccountTierSchema,T as BACKUP_VAULT_NAME,U as CAPACITY_ANCHOR_MAX_LENGTH,L as CAPACITY_ANCHOR_PATTERN,u as CAPACITY_IDENTITY_CONTEXT_KEY,d as CAPACITY_SLOT_MAX_LENGTH,M as CAPACITY_SLOT_PATTERN,JE as CLICKHOUSE_MIGRATION_SKIP_RE,hE as CONTENT_HASH_TAG_PATTERN,G as CapacityIdentityConfigSchema,V as CapacityIdentityPinSchema,l as CapacityIdentityWireSchema,SE as ConnectionWireSchema,TE as ConnectionsListResponseSchema,$ as DANGEROUS_ENV_VARS,x as DEFAULT_CAPACITY_SLOT,ir as DEFAULT_FORMS_FROM_LOCAL_PART,Ye as DEFAULT_REGION,Ar as DEPLOYABLE_PATTERN_TYPES,YE as DEPLOY_MODES,Ir as DEV_SUBSTRATE_ENTRYPOINT_SOURCE,Pr as DEV_SUBSTRATE_PARAMS_FILENAME,Or as DEV_SUBSTRATE_PARAMS_SCHEMA_VERSION,r as DNS_APEX,a as DOMAIN_DEPLOY_DEFAULT_PHASE,HE as DeployModeSchema,cr as DevSubstrateParamsSchema,sr as DevSubstrateSynthPropsSchema,QE as EXPECTED_CH_SCHEMA_VERSION_ENV,jE as EXPECTED_SCHEMA_VERSION_ENV,zE as EXPECTED_SCHEMA_VERSION_TOOL_ENV,ce as GOVERNANCE_ACCOUNT_TIERS,ze as GOVERNANCE_SCOPE_REQUIRED_CODE,vE as IMAGE_TAG_PATTERN,yE as ImageTagSchema,ke as MACHINE_ONLY_SCOPES,Ee as MASKED_VALUE_MARKER,ve as MAX_SECONDARY_REGIONS,kE as MIGRATION_SNAPSHOT_NAME_PREFIX,ar as OPENNEXT_PATTERN_TYPES,ye as OPT_IN_REGION_CODES,_r as PATTERN_REGISTRY,tr as PATTERN_TYPES,rr as PATTERN_TYPE_VALUES,er as PHYSICAL_NAME_FALLBACK_PROPERTIES,wE as PRISMA_MIGRATION_DIR_RE,oe as REDACTED_KEY_SENTINEL,X as REGION_SHORT_CODES,dE as RESERVED_APP_NAMES,xE as RESERVED_APP_NAME_MESSAGE,UE as RESERVED_APP_NAME_SUFFIX,uE as RESERVED_APP_NAME_SUFFIX_MESSAGE,xe as RESOURCE_CATEGORIES,qE as SCHEMA_ADMIN_PASSWORD_ENV,ZE as SCHEMA_ADMIN_USER_ENV,_e as SCOPED_TOKEN_REGEX,We as SCOPE_VALUES,qe as SECRET_NAME_ERROR,Ze as SECRET_NAME_PATTERN,Je as SSM_COMPONENT_ERROR,we as SSM_COMPONENT_PATTERN,$e as SSM_STANDARD_MAX_VALUE_BYTES,Tr as STATIC_SITE_ROUTING_VALUES,ne as STRUCTURAL_ENVIRONMENTS,eE as SecretNamespaceSchema,XE as ServiceArtefactSchema,KE as ServiceArtefactsSchema,n as TOKEN_STDERR_PREFIX,je as USER_GRANTABLE_SCOPES,he as abbreviateRegion,f as accountConstructKey,De as accountTier,BE as artefactOutputKey,sE as buildAppConfigPath,EE as buildNamespaceParts,rE as buildParameterPath,p as capitalise,Le as categoriseResource,v as defaultConnectedAccountName,Nr as defaultFormsCorsOrigin,nr as defaultFormsFromAddress,NE as deriveAllTargets,GE as deriveContentHashTag,iE as deriveRegionsFromOrgConfig,nE as deriveTargets,CE as environmentOrTier,Ie as environmentToTier,AE as escapeDotEnvValue,ee as filterDangerousEnvVars,Y as findAccountNameCollision,IE as findBoundaryPath,pE as findInfrastructurePaths,mE as findTarget,K as findTrailingRegionShortCode,Z as formatErrorString,OE as generateTargetName,t as getDomainExportNames,o as getDomainStackName,_ as getDomainUsEast1CertificatesStackName,ge as getEnvironmentLabel,z as getErrorCode,k as getErrorMessage,Q as getErrorStack,Ue as getExpectedDuration,ue as getFriendlyResourceType,He as getRegionInfo,I as getSafeZoneName,D as hasAsciiStableConstructKey,j as hasErrorCode,VE as hasReservedAppNameSuffix,C as imageTagParameterName,gE as inferContainerFromCandidates,me as isAccountStage,se as isAccountTier,Cr as isAddressAtDomain,pe as isGovernanceTier,fE as isInfrastructureFile,oE as isManageablePath,A as isManagedDomainBinding,Sr as isOpenNextPatternType,or as isPatternType,LE as isReservedAppName,Te as mapSettledWithConcurrency,re as maskSensitiveOutput,W as normaliseError,Xe as optInRegionWarning,_E as parseDotEnv,le as parseGitRemoteUrl,tE as parseParameterPath,te as parseShellArgs,h as projectCapacityIdentityToTarget,b as regionSuffixRejectionMessage,Ke as regions,w as singleton,ae as sleep,fe as stageFromWireEnvironment,y as suffixedAccountName,be as suggestRegionForTimezone,P as toKebab,O as toPascalCase,c as toScreamingSnake,s as toValidDatabaseName};
1
+ import{DNS_APEX as r,getDomainExportNames as t,getDomainStackName as o,getDomainUsEast1CertificatesStackName as _,isManagedDomainBinding as a,DOMAIN_DEPLOY_DEFAULT_PHASE as A}from"./infra/domainExports.js";import{BACKUP_VAULT_NAME as T}from"./infra/backupVault.js";import{APPROVAL_TOKEN_OUTPUT_PREFIX as i,TOKEN_STDERR_PREFIX as R}from"./deploy/approvalTokenOutput.js";import{imageTagParameterName as m}from"./infra/imageTags.js";import{toPascalCase as s,toKebab as O,toValidDatabaseName as P,toScreamingSnake as p,capitalise as c,getSafeZoneName as I,accountConstructKey as f,hasAsciiStableConstructKey as D}from"./naming/caseConversion.js";import{albDnsExportName as M,albHostedZoneIdExportName as d,cdnDomainExportName as x,bucketWebsiteEndpointExportName as u,bucketWebsiteHostedZoneIdExportName as L}from"./naming/targetExportNames.js";import{CAPACITY_SLOT_PATTERN as l,CAPACITY_SLOT_MAX_LENGTH as V,DEFAULT_CAPACITY_SLOT as h,CAPACITY_ANCHOR_PATTERN as G,CAPACITY_ANCHOR_MAX_LENGTH as F,CAPACITY_IDENTITY_CONTEXT_KEY as H,CapacityIdentityPinSchema as v,CapacityIdentityWireSchema as Y,CapacityIdentityConfigSchema as y,projectCapacityIdentityToTarget as b}from"./capacityIdentity.js";import{findAccountNameCollision as K}from"./naming/accountNameCollision.js";import{defaultConnectedAccountName as W,suffixedAccountName as k,REGION_SHORT_CODES as Z,findTrailingRegionShortCode as j,regionSuffixRejectionMessage as z}from"./naming/connectedAccountName.js";import{normaliseError as q,getErrorMessage as w,hasErrorCode as J,getErrorCode as $,getErrorStack as ee,formatErrorString as Ee}from"./errorUtils.js";import{singleton as te}from"./async/singleton.js";import{DANGEROUS_ENV_VARS as _e,filterDangerousEnvVars as ae,MASKED_VALUE_MARKER as Ae,maskSensitiveOutput as Se,parseShellArgs as Te,REDACTED_KEY_SENTINEL as ne,SCOPED_TOKEN_REGEX as ie}from"./securityHelpers.js";import{sleep as Ne}from"./async/sleep.js";import{mapSettledWithConcurrency as Ce}from"./async/concurrency.js";import{ACCOUNT_STAGES_WITH_ROOT as Oe,STRUCTURAL_ENVIRONMENTS as Pe,ACCOUNT_STAGES as pe,ACCOUNT_STAGE_LABELS as ce,isAccountStage as Ie,ACCOUNT_TIERS as fe,AccountTierSchema as De,isAccountTier as ge,GOVERNANCE_ACCOUNT_TIERS as Me,isGovernanceTier as de,environmentToTier as xe,stageFromWireEnvironment as ue,accountTier as Le,resolveSynthEnvironment as Ue,getEnvironmentLabel as le,ACCOUNT_ROLES as Ve}from"./environments.js";import{RESOURCE_CATEGORIES as Ge,categoriseResource as Fe,getExpectedDuration as He,getFriendlyResourceType as ve}from"./resourceCategorisation.js";import{parseGitRemoteUrl as ye}from"./repo/gitRemoteParser.js";import{abbreviateRegion as Xe,AWS_REGIONS_METADATA as Ke,DEFAULT_REGION as Be,getRegionInfo as We,MAX_SECONDARY_REGIONS as ke,OPT_IN_REGION_CODES as Ze,optInRegionWarning as je,regions as ze,suggestRegionForTimezone as Qe}from"./infra/regions.js";import{SCOPE_VALUES as we,MACHINE_ONLY_SCOPES as Je,USER_GRANTABLE_SCOPES as $e,GOVERNANCE_SCOPE_REQUIRED_CODE as eE}from"./infra/tokenScopes.js";import{SECRET_NAME_PATTERN as rE,SECRET_NAME_ERROR as tE,SSM_COMPONENT_PATTERN as oE,SSM_COMPONENT_ERROR as _E,SSM_STANDARD_MAX_VALUE_BYTES as aE,SecretNamespaceSchema as AE,buildNamespaceParts as SE,buildParameterPath as TE,parseParameterPath as nE,isManageablePath as iE,parseDotEnv as RE,escapeDotEnvValue as NE}from"./secrets.js";import{ConnectionWireSchema as CE,ConnectionsListResponseSchema as sE}from"./infra/connectionsWire.js";import{deriveRegionsFromOrgConfig as PE,deriveTargets as pE,deriveAllTargets as cE,environmentOrTier as IE,findTarget as fE,generateTargetName as DE}from"./targets.js";import{buildAppConfigPath as ME}from"./repo/appPath.js";import{findInfrastructurePaths as xE,findBoundaryPath as uE,isInfrastructureFile as LE}from"./repo/findInfrastructurePaths.js";import{inferContainerFromCandidates as lE}from"./repo/inferContainerFromCandidates.js";import{RESERVED_APP_NAMES as hE,RESERVED_APP_NAME_MESSAGE as GE,isReservedAppName as FE,RESERVED_APP_NAME_SUFFIX as HE,RESERVED_APP_NAME_SUFFIX_MESSAGE as vE,hasReservedAppNameSuffix as YE}from"./naming/reservedAppNames.js";import{deriveContentHashTag as bE,CONTENT_HASH_TAG_PATTERN as XE}from"./infra/deriveContentHashTag.js";import{DEPLOY_MODES as BE,DeployModeSchema as WE,IMAGE_TAG_PATTERN as kE,ImageTagSchema as ZE,ServiceArtefactSchema as jE,ServiceArtefactsSchema as zE,ARTEFACT_OUTPUT_FIELDS as QE,artefactOutputKey as qE}from"./infra/deployArtefacts.js";import{MIGRATION_SNAPSHOT_NAME_PREFIX as JE,EXPECTED_SCHEMA_VERSION_ENV as $E,EXPECTED_SCHEMA_VERSION_TOOL_ENV as er,EXPECTED_CH_SCHEMA_VERSION_ENV as Er,SCHEMA_ADMIN_USER_ENV as rr,SCHEMA_ADMIN_PASSWORD_ENV as tr,PRISMA_MIGRATION_DIR_RE as or,CLICKHOUSE_MIGRATION_SKIP_RE as _r}from"./migration/constants.js";import{PHYSICAL_NAME_FALLBACK_PROPERTIES as Ar}from"./cfn/physicalNameProperties.js";import{PATTERN_TYPE_VALUES as Tr,PATTERN_TYPES as nr,isPatternType as ir,PATTERN_REGISTRY as Rr,DEPLOYABLE_PATTERN_TYPES as Nr,OPENNEXT_PATTERN_TYPES as mr,isOpenNextPatternType as Cr,STATIC_SITE_ROUTING_VALUES as sr}from"./patterns/patternTypes.js";import{DEFAULT_FORMS_FROM_LOCAL_PART as Pr,defaultFormsFromAddress as pr,defaultFormsCorsOrigin as cr,isAddressAtDomain as Ir}from"./patterns/staticSiteForms.js";import{DEV_SUBSTRATE_PARAMS_SCHEMA_VERSION as Dr,DEV_SUBSTRATE_PARAMS_FILENAME as gr,DevSubstrateSynthPropsSchema as Mr,DevSubstrateParamsSchema as dr}from"./devSubstrate/params.js";import{DEV_SUBSTRATE_ENTRYPOINT_SOURCE as ur}from"./devSubstrate/entrypoint.js";export{Ve as ACCOUNT_ROLES,pe as ACCOUNT_STAGES,Oe as ACCOUNT_STAGES_WITH_ROOT,ce as ACCOUNT_STAGE_LABELS,fe as ACCOUNT_TIERS,i as APPROVAL_TOKEN_OUTPUT_PREFIX,QE as ARTEFACT_OUTPUT_FIELDS,Ke as AWS_REGIONS_METADATA,De as AccountTierSchema,T as BACKUP_VAULT_NAME,F as CAPACITY_ANCHOR_MAX_LENGTH,G as CAPACITY_ANCHOR_PATTERN,H as CAPACITY_IDENTITY_CONTEXT_KEY,V as CAPACITY_SLOT_MAX_LENGTH,l as CAPACITY_SLOT_PATTERN,_r as CLICKHOUSE_MIGRATION_SKIP_RE,XE as CONTENT_HASH_TAG_PATTERN,y as CapacityIdentityConfigSchema,v as CapacityIdentityPinSchema,Y as CapacityIdentityWireSchema,CE as ConnectionWireSchema,sE as ConnectionsListResponseSchema,_e as DANGEROUS_ENV_VARS,h as DEFAULT_CAPACITY_SLOT,Pr as DEFAULT_FORMS_FROM_LOCAL_PART,Be as DEFAULT_REGION,Nr as DEPLOYABLE_PATTERN_TYPES,BE as DEPLOY_MODES,ur as DEV_SUBSTRATE_ENTRYPOINT_SOURCE,gr as DEV_SUBSTRATE_PARAMS_FILENAME,Dr as DEV_SUBSTRATE_PARAMS_SCHEMA_VERSION,r as DNS_APEX,A as DOMAIN_DEPLOY_DEFAULT_PHASE,WE as DeployModeSchema,dr as DevSubstrateParamsSchema,Mr as DevSubstrateSynthPropsSchema,Er as EXPECTED_CH_SCHEMA_VERSION_ENV,$E as EXPECTED_SCHEMA_VERSION_ENV,er as EXPECTED_SCHEMA_VERSION_TOOL_ENV,Me as GOVERNANCE_ACCOUNT_TIERS,eE as GOVERNANCE_SCOPE_REQUIRED_CODE,kE as IMAGE_TAG_PATTERN,ZE as ImageTagSchema,Je as MACHINE_ONLY_SCOPES,Ae as MASKED_VALUE_MARKER,ke as MAX_SECONDARY_REGIONS,JE as MIGRATION_SNAPSHOT_NAME_PREFIX,mr as OPENNEXT_PATTERN_TYPES,Ze as OPT_IN_REGION_CODES,Rr as PATTERN_REGISTRY,nr as PATTERN_TYPES,Tr as PATTERN_TYPE_VALUES,Ar as PHYSICAL_NAME_FALLBACK_PROPERTIES,or as PRISMA_MIGRATION_DIR_RE,ne as REDACTED_KEY_SENTINEL,Z as REGION_SHORT_CODES,hE as RESERVED_APP_NAMES,GE as RESERVED_APP_NAME_MESSAGE,HE as RESERVED_APP_NAME_SUFFIX,vE as RESERVED_APP_NAME_SUFFIX_MESSAGE,Ge as RESOURCE_CATEGORIES,tr as SCHEMA_ADMIN_PASSWORD_ENV,rr as SCHEMA_ADMIN_USER_ENV,ie as SCOPED_TOKEN_REGEX,we as SCOPE_VALUES,tE as SECRET_NAME_ERROR,rE as SECRET_NAME_PATTERN,_E as SSM_COMPONENT_ERROR,oE as SSM_COMPONENT_PATTERN,aE as SSM_STANDARD_MAX_VALUE_BYTES,sr as STATIC_SITE_ROUTING_VALUES,Pe as STRUCTURAL_ENVIRONMENTS,AE as SecretNamespaceSchema,jE as ServiceArtefactSchema,zE as ServiceArtefactsSchema,R as TOKEN_STDERR_PREFIX,$e as USER_GRANTABLE_SCOPES,Xe as abbreviateRegion,f as accountConstructKey,Le as accountTier,M as albDnsExportName,d as albHostedZoneIdExportName,qE as artefactOutputKey,u as bucketWebsiteEndpointExportName,L as bucketWebsiteHostedZoneIdExportName,ME as buildAppConfigPath,SE as buildNamespaceParts,TE as buildParameterPath,c as capitalise,Fe as categoriseResource,x as cdnDomainExportName,W as defaultConnectedAccountName,cr as defaultFormsCorsOrigin,pr as defaultFormsFromAddress,cE as deriveAllTargets,bE as deriveContentHashTag,PE as deriveRegionsFromOrgConfig,pE as deriveTargets,IE as environmentOrTier,xe as environmentToTier,NE as escapeDotEnvValue,ae as filterDangerousEnvVars,K as findAccountNameCollision,uE as findBoundaryPath,xE as findInfrastructurePaths,fE as findTarget,j as findTrailingRegionShortCode,Ee as formatErrorString,DE as generateTargetName,t as getDomainExportNames,o as getDomainStackName,_ as getDomainUsEast1CertificatesStackName,le as getEnvironmentLabel,$ as getErrorCode,w as getErrorMessage,ee as getErrorStack,He as getExpectedDuration,ve as getFriendlyResourceType,We as getRegionInfo,I as getSafeZoneName,D as hasAsciiStableConstructKey,J as hasErrorCode,YE as hasReservedAppNameSuffix,m as imageTagParameterName,lE as inferContainerFromCandidates,Ie as isAccountStage,ge as isAccountTier,Ir as isAddressAtDomain,de as isGovernanceTier,LE as isInfrastructureFile,iE as isManageablePath,a as isManagedDomainBinding,Cr as isOpenNextPatternType,ir as isPatternType,FE as isReservedAppName,Ce as mapSettledWithConcurrency,Se as maskSensitiveOutput,q as normaliseError,je as optInRegionWarning,RE as parseDotEnv,ye as parseGitRemoteUrl,nE as parseParameterPath,Te as parseShellArgs,b as projectCapacityIdentityToTarget,z as regionSuffixRejectionMessage,ze as regions,Ue as resolveSynthEnvironment,te as singleton,Ne as sleep,ue as stageFromWireEnvironment,k as suffixedAccountName,Qe as suggestRegionForTimezone,O as toKebab,s as toPascalCase,p as toScreamingSnake,P as toValidDatabaseName};
@@ -1,18 +1,25 @@
1
1
  /**
2
- * Tool-discriminated boot-time gate: verify a relational database's most
3
- * recently applied migration matches the expected version baked into the
4
- * deployed image. Companion to {@link pickLatestPrismaMigration} (which
2
+ * Tool-discriminated boot-time gate: verify a relational database's
3
+ * latest-by-name applied migration matches the expected version baked into
4
+ * the deployed image. Companion to {@link pickLatestPrismaMigration} (which
5
5
  * resolves the expected version FROM disk at synth/runner time); this
6
6
  * helper closes the loop by reading what the DB actually has APPLIED.
7
7
  *
8
+ * "Latest" MUST mean lexicographic max of migration_name, mirroring
9
+ * pickLatestPrismaMigration — NOT most recently finished. Prisma's
10
+ * `migrate deploy` applies a pending migration even when it name-sorts
11
+ * before already-applied ones (parallel branches landing interleaved
12
+ * timestamps), so latest-by-finished_at can be an OLDER name than what the
13
+ * schema actually satisfies, false-failing the gate against a complete DB.
14
+ *
8
15
  * Consumer supplies the driver via the {@link MigrationsSqlClient} shim so
9
16
  * the package stays driver-agnostic (pg, mysql2, postgres.js, Drizzle
10
17
  * session, raw Prisma `$queryRawUnsafe`, …). The shim's single `query(sql)`
11
18
  * surface is intentionally narrower than any real driver — callers wrap.
12
19
  *
13
20
  * Two tool branches today:
14
- * - `tool: "prisma"` reads `_prisma_migrations.migration_name` (most-recent
15
- * `finished_at IS NOT NULL`). Stable across all Prisma DB engines.
21
+ * - `tool: "prisma"` reads `_prisma_migrations.migration_name` (max name
22
+ * among `finished_at IS NOT NULL`). Stable across all Prisma DB engines.
16
23
  * - `tool: "custom"` lets a caller pass a `{ sql, column }` pair when the
17
24
  * migration tool's metadata table doesn't match the Prisma shape (e.g.
18
25
  * Drizzle's `__drizzle_migrations.hash`, Knex's `knex_migrations.name`).
@@ -1 +1 @@
1
- var s=Object.defineProperty;var c=(e,r)=>s(e,"name",{value:r,configurable:!0});import{isSchemaVersionSatisfied as a}from"./compareSchemaVersion.js";const u="SELECT migration_name FROM _prisma_migrations WHERE finished_at IS NOT NULL ORDER BY finished_at DESC LIMIT 1",l="migration_name";async function E(e){if(e.signal?.aborted)throw new Error("verifyExpectedSchemaVersion: aborted by signal before query");let r,n;if(e.tool==="prisma")r=u,n=l;else if(e.tool==="custom"){if(e.customQuery===void 0)throw new Error('verifyExpectedSchemaVersion: tool="custom" requires customQuery');r=e.customQuery.sql,n=e.customQuery.column}else throw new Error(`verifyExpectedSchemaVersion: unknown tool ${String(e.tool)}`);const i=(await e.client.query(r)).rows[0],o=i!==void 0?i[n]:void 0,t=typeof o=="string"?o:null;return{matches:t!==null&&a(e.expected,t),expected:e.expected,actual:t}}c(E,"verifyExpectedSchemaVersion");export{E as verifyExpectedSchemaVersion};
1
+ var a=Object.defineProperty;var c=(e,r)=>a(e,"name",{value:r,configurable:!0});import{isSchemaVersionSatisfied as s}from"./compareSchemaVersion.js";const u="SELECT migration_name FROM _prisma_migrations WHERE finished_at IS NOT NULL ORDER BY migration_name DESC LIMIT 1",m="migration_name";async function E(e){if(e.signal?.aborted)throw new Error("verifyExpectedSchemaVersion: aborted by signal before query");let r,n;if(e.tool==="prisma")r=u,n=m;else if(e.tool==="custom"){if(e.customQuery===void 0)throw new Error('verifyExpectedSchemaVersion: tool="custom" requires customQuery');r=e.customQuery.sql,n=e.customQuery.column}else throw new Error(`verifyExpectedSchemaVersion: unknown tool ${String(e.tool)}`);const i=(await e.client.query(r)).rows[0],o=i!==void 0?i[n]:void 0,t=typeof o=="string"?o:null;return{matches:t!==null&&s(e.expected,t),expected:e.expected,actual:t}}c(E,"verifyExpectedSchemaVersion");export{E as verifyExpectedSchemaVersion};
@@ -1 +1 @@
1
- var d=Object.defineProperty;var i=(t,e)=>d(t,"name",{value:e,configurable:!0});import{describe as c,expect as a,it as s,vi as u}from"vitest";import{verifyExpectedSchemaVersion as o}from"./verifyExpectedSchemaVersion.js";function n(t){const e=[];return{client:{query:u.fn(async l=>(e.push(l),{rows:t}))},queries:e}}i(n,"makeMockClient"),c("verifyExpectedSchemaVersion",()=>{c('tool: "prisma"',()=>{s("returns matches=true when actual === expected",async()=>{const{client:t,queries:e}=n([{migration_name:"20260520000000_add_widgets"}]),r=await o({tool:"prisma",expected:"20260520000000_add_widgets",client:t});a(r).toEqual({matches:!0,expected:"20260520000000_add_widgets",actual:"20260520000000_add_widgets"}),a(e).toHaveLength(1),a(e[0]).toContain("_prisma_migrations"),a(e[0]).toContain("finished_at IS NOT NULL"),a(e[0]).toContain("ORDER BY finished_at DESC LIMIT 1")}),s("returns matches=false with actual when DB trails image",async()=>{const{client:t}=n([{migration_name:"20260519000000_old"}]),e=await o({tool:"prisma",expected:"20260520000000_add_widgets",client:t});a(e).toEqual({matches:!1,expected:"20260520000000_add_widgets",actual:"20260519000000_old"})}),s("returns matches=true when DB is AHEAD (expand-only rollback)",async()=>{const{client:t}=n([{migration_name:"20260521000000_add_more_widgets"}]),e=await o({tool:"prisma",expected:"20260520000000_add_widgets",client:t});a(e).toEqual({matches:!0,expected:"20260520000000_add_widgets",actual:"20260521000000_add_more_widgets"})}),s("returns actual=null on empty result set",async()=>{const{client:t}=n([]),e=await o({tool:"prisma",expected:"20260520000000_add_widgets",client:t});a(e).toEqual({matches:!1,expected:"20260520000000_add_widgets",actual:null})}),s("returns actual=null when row's migration_name is not a string",async()=>{const{client:t}=n([{migration_name:12345}]),e=await o({tool:"prisma",expected:"x",client:t});a(e.actual).toBeNull(),a(e.matches).toBe(!1)})}),c('tool: "custom"',()=>{s("uses customQuery sql and column",async()=>{const{client:t,queries:e}=n([{hash:"deadbeef"}]),r=await o({tool:"custom",expected:"deadbeef",client:t,customQuery:{sql:"SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1",column:"hash"}});a(r.matches).toBe(!0),a(r.actual).toBe("deadbeef"),a(e[0]).toBe("SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1")}),s("stays strict for non-orderable versions even when actual sorts later",async()=>{const{client:t}=n([{hash:"ffffffff"}]),e=await o({tool:"custom",expected:"00000000",client:t,customQuery:{sql:"SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1",column:"hash"}});a(e.matches).toBe(!1),a(e.actual).toBe("ffffffff")}),s("throws when customQuery is omitted",async()=>{const{client:t}=n([]);await a(o({tool:"custom",expected:"x",client:t})).rejects.toThrow(/tool="custom" requires customQuery/)})}),c("abort signal",()=>{s("short-circuits before query when signal is already aborted",async()=>{const{client:t,queries:e}=n([{migration_name:"irrelevant"}]),r=new AbortController;r.abort(),await a(o({tool:"prisma",expected:"x",client:t,signal:r.signal})).rejects.toThrow(/aborted by signal before query/),a(e).toEqual([])})})});
1
+ var d=Object.defineProperty;var c=(e,t)=>d(e,"name",{value:t,configurable:!0});import{describe as r,expect as a,it as o,vi as u}from"vitest";import{verifyExpectedSchemaVersion as n}from"./verifyExpectedSchemaVersion.js";function i(e){const t=[];return{client:{query:u.fn(async l=>(t.push(l),{rows:e}))},queries:t}}c(i,"makeMockClient"),r("verifyExpectedSchemaVersion",()=>{r('tool: "prisma"',()=>{o("returns matches=true when actual === expected",async()=>{const{client:e,queries:t}=i([{migration_name:"20260520000000_add_widgets"}]),s=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(s).toEqual({matches:!0,expected:"20260520000000_add_widgets",actual:"20260520000000_add_widgets"}),a(t).toHaveLength(1),a(t[0]).toContain("_prisma_migrations"),a(t[0]).toContain("finished_at IS NOT NULL"),a(t[0]).toContain("ORDER BY migration_name DESC LIMIT 1")}),o("orders by migration_name, not finished_at (out-of-order application)",async()=>{const{client:e,queries:t}=i([{migration_name:"20260809140000_drop_admin_plugin_columns"}]),s=await n({tool:"prisma",expected:"20260809140000_drop_admin_plugin_columns",client:e});a(s.matches).toBe(!0),a(t[0]).not.toContain("ORDER BY finished_at"),a(t[0]).toContain("ORDER BY migration_name DESC LIMIT 1")}),o("returns matches=false with actual when DB trails image",async()=>{const{client:e}=i([{migration_name:"20260519000000_old"}]),t=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(t).toEqual({matches:!1,expected:"20260520000000_add_widgets",actual:"20260519000000_old"})}),o("returns matches=true when DB is AHEAD (expand-only rollback)",async()=>{const{client:e}=i([{migration_name:"20260521000000_add_more_widgets"}]),t=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(t).toEqual({matches:!0,expected:"20260520000000_add_widgets",actual:"20260521000000_add_more_widgets"})}),o("returns actual=null on empty result set",async()=>{const{client:e}=i([]),t=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(t).toEqual({matches:!1,expected:"20260520000000_add_widgets",actual:null})}),o("returns actual=null when row's migration_name is not a string",async()=>{const{client:e}=i([{migration_name:12345}]),t=await n({tool:"prisma",expected:"x",client:e});a(t.actual).toBeNull(),a(t.matches).toBe(!1)})}),r('tool: "custom"',()=>{o("uses customQuery sql and column",async()=>{const{client:e,queries:t}=i([{hash:"deadbeef"}]),s=await n({tool:"custom",expected:"deadbeef",client:e,customQuery:{sql:"SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1",column:"hash"}});a(s.matches).toBe(!0),a(s.actual).toBe("deadbeef"),a(t[0]).toBe("SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1")}),o("stays strict for non-orderable versions even when actual sorts later",async()=>{const{client:e}=i([{hash:"ffffffff"}]),t=await n({tool:"custom",expected:"00000000",client:e,customQuery:{sql:"SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1",column:"hash"}});a(t.matches).toBe(!1),a(t.actual).toBe("ffffffff")}),o("throws when customQuery is omitted",async()=>{const{client:e}=i([]);await a(n({tool:"custom",expected:"x",client:e})).rejects.toThrow(/tool="custom" requires customQuery/)})}),r("abort signal",()=>{o("short-circuits before query when signal is already aborted",async()=>{const{client:e,queries:t}=i([{migration_name:"irrelevant"}]),s=new AbortController;s.abort(),await a(n({tool:"prisma",expected:"x",client:e,signal:s.signal})).rejects.toThrow(/aborted by signal before query/),a(t).toEqual([])})})});
@@ -0,0 +1,5 @@
1
+ export declare function albDnsExportName(appName: string, computeName?: string): string;
2
+ export declare function albHostedZoneIdExportName(appName: string, computeName?: string): string;
3
+ export declare function cdnDomainExportName(appName: string): string;
4
+ export declare function bucketWebsiteEndpointExportName(bucketName: string): string;
5
+ export declare function bucketWebsiteHostedZoneIdExportName(bucketName: string): string;
@@ -0,0 +1 @@
1
+ var a=Object.defineProperty;var n=(e,t)=>a(e,"name",{value:t,configurable:!0});import{toPascalCase as p}from"./caseConversion.js";function o(e){return p(e.replace(/[^A-Za-z0-9-]/g,""))}n(o,"safeExportToken");function i(e,t){const r=o(e);return t===void 0?r:`${r}-${o(t)}-`}n(i,"albExportScope");function d(e,t){return`${i(e,t)}AlbDnsName`}n(d,"albDnsExportName");function c(e,t){return`${i(e,t)}AlbHostedZoneId`}n(c,"albHostedZoneIdExportName");function b(e){return`${o(e)}CdnDistributionDomainName`}n(b,"cdnDomainExportName");function x(e){return`${o(e)}WebsiteEndpoint`}n(x,"bucketWebsiteEndpointExportName");function f(e){return`${o(e)}WebsiteHostedZoneId`}n(f,"bucketWebsiteHostedZoneIdExportName");export{d as albDnsExportName,c as albHostedZoneIdExportName,x as bucketWebsiteEndpointExportName,f as bucketWebsiteHostedZoneIdExportName,b as cdnDomainExportName};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/util",
3
- "version": "7.3.0",
3
+ "version": "9.0.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/fjall-tech/fjall.git",