@fjall/util 37.0.0 → 39.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.
- package/dist/.minified +1 -1
- package/dist/appTypes.d.ts +27 -0
- package/dist/appTypes.js +1 -0
- package/dist/aws/index.d.ts +2 -1
- package/dist/aws/index.js +1 -1
- package/dist/aws/infraTags.d.ts +50 -4
- package/dist/aws/infraTags.js +1 -1
- package/dist/aws/resourceTypes.d.ts +54 -0
- package/dist/aws/resourceTypes.js +1 -0
- package/dist/backupTiers.d.ts +11 -4
- package/dist/childEnvPolicy.d.ts +72 -0
- package/dist/childEnvPolicy.js +1 -0
- package/dist/ciSetup.d.ts +25 -0
- package/dist/ciSetup.js +1 -0
- package/dist/complianceIssue.d.ts +10 -0
- package/dist/complianceIssue.js +1 -1
- package/dist/deploy/approvalTokenOutput.d.ts +0 -9
- package/dist/deploy/approvalTokenOutput.js +1 -1
- package/dist/index.d.ts +13 -5
- package/dist/index.js +1 -1
- package/dist/infra/backupVault.d.ts +79 -2
- package/dist/infra/backupVault.js +1 -1
- package/dist/insights/vocabulary.d.ts +29 -0
- package/dist/insights/vocabulary.js +1 -0
- package/dist/manifest/io.d.ts +9 -0
- package/dist/manifest/io.js +1 -1
- package/dist/mcpProtocol/index.d.ts +47 -10
- package/dist/mcpProtocol/index.js +1 -1
- package/dist/naming/applicationStackNames.d.ts +47 -0
- package/dist/naming/applicationStackNames.js +1 -0
- package/dist/naming/stackExportNames.d.ts +78 -0
- package/dist/naming/stackExportNames.js +1 -0
- package/dist/nonEmptyPartial.d.ts +19 -0
- package/dist/nonEmptyPartial.js +1 -0
- package/dist/patterns/frameworkPatterns.d.ts +1 -8
- package/dist/patterns/index.d.ts +2 -2
- package/dist/patterns/index.js +1 -1
- package/dist/patterns/patternTypes.d.ts +44 -2
- package/dist/patterns/patternTypes.js +1 -1
- package/dist/posturePolicy/registry.d.ts +6 -10
- package/dist/posturePolicy/resourceKinds.d.ts +6 -6
- package/dist/posturePolicy/resourceKinds.js +1 -1
- package/package.json +6 -2
|
@@ -1,7 +1,84 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
/**
|
|
2
3
|
* Fixed name of the disaster-recovery backup vault. Single source of truth for
|
|
3
4
|
* the @fjall/components-infrastructure DisasterRecovery construct (which
|
|
4
|
-
* creates the vault under this name) and deploy-core's
|
|
5
|
-
*
|
|
5
|
+
* creates the vault under this name) and deploy-core's ownership and survival
|
|
6
|
+
* probes (which look it up by the same name).
|
|
6
7
|
*/
|
|
7
8
|
export declare const BACKUP_VAULT_NAME = "backupVault";
|
|
9
|
+
/**
|
|
10
|
+
* CDK context key the deploy engine injects the backup-vault ownership verdict
|
|
11
|
+
* under (`-c fjallBackupVault=<json>`), read by `readBackupVaultVerdict` in
|
|
12
|
+
* @fjall/components-infrastructure (`utils/cdkContext.ts`). One JSON value,
|
|
13
|
+
* not a boolean: the construct needs the live key ARN (a create-only vault
|
|
14
|
+
* property) to declare a re-owned vault without replacing it, and the live
|
|
15
|
+
* lock to report it and warn when the configured intent differs.
|
|
16
|
+
*/
|
|
17
|
+
export declare const BACKUP_VAULT_CONTEXT_KEY = "fjallBackupVault";
|
|
18
|
+
/**
|
|
19
|
+
* The live vault lock as `DescribeBackupVault` reports it. `lockDate` is the
|
|
20
|
+
* instant a compliance-mode lock became (or becomes) immutable; a governance
|
|
21
|
+
* lock carries none. Every field is optional: a lock put through the Backup
|
|
22
|
+
* API may carry a maximum without a minimum, or a lock date alone, so a
|
|
23
|
+
* locked vault can report none of them. The lock is never declared in a
|
|
24
|
+
* template — the construct reads it for the `VaultLockEnabled` output and the
|
|
25
|
+
* intent warning only.
|
|
26
|
+
*/
|
|
27
|
+
export declare const BackupVaultLockSchema: z.ZodObject<{
|
|
28
|
+
minRetentionDays: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
maxRetentionDays: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
lockDate: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strict>;
|
|
32
|
+
export type BackupVaultLock = z.infer<typeof BackupVaultLockSchema>;
|
|
33
|
+
/**
|
|
34
|
+
* Ownership verdict for the fixed-name DR vault in one account/region, probed
|
|
35
|
+
* by the deploy engine before synth (`probeBackupVaultOwnership` in
|
|
36
|
+
* deploy-core):
|
|
37
|
+
*
|
|
38
|
+
* - `absent` — no vault; the construct creates it with a stack-managed key.
|
|
39
|
+
* - `owned` — an `AWS::Backup::BackupVault` with physical id
|
|
40
|
+
* `backupVault` is a current resource of THIS account stack. `keyInStack`
|
|
41
|
+
* says whether its KMS key is too: if so the template is the create
|
|
42
|
+
* template (the vault keeps converging to intent); if not the key is a
|
|
43
|
+
* retained survivor and the vault is re-owned — declared against the live
|
|
44
|
+
* key, with no lock declared (Fjall never issues a lock call against a
|
|
45
|
+
* vault it did not create; the live lock stays as it is).
|
|
46
|
+
* - `unowned` — the vault exists but is not in the stack: the import
|
|
47
|
+
* candidate. The construct declares identity only and the engine deploys
|
|
48
|
+
* with `--import-existing-resources`, then re-probes and converges.
|
|
49
|
+
*
|
|
50
|
+
* `keyArn` is always a customer-managed key: the probe refuses a vault on an
|
|
51
|
+
* AWS-owned or AWS-managed key before any verdict is issued, because the
|
|
52
|
+
* re-owned template aliases the key and the DR plans' cross-account copies
|
|
53
|
+
* need a customer-managed one. A vault owned by ANOTHER stack is not
|
|
54
|
+
* distinguished here: the import change set fails with CloudFormation's own
|
|
55
|
+
* "already belongs to another stack".
|
|
56
|
+
*/
|
|
57
|
+
export declare const BackupVaultVerdictSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
58
|
+
state: z.ZodLiteral<"absent">;
|
|
59
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
60
|
+
state: z.ZodLiteral<"owned">;
|
|
61
|
+
keyArn: z.ZodString;
|
|
62
|
+
keyInStack: z.ZodBoolean;
|
|
63
|
+
lock: z.ZodNullable<z.ZodObject<{
|
|
64
|
+
minRetentionDays: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
maxRetentionDays: z.ZodOptional<z.ZodNumber>;
|
|
66
|
+
lockDate: z.ZodOptional<z.ZodString>;
|
|
67
|
+
}, z.core.$strict>>;
|
|
68
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
69
|
+
state: z.ZodLiteral<"unowned">;
|
|
70
|
+
keyArn: z.ZodString;
|
|
71
|
+
lock: z.ZodNullable<z.ZodObject<{
|
|
72
|
+
minRetentionDays: z.ZodOptional<z.ZodNumber>;
|
|
73
|
+
maxRetentionDays: z.ZodOptional<z.ZodNumber>;
|
|
74
|
+
lockDate: z.ZodOptional<z.ZodString>;
|
|
75
|
+
}, z.core.$strict>>;
|
|
76
|
+
}, z.core.$strict>], "state">;
|
|
77
|
+
export type BackupVaultVerdict = z.infer<typeof BackupVaultVerdictSchema>;
|
|
78
|
+
/**
|
|
79
|
+
* Whether a verdict selects the re-owned template: the vault is (or is about
|
|
80
|
+
* to be) a stack resource whose key lives outside the stack. Shared by the
|
|
81
|
+
* construct (mode selection) and the engine (the import pass is the
|
|
82
|
+
* `unowned` half of this).
|
|
83
|
+
*/
|
|
84
|
+
export declare function isReownedBackupVault(verdict: BackupVaultVerdict): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
var i=Object.defineProperty;var n=(e,a)=>i(e,"name",{value:a,configurable:!0});import{z as t}from"zod";const s="backupVault",r="fjallBackupVault",o=t.object({minRetentionDays:t.number().int().positive().optional(),maxRetentionDays:t.number().int().positive().optional(),lockDate:t.string().datetime({offset:!0}).optional()}).strict(),u=t.discriminatedUnion("state",[t.object({state:t.literal("absent")}).strict(),t.object({state:t.literal("owned"),keyArn:t.string().min(1),keyInStack:t.boolean(),lock:o.nullable()}).strict(),t.object({state:t.literal("unowned"),keyArn:t.string().min(1),lock:o.nullable()}).strict()]);function p(e){return e.state==="unowned"||e.state==="owned"&&!e.keyInStack}n(p,"isReownedBackupVault");export{r as BACKUP_VAULT_CONTEXT_KEY,s as BACKUP_VAULT_NAME,o as BackupVaultLockSchema,u as BackupVaultVerdictSchema,p as isReownedBackupVault};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insight list vocabulary — the filter and ordering tokens `GET /api/insights`
|
|
3
|
+
* accepts, minted once so every consumer spells them the same way.
|
|
4
|
+
*
|
|
5
|
+
* Owner today: the webapp (`webapp/app/lib/insights/insights.ts` —
|
|
6
|
+
* `TAB_VALUES`, `INSIGHT_CATEGORIES`, `INSIGHT_SEVERITIES`, `SORT_VALUES`).
|
|
7
|
+
* The MCP's `list_insights` tool re-typed all four by hand and advertised
|
|
8
|
+
* them on its wire surface, so a token added or renamed in the webapp left
|
|
9
|
+
* the tool silently offering a filter the route rejects. The MCP now derives
|
|
10
|
+
* from here, and the route's 400-on-unknown gate is what keeps the two honest
|
|
11
|
+
* while the webapp still carries its own copies.
|
|
12
|
+
*
|
|
13
|
+
* Client-safe (no node built-ins): exported from the root barrel and as the
|
|
14
|
+
* `@fjall/util/insights/vocabulary` subpath so browser code can take it
|
|
15
|
+
* without the root barrel.
|
|
16
|
+
*/
|
|
17
|
+
export declare const INSIGHT_TAB_VALUES: readonly ["open", "snoozed", "resolved", "all"];
|
|
18
|
+
/** @public — tuple companion type; ships with its tuple (knip skips @public) */
|
|
19
|
+
export type InsightTab = (typeof INSIGHT_TAB_VALUES)[number];
|
|
20
|
+
export declare const INSIGHT_CATEGORIES: readonly ["performance", "cost", "reliability", "security", "deployment"];
|
|
21
|
+
/** @public — tuple companion type; ships with its tuple (knip skips @public) */
|
|
22
|
+
export type InsightCategory = (typeof INSIGHT_CATEGORIES)[number];
|
|
23
|
+
/** Most severe first. */
|
|
24
|
+
export declare const INSIGHT_SEVERITIES: readonly ["critical", "warning", "recommendation", "info"];
|
|
25
|
+
/** @public — tuple companion type; ships with its tuple (knip skips @public) */
|
|
26
|
+
export type InsightSeverity = (typeof INSIGHT_SEVERITIES)[number];
|
|
27
|
+
export declare const INSIGHT_SORT_VALUES: readonly ["matters", "severity", "newest", "oldest", "savings"];
|
|
28
|
+
/** @public — tuple companion type; ships with its tuple (knip skips @public) */
|
|
29
|
+
export type InsightSort = (typeof INSIGHT_SORT_VALUES)[number];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=["open","snoozed","resolved","all"],o=["performance","cost","reliability","security","deployment"],t=["critical","warning","recommendation","info"],n=["matters","severity","newest","oldest","savings"];export{o as INSIGHT_CATEGORIES,t as INSIGHT_SEVERITIES,n as INSIGHT_SORT_VALUES,e as INSIGHT_TAB_VALUES};
|
package/dist/manifest/io.d.ts
CHANGED
|
@@ -75,6 +75,15 @@ export interface ManifestDockerService {
|
|
|
75
75
|
* `dockerPlatformForArchitecture` in `@fjall/util/docker`.
|
|
76
76
|
*/
|
|
77
77
|
readonly architecture?: LambdaArchitecture;
|
|
78
|
+
/**
|
|
79
|
+
* The ECS cluster the service is placed in — the construct id of the
|
|
80
|
+
* cluster, which is also its physical cluster name and the token the
|
|
81
|
+
* `DeployableService` export is built from. Present for every service the
|
|
82
|
+
* compute pattern records (constructs >= 0.87.0); absent for a manifest
|
|
83
|
+
* written by an older assembly, in which case the deploy engine cannot
|
|
84
|
+
* bind the entry to a live service by name and must say so.
|
|
85
|
+
*/
|
|
86
|
+
readonly clusterName?: string;
|
|
78
87
|
}
|
|
79
88
|
/**
|
|
80
89
|
* The engine-compatibility envelope, hand-walked from the manifest rather than
|
package/dist/manifest/io.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var M=Object.defineProperty;var s=(n,e)=>M(n,"name",{value:e,configurable:!0});import{readFile as k,writeFile as E,unlink as N,rename as S,mkdir as w}from"fs/promises";import{readFileSync as p}from"fs";import{dirname as F,join as m}from"path";import{logger as c}from"../logger.js";import{maskSensitiveOutput as f}from"../securityHelpers.js";import{fileExists as x}from"../fsHelpers.js";import{getErrorMessage as d}from"../errorUtils.js";import{recordToConstructMap as A}from"../constructMap.js";import{FjallManifestSchema as v,FJALL_MANIFEST_FILENAME as l,MANIFEST_SCHEMA_VERSION as j,normaliseDockerBuild as y,LAMBDA_ARCHITECTURE_VALUES as C}from"./schemas.js";function h(n){return m(n,l)}s(h,"getManifestFilePath");async function O(n){const e=h(n);if(!await x(e))return{status:"absent"};try{const
|
|
1
|
+
var M=Object.defineProperty;var s=(n,e)=>M(n,"name",{value:e,configurable:!0});import{readFile as k,writeFile as E,unlink as N,rename as S,mkdir as w}from"fs/promises";import{readFileSync as p}from"fs";import{dirname as F,join as m}from"path";import{logger as c}from"../logger.js";import{maskSensitiveOutput as f}from"../securityHelpers.js";import{fileExists as x}from"../fsHelpers.js";import{getErrorMessage as d}from"../errorUtils.js";import{recordToConstructMap as A}from"../constructMap.js";import{FjallManifestSchema as v,FJALL_MANIFEST_FILENAME as l,MANIFEST_SCHEMA_VERSION as j,normaliseDockerBuild as y,LAMBDA_ARCHITECTURE_VALUES as C}from"./schemas.js";function h(n){return m(n,l)}s(h,"getManifestFilePath");async function O(n){const e=h(n);if(!await x(e))return{status:"absent"};try{const r=await k(e,"utf-8"),t=JSON.parse(r),a=v.safeParse(t);if(!a.success){const i=f(a.error.issues.map(o=>`${o.path.join(".")}: ${o.message}`).join("; "));return c.debug("FjallManifest","Manifest validation failed",{path:e,errors:i}),{status:"unreadable",detail:i}}return{status:"ok",manifest:a.data}}catch(r){const t=f(d(r));return c.debug("FjallManifest","Failed to read manifest file",{path:e,error:t}),{status:"unreadable",detail:t}}}s(O,"readManifestFileOutcome");async function I(n){const e=await O(n);return e.status==="ok"?e.manifest:null}s(I,"readManifestFile");async function U(n,e){const r=h(n),t=`${r}.${Date.now()}.tmp`;await w(F(r),{recursive:!0});try{await E(t,JSON.stringify(e,null,2),"utf-8"),await S(t,r)}catch(a){try{await N(t)}catch(i){c.debug("FjallManifest","Temp file cleanup failed (non-fatal)",{path:t,error:d(i)})}throw a}}s(U,"writeManifestFile");function q(n){return{version:j,generatedAt:new Date().toISOString(),appName:n,services:[],lambdas:[],stacks:{}}}s(q,"createEmptyManifest");async function z(n){const e=await I(n);return e?.resourceMap?A(e.resourceMap):new Map}s(z,"readConstructMap");function u(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}s(u,"isRecord");function g(n,e){const r=m(n,l);let t;try{t=p(r,"utf-8")}catch{c.debug("FjallManifest",`Manifest file not readable \u2014 no ${e} extracted`,{path:r});return}let a;try{a=JSON.parse(t)}catch{c.debug("FjallManifest",`Manifest is not valid JSON \u2014 no ${e} extracted`,{path:r});return}return u(a)?a:void 0}s(g,"readManifestRecord");function T(n){const e=n.engineCompat;if(!u(e))return;const r=e.minimumEngineVersion;if(typeof r!="string"||r.length===0)return;const t=typeof e.synthesisedBy=="string"&&e.synthesisedBy.length>0?e.synthesisedBy:"",a=typeof e.maximumEngineMajor=="number"&&Number.isInteger(e.maximumEngineMajor)&&e.maximumEngineMajor>=0?e.maximumEngineMajor:void 0,i=e.minimumAwsCdkCli,o=i===void 0?void 0:typeof i=="string"?i:String(i);return{synthesisedBy:t,minimumEngineVersion:r,...a!==void 0&&{maximumEngineMajor:a},...o!==void 0&&{minimumAwsCdkCli:o}}}s(T,"extractEngineCompat");function Q(n){const e=g(n,"engine compatibility");if(e===void 0)return{manifestVersion:void 0,engineCompatPresent:!1,engineCompat:void 0};const r=typeof e.version=="number"?e.version:void 0,t=u(e.engineCompat),a=T(e);return{manifestVersion:r,engineCompatPresent:t,engineCompat:a}}s(Q,"readEngineCompatEnvelope");function W(n){const e=$(n);return e.status==="ok"?e.appName:void 0}s(W,"readManifestAppName");function $(n){const e=m(n,l);let r;try{r=p(e,"utf-8")}catch(a){const i=a!==null&&typeof a=="object"&&"code"in a?a.code:void 0;return i==="ENOENT"||i==="ENOTDIR"?{status:"absent"}:(c.debug("FjallManifest","Manifest file not readable \u2014 no app name",{path:e,error:f(d(a))}),{status:"unreadable"})}let t;try{t=JSON.parse(r)}catch(a){return c.debug("FjallManifest","Manifest is not valid JSON \u2014 no app name",{path:e,error:f(d(a))}),{status:"unreadable"}}return u(t)?{status:"ok",appName:typeof t.appName=="string"&&t.appName!==""?t.appName:void 0}:{status:"unreadable"}}s($,"readManifestAppNameOutcome");function D(n){const e=g(n,"Docker services");if(e===void 0||!Array.isArray(e.services))return[];const r=[];for(const t of e.services){if(!u(t)||typeof t.name!="string")continue;const a=y(t.docker);a!==void 0&&r.push({name:t.name,docker:a,isLambda:!1,...typeof t.clusterName=="string"&&{clusterName:t.clusterName}})}return r}s(D,"parseDockerServicesFromManifest");function X(n){const e=new Map;for(const{name:r,imageKey:t,docker:a,architecture:i}of b(n)){const o=e.get(t);if(o===void 0){e.set(t,{name:t,docker:a,isLambda:!0,...i!==void 0&&{architecture:i}});continue}if(JSON.stringify(o.docker)!==JSON.stringify(a)||o.architecture!==i)throw new Error(`Lambda functions sharing image key "${t}" declare different \`docker\` configs or \`architecture\` \u2014 every Lambda function sharing an \`image\` must build from the identical Dockerfile/context/target/buildArgs and target the same architecture (offending function: "${r}").`)}return Array.from(e.values())}s(X,"parseLambdaDockerServicesFromManifest");function b(n){const e=g(n,"Lambda Docker entries");if(e===void 0||!Array.isArray(e.lambdas))return[];const r=[];for(const t of e.lambdas){if(!u(t)||typeof t.name!="string")continue;const a=y(t.docker);if(a===void 0)continue;const i=typeof t.imageKey=="string"&&t.imageKey.length>0?t.imageKey:t.name;let o;typeof t.architecture=="string"&&(C.includes(t.architecture)?o=t.architecture:c.debug("FjallManifest","Ignoring unrecognised Lambda architecture \u2014 build falls back to the default platform",{lambda:t.name,architecture:f(t.architecture)})),r.push({name:t.name,imageKey:i,docker:a,...o!==void 0&&{architecture:o}})}return r}s(b,"parseLambdaDockerEntriesFromManifest");function Y(n){const e=D(n),r=b(n);return{ecsServices:e,lambdaEntries:r,declaresBuild:e.length>0||r.length>0}}s(Y,"parseDockerDeclarationsFromManifest");function Z(n){const e=m(n,l);let r;try{r=p(e,"utf-8")}catch(i){const o=i.code;return o==="ENOENT"?{outcome:"ok",tags:[]}:{outcome:"manifest-unreadable",reason:`manifest at ${e} exists but could not be read (${o??"unknown error"})`}}let t;try{t=JSON.parse(r)}catch{return{outcome:"manifest-unreadable",reason:`manifest at ${e} is not valid JSON`}}if(!u(t))return{outcome:"manifest-unreadable",reason:`manifest at ${e} is not a JSON object`};if(t.services===void 0)return{outcome:"ok",tags:[]};if(!Array.isArray(t.services))return{outcome:"manifest-unreadable",reason:`manifest at ${e} has a non-array \`services\` field`};const a=new Set;for(const i of t.services)if(u(i)&&i.schemaGateImageTag!==void 0){if(typeof i.schemaGateImageTag!="string"||i.schemaGateImageTag==="")return{outcome:"manifest-unreadable",reason:`manifest at ${e} declares an invalid schemaGateImageTag for service '${typeof i.name=="string"?i.name:"<unnamed>"}'`};a.add(i.schemaGateImageTag)}return{outcome:"ok",tags:[...a].sort()}}s(Z,"parseSchemaGateImageTagsFromManifest");export{q as createEmptyManifest,h as getManifestFilePath,Y as parseDockerDeclarationsFromManifest,D as parseDockerServicesFromManifest,b as parseLambdaDockerEntriesFromManifest,X as parseLambdaDockerServicesFromManifest,Z as parseSchemaGateImageTagsFromManifest,z as readConstructMap,Q as readEngineCompatEnvelope,W as readManifestAppName,$ as readManifestAppNameOutcome,I as readManifestFile,O as readManifestFileOutcome,U as writeManifestFile};
|
|
@@ -176,23 +176,32 @@ export declare const TargetAccountSchema: z.ZodObject<{
|
|
|
176
176
|
source: z.ZodString;
|
|
177
177
|
}, z.core.$strict>;
|
|
178
178
|
export type TargetAccount = z.infer<typeof TargetAccountSchema>;
|
|
179
|
+
/**
|
|
180
|
+
* Every input `plan_app_scaffold` accepts, as the plan records it and
|
|
181
|
+
* `apply_app_scaffold` replays it (`buildApplyCommand`). Plan keys ⊆ these
|
|
182
|
+
* keys is pinned by the MCP's resolvedInputsParity test: a key the plan
|
|
183
|
+
* accepts but this schema drops was silently absent from the apply argv
|
|
184
|
+
* (`type`, `database`, `containerPort` were, until Train 4).
|
|
185
|
+
*/
|
|
179
186
|
export declare const ResolvedInputsSchema: z.ZodObject<{
|
|
180
187
|
name: z.ZodString;
|
|
181
|
-
pattern: z.ZodOptional<z.
|
|
188
|
+
pattern: z.ZodOptional<z.ZodEnum<{
|
|
189
|
+
payload: "payload";
|
|
190
|
+
staticsite: "staticsite";
|
|
191
|
+
}>>;
|
|
182
192
|
patternTier: z.ZodOptional<z.ZodEnum<{
|
|
193
|
+
lightweight: "lightweight";
|
|
183
194
|
standard: "standard";
|
|
184
195
|
resilient: "resilient";
|
|
185
|
-
|
|
186
|
-
tinkerer: "tinkerer";
|
|
187
|
-
lightweight: "lightweight";
|
|
196
|
+
custom: "custom";
|
|
188
197
|
}>>;
|
|
189
198
|
patternDomain: z.ZodOptional<z.ZodString>;
|
|
190
199
|
network: z.ZodOptional<z.ZodEnum<{
|
|
200
|
+
lightweight: "lightweight";
|
|
191
201
|
standard: "standard";
|
|
192
202
|
resilient: "resilient";
|
|
193
203
|
enterprise: "enterprise";
|
|
194
204
|
none: "none";
|
|
195
|
-
lightweight: "lightweight";
|
|
196
205
|
}>>;
|
|
197
206
|
template: z.ZodOptional<z.ZodString>;
|
|
198
207
|
docker: z.ZodOptional<z.ZodObject<{
|
|
@@ -200,6 +209,19 @@ export declare const ResolvedInputsSchema: z.ZodObject<{
|
|
|
200
209
|
context: z.ZodOptional<z.ZodString>;
|
|
201
210
|
target: z.ZodOptional<z.ZodString>;
|
|
202
211
|
}, z.core.$strict>>;
|
|
212
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
213
|
+
tinkerer: "tinkerer";
|
|
214
|
+
lightweight: "lightweight";
|
|
215
|
+
standard: "standard";
|
|
216
|
+
resilient: "resilient";
|
|
217
|
+
enterprise: "enterprise";
|
|
218
|
+
custom: "custom";
|
|
219
|
+
}>>;
|
|
220
|
+
database: z.ZodOptional<z.ZodBoolean>;
|
|
221
|
+
containerPort: z.ZodOptional<z.ZodNumber>;
|
|
222
|
+
source: z.ZodOptional<z.ZodString>;
|
|
223
|
+
buildCommand: z.ZodOptional<z.ZodString>;
|
|
224
|
+
outputDir: z.ZodOptional<z.ZodString>;
|
|
203
225
|
git: z.ZodOptional<z.ZodBoolean>;
|
|
204
226
|
github: z.ZodOptional<z.ZodBoolean>;
|
|
205
227
|
repoVisibility: z.ZodOptional<z.ZodEnum<{
|
|
@@ -214,21 +236,23 @@ export declare const ScaffoldPlanSchema: z.ZodObject<{
|
|
|
214
236
|
normalisedPath: z.ZodString;
|
|
215
237
|
resolvedInputs: z.ZodObject<{
|
|
216
238
|
name: z.ZodString;
|
|
217
|
-
pattern: z.ZodOptional<z.
|
|
239
|
+
pattern: z.ZodOptional<z.ZodEnum<{
|
|
240
|
+
payload: "payload";
|
|
241
|
+
staticsite: "staticsite";
|
|
242
|
+
}>>;
|
|
218
243
|
patternTier: z.ZodOptional<z.ZodEnum<{
|
|
244
|
+
lightweight: "lightweight";
|
|
219
245
|
standard: "standard";
|
|
220
246
|
resilient: "resilient";
|
|
221
|
-
|
|
222
|
-
tinkerer: "tinkerer";
|
|
223
|
-
lightweight: "lightweight";
|
|
247
|
+
custom: "custom";
|
|
224
248
|
}>>;
|
|
225
249
|
patternDomain: z.ZodOptional<z.ZodString>;
|
|
226
250
|
network: z.ZodOptional<z.ZodEnum<{
|
|
251
|
+
lightweight: "lightweight";
|
|
227
252
|
standard: "standard";
|
|
228
253
|
resilient: "resilient";
|
|
229
254
|
enterprise: "enterprise";
|
|
230
255
|
none: "none";
|
|
231
|
-
lightweight: "lightweight";
|
|
232
256
|
}>>;
|
|
233
257
|
template: z.ZodOptional<z.ZodString>;
|
|
234
258
|
docker: z.ZodOptional<z.ZodObject<{
|
|
@@ -236,6 +260,19 @@ export declare const ScaffoldPlanSchema: z.ZodObject<{
|
|
|
236
260
|
context: z.ZodOptional<z.ZodString>;
|
|
237
261
|
target: z.ZodOptional<z.ZodString>;
|
|
238
262
|
}, z.core.$strict>>;
|
|
263
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
264
|
+
tinkerer: "tinkerer";
|
|
265
|
+
lightweight: "lightweight";
|
|
266
|
+
standard: "standard";
|
|
267
|
+
resilient: "resilient";
|
|
268
|
+
enterprise: "enterprise";
|
|
269
|
+
custom: "custom";
|
|
270
|
+
}>>;
|
|
271
|
+
database: z.ZodOptional<z.ZodBoolean>;
|
|
272
|
+
containerPort: z.ZodOptional<z.ZodNumber>;
|
|
273
|
+
source: z.ZodOptional<z.ZodString>;
|
|
274
|
+
buildCommand: z.ZodOptional<z.ZodString>;
|
|
275
|
+
outputDir: z.ZodOptional<z.ZodString>;
|
|
239
276
|
git: z.ZodOptional<z.ZodBoolean>;
|
|
240
277
|
github: z.ZodOptional<z.ZodBoolean>;
|
|
241
278
|
repoVisibility: z.ZodOptional<z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l=Object.defineProperty;var a=(e,r)=>l(e,"name",{value:r,configurable:!0});import{z as t}from"zod";import{APP_TYPES as g}from"../appTypes.js";import{DEPLOYABLE_PATTERN_TYPES as u,PATTERN_TIER_VALUES as d}from"../patterns/patternTypes.js";const b=2,L={AUTHENTICATION_REQUIRED:"AUTHENTICATION_REQUIRED",VALIDATION_ERROR:"VALIDATION_ERROR",INTERNAL_ERROR:"INTERNAL_ERROR",INVALID_SUBCOMMAND:"INVALID_SUBCOMMAND",INVALID_FRAME:"INVALID_FRAME"},s=1e3,n=t.literal(b),A=t.enum(["completed","error","skipped"]),R=t.object({v:n,kind:t.literal("step.start"),stepId:t.string().min(1),name:t.string().min(1),index:t.number().int().min(0),total:t.number().int().min(1)}).strict(),S=t.object({v:n,kind:t.literal("step.complete"),stepId:t.string().min(1),name:t.string().min(1),status:A,index:t.number().int().min(0),total:t.number().int().min(1),errorMessage:t.string().optional()}).strict(),E=t.object({v:n,kind:t.literal("warning"),message:t.string().min(1)}).strict(),h=t.object({code:t.string().min(1),message:t.string().min(1),details:t.record(t.string(),t.unknown()).optional()}).strict(),I=t.object({v:n,kind:t.literal("error"),error:h}).strict(),x=t.object({v:n,kind:t.literal("result"),data:t.unknown()}).strict(),T=t.object({v:n,kind:t.literal("auth.browser.required"),url:t.string().url(),externalId:t.string().min(1),region:t.string().min(1),environment:t.string().min(1),reason:t.string().min(1)}).strict(),y=t.object({v:n,kind:t.literal("auth.browser.complete"),awsAccountId:t.string().min(1),accountName:t.string().min(1),roleArn:t.string().min(1)}).strict(),N=t.discriminatedUnion("kind",[R,S,E,I,x,T,y]),m=t.object({path:t.string().min(1),sizeBytes:t.number().int().nonnegative(),collisionMode:t.enum(["create","overwrite"])}).strict(),c=t.object({type:t.enum(["register-application","create-activity","auto-link-repository","writeback-config-path"]),description:t.string().min(1)}).strict(),f=t.enum(d),k=t.enum(u),P=t.enum(g),_=t.enum(["lightweight","standard","resilient","enterprise","none"]),p=t.object({name:t.string().min(1),environment:t.string().min(1).nullable(),source:t.string().min(1)}).strict(),j=t.object({name:t.string().min(1),pattern:k.optional(),patternTier:f.optional(),patternDomain:t.string().min(1).optional(),network:_.optional(),template:t.string().min(1).optional(),docker:t.object({path:t.string().min(1).optional(),context:t.string().min(1).optional(),target:t.string().min(1).optional()}).strict().optional(),type:P.optional(),database:t.boolean().optional(),containerPort:t.number().int().min(1).max(65535).optional(),source:t.string().min(1).optional(),buildCommand:t.string().min(1).optional(),outputDir:t.string().min(1).optional(),git:t.boolean().optional(),github:t.boolean().optional(),repoVisibility:t.enum(["private","public"]).optional(),intent:t.string().max(s).optional()}).strict(),C=t.object({planId:t.string().regex(/^[0-9a-f]{32}$/),normalisedPath:t.string().min(1),resolvedInputs:j,targetAccount:p.nullable(),targetAccountCandidates:t.array(p),filesToWrite:t.array(m),npmPackages:t.array(t.string().min(1)),registryActions:t.array(c),patternUnsupportedForDryRun:t.boolean().optional(),intent:t.string().max(s).optional(),framework:t.string().min(1).optional(),summary:t.string().min(1)}).strict(),D=t.object({filesToWrite:t.array(m),npmPackages:t.array(t.string().min(1)),registryActions:t.array(c),patternUnsupportedForDryRun:t.boolean().optional()}).strict(),M=t.object({path:t.string().min(1),name:t.string().min(1),mode:t.enum(["application","pattern"]),dependenciesInstalled:t.boolean().optional(),warning:t.string().optional(),dryRunArtefacts:D.optional()}).strict(),U=t.object({step:t.string().min(1),current:t.number().int().nonnegative(),total:t.number().int().positive().optional(),message:t.string().min(1)}).strict();function V(e){let r;try{r=JSON.parse(e)}catch(i){return{ok:!1,reason:"json",raw:e,error:i instanceof Error?i.message:String(i)}}const o=N.safeParse(r);return o.success?{ok:!0,frame:o.data}:{ok:!1,reason:"schema",raw:e,error:o.error.message}}a(V,"parseFrame");export{y as AuthBrowserCompleteFrameSchema,T as AuthBrowserRequiredFrameSchema,D as DryRunArtefactsSchema,I as ErrorFrameSchema,m as FileToWriteSchema,s as INTENT_MAX_LENGTH,L as MCP_ERROR_CODES,b as MCP_PROTOCOL_VERSION,N as McpProtocolFrameSchema,c as RegistryActionSchema,j as ResolvedInputsSchema,x as ResultFrameSchema,C as ScaffoldPlanSchema,U as ScaffoldProgressFrameSchema,M as ScaffoldResultDataSchema,S as StepCompleteFrameSchema,R as StepStartFrameSchema,p as TargetAccountSchema,E as WarningFrameSchema,V as parseFrame};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application infrastructure stacks.
|
|
3
|
+
*
|
|
4
|
+
* UsEast1Certificates is the app-owned us-east-1 certificate stack (domain
|
|
5
|
+
* gold-plating D3, BYO CloudFront path — components/infrastructure
|
|
6
|
+
* `App.getUsEast1CertificateStack`). It exists only when a CloudFront-facing
|
|
7
|
+
* pattern carries a custom domain outside us-east-1, so ordering derivations
|
|
8
|
+
* include it ONLY when the post-synth manifest proves it
|
|
9
|
+
* (`AppResourceFlags.hasUsEast1Certificates`) — a fixed-set entry would make
|
|
10
|
+
* every deploy attempt a stack that does not exist. It must deploy BEFORE Cdn
|
|
11
|
+
* (the distribution consumes its certificate ARN through cross-region
|
|
12
|
+
* references) and destroy AFTER Cdn.
|
|
13
|
+
*
|
|
14
|
+
* UsEast1CdnLogging is the app-owned us-east-1 CloudFront standard-logging
|
|
15
|
+
* (v2) stack (components/infrastructure `App.getUsEast1CdnLoggingStack`).
|
|
16
|
+
* CloudWatch vends CloudFront delivery sources, destinations and deliveries
|
|
17
|
+
* in us-east-1 only, so a logging CDN whose app deploys elsewhere creates
|
|
18
|
+
* them there. It CONSUMES the Cdn stack's distribution and bucket ARNs
|
|
19
|
+
* through cross-region references, so it is the mirror of the certificate
|
|
20
|
+
* stack: it deploys AFTER Cdn and is destroyed BEFORE it, and it is likewise
|
|
21
|
+
* conditional — a CDN in a us-east-1 app never creates it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const APPLICATION_STACKS: {
|
|
24
|
+
readonly NETWORK: "Network";
|
|
25
|
+
readonly DATABASE: "Database";
|
|
26
|
+
readonly STORAGE: "Storage";
|
|
27
|
+
readonly COMPUTE: "Compute";
|
|
28
|
+
readonly US_EAST_1_CERTIFICATES: "UsEast1Certificates";
|
|
29
|
+
readonly CDN: "Cdn";
|
|
30
|
+
readonly US_EAST_1_CDN_LOGGING: "UsEast1CdnLogging";
|
|
31
|
+
readonly MESSAGING: "Messaging";
|
|
32
|
+
};
|
|
33
|
+
export type ApplicationStack = (typeof APPLICATION_STACKS)[keyof typeof APPLICATION_STACKS];
|
|
34
|
+
export declare function isApplicationStack(value: string): value is ApplicationStack;
|
|
35
|
+
/**
|
|
36
|
+
* CloudFormation stack name of one of an application's stacks.
|
|
37
|
+
*
|
|
38
|
+
* This is the derivation `@fjall/components-infrastructure` uses to NAME the
|
|
39
|
+
* stack at synth (`App` keys every stack on `toPascalCase(appName)` and the
|
|
40
|
+
* stack id is the CloudFormation stack name), so it is the only way runtime
|
|
41
|
+
* code may address one: a re-implementation agrees with the construct for a
|
|
42
|
+
* lowercase app name and diverges for `billing-api` or `WebApp`, which is how
|
|
43
|
+
* a hand-rolled `${appName}Network` shipped through typecheck and every
|
|
44
|
+
* kebab-named fixture before failing for the first hyphenated app. Both sides
|
|
45
|
+
* call this function; neither composes the string.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getApplicationStackName(appName: string, stack: ApplicationStack): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var A=Object.defineProperty;var a=(t,e)=>A(t,"name",{value:e,configurable:!0});import{toPascalCase as S}from"./caseConversion.js";const o={NETWORK:"Network",DATABASE:"Database",STORAGE:"Storage",COMPUTE:"Compute",US_EAST_1_CERTIFICATES:"UsEast1Certificates",CDN:"Cdn",US_EAST_1_CDN_LOGGING:"UsEast1CdnLogging",MESSAGING:"Messaging"},n=new Set(Object.values(o));function i(t){return n.has(t)}a(i,"isApplicationStack");function r(t,e){return`${S(t)}${e}`}a(r,"getApplicationStackName");export{o as APPLICATION_STACKS,r as getApplicationStackName,i as isApplicationStack};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export names an application's own stacks emit for the runtime to read back.
|
|
3
|
+
*
|
|
4
|
+
* These names are a contract between `@fjall/components-infrastructure`,
|
|
5
|
+
* which emits them as CloudFormation exports at synth, and the runtime
|
|
6
|
+
* consumers that address the live resources they name: deploy-core's
|
|
7
|
+
* `EcsServiceResolver` (the ECS services `fjall services`, `fjall rollout`,
|
|
8
|
+
* a code-only deploy, a rollback and a restart act on) and the fjall.io
|
|
9
|
+
* webapp's VPC CIDR capture. Both sides MUST call these functions rather than
|
|
10
|
+
* compose or pattern-match the string themselves. The producer once built
|
|
11
|
+
* the service name from `toPascalCase(appName)` while the consumer searched
|
|
12
|
+
* exports for the app name as written, so no hyphenated app could resolve
|
|
13
|
+
* its services; and a substring match on the consumer side returned a
|
|
14
|
+
* sibling app's services whenever one name contained the other.
|
|
15
|
+
*
|
|
16
|
+
* Every builder takes RAW names — the CloudFormation stack name, the
|
|
17
|
+
* cluster's construct id, the service's manifest name, the VPC's construct
|
|
18
|
+
* id — never a pre-sanitised token, so the two sides cannot normalise
|
|
19
|
+
* differently. `stackName` is the stack the output lives in
|
|
20
|
+
* (`getApplicationStackName`), which is what makes the name unique per
|
|
21
|
+
* account and region: export names are a flat namespace, and a name built
|
|
22
|
+
* only from the literal ids inside a pattern is shared by every app that
|
|
23
|
+
* uses that pattern.
|
|
24
|
+
*
|
|
25
|
+
* The `is*ExportName` predicates identify an output that CLAIMS the contract
|
|
26
|
+
* (they read the marker suffix, case-sensitively). A consumer that selects
|
|
27
|
+
* by predicate must then verify the claim by rebuilding the name from the
|
|
28
|
+
* output's own value and refuse the output when the two disagree — the
|
|
29
|
+
* predicate is a filter, never proof.
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* Qualify an export name with the stack that emits it. The suffix stays
|
|
33
|
+
* last: every builder below composes through this function, and the
|
|
34
|
+
* predicates read the tail.
|
|
35
|
+
*/
|
|
36
|
+
export declare function stackScopedExportName(stackName: string, suffix: string): string;
|
|
37
|
+
export declare const DEPLOYABLE_SERVICE_EXPORT_MARKER = "DeployableService";
|
|
38
|
+
export declare const DEPLOYABLE_CLUSTER_EXPORT_MARKER = "DeployableCluster";
|
|
39
|
+
export declare const CLUSTER_ARN_EXPORT_MARKER = "ClusterArn";
|
|
40
|
+
export declare const VPC_CIDR_EXPORT_MARKER = "-vpc-cidr";
|
|
41
|
+
/**
|
|
42
|
+
* Export carrying the ARN of one deployable ECS service.
|
|
43
|
+
*
|
|
44
|
+
* `clusterName` is the ECS cluster's construct id, which is also its physical
|
|
45
|
+
* cluster name; `serviceName` is the service's manifest name, which is also
|
|
46
|
+
* its physical ECS service name. Both therefore reappear verbatim in the
|
|
47
|
+
* exported ARN (`…:service/<clusterName>/<serviceName>`), so a consumer can
|
|
48
|
+
* rebuild this name from the ARN alone and check the export against it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function deployableServiceExportName(stackName: string, clusterName: string, serviceName: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* The unqualified form constructs 2.0.0 through 7.x emitted, before 8.0.0
|
|
53
|
+
* qualified every export with its stack. Consumers accept it so an app last
|
|
54
|
+
* deployed on those versions still resolves; nothing emits it any more.
|
|
55
|
+
*/
|
|
56
|
+
export declare function legacyDeployableServiceExportName(clusterName: string, serviceName: string): string;
|
|
57
|
+
export declare function isDeployableServiceExportName(exportName: string): boolean;
|
|
58
|
+
/** Export carrying the ARN of a cluster that holds deployable services. */
|
|
59
|
+
export declare function deployableClusterExportName(stackName: string, clusterName: string): string;
|
|
60
|
+
/** Export carrying an ECS cluster's ARN under its plain name. */
|
|
61
|
+
export declare function clusterArnExportName(stackName: string, clusterName: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Construct id of the VPC `App.getApp(name, { network })` creates in the
|
|
64
|
+
* app's Network stack — the id the VPC CIDR export is keyed on.
|
|
65
|
+
*/
|
|
66
|
+
export declare function defaultVpcConstructId(appName: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Export carrying a VPC's CIDR block. The construct id is load-bearing: a
|
|
69
|
+
* stack holding two VPCs (`app.addNetwork`) would otherwise emit one name
|
|
70
|
+
* twice, and CloudFormation rejects the template.
|
|
71
|
+
*/
|
|
72
|
+
export declare function vpcCidrExportName(stackName: string, vpcConstructId: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* The form constructs before 8.0.0 emitted, keyed on the stack alone.
|
|
75
|
+
* Accepted by consumers for apps last deployed on those versions.
|
|
76
|
+
*/
|
|
77
|
+
export declare function legacyVpcCidrExportName(stackName: string): string;
|
|
78
|
+
export declare function isVpcCidrExportName(exportName: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var u=Object.defineProperty;var t=(e,r)=>u(e,"name",{value:r,configurable:!0});import{toPascalCase as E}from"./caseConversion.js";function o(e,r){return`${e}${r}`}t(o,"stackScopedExportName");const n="DeployableService",i="DeployableCluster",x="ClusterArn",p="-vpc-cidr";function R(e,r,c){return o(e,`${r}${c}${n}`)}t(R,"deployableServiceExportName");function s(e,r){return`${e}${r}${n}`}t(s,"legacyDeployableServiceExportName");function $(e){return e.endsWith(n)}t($,"isDeployableServiceExportName");function C(e,r){return o(e,`${r}${i}`)}t(C,"deployableClusterExportName");function f(e,r){return o(e,`${r}${x}`)}t(f,"clusterArnExportName");function _(e){return`${E(e)}Vpc`}t(_,"defaultVpcConstructId");function d(e,r){return o(e,`${r}${p}`)}t(d,"vpcCidrExportName");function m(e){return o(e,p)}t(m,"legacyVpcCidrExportName");function N(e){return e.endsWith(p)}t(N,"isVpcCidrExportName");export{x as CLUSTER_ARN_EXPORT_MARKER,i as DEPLOYABLE_CLUSTER_EXPORT_MARKER,n as DEPLOYABLE_SERVICE_EXPORT_MARKER,p as VPC_CIDR_EXPORT_MARKER,f as clusterArnExportName,_ as defaultVpcConstructId,C as deployableClusterExportName,R as deployableServiceExportName,$ as isDeployableServiceExportName,N as isVpcCidrExportName,s as legacyDeployableServiceExportName,m as legacyVpcCidrExportName,o as stackScopedExportName,d as vpcCidrExportName};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A read-only partial record that cannot be empty: the union, over every
|
|
3
|
+
* key of `T`, of "this key required, the rest optional". `{}` is
|
|
4
|
+
* unrepresentable whether or not `T` declares the key optional (the
|
|
5
|
+
* required arm strips `?`, so the carried key is present with its value),
|
|
6
|
+
* a key `T` does not carry fails typecheck on a literal, and each present
|
|
7
|
+
* key keeps its own value type — `T[K]` may differ per key, which is what a
|
|
8
|
+
* plain `Partial<T>` with a non-emptiness check cannot express. The shape a
|
|
9
|
+
* cure map is declared on: the posture registries' `PolicyCure`, and a
|
|
10
|
+
* consumer mirroring the cure map declares its own on this helper rather
|
|
11
|
+
* than re-spelling the union.
|
|
12
|
+
*/
|
|
13
|
+
export type NonEmptyPartial<T> = {
|
|
14
|
+
[Key in keyof T]-?: {
|
|
15
|
+
readonly [K in Key]-?: T[K];
|
|
16
|
+
} & {
|
|
17
|
+
readonly [K in Exclude<keyof T, Key>]?: T[K];
|
|
18
|
+
};
|
|
19
|
+
}[keyof T];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const n={first:1},o={second:"two"},t={first:1,second:"two"},s={},e={first:1,third:3},c={second:"two"},i={},d={second:void 0};
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* than left behind as a lie. The reverse holds too: a pattern that loses its
|
|
31
31
|
* construct cannot stay in `recommended`.
|
|
32
32
|
*/
|
|
33
|
-
import { PATTERN_REGISTRY, type PatternType, type PatternCreateInput } from "./patternTypes.js";
|
|
33
|
+
import { PATTERN_REGISTRY, type PatternType, type PatternCreateInput, type DeployablePatternType } from "./patternTypes.js";
|
|
34
34
|
/**
|
|
35
35
|
* Every framework the detector can name.
|
|
36
36
|
*
|
|
@@ -50,13 +50,6 @@ export declare const FRAMEWORK_VALUES: readonly ["nextjs", "payload", "nextjs+pa
|
|
|
50
50
|
export type Framework = (typeof FRAMEWORK_VALUES)[number];
|
|
51
51
|
export declare const FRAMEWORKS: ReadonlySet<string>;
|
|
52
52
|
export declare function isFramework(value: unknown): value is Framework;
|
|
53
|
-
/**
|
|
54
|
-
* The patterns that can deploy end-to-end, derived from the registry's own
|
|
55
|
-
* flag at the type level. `DEPLOYABLE_PATTERN_TYPES` is the value-level twin.
|
|
56
|
-
*/
|
|
57
|
-
export type DeployablePatternType = {
|
|
58
|
-
[K in PatternType]: (typeof PATTERN_REGISTRY)[K]["deployable"] extends true ? K : never;
|
|
59
|
-
}[PatternType];
|
|
60
53
|
/**
|
|
61
54
|
* The patterns the generator knows but cannot yet synthesise. Uninhabited once
|
|
62
55
|
* every pattern is deployable — at which point the `blocked` verdict below
|
package/dist/patterns/index.d.ts
CHANGED
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
* the webapp bundles) can take the vocabulary without depending on the root
|
|
8
8
|
* barrel's contents staying pure.
|
|
9
9
|
*/
|
|
10
|
-
export { PATTERN_TYPE_VALUES, type PatternType, PATTERN_TYPES, isPatternType, type PatternArtefact, type PatternStackPlacement, type PatternDescriptor, PATTERN_REGISTRY, patternConstructId, DEPLOYABLE_PATTERN_TYPES, type OpenNextPatternType, OPENNEXT_PATTERN_TYPES, isOpenNextPatternType, CLOUDFRONT_PRICE_CLASS_VALUES, type CloudFrontPriceClass, STATIC_SITE_CONFIG_KEYS, type StaticSiteConfigKey, STATIC_SITE_DEPLOY_INJECTED_KEYS, type StaticSiteDeployInjectedKey, STATIC_SITE_CDN_CONFIG_KEYS, type StaticSiteCdnConfigKey, STATIC_SITE_ROUTING_VALUES, STATIC_SITE_ROUTING_INFO, type StaticSiteRouting, type StaticSiteRoutingDescriptor, PATTERN_CREATE_INPUT_VALUES, type PatternCreateInput, PATTERN_CREATE_INPUT_FLAGS } from "./patternTypes.js";
|
|
11
|
-
export { FRAMEWORK_VALUES, type Framework, FRAMEWORKS, isFramework, type
|
|
10
|
+
export { PATTERN_TYPE_VALUES, type PatternType, PATTERN_TYPES, isPatternType, type PatternArtefact, type PatternStackPlacement, type PatternDescriptor, PATTERN_REGISTRY, patternConstructId, type DeployablePatternType, DEPLOYABLE_PATTERN_TYPES, PATTERN_TIER_VALUES, type PatternTier, type OpenNextPatternType, OPENNEXT_PATTERN_TYPES, isOpenNextPatternType, OPENNEXT_BUCKET_KEYS, type OpenNextBucketKey, isOpenNextBucketKey, patternBucketConstructId, CLOUDFRONT_PRICE_CLASS_VALUES, type CloudFrontPriceClass, STATIC_SITE_CONFIG_KEYS, type StaticSiteConfigKey, STATIC_SITE_DEPLOY_INJECTED_KEYS, type StaticSiteDeployInjectedKey, STATIC_SITE_CDN_CONFIG_KEYS, type StaticSiteCdnConfigKey, STATIC_SITE_ROUTING_VALUES, STATIC_SITE_ROUTING_INFO, type StaticSiteRouting, type StaticSiteRoutingDescriptor, PATTERN_CREATE_INPUT_VALUES, type PatternCreateInput, PATTERN_CREATE_INPUT_FLAGS } from "./patternTypes.js";
|
|
11
|
+
export { FRAMEWORK_VALUES, type Framework, FRAMEWORKS, isFramework, type UndeployablePatternType, type PatternRecommendation, FRAMEWORK_PATTERN_RECOMMENDATIONS, recommendPatternForFramework, CREATABLE_FRAMEWORKS, requiredInputsForFramework } from "./frameworkPatterns.js";
|
|
12
12
|
export { DEFAULT_FORMS_FROM_LOCAL_PART, defaultFormsFromAddress, defaultFormsCorsOrigin, isAddressAtDomain } from "./staticSiteForms.js";
|
package/dist/patterns/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PATTERN_TYPE_VALUES as _,PATTERN_TYPES as A,isPatternType as r,PATTERN_REGISTRY as R,patternConstructId as S,DEPLOYABLE_PATTERN_TYPES as
|
|
1
|
+
import{PATTERN_TYPE_VALUES as _,PATTERN_TYPES as A,isPatternType as r,PATTERN_REGISTRY as R,patternConstructId as S,DEPLOYABLE_PATTERN_TYPES as e,PATTERN_TIER_VALUES as N,OPENNEXT_PATTERN_TYPES as t,isOpenNextPatternType as I,OPENNEXT_BUCKET_KEYS as P,isOpenNextBucketKey as O,patternBucketConstructId as C,CLOUDFRONT_PRICE_CLASS_VALUES as F,STATIC_SITE_CONFIG_KEYS as o,STATIC_SITE_DEPLOY_INJECTED_KEYS as L,STATIC_SITE_CDN_CONFIG_KEYS as s,STATIC_SITE_ROUTING_VALUES as n,STATIC_SITE_ROUTING_INFO as U,PATTERN_CREATE_INPUT_VALUES as m,PATTERN_CREATE_INPUT_FLAGS as a}from"./patternTypes.js";import{FRAMEWORK_VALUES as d,FRAMEWORKS as p,isFramework as K,FRAMEWORK_PATTERN_RECOMMENDATIONS as i,recommendPatternForFramework as u,CREATABLE_FRAMEWORKS as D,requiredInputsForFramework as M}from"./frameworkPatterns.js";import{DEFAULT_FORMS_FROM_LOCAL_PART as V,defaultFormsFromAddress as c,defaultFormsCorsOrigin as f,isAddressAtDomain as k}from"./staticSiteForms.js";export{F as CLOUDFRONT_PRICE_CLASS_VALUES,D as CREATABLE_FRAMEWORKS,V as DEFAULT_FORMS_FROM_LOCAL_PART,e as DEPLOYABLE_PATTERN_TYPES,p as FRAMEWORKS,i as FRAMEWORK_PATTERN_RECOMMENDATIONS,d as FRAMEWORK_VALUES,P as OPENNEXT_BUCKET_KEYS,t as OPENNEXT_PATTERN_TYPES,a as PATTERN_CREATE_INPUT_FLAGS,m as PATTERN_CREATE_INPUT_VALUES,R as PATTERN_REGISTRY,N as PATTERN_TIER_VALUES,A as PATTERN_TYPES,_ as PATTERN_TYPE_VALUES,s as STATIC_SITE_CDN_CONFIG_KEYS,o as STATIC_SITE_CONFIG_KEYS,L as STATIC_SITE_DEPLOY_INJECTED_KEYS,U as STATIC_SITE_ROUTING_INFO,n as STATIC_SITE_ROUTING_VALUES,f as defaultFormsCorsOrigin,c as defaultFormsFromAddress,k as isAddressAtDomain,K as isFramework,O as isOpenNextBucketKey,I as isOpenNextPatternType,r as isPatternType,C as patternBucketConstructId,S as patternConstructId,u as recommendPatternForFramework,M as requiredInputsForFramework};
|
|
@@ -128,12 +128,54 @@ export declare const PATTERN_REGISTRY: {
|
|
|
128
128
|
* detection silently re-admits the synth-fatal id collision.
|
|
129
129
|
*/
|
|
130
130
|
export declare function patternConstructId(name: string, type: PatternType): string;
|
|
131
|
+
/**
|
|
132
|
+
* The buckets an OpenNext pattern's construct builds, keyed as the pattern
|
|
133
|
+
* statement's `storage` config spells them (`storage.media.versioned`): the
|
|
134
|
+
* build output, the ISR cache and the uploads. The constructs' props type
|
|
135
|
+
* and the generator's config schema are both pinned to this tuple, so a
|
|
136
|
+
* bucket the construct starts building appears in the config vocabulary
|
|
137
|
+
* before either can compile without it.
|
|
138
|
+
*/
|
|
139
|
+
export declare const OPENNEXT_BUCKET_KEYS: readonly ["assets", "cache", "media"];
|
|
140
|
+
export type OpenNextBucketKey = (typeof OPENNEXT_BUCKET_KEYS)[number];
|
|
141
|
+
export declare function isOpenNextBucketKey(value: unknown): value is OpenNextBucketKey;
|
|
142
|
+
/**
|
|
143
|
+
* The construct id of one bucket an OpenNext pattern builds — the FIRST
|
|
144
|
+
* ARGUMENT of the `StorageFactory.build` call the construct makes for it:
|
|
145
|
+
* the pattern statement's `name` prop (the workload name the engine lists
|
|
146
|
+
* as `resourceName`), a hyphen, the bucket key. The bucket's CloudFormation
|
|
147
|
+
* logical id is derived from this id, so a consumer matching a logical id
|
|
148
|
+
* back to the statement that owns the bucket derives the same string here
|
|
149
|
+
* rather than re-composing it; a drifted re-composition agrees for every
|
|
150
|
+
* kebab-case name and diverges the first time a name carries a case
|
|
151
|
+
* boundary the id derivation folds.
|
|
152
|
+
*/
|
|
153
|
+
export declare function patternBucketConstructId(name: string, bucket: OpenNextBucketKey): string;
|
|
154
|
+
/**
|
|
155
|
+
* The patterns that can deploy end-to-end, derived from the registry's own
|
|
156
|
+
* flag at the type level. `DEPLOYABLE_PATTERN_TYPES` is the value-level twin.
|
|
157
|
+
*/
|
|
158
|
+
export type DeployablePatternType = {
|
|
159
|
+
[K in PatternType]: (typeof PATTERN_REGISTRY)[K]["deployable"] extends true ? K : never;
|
|
160
|
+
}[PatternType];
|
|
131
161
|
/**
|
|
132
162
|
* Patterns the toolchain may offer for creation, derived from the registry —
|
|
133
163
|
* pickers and validation reject the rest at create time instead of letting a
|
|
134
|
-
* scaffold fail at first deploy.
|
|
164
|
+
* scaffold fail at first deploy. Typed to the deployable subset so an enum
|
|
165
|
+
* built from it (`z.enum(DEPLOYABLE_PATTERN_TYPES)`) infers exactly the
|
|
166
|
+
* members it accepts at runtime.
|
|
167
|
+
*/
|
|
168
|
+
export declare const DEPLOYABLE_PATTERN_TYPES: readonly DeployablePatternType[];
|
|
169
|
+
/**
|
|
170
|
+
* Tier presets a pattern may be created with — the ONE spelling the generator
|
|
171
|
+
* (`PatternTierSchema`), the CLI's SKILL vocabulary, the MCP protocol's
|
|
172
|
+
* `ResolvedInputsSchema` and the MCP `plan_app_scaffold` input derive from.
|
|
173
|
+
* Not the infrastructure tiers (`TIER_NAMES`: tinkerer … enterprise), which
|
|
174
|
+
* govern `fjall add … --tier` — the two vocabularies were conflated on the MCP
|
|
175
|
+
* surface until Train 4 of the 2026-09-07 hardening prompt.
|
|
135
176
|
*/
|
|
136
|
-
export declare const
|
|
177
|
+
export declare const PATTERN_TIER_VALUES: readonly ["lightweight", "standard", "resilient", "custom"];
|
|
178
|
+
export type PatternTier = (typeof PATTERN_TIER_VALUES)[number];
|
|
137
179
|
/**
|
|
138
180
|
* The OpenNext-shaped patterns, derived from the registry at both the type and
|
|
139
181
|
* the value level — a new OpenNext pattern joins this accept-set by declaring
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var n=Object.defineProperty;var e=(t,
|
|
1
|
+
var n=Object.defineProperty;var e=(t,s)=>n(t,"name",{value:s,configurable:!0});import{toPascalCase as r}from"../naming/caseConversion.js";const o=["payload","nextjs","staticsite"],c=new Set(o);function S(t){return typeof t=="string"&&c.has(t)}e(S,"isPatternType");const d=["source","buildCommand","outputDir"],_={source:"--source",buildCommand:"--build-command",outputDir:"--output-dir"},a={payload:{label:"Payload CMS",constructIdSuffix:"Payload",artefact:"opennext-lambda",stackPlacement:"compute",deployable:!0,requiredCreateInputs:[],synthesises:["AWS::S3::Bucket","AWS::KMS::Key"]},nextjs:{label:"Next.js",constructIdSuffix:"Nextjs",artefact:"opennext-lambda",stackPlacement:"compute",deployable:!1,requiredCreateInputs:[],synthesises:["AWS::S3::Bucket","AWS::KMS::Key"]},staticsite:{label:"Static site",constructIdSuffix:"StaticSite",artefact:"static-assets",stackPlacement:"cdn",deployable:!0,requiredCreateInputs:["source","buildCommand","outputDir"],synthesises:["AWS::S3::Bucket"]}};function m(t,s){return`${r(t)}${a[s].constructIdSuffix}`}e(m,"patternConstructId");const i=["assets","cache","media"],u=new Set(i);function x(t){return typeof t=="string"&&u.has(t)}e(x,"isOpenNextBucketKey");function P(t,s){return`${t}-${s}`}e(P,"patternBucketConstructId");const N=o.filter(t=>a[t].deployable),I=["lightweight","standard","resilient","custom"],p=o.filter(t=>a[t].artefact==="opennext-lambda"),l=new Set(p);function A(t){return t!=null&&l.has(t)}e(A,"isOpenNextPatternType");const C=["multipage","directory","spa"],f={multipage:{label:"Multi-page (.html files)",summary:"/about serves /about.html"},directory:{label:"Directory index",summary:"/about serves /about/index.html"},spa:{label:"Single-page app",summary:"unknown paths fall back to /index.html"}},y=["PriceClass_100","PriceClass_200","PriceClass_All"],b=["type","name","source","build","routing","security","domain","managedDomain","zoneName","hostedZoneId","forms","cdn","accessGate"],R=["managedDomain"],h=["behaviours","priceClass","invalidateOnDeploy"];export{y as CLOUDFRONT_PRICE_CLASS_VALUES,N as DEPLOYABLE_PATTERN_TYPES,i as OPENNEXT_BUCKET_KEYS,p as OPENNEXT_PATTERN_TYPES,_ as PATTERN_CREATE_INPUT_FLAGS,d as PATTERN_CREATE_INPUT_VALUES,a as PATTERN_REGISTRY,I as PATTERN_TIER_VALUES,c as PATTERN_TYPES,o as PATTERN_TYPE_VALUES,h as STATIC_SITE_CDN_CONFIG_KEYS,b as STATIC_SITE_CONFIG_KEYS,R as STATIC_SITE_DEPLOY_INJECTED_KEYS,f as STATIC_SITE_ROUTING_INFO,C as STATIC_SITE_ROUTING_VALUES,x as isOpenNextBucketKey,A as isOpenNextPatternType,S as isPatternType,P as patternBucketConstructId,m as patternConstructId};
|