@jaypie/mcp 0.8.23 → 0.8.24

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 @@ import { gt } from 'semver';
9
9
  /**
10
10
  * Docs Suite - Documentation services (skill, version, release_notes)
11
11
  */
12
- const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.23#3db47ebf"
12
+ const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.24#3651d9a7"
13
13
  ;
14
14
  const __filename$1 = fileURLToPath(import.meta.url);
15
15
  const __dirname$1 = path.dirname(__filename$1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaypie/mcp",
3
- "version": "0.8.23",
3
+ "version": "0.8.24",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,11 @@
1
+ ---
2
+ version: 1.2.42
3
+ date: 2026-04-10
4
+ summary: Add deleteExistingRecord prop to JaypieApiGateway and JaypieDistribution for clean DNS swaps
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Add `deleteExistingRecord` prop to `JaypieApiGatewayProps` and `JaypieDistributionProps` (default `false`)
10
+ - When `true`, the underlying Route53 `ARecord` (and `AaaaRecord` for `JaypieDistribution`) sets `deleteExisting: true`, force-deleting any existing record with the same name before creating the alias
11
+ - Enables single-deploy migration between `JaypieApiGateway` and `JaypieDistribution` for the same hostname, where CloudFormation's default create-before-delete ordering would otherwise collide on the Route53 record name
@@ -0,0 +1,11 @@
1
+ ---
2
+ version: 0.8.24
3
+ date: 2026-04-10
4
+ summary: Add apigateway skill and constructs 1.2.42 release notes
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Added `apigateway` skill covering `JaypieApiGateway` props, hostname resolution, and migration to `JaypieDistribution` (including the DNS record collision gotcha and `deleteExistingRecord` workaround)
10
+ - Added release notes for `@jaypie/constructs` 1.2.42
11
+ - Indexed `apigateway` under the infrastructure category in `skills.md` and `agents.md`
package/skills/agents.md CHANGED
@@ -34,7 +34,7 @@ Complete stack styles, techniques, and traditions.
34
34
 
35
35
  Contents: index, releasenotes
36
36
  Development: apikey, documentation, errors, llm, logs, mocks, monorepo, style, subpackages, tests, tools
37
- Infrastructure: aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, websockets
37
+ Infrastructure: apigateway, aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, websockets
38
38
  Patterns: api, fabric, handlers, models, services, vocabulary
39
39
  Recipes: recipe-api-server
40
40
  Meta: issues, jaypie, mcp, skills
@@ -0,0 +1,208 @@
1
+ ---
2
+ description: JaypieApiGateway construct and migration to JaypieDistribution
3
+ related: cdk, dns, express, lambda, streaming, variables
4
+ ---
5
+
6
+ # JaypieApiGateway
7
+
8
+ `JaypieApiGateway` wraps `apiGateway.LambdaRestApi` with environment-aware domain resolution, automatic ACM certificate provisioning, Route53 alias records, and standard Jaypie tagging.
9
+
10
+ ```typescript
11
+ import { JaypieApiGateway, JaypieExpressLambda } from "@jaypie/constructs";
12
+
13
+ const handler = new JaypieExpressLambda(this, "Api", {
14
+ code: "dist/api",
15
+ handler: "index.handler",
16
+ });
17
+
18
+ new JaypieApiGateway(this, "ApiGateway", { handler });
19
+ ```
20
+
21
+ ## Props
22
+
23
+ `JaypieApiGatewayProps` extends `apiGateway.LambdaRestApiProps` and adds:
24
+
25
+ | Prop | Type | Default | Description |
26
+ |------|------|---------|-------------|
27
+ | `handler` | `lambda.IFunction` | required | Lambda backing the REST API (from `LambdaRestApiProps`) |
28
+ | `certificate` | `boolean \| acm.ICertificate` | `true` | `true` creates/reuses a stack-level certificate; pass an `ICertificate` to share one (e.g. from `JaypieCertificate`); `false` disables custom domain wiring |
29
+ | `deleteExistingRecord` | `boolean` | `false` | Force-delete any existing Route53 A record with the same name before creating the alias. Use when migrating from another construct (e.g., `JaypieDistribution`) that already owns the same hostname |
30
+ | `host` | `string \| HostConfig` | from env | Custom domain name — see "Hostname Options" below |
31
+ | `name` | `string` | `constructEnvName("ApiGateway")` | Override the REST API name |
32
+ | `roleTag` | `string` | `CDK.ROLE.API` | Role tag applied to the API, domain, and certificate resources |
33
+ | `zone` | `string \| route53.IHostedZone` | `CDK_ENV_API_HOSTED_ZONE` | Hosted zone for DNS alias record; resolved via `resolveHostedZone` |
34
+
35
+ All remaining `LambdaRestApiProps` (e.g. `deployOptions`, `defaultCorsPreflightOptions`, `proxy`) pass through to the underlying `LambdaRestApi`.
36
+
37
+ ### Side Effects
38
+
39
+ - When `host` resolves, sets `PROJECT_BASE_URL=https://${host}` on the `handler` Lambda (if it supports `addEnvironment`).
40
+ - When `host` and `zone` resolve, creates an ACM certificate (via `resolveCertificate`), attaches a custom domain, and adds an `ARecord` alias pointing at the API Gateway domain.
41
+
42
+ ## Hostname Options
43
+
44
+ `host` accepts either a literal string or a `HostConfig` object that feeds `envHostname()`:
45
+
46
+ ```typescript
47
+ // Literal string — used verbatim
48
+ new JaypieApiGateway(this, "Api", { handler, host: "api.example.com" });
49
+
50
+ // HostConfig — resolved via envHostname()
51
+ new JaypieApiGateway(this, "Api", {
52
+ handler,
53
+ host: { subdomain: "api" }, // + CDK_ENV_DOMAIN/CDK_ENV_HOSTED_ZONE + PROJECT_ENV
54
+ });
55
+ ```
56
+
57
+ `HostConfig` fields (all optional, default to env vars):
58
+
59
+ | Field | Env Fallback | Notes |
60
+ |-------|--------------|-------|
61
+ | `component` | — | Extra leading label; `"@"` or `""` clears it |
62
+ | `domain` | `CDK_ENV_DOMAIN` → `CDK_ENV_HOSTED_ZONE` | Required (directly or from env); throws `ConfigurationError` if missing |
63
+ | `env` | `PROJECT_ENV` | Dropped when equal to `production` or to `CDK_ENV_PERSONAL` |
64
+ | `subdomain` | `CDK_ENV_SUBDOMAIN` | `"@"` or `""` clears it |
65
+
66
+ `envHostname` also prepends `CDK_ENV_PERSONAL` for personal builds and de-duplicates parts already present in the domain.
67
+
68
+ ### Host Resolution Order
69
+
70
+ When `host` is not provided as a prop, `JaypieApiGateway` falls back to these environment variables in order:
71
+
72
+ 1. `CDK_ENV_API_HOST_NAME` — used directly
73
+ 2. `CDK_ENV_API_SUBDOMAIN` + `CDK_ENV_API_HOSTED_ZONE` — joined via `mergeDomain`
74
+
75
+ If neither resolves, no custom domain, certificate, or DNS record is created and the construct exposes the default execute-api URL via `.url`.
76
+
77
+ ### Zone Resolution
78
+
79
+ - `props.zone` wins if provided.
80
+ - Otherwise falls back to `CDK_ENV_API_HOSTED_ZONE` (note: `JaypieApiGateway` does *not* fall back to `CDK_ENV_HOSTED_ZONE`; `JaypieDistribution` does).
81
+
82
+ ## Exposed Properties
83
+
84
+ `JaypieApiGateway` implements `apiGateway.IRestApi` and surfaces:
85
+
86
+ - `api` — underlying `LambdaRestApi`
87
+ - `url` — default invoke URL
88
+ - `host` — resolved custom hostname (if any)
89
+ - `certificateArn`, `domainName`, `domainNameAliasDomainName`, `domainNameAliasHostedZoneId`
90
+ - `restApiId`, `restApiName`, `restApiRootResourceId`, `restApiRef`
91
+ - `deploymentStage`, `root`, `env`, `stack`
92
+ - `arnForExecuteApi(method, path, stage)` and the standard `metric*()` helpers
93
+
94
+ ## Migrating to JaypieDistribution
95
+
96
+ `JaypieDistribution` is the preferred front door for new Jaypie APIs. It fronts the Lambda with CloudFront + Lambda Function URLs instead of API Gateway, and ships with capabilities `JaypieApiGateway` lacks:
97
+
98
+ - **WAFv2 WebACL** (managed rules + IP rate limiting + logging) by default — see `skill("cdk")`
99
+ - **Security response headers** (HSTS, CSP, X-Frame-Options, etc.) by default
100
+ - **Response streaming** via `streaming: true` (requires Lambda Function URL, not API Gateway) — see `skill("streaming")`
101
+ - **CloudFront access logs** with Datadog forwarding
102
+ - **Lower request cost** at scale (no API Gateway per-request charge)
103
+ - **IPv6** via automatic `AaaaRecord`
104
+
105
+ ### Swap the Construct
106
+
107
+ ```typescript
108
+ // Before
109
+ new JaypieApiGateway(this, "ApiGateway", {
110
+ handler,
111
+ host: { subdomain: "api" },
112
+ });
113
+
114
+ // After
115
+ new JaypieDistribution(this, "Distribution", {
116
+ handler,
117
+ host: { subdomain: "api" },
118
+ });
119
+ ```
120
+
121
+ Both constructs accept `handler`, `host`, `zone`, `certificate`, and `roleTag` with the same semantics, and both set `PROJECT_BASE_URL` on the Lambda.
122
+
123
+ ### Certificate Reuse (swap without tearing down)
124
+
125
+ No pre-work is required for the common case. `JaypieApiGateway` and `JaypieDistribution` both call `resolveCertificate()` with `certificate: true` by default, which creates the ACM cert at **stack scope** with a deterministic logical ID of `Certificate-{sanitized-domain}` cached by domain. In a single deploy that removes the gateway and adds the distribution for the same `host`, CloudFormation sees the same logical ID and preserves the cert — it simply detaches it from the API Gateway custom domain and attaches it to the new CloudFront distribution.
126
+
127
+ ```typescript
128
+ // Before — first deploy
129
+ new JaypieApiGateway(this, "Api", { handler, host: "api.example.com" });
130
+
131
+ // After — next deploy, same host, cert is preserved
132
+ new JaypieDistribution(this, "Dist", { handler, host: "api.example.com" });
133
+ ```
134
+
135
+ Caveats where the cert *will* be replaced:
136
+
137
+ - **Old Jaypie versions** that created the certificate as a child of `JaypieApiGateway` (pre-`resolveCertificate`). The logical ID lives under the gateway path, so removing the gateway destroys the cert.
138
+ - **Changing `host`** at the same time as the swap — different domain, different logical ID.
139
+
140
+ If you want to be explicit (or share the cert across multiple constructs), create a `JaypieCertificate` — it uses the same `resolveCertificate()` under the hood and resolves to the same stack-level logical ID:
141
+
142
+ ```typescript
143
+ const cert = new JaypieCertificate(this, {
144
+ domainName: "api.example.com",
145
+ zone: "example.com",
146
+ });
147
+
148
+ new JaypieDistribution(this, "Dist", { handler, certificate: cert });
149
+ ```
150
+
151
+ ### DNS Records (the actual blocker)
152
+
153
+ The Route53 alias records are the real obstacle to a clean swap. Both constructs create a `route53.ARecord` (and `JaypieDistribution` adds an `AaaaRecord`) with the same `recordName: host`, but the CDK construct paths differ — `<gateway>/AliasRecord` vs `<distribution>/AliasRecord` — so CloudFormation generates different logical IDs and treats them as independent resources. The default create-before-delete ordering tries to create the new record while the old one still exists, and Route53 rejects it with `Tried to create resource record set [...] but it already exists`.
154
+
155
+ Use `deleteExistingRecord: true` on the new construct to force-delete the old record (via a CDK custom resource) before the alias is created:
156
+
157
+ ```typescript
158
+ // Before
159
+ new JaypieApiGateway(this, "Api", { handler, host: "api.example.com" });
160
+
161
+ // After — single deploy, no DNS collision
162
+ new JaypieDistribution(this, "Dist", {
163
+ handler,
164
+ host: "api.example.com",
165
+ deleteExistingRecord: true,
166
+ });
167
+ ```
168
+
169
+ You only need `deleteExistingRecord` on the deploy that performs the swap. Drop it back to the default (`false`) on the next change.
170
+
171
+ If you need to skip the prop entirely (older Jaypie, or you'd rather not run a custom resource), the alternative is a two-phase deploy:
172
+
173
+ 1. Deploy 1: remove `JaypieApiGateway` (or set `host: undefined` to drop the alias) — old record deleted
174
+ 2. Deploy 2: add `JaypieDistribution` with the target `host` — new record created
175
+
176
+ This costs a brief downtime window between deploys; the cert is preserved across both because it's at stack scope.
177
+
178
+ ### Key Differences to Plan For
179
+
180
+ | Concern | JaypieApiGateway | JaypieDistribution |
181
+ |---------|------------------|-------------------|
182
+ | Origin | API Gateway REST | CloudFront → Function URL |
183
+ | Host env fallback | `CDK_ENV_API_HOST_NAME` → `CDK_ENV_API_SUBDOMAIN`+`CDK_ENV_API_HOSTED_ZONE` | Same, plus falls back to `CDK_ENV_HOSTED_ZONE` |
184
+ | Zone env fallback | `CDK_ENV_API_HOSTED_ZONE` | `CDK_ENV_HOSTED_ZONE` |
185
+ | DNS | A record only | A + AAAA records |
186
+ | WAF | Not built in | Enabled by default (`waf: false` to disable) |
187
+ | Security headers | Not built in | Enabled by default (`securityHeaders: false` to disable) |
188
+ | Streaming | Not supported | `streaming: true` |
189
+ | Request timeout | API Gateway 29s hard cap | CloudFront `originReadTimeout` up to 120s |
190
+ | Request/response size | API Gateway limits (10MB request) | Function URL limits (6MB request, 20MB response) — may require `SizeRestrictions_BODY` WAF override |
191
+ | Access logs | API Gateway stage logs | CloudFront logs → S3 → Datadog |
192
+ | Custom `LambdaRestApiProps` | Passed through | N/A — use `cloudfront.DistributionProps` instead |
193
+
194
+ ### Gotchas
195
+
196
+ - **Lambda permissions** — `LambdaRestApi` auto-grants invoke from API Gateway; `JaypieDistribution` creates a Function URL with `authType: NONE`, so the WAF is your front-line auth/rate-limiter. Keep `waf` enabled unless you have a replacement.
197
+ - **DNS record collision** — see "DNS Records" above. Set `deleteExistingRecord: true` on the new construct (or do a two-phase deploy) or the swap fails on Route53.
198
+ - **Large request bodies** — the default `AWSManagedRulesCommonRuleSet` blocks bodies over 8KB. If your API accepts larger payloads, override `SizeRestrictions_BODY` — see `skill("cdk")` WAF section.
199
+ - **`LambdaRestApiProps`-only features** — usage plans, API keys, request validators, and stage variables have no CloudFront equivalent. Keep `JaypieApiGateway` if you rely on them, or move that logic into the Lambda.
200
+ - **CORS** — `defaultCorsPreflightOptions` on API Gateway is replaced by handling CORS in the Express app (see `skill("cors")`).
201
+
202
+ ## See Also
203
+
204
+ - **`skill("cdk")`** — `JaypieDistribution` WAF, security headers, and other construct patterns
205
+ - **`skill("streaming")`** — response streaming via `JaypieDistribution`
206
+ - **`skill("dns")`** — hosted zones and DNS records
207
+ - **`skill("express")`** — `JaypieExpressLambda` and the Express handler wrapper
208
+ - **`skill("variables")`** — `CDK_ENV_*` environment variables reference
package/skills/skills.md CHANGED
@@ -17,7 +17,7 @@ Look up skills by alias: `mcp__jaypie__skill(alias)`
17
17
  |----------|--------|
18
18
  | contents | index, releasenotes |
19
19
  | development | apikey, documentation, errors, llm, logs, mocks, monorepo, style, subpackages, tests, tools |
20
- | infrastructure | aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, websockets |
20
+ | infrastructure | apigateway, aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, websockets |
21
21
  | patterns | api, fabric, handlers, models, services, vocabulary |
22
22
  | recipes | recipe-api-server |
23
23
  | meta | issues, jaypie, mcp, skills |