@fjall/util 2.12.0 → 2.13.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 +1 -1
- package/dist/Config.d.ts +82 -3
- package/dist/Config.js +1 -1
- package/dist/backupVault.d.ts +7 -0
- package/dist/backupVault.js +1 -0
- package/dist/connectionsWire.d.ts +30 -0
- package/dist/connectionsWire.js +1 -0
- package/dist/environments.d.ts +14 -8
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/mcpProtocol/index.d.ts +3 -4
- package/dist/targets.d.ts +9 -0
- package/dist/targets.js +1 -1
- package/package.json +2 -2
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
61 files minified at 2026-06-10T21:04:19.408Z
|
package/dist/Config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { type Result } from "./docker/result.js";
|
|
2
3
|
import { type AccountTier } from "./environments.js";
|
|
3
4
|
/**
|
|
4
5
|
* Backup Vault Lock modes for an account's DisasterRecovery vault.
|
|
@@ -13,6 +14,40 @@ export type VaultLockMode = (typeof VAULT_LOCK_MODES)[number];
|
|
|
13
14
|
*/
|
|
14
15
|
export declare const S3_BPA_MODES: readonly ["enforced", "off"];
|
|
15
16
|
export type S3BpaMode = (typeof S3_BPA_MODES)[number];
|
|
17
|
+
/**
|
|
18
|
+
* Per-account management-events-trail lifecycle for the organisation-trail
|
|
19
|
+
* migration. Absent ⇒ legacy per-account trail, auto-eligible for migration
|
|
20
|
+
* once org-trail delivery is verified. "account" pins the per-account trail
|
|
21
|
+
* (the explicit reverse path). "draining" removes the trail resource while
|
|
22
|
+
* retaining its bucket + CMK. "org" is terminal: the organisation trail
|
|
23
|
+
* covers the account and local storage has been decommissioned.
|
|
24
|
+
*/
|
|
25
|
+
export declare const TRAIL_LIFECYCLE_STATES: readonly ["account", "draining", "org"];
|
|
26
|
+
export type TrailLifecycleState = (typeof TRAIL_LIFECYCLE_STATES)[number];
|
|
27
|
+
/**
|
|
28
|
+
* Trail names shared between the CDK constructs
|
|
29
|
+
* (@fjall/components-infrastructure) and the deploy-core org-trail migration —
|
|
30
|
+
* SDK probes (DescribeTrails) must match what the constructs synthesise.
|
|
31
|
+
*/
|
|
32
|
+
export declare const ACCOUNT_TRAIL_NAME = "managementEvents";
|
|
33
|
+
export declare const ORGANISATION_TRAIL_NAME = "organisationManagementEvents";
|
|
34
|
+
/**
|
|
35
|
+
* CDK-side trail-state vocabulary (the `fjallAccountTrailState` context
|
|
36
|
+
* value), shared between the CDK constructs and deploy-core's context
|
|
37
|
+
* builders. Distinct from TRAIL_LIFECYCLE_STATES: config intent
|
|
38
|
+
* ("account"/"draining"/"org") maps onto synth behaviour
|
|
39
|
+
* ("active"/"draining"/"removed").
|
|
40
|
+
*/
|
|
41
|
+
export declare const ACCOUNT_TRAIL_STATES: readonly ["active", "draining", "removed"];
|
|
42
|
+
export type AccountTrailState = (typeof ACCOUNT_TRAIL_STATES)[number];
|
|
43
|
+
/**
|
|
44
|
+
* Stack output keys (CfnOutput key + exportName) emitted by the Account /
|
|
45
|
+
* Organisation CDK patterns and read back by the deploy-core org-trail
|
|
46
|
+
* migration reconciler — both sides must use the same literals.
|
|
47
|
+
*/
|
|
48
|
+
export declare const TRAIL_BUCKET_OUTPUT_KEY = "FjallTrailBucketName";
|
|
49
|
+
export declare const TRAIL_KEY_ARN_OUTPUT_KEY = "FjallTrailKeyArn";
|
|
50
|
+
export declare const ORG_TRAIL_BUCKET_OUTPUT_KEY = "OrganisationTrailBucketName";
|
|
16
51
|
export type ProviderAccount = {
|
|
17
52
|
id: string;
|
|
18
53
|
name: string;
|
|
@@ -52,6 +87,17 @@ export type ProviderAccount = {
|
|
|
52
87
|
* instead). "enforced" sets all four account-level public-access flags true.
|
|
53
88
|
*/
|
|
54
89
|
s3BlockPublicAccess?: S3BpaMode;
|
|
90
|
+
/**
|
|
91
|
+
* Management-events-trail lifecycle for the org-trail migration. Absent ⇒
|
|
92
|
+
* legacy per-account trail (auto-eligible); see TRAIL_LIFECYCLE_STATES.
|
|
93
|
+
*/
|
|
94
|
+
trailLifecycle?: TrailLifecycleState;
|
|
95
|
+
/**
|
|
96
|
+
* Explicit acknowledgement that decommissioning the per-account trail
|
|
97
|
+
* discards its retained log history. Bucket deletion never proceeds without
|
|
98
|
+
* it — back up the bucket first if the history matters.
|
|
99
|
+
*/
|
|
100
|
+
acknowledgeTrailHistoryLoss?: boolean;
|
|
55
101
|
};
|
|
56
102
|
export type Profile = {
|
|
57
103
|
type: "sso" | "oidc";
|
|
@@ -100,17 +146,50 @@ export type RootConfig = z.infer<typeof RootConfigSchema>;
|
|
|
100
146
|
export declare class Config {
|
|
101
147
|
rootConfig: RootConfig;
|
|
102
148
|
private configPath;
|
|
149
|
+
/**
|
|
150
|
+
* True when the config file was FOUND on disk but could not be read.
|
|
151
|
+
* saveConfig refuses to write in that state — the in-memory config never
|
|
152
|
+
* included the real file's contents, so writing would clobber them.
|
|
153
|
+
*/
|
|
154
|
+
private loadFailed;
|
|
155
|
+
/**
|
|
156
|
+
* Top-level keys explicitly cleared this session (clearActiveTarget).
|
|
157
|
+
* The disk-preserving merge in saveConfig would otherwise resurrect them
|
|
158
|
+
* from the on-disk copy.
|
|
159
|
+
*/
|
|
160
|
+
private readonly clearedKeys;
|
|
103
161
|
constructor(rootConfig?: RootConfig, configPath?: string);
|
|
104
162
|
/**
|
|
105
163
|
* Find the config directory by walking up the directory tree.
|
|
106
164
|
* Looks for fjall/fjall-config.json or direct fjall-config.json.
|
|
165
|
+
* Walks up from `startDir` when provided, otherwise from process.cwd().
|
|
107
166
|
*/
|
|
108
167
|
private static findConfigDirectory;
|
|
109
168
|
private static loadConfigFile;
|
|
110
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Load the config, walking up from `startDir` (default process.cwd()).
|
|
171
|
+
*/
|
|
172
|
+
static loadConfig(startDir?: string): Config;
|
|
111
173
|
private static formatZodError;
|
|
112
|
-
saveConfig(): void
|
|
113
|
-
|
|
174
|
+
saveConfig(): Result<void, Error>;
|
|
175
|
+
/**
|
|
176
|
+
* Writability is checked at save time, not load time: POSIX rename replaces
|
|
177
|
+
* a read-only destination whenever the directory is writable, so without
|
|
178
|
+
* this guard the tmp-plus-rename write would silently replace a chmod-444
|
|
179
|
+
* config.
|
|
180
|
+
*/
|
|
181
|
+
private static assertWritable;
|
|
182
|
+
/**
|
|
183
|
+
* Disk-preserving merge: re-reads the on-disk config immediately before
|
|
184
|
+
* writing so sibling top-level keys written by a concurrent process between
|
|
185
|
+
* this session's load and save survive. In-memory keys win at top-level-key
|
|
186
|
+
* granularity; keys explicitly cleared this session are removed even when
|
|
187
|
+
* the disk copy still carries them. Unreadable or invalid disk state falls
|
|
188
|
+
* back to the in-memory state with a warning rather than blocking the save.
|
|
189
|
+
*/
|
|
190
|
+
private mergeWithDisk;
|
|
191
|
+
private static readDiskConfigForMerge;
|
|
192
|
+
static getConfigDirectory(startDir?: string): string | null;
|
|
114
193
|
getActiveTarget(): string | undefined;
|
|
115
194
|
setActiveTarget(name: string): void;
|
|
116
195
|
clearActiveTarget(): void;
|
package/dist/Config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as i from"fs";import*as f from"path";import{z as c}from"zod";import{failure as d,success as h}from"./docker/result.js";import{getErrorMessage as g}from"./errorUtils.js";import{logger as u}from"./logger.js";import{maskSensitiveOutput as l}from"./securityHelpers.js";const y=10,O=["compliance","governance","none"],$=["enforced","off"],_=["account","draining","org"],x="managementEvents",F="organisationManagementEvents",K=["active","draining","removed"],b="FjallTrailBucketName",k="FjallTrailKeyArn",L="OrganisationTrailBucketName",w=c.object({name:c.string(),type:c.enum(["apex","delegated"]),parentDomain:c.string().optional(),account:c.string().optional()}).strict(),m=c.object({activeTarget:c.string().optional(),domains:c.array(w).optional()}).strict(),T=m.keyof().options;function E(C,e,t){const n=e[t];n!==void 0&&(C[t]=n)}class s{rootConfig;configPath=null;loadFailed=!1;clearedKeys=new Set;constructor(e,t){this.rootConfig=e??{},this.configPath=t??null}static findConfigDirectory(e){let t=e!==void 0&&e!==""?e:process.cwd();for(let n=0;n<y;n++){const o=f.join(t,"fjall"),a=f.join(o,"fjall-config.json");if(i.existsSync(a))return o;const r=f.join(t,"fjall-config.json");if(i.existsSync(r))return t;const p=f.dirname(t);if(p===t)break;t=p}return null}static loadConfigFile(e){try{return i.accessSync(e,i.constants.R_OK),i.readFileSync(e,{encoding:"utf8"})}catch(t){return u.warn("Config",`Config file at ${e} could not be read; using defaults`,{file:e,error:l(g(t))}),null}}static loadConfig(e){const t=s.findConfigDirectory(e);if(!t)return new s;const n=f.join(t,"fjall-config.json"),o=s.loadConfigFile(n);if(o===null){const r=new s(void 0,n);return r.loadFailed=!0,r}let a;if(o!=="")try{a=m.parse(JSON.parse(o))}catch(r){throw s.formatZodError(r,"fjall-config.json")}return new s(a,n)}static formatZodError(e,t){if(e instanceof c.ZodError&&e.issues.length>0){const a=e.issues.map(r=>`${r.path.join(".")}: ${r.message}`).join("; ");return new Error(`Failed to parse ${t}: ${a}`)}const o=(e instanceof Error?e.message:String(e)).replace(/\n/g," ").substring(0,500);return new Error(`Failed to parse ${t}: ${o}`)}saveConfig(){let e=this.configPath;if(!e){const r=s.findConfigDirectory()||f.join(process.cwd(),"fjall");e=f.join(r,"fjall-config.json")}if(this.loadFailed)return d(new Error(`Refusing to save ${e}: the file exists but could not be read when this config loaded, so saving would replace its contents with state that never included them. Fix the file permissions (e.g. chmod u+rw ${e}) and retry.`));const t=f.dirname(e);try{i.mkdirSync(t,{recursive:!0})}catch(r){return d(new Error(`Cannot create config directory ${t}: ${l(g(r))}`))}const n=s.assertWritable(e,t);if(!n.success)return n;const o=JSON.stringify(this.mergeWithDisk(e),null,2),a=`${e}.tmp-${process.pid}`;try{i.writeFileSync(a,o,{mode:384}),i.renameSync(a,e)}catch(r){return d(new Error(`Failed to save ${e}: ${l(g(r))}`))}return h(void 0)}static assertWritable(e,t){if(i.existsSync(e))try{i.accessSync(e,i.constants.W_OK)}catch{return d(new Error(`Cannot save ${e}: the file is read-only. Make it writable (e.g. chmod u+w ${e}) and retry.`))}try{i.accessSync(t,i.constants.W_OK)}catch{return d(new Error(`Cannot save ${e}: the directory ${t} is not writable. Make it writable (e.g. chmod u+w ${t}) and retry.`))}return h(void 0)}mergeWithDisk(e){const t=s.readDiskConfigForMerge(e);if(t===void 0)return this.rootConfig;const n={...t};for(const o of T)E(n,this.rootConfig,o);for(const o of this.clearedKeys)delete n[o];return n}static readDiskConfigForMerge(e){if(!i.existsSync(e))return;let t;try{t=JSON.parse(i.readFileSync(e,{encoding:"utf8"}))}catch(o){u.warn("Config",`Could not re-read ${e} before saving; writing in-memory state without merging`,{file:e,error:l(g(o))});return}const n=m.safeParse(t);if(!n.success){u.warn("Config",`On-disk ${e} failed validation before saving; writing in-memory state without merging`,{file:e,error:l(n.error.message)});return}return n.data}static getConfigDirectory(e){return s.findConfigDirectory(e)}getActiveTarget(){return this.rootConfig.activeTarget}setActiveTarget(e){this.rootConfig.activeTarget=e,this.clearedKeys.delete("activeTarget")}clearActiveTarget(){this.rootConfig.activeTarget=void 0,this.clearedKeys.add("activeTarget")}getDomains(){return this.rootConfig.domains??[]}setDomains(e){this.rootConfig.domains=e}addDomain(e){this.rootConfig.domains||(this.rootConfig.domains=[]),this.rootConfig.domains.push(e)}getDomain(e){return this.rootConfig.domains?.find(t=>t.name.toLowerCase()===e.toLowerCase())}removeDomain(e){if(!this.rootConfig.domains)return!1;const t=this.rootConfig.domains.findIndex(n=>n.name.toLowerCase()===e.toLowerCase());return t===-1?!1:(this.rootConfig.domains.splice(t,1),!0)}}export{x as ACCOUNT_TRAIL_NAME,K as ACCOUNT_TRAIL_STATES,s as Config,F as ORGANISATION_TRAIL_NAME,L as ORG_TRAIL_BUCKET_OUTPUT_KEY,m as RootConfigSchema,$ as S3_BPA_MODES,b as TRAIL_BUCKET_OUTPUT_KEY,k as TRAIL_KEY_ARN_OUTPUT_KEY,_ as TRAIL_LIFECYCLE_STATES,O as VAULT_LOCK_MODES};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed name of the disaster-recovery backup vault. Single source of truth for
|
|
3
|
+
* the @fjall/components-infrastructure DisasterRecovery construct (which
|
|
4
|
+
* creates the vault under this name) and deploy-core's adopt-vs-create and
|
|
5
|
+
* survival probes (which look it up by the same name).
|
|
6
|
+
*/
|
|
7
|
+
export declare const BACKUP_VAULT_NAME = "backupVault";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t="backupVault";export{t as BACKUP_VAULT_NAME};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract for `GET /api/connections/list` — the single shared shape
|
|
3
|
+
* between the webapp producer (`webapp/app/routes/api/connections/list.ts`)
|
|
4
|
+
* and the CLI consumer (`FjallApiClient.getConnectedAccounts`). Neither side
|
|
5
|
+
* may redeclare this record: the producer conforms at compile time via
|
|
6
|
+
* `satisfies ConnectionWire`, the consumer parses with `safeParse`.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
export declare const ConnectionWireSchema: z.ZodObject<{
|
|
10
|
+
awsAccountId: z.ZodString;
|
|
11
|
+
accountName: z.ZodNullable<z.ZodString>;
|
|
12
|
+
status: z.ZodString;
|
|
13
|
+
role: z.ZodString;
|
|
14
|
+
roleArn: z.ZodString;
|
|
15
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
16
|
+
connectedAt: z.ZodString;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export type ConnectionWire = z.infer<typeof ConnectionWireSchema>;
|
|
19
|
+
export declare const ConnectionsListResponseSchema: z.ZodObject<{
|
|
20
|
+
accounts: z.ZodArray<z.ZodObject<{
|
|
21
|
+
awsAccountId: z.ZodString;
|
|
22
|
+
accountName: z.ZodNullable<z.ZodString>;
|
|
23
|
+
status: z.ZodString;
|
|
24
|
+
role: z.ZodString;
|
|
25
|
+
roleArn: z.ZodString;
|
|
26
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
27
|
+
connectedAt: z.ZodString;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
export type ConnectionsListResponse = z.infer<typeof ConnectionsListResponseSchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as n}from"zod";const t=n.object({awsAccountId:n.string(),accountName:n.string().nullable(),status:n.string(),role:n.string(),roleArn:n.string(),environment:n.string().optional(),connectedAt:n.string()}),e=n.object({accounts:n.array(t)});export{t as ConnectionWireSchema,e as ConnectionsListResponseSchema};
|
package/dist/environments.d.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Environment + account-axis constants shared across CLI, webapp, and
|
|
3
3
|
* deploy-core. Two independent axes live here: the workload STAGE
|
|
4
4
|
* ([[ACCOUNT_STAGES]]) and the structural TIER ([[ACCOUNT_TIERS]]). "root" is
|
|
5
|
-
* NOT a stage — it is the
|
|
6
|
-
*
|
|
5
|
+
* NOT a stage and NOT a tier — it is the wire environment marker that decodes
|
|
6
|
+
* to tier "organisation" via [[environmentToTier]], and is never
|
|
7
|
+
* user-selectable.
|
|
7
8
|
*/
|
|
8
9
|
import { z } from "zod";
|
|
9
10
|
export declare const ACCOUNT_STAGES: readonly ["production", "staging", "development", "platform", "compliance"];
|
|
@@ -27,8 +28,12 @@ export declare const STRUCTURAL_ENVIRONMENTS: {
|
|
|
27
28
|
* GET→PUT round-trip accept this superset, then decode "root" → null at
|
|
28
29
|
* PERSISTENCE via [[stageFromWireEnvironment]] (the DB never stores structural
|
|
29
30
|
* root). NOT a user-facing picker vocabulary — pickers use ACCOUNT_STAGES.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* PERMANENT ingest vocabulary, not a drain-gated shim: the separate-root
|
|
32
|
+
* connect deliberately carries environment:"root" as its intent marker
|
|
33
|
+
* (solo-to-org lifecycle ADR, decision 7), so wire-rejection of "root" is
|
|
34
|
+
* unreachable; only derived-EMIT of "root" retires, per-org, behind the CLI
|
|
35
|
+
* telemetry gate. See decisions/2026-06-07-account-tier-vs-stage-separation.md
|
|
36
|
+
* § "Wire back-compat (permanent, not transitional)".
|
|
32
37
|
*/
|
|
33
38
|
export declare const ACCOUNT_STAGES_WITH_ROOT: readonly ["production", "staging", "development", "platform", "compliance", "root"];
|
|
34
39
|
export type AccountStageWithRoot = (typeof ACCOUNT_STAGES_WITH_ROOT)[number];
|
|
@@ -37,8 +42,9 @@ export declare function getEnvironmentLabel(env: string): string;
|
|
|
37
42
|
/**
|
|
38
43
|
* Structural TIER axis: an account's role in the organisation. Independent of
|
|
39
44
|
* the workload STAGE axis ([[ACCOUNT_STAGES]]) — a tier is never derived from a
|
|
40
|
-
* stage and vice versa. Same literals as [[ACCOUNT_ROLES]]
|
|
41
|
-
*
|
|
45
|
+
* stage and vice versa. Same literals as [[ACCOUNT_ROLES]]: its `satisfies`
|
|
46
|
+
* clause rejects non-tier values, and [[ACCOUNT_ROLE_TIER_PRESENCE]] rejects a
|
|
47
|
+
* missing or duplicated tier, so the two cannot drift.
|
|
42
48
|
*/
|
|
43
49
|
export declare const ACCOUNT_TIERS: readonly ["organisation", "platform", "account"];
|
|
44
50
|
export type AccountTier = (typeof ACCOUNT_TIERS)[number];
|
|
@@ -47,8 +53,6 @@ export declare const AccountTierSchema: z.ZodEnum<{
|
|
|
47
53
|
organisation: "organisation";
|
|
48
54
|
account: "account";
|
|
49
55
|
}>;
|
|
50
|
-
/** Type guard: checks whether a string is a valid account tier. */
|
|
51
|
-
export declare function isAccountTier(value: string): value is AccountTier;
|
|
52
56
|
/**
|
|
53
57
|
* AWS account roles in the wire format used across the CLI, webapp API
|
|
54
58
|
* responses, and the Prisma `AccountRole` enum. This is the SINGLE SOURCE
|
|
@@ -69,6 +73,8 @@ export declare const ACCOUNT_ROLES: {
|
|
|
69
73
|
readonly PLATFORM: "platform";
|
|
70
74
|
readonly ACCOUNT: "account";
|
|
71
75
|
};
|
|
76
|
+
/** Type guard: checks whether a string is a valid account tier. */
|
|
77
|
+
export declare function isAccountTier(value: string): value is AccountTier;
|
|
72
78
|
/**
|
|
73
79
|
* Decode an inbound wire `environment` to its structural TIER. The wire stays
|
|
74
80
|
* superset-tolerant: out-of-version CLIs and the post-`fjall create org`
|
package/dist/environments.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as c}from"zod";const
|
|
1
|
+
import{z as c}from"zod";const n=["production","staging","development","platform","compliance"],T={production:"Production",staging:"Staging",development:"Development",platform:"Platform",compliance:"Compliance"},i=new Set(n);function e(t){return i.has(t)}const o={ROOT:"root",PLATFORM:"platform"},C=[...n,o.ROOT];function s(t){return e(t)?T[t]:t.charAt(0).toUpperCase()+t.slice(1)}const u=["organisation","platform","account"],l=c.enum(u),r={ORGANISATION:"organisation",PLATFORM:"platform",ACCOUNT:"account"},O={[r.ORGANISATION]:!0,[r.PLATFORM]:!0,[r.ACCOUNT]:!0},a=new Set(Object.keys(O));function S(t){return a.has(t)}function p(t){return t===o.ROOT?"organisation":t===o.PLATFORM?"platform":"account"}function R(t){return t==null||t===""||t===o.ROOT?null:e(t)?t:null}function E(t){return t.tier??p(t.environment)}export{r as ACCOUNT_ROLES,n as ACCOUNT_STAGES,C as ACCOUNT_STAGES_WITH_ROOT,T as ACCOUNT_STAGE_LABELS,u as ACCOUNT_TIERS,l as AccountTierSchema,o as STRUCTURAL_ENVIRONMENTS,E as accountTier,p as environmentToTier,s as getEnvironmentLabel,e as isAccountStage,S as isAccountTier,R as stageFromWireEnvironment};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { DNS_APEX, getDomainExportNames, type ManagedDomainExports } from "./domainExports.js";
|
|
2
|
+
export { BACKUP_VAULT_NAME } from "./backupVault.js";
|
|
2
3
|
export { toPascalCase, toKebab, toValidDatabaseName, toScreamingSnake, capitalise, getSafeZoneName, accountConstructKey, hasAsciiStableConstructKey } from "./caseConversion.js";
|
|
3
4
|
export { findAccountNameCollision, type AccountNameCollision } from "./accountNameCollision.js";
|
|
4
5
|
export { normaliseError, getErrorMessage, hasErrorCode, getErrorCode, getErrorStack, formatErrorString } from "./errorUtils.js";
|
|
@@ -11,7 +12,8 @@ export { RESOURCE_CATEGORIES, type ResourceCategory, categoriseResource, getExpe
|
|
|
11
12
|
export { parseGitRemoteUrl, type GitProvider, type ParsedGitRemote } from "./gitRemoteParser.js";
|
|
12
13
|
export { abbreviateRegion } from "./regions.js";
|
|
13
14
|
export { SCOPE_VALUES, type TokenScope } from "./tokenScopes.js";
|
|
14
|
-
export {
|
|
15
|
+
export { ConnectionWireSchema, type ConnectionWire, ConnectionsListResponseSchema, type ConnectionsListResponse } from "./connectionsWire.js";
|
|
16
|
+
export { deriveRegionsFromOrgConfig, deriveTargets, deriveAllTargets, environmentOrTier, findTarget, generateTargetName, type OrgConfigRegions, type TargetAccount, type DerivedTarget } from "./targets.js";
|
|
15
17
|
export { buildAppConfigPath } from "./appPath.js";
|
|
16
18
|
export { type ScanPath } from "./scanTypes.js";
|
|
17
19
|
export { findInfrastructurePaths, findBoundaryPath, isInfrastructureFile, type MarkerEntry, type FindInfrastructurePathsOptions } from "./findInfrastructurePaths.js";
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DNS_APEX as o,getDomainExportNames as t}from"./domainExports.js";import{toPascalCase as
|
|
1
|
+
import{DNS_APEX as o,getDomainExportNames as t}from"./domainExports.js";import{BACKUP_VAULT_NAME as n}from"./backupVault.js";import{toPascalCase as i,toKebab as S,toValidDatabaseName as m,toScreamingSnake as s,capitalise as _,getSafeZoneName as A,accountConstructKey as C,hasAsciiStableConstructKey as p}from"./caseConversion.js";import{findAccountNameCollision as f}from"./accountNameCollision.js";import{normaliseError as R,getErrorMessage as c,hasErrorCode as g,getErrorCode as O,getErrorStack as x,formatErrorString as I}from"./errorUtils.js";import{singleton as l}from"./singleton.js";import{DANGEROUS_ENV_VARS as P,filterDangerousEnvVars as M,maskSensitiveOutput as V,parseShellArgs as U}from"./securityHelpers.js";import{sleep as v}from"./sleep.js";import{mapSettledWithConcurrency as H}from"./concurrency.js";import{ACCOUNT_STAGES_WITH_ROOT as G,STRUCTURAL_ENVIRONMENTS as b,ACCOUNT_STAGES as y,ACCOUNT_STAGE_LABELS as F,isAccountStage as K,ACCOUNT_TIERS as W,AccountTierSchema as X,isAccountTier as k,environmentToTier as B,stageFromWireEnvironment as Z,accountTier as j,getEnvironmentLabel as q,ACCOUNT_ROLES as w}from"./environments.js";import{RESOURCE_CATEGORIES as J,categoriseResource as Q,getExpectedDuration as Y,getFriendlyResourceType as $}from"./resourceCategorisation.js";import{parseGitRemoteUrl as re}from"./gitRemoteParser.js";import{abbreviateRegion as te}from"./regions.js";import{SCOPE_VALUES as ne}from"./tokenScopes.js";import{ConnectionWireSchema as ie,ConnectionsListResponseSchema as Se}from"./connectionsWire.js";import{deriveRegionsFromOrgConfig as se,deriveTargets as _e,deriveAllTargets as Ae,environmentOrTier as Ce,findTarget as pe,generateTargetName as Te}from"./targets.js";import{buildAppConfigPath as Ne}from"./appPath.js";import{findInfrastructurePaths as ce,findBoundaryPath as ge,isInfrastructureFile as Oe}from"./findInfrastructurePaths.js";import{inferContainerFromCandidates as Ie}from"./inferContainerFromCandidates.js";import{RESERVED_APP_NAMES as le,isReservedAppName as de}from"./reservedAppNames.js";import{deriveContentHashTag as Me}from"./deriveContentHashTag.js";import{MIGRATION_SNAPSHOT_NAME_PREFIX as Ue,EXPECTED_SCHEMA_VERSION_ENV as De,EXPECTED_SCHEMA_VERSION_TOOL_ENV as ve,EXPECTED_CH_SCHEMA_VERSION_ENV as he,SCHEMA_ADMIN_USER_ENV as He,SCHEMA_ADMIN_PASSWORD_ENV as Le,PRISMA_MIGRATION_DIR_RE as Ge,CLICKHOUSE_MIGRATION_SKIP_RE as be}from"./migration/constants.js";export{w as ACCOUNT_ROLES,y as ACCOUNT_STAGES,G as ACCOUNT_STAGES_WITH_ROOT,F as ACCOUNT_STAGE_LABELS,W as ACCOUNT_TIERS,X as AccountTierSchema,n as BACKUP_VAULT_NAME,be as CLICKHOUSE_MIGRATION_SKIP_RE,ie as ConnectionWireSchema,Se as ConnectionsListResponseSchema,P as DANGEROUS_ENV_VARS,o as DNS_APEX,he as EXPECTED_CH_SCHEMA_VERSION_ENV,De as EXPECTED_SCHEMA_VERSION_ENV,ve as EXPECTED_SCHEMA_VERSION_TOOL_ENV,Ue as MIGRATION_SNAPSHOT_NAME_PREFIX,Ge as PRISMA_MIGRATION_DIR_RE,le as RESERVED_APP_NAMES,J as RESOURCE_CATEGORIES,Le as SCHEMA_ADMIN_PASSWORD_ENV,He as SCHEMA_ADMIN_USER_ENV,ne as SCOPE_VALUES,b as STRUCTURAL_ENVIRONMENTS,te as abbreviateRegion,C as accountConstructKey,j as accountTier,Ne as buildAppConfigPath,_ as capitalise,Q as categoriseResource,Ae as deriveAllTargets,Me as deriveContentHashTag,se as deriveRegionsFromOrgConfig,_e as deriveTargets,Ce as environmentOrTier,B as environmentToTier,M as filterDangerousEnvVars,f as findAccountNameCollision,ge as findBoundaryPath,ce as findInfrastructurePaths,pe as findTarget,I as formatErrorString,Te as generateTargetName,t as getDomainExportNames,q as getEnvironmentLabel,O as getErrorCode,c as getErrorMessage,x as getErrorStack,Y as getExpectedDuration,$ as getFriendlyResourceType,A as getSafeZoneName,p as hasAsciiStableConstructKey,g as hasErrorCode,Ie as inferContainerFromCandidates,K as isAccountStage,k as isAccountTier,Oe as isInfrastructureFile,de as isReservedAppName,H as mapSettledWithConcurrency,V as maskSensitiveOutput,R as normaliseError,re as parseGitRemoteUrl,U as parseShellArgs,l as singleton,v as sleep,Z as stageFromWireEnvironment,S as toKebab,i as toPascalCase,s as toScreamingSnake,m as toValidDatabaseName};
|
|
@@ -147,10 +147,9 @@ export type McpProtocolFrame = z.infer<typeof McpProtocolFrameSchema>;
|
|
|
147
147
|
* Scaffold protocol schemas — wire types for the `plan_app_scaffold`,
|
|
148
148
|
* `apply_app_scaffold`, and dry-run helper paths in `@fjall/mcp`.
|
|
149
149
|
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* is a wire-level bug; both sides MUST move together.
|
|
150
|
+
* These schemas are the single source of truth: the CLI imports them from
|
|
151
|
+
* `@fjall/util/mcpProtocol` and re-exports aliases in
|
|
152
|
+
* `cli/src/operations/types.ts`.
|
|
154
153
|
*/
|
|
155
154
|
export declare const FileToWriteSchema: z.ZodObject<{
|
|
156
155
|
path: z.ZodString;
|
package/dist/targets.d.ts
CHANGED
|
@@ -30,6 +30,15 @@ export interface DerivedTarget {
|
|
|
30
30
|
environment: string;
|
|
31
31
|
region: string;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Canonical stage-or-tier fallback. Structural accounts carry a null workload
|
|
35
|
+
* stage, so display/naming/OU derivation fall back to the structural tier to
|
|
36
|
+
* stay non-null. Single source for every `environment ?? tier` consumer.
|
|
37
|
+
*/
|
|
38
|
+
export declare function environmentOrTier(account: {
|
|
39
|
+
environment?: string | null;
|
|
40
|
+
tier?: AccountTier | null;
|
|
41
|
+
}): string;
|
|
33
42
|
/**
|
|
34
43
|
* Generate a canonical target name from account name and region.
|
|
35
44
|
* e.g. ("Production-US", "us-east-1") → "production-us-use1"
|
package/dist/targets.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{abbreviateRegion as
|
|
1
|
+
import{abbreviateRegion as m}from"./regions.js";import{accountTier as c}from"./environments.js";function s(e){const r=[e.primaryRegion,...e.secondaryRegions??[],e.disasterRecoveryRegion].filter(t=>t!==void 0);return[...new Set(r)]}function u(e){return e.environment??c(e)}function f(e,r){return`${e.toLowerCase()}-${m(r)}`}function p(e,r){const t=[];for(const n of e){if(c(n)==="organisation")continue;const o=u(n);for(const i of r)t.push({name:f(n.name,i),accountName:n.name,accountId:n.id,environment:o,region:i})}return t.sort((n,o)=>{const i=n.environment.localeCompare(o.environment);if(i!==0)return i;const a=n.accountName.localeCompare(o.accountName);return a!==0?a:n.region.localeCompare(o.region)})}function v(e){return p(e.providerAccounts,s(e))}function l(e,r){if(r.length===0)return e;const t=new Set([e.primaryRegion,e.disasterRecoveryRegion].filter(Boolean)),n=r.filter(o=>!t.has(o));return{...e,secondaryRegions:n.length>0?n:void 0}}function R(e,r){return e.find(t=>t.name===r)}export{v as deriveAllTargets,s as deriveRegionsFromOrgConfig,p as deriveTargets,u as environmentOrTier,R as findTarget,f as generateTargetName,l as mergeSecondaryRegions};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/util",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "Common utility methods",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"engines": {
|
|
118
118
|
"node": ">=22.0.0"
|
|
119
119
|
},
|
|
120
|
-
"gitHead": "
|
|
120
|
+
"gitHead": "5b16c5731256628f829d4168c65cf165b3516f9a"
|
|
121
121
|
}
|