alchemy 0.49.1 → 0.51.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/lib/apply.js +10 -9
- package/lib/apply.js.map +1 -1
- package/lib/aws/control/types.d.ts +4 -4
- package/lib/cloudflare/api-gateway-operation.d.ts +141 -0
- package/lib/cloudflare/api-gateway-operation.d.ts.map +1 -0
- package/lib/cloudflare/api-gateway-operation.js +153 -0
- package/lib/cloudflare/api-gateway-operation.js.map +1 -0
- package/lib/cloudflare/api-mitigation.d.ts +19 -0
- package/lib/cloudflare/api-mitigation.d.ts.map +1 -0
- package/lib/cloudflare/api-mitigation.js +1 -0
- package/lib/cloudflare/api-mitigation.js.map +1 -0
- package/lib/cloudflare/api-response.d.ts +2 -2
- package/lib/cloudflare/api-response.d.ts.map +1 -1
- package/lib/cloudflare/api-response.js +2 -1
- package/lib/cloudflare/api-response.js.map +1 -1
- package/lib/cloudflare/api-schema.d.ts +137 -0
- package/lib/cloudflare/api-schema.d.ts.map +1 -0
- package/lib/cloudflare/api-schema.js +197 -0
- package/lib/cloudflare/api-schema.js.map +1 -0
- package/lib/cloudflare/api-shield.d.ts +366 -0
- package/lib/cloudflare/api-shield.d.ts.map +1 -0
- package/lib/cloudflare/api-shield.js +427 -0
- package/lib/cloudflare/api-shield.js.map +1 -0
- package/lib/cloudflare/bucket.d.ts +70 -105
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +127 -244
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/certificate-pack.d.ts +1 -1
- package/lib/cloudflare/certificate-pack.d.ts.map +1 -1
- package/lib/cloudflare/certificate-pack.js +18 -88
- package/lib/cloudflare/certificate-pack.js.map +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/index.d.ts +3 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +3 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/nuxt.js +1 -1
- package/lib/cloudflare/nuxt.js.map +1 -1
- package/lib/cloudflare/orange.d.ts.map +1 -1
- package/lib/cloudflare/orange.js +4 -1
- package/lib/cloudflare/orange.js.map +1 -1
- package/lib/cloudflare/redwood.d.ts.map +1 -1
- package/lib/cloudflare/redwood.js +5 -1
- package/lib/cloudflare/redwood.js.map +1 -1
- package/lib/cloudflare/vite.d.ts.map +1 -1
- package/lib/cloudflare/vite.js +2 -10
- package/lib/cloudflare/vite.js.map +1 -1
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +1 -0
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +1 -0
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/zone.d.ts +12 -0
- package/lib/cloudflare/zone.d.ts.map +1 -1
- package/lib/cloudflare/zone.js +35 -0
- package/lib/cloudflare/zone.js.map +1 -1
- package/lib/destroy.d.ts.map +1 -1
- package/lib/destroy.js +26 -18
- package/lib/destroy.js.map +1 -1
- package/lib/os/exec.d.ts +1 -1
- package/lib/os/exec.d.ts.map +1 -1
- package/lib/os/exec.js +1 -1
- package/lib/os/exec.js.map +1 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +2 -2
- package/lib/scope.js.map +1 -1
- package/package.json +2 -1
- package/src/apply.ts +11 -12
- package/src/aws/control/types.ts +4 -4
- package/src/cloudflare/api-gateway-operation.ts +340 -0
- package/src/cloudflare/api-mitigation.ts +22 -0
- package/src/cloudflare/api-response.ts +7 -3
- package/src/cloudflare/api-schema.ts +364 -0
- package/src/cloudflare/api-shield.ts +676 -0
- package/src/cloudflare/bucket.ts +276 -468
- package/src/cloudflare/certificate-pack.ts +28 -152
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/index.ts +3 -0
- package/src/cloudflare/nuxt.ts +1 -1
- package/src/cloudflare/orange.ts +4 -1
- package/src/cloudflare/redwood.ts +6 -1
- package/src/cloudflare/vite.ts +2 -10
- package/src/cloudflare/website.ts +1 -0
- package/src/cloudflare/worker.ts +2 -1
- package/src/cloudflare/zone.ts +52 -0
- package/src/destroy.ts +26 -20
- package/src/os/exec.ts +2 -2
- package/src/scope.ts +3 -3
- package/templates/tanstack-start/package.json +3 -3
- package/templates/tanstack-start/vite.config.ts +2 -6
package/src/apply.ts
CHANGED
|
@@ -223,6 +223,14 @@ async function _apply<Out extends Resource>(
|
|
|
223
223
|
output: resource,
|
|
224
224
|
},
|
|
225
225
|
});
|
|
226
|
+
} else {
|
|
227
|
+
const pendingDeletions =
|
|
228
|
+
(await scope.get<PendingDeletions>("pendingDeletions")) ?? [];
|
|
229
|
+
pendingDeletions.push({
|
|
230
|
+
resource: oldOutput,
|
|
231
|
+
oldProps: state.oldProps,
|
|
232
|
+
});
|
|
233
|
+
await scope.set("pendingDeletions", pendingDeletions);
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
output = await alchemy.run(
|
|
@@ -237,8 +245,8 @@ async function _apply<Out extends Resource>(
|
|
|
237
245
|
id: resource[ResourceID],
|
|
238
246
|
fqn: resource[ResourceFQN],
|
|
239
247
|
seq: resource[ResourceSeq],
|
|
240
|
-
props: state
|
|
241
|
-
state
|
|
248
|
+
props: state!.props,
|
|
249
|
+
state: state!,
|
|
242
250
|
isReplacement: true,
|
|
243
251
|
replace: () => {
|
|
244
252
|
throw new Error(
|
|
@@ -248,16 +256,6 @@ async function _apply<Out extends Resource>(
|
|
|
248
256
|
}),
|
|
249
257
|
)(resource[ResourceID], props),
|
|
250
258
|
);
|
|
251
|
-
|
|
252
|
-
if (!error.force) {
|
|
253
|
-
const pendingDeletions =
|
|
254
|
-
(await scope.get<PendingDeletions>("pendingDeletions")) ?? [];
|
|
255
|
-
pendingDeletions.push({
|
|
256
|
-
resource: oldOutput,
|
|
257
|
-
oldProps: state.oldProps,
|
|
258
|
-
});
|
|
259
|
-
await scope.set("pendingDeletions", pendingDeletions);
|
|
260
|
-
}
|
|
261
259
|
} else {
|
|
262
260
|
throw error;
|
|
263
261
|
}
|
|
@@ -282,6 +280,7 @@ async function _apply<Out extends Resource>(
|
|
|
282
280
|
replaced: isReplaced,
|
|
283
281
|
});
|
|
284
282
|
|
|
283
|
+
state = (await scope.state.get(resource[ResourceID]))!;
|
|
285
284
|
await scope.state.set(resource[ResourceID], {
|
|
286
285
|
kind: resource[ResourceKind],
|
|
287
286
|
id: resource[ResourceID],
|
package/src/aws/control/types.ts
CHANGED
|
@@ -9717,7 +9717,7 @@ declare namespace AWS {
|
|
|
9717
9717
|
): Promise<SchedulingPolicy>;
|
|
9718
9718
|
}
|
|
9719
9719
|
namespace Bedrock {
|
|
9720
|
-
interface
|
|
9720
|
+
interface ApiSchema {
|
|
9721
9721
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-bedrock-agent-apischema.html#cfn-bedrock-agent-apischema-s3 */
|
|
9722
9722
|
S3?: S3Identifier;
|
|
9723
9723
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-bedrock-agent-apischema.html#cfn-bedrock-agent-apischema-payload */
|
|
@@ -9733,7 +9733,7 @@ declare namespace AWS {
|
|
|
9733
9733
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-bedrock-agent-agentactiongroup.html#cfn-bedrock-agent-agentactiongroup-description */
|
|
9734
9734
|
Description?: string;
|
|
9735
9735
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-bedrock-agent-agentactiongroup.html#cfn-bedrock-agent-agentactiongroup-apischema */
|
|
9736
|
-
ApiSchema?:
|
|
9736
|
+
ApiSchema?: ApiSchema;
|
|
9737
9737
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-bedrock-agent-agentactiongroup.html#cfn-bedrock-agent-agentactiongroup-functionschema */
|
|
9738
9738
|
FunctionSchema?: FunctionSchema;
|
|
9739
9739
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-bedrock-agent-agentactiongroup.html#cfn-bedrock-agent-agentactiongroup-skipresourceinusecheckondelete */
|
|
@@ -61212,7 +61212,7 @@ declare namespace AWS {
|
|
|
61212
61212
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qbusiness-index-textdocumentstatistics.html#cfn-qbusiness-index-textdocumentstatistics-indexedtextdocumentcount */
|
|
61213
61213
|
IndexedTextDocumentCount?: number;
|
|
61214
61214
|
}
|
|
61215
|
-
interface
|
|
61215
|
+
interface ApiSchema {
|
|
61216
61216
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qbusiness-plugin-apischema.html#cfn-qbusiness-plugin-apischema-s3 */
|
|
61217
61217
|
S3?: S3;
|
|
61218
61218
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qbusiness-plugin-apischema.html#cfn-qbusiness-plugin-apischema-payload */
|
|
@@ -61228,7 +61228,7 @@ declare namespace AWS {
|
|
|
61228
61228
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qbusiness-plugin-custompluginconfiguration.html#cfn-qbusiness-plugin-custompluginconfiguration-description */
|
|
61229
61229
|
Description: string;
|
|
61230
61230
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qbusiness-plugin-custompluginconfiguration.html#cfn-qbusiness-plugin-custompluginconfiguration-apischema */
|
|
61231
|
-
ApiSchema:
|
|
61231
|
+
ApiSchema: ApiSchema;
|
|
61232
61232
|
/** http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qbusiness-plugin-custompluginconfiguration.html#cfn-qbusiness-plugin-custompluginconfiguration-apischematype */
|
|
61233
61233
|
ApiSchemaType: string;
|
|
61234
61234
|
}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import type { Context } from "../context.ts";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import { handleApiError } from "./api-error.ts";
|
|
4
|
+
import type { APIMitigation } from "./api-mitigation.ts";
|
|
5
|
+
import {
|
|
6
|
+
createCloudflareApi,
|
|
7
|
+
type CloudflareApi,
|
|
8
|
+
type CloudflareApiOptions,
|
|
9
|
+
} from "./api.ts";
|
|
10
|
+
import type { Zone } from "./zone.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* HTTP methods supported by API Gateway
|
|
14
|
+
*/
|
|
15
|
+
export type HTTPMethod =
|
|
16
|
+
| "get"
|
|
17
|
+
| "post"
|
|
18
|
+
| "put"
|
|
19
|
+
| "patch"
|
|
20
|
+
| "delete"
|
|
21
|
+
| "head"
|
|
22
|
+
| "options"
|
|
23
|
+
| "trace";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Properties for creating or updating an API Operation
|
|
27
|
+
*/
|
|
28
|
+
export interface APIGatewayOperationProps extends CloudflareApiOptions {
|
|
29
|
+
/**
|
|
30
|
+
* The zone this operation belongs to
|
|
31
|
+
*/
|
|
32
|
+
zone: string | Zone;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The API endpoint path (can contain path variables like /users/{id})
|
|
36
|
+
*/
|
|
37
|
+
endpoint: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The host for this operation
|
|
41
|
+
*/
|
|
42
|
+
host: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The HTTP method (GET, POST, PUT, DELETE, etc.)
|
|
46
|
+
*/
|
|
47
|
+
method: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Mitigation action for this operation
|
|
51
|
+
* @default "none"
|
|
52
|
+
*/
|
|
53
|
+
mitigation?: APIMitigation;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* API Operation output
|
|
58
|
+
*/
|
|
59
|
+
export interface APIGatewayOperation
|
|
60
|
+
extends Resource<"cloudflare::APIGatewayOperation"> {
|
|
61
|
+
/**
|
|
62
|
+
* Zone ID
|
|
63
|
+
*/
|
|
64
|
+
zoneId: string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Zone name
|
|
68
|
+
*/
|
|
69
|
+
zoneName: string;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Operation ID assigned by Cloudflare
|
|
73
|
+
*/
|
|
74
|
+
operationId: string;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The API endpoint path
|
|
78
|
+
*/
|
|
79
|
+
endpoint: string;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The host for this operation
|
|
83
|
+
*/
|
|
84
|
+
host: string;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The HTTP method
|
|
88
|
+
*/
|
|
89
|
+
method: string;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The mitigation action for this operation
|
|
93
|
+
*/
|
|
94
|
+
action: APIMitigation;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Cloudflare API Gateway Operation manages individual API endpoints that can be
|
|
99
|
+
* monitored, secured, and configured through Cloudflare's API Shield.
|
|
100
|
+
*
|
|
101
|
+
* Operations are the building blocks for API management, representing specific
|
|
102
|
+
* HTTP method + endpoint + host combinations that your API exposes.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ## Basic API operation
|
|
106
|
+
*
|
|
107
|
+
* Create a simple GET endpoint for user retrieval
|
|
108
|
+
*
|
|
109
|
+
* const getUserOp = await APIGatewayOperation("get-users", {
|
|
110
|
+
* zone: myZone,
|
|
111
|
+
* endpoint: "/users",
|
|
112
|
+
* host: "api.example.com",
|
|
113
|
+
* method: "GET"
|
|
114
|
+
* });
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ## API operation with path parameters
|
|
118
|
+
*
|
|
119
|
+
* Create an operation that includes path variables
|
|
120
|
+
*
|
|
121
|
+
* const getUserByIdOp = await APIGatewayOperation("get-user-by-id", {
|
|
122
|
+
* zone: "api.example.com",
|
|
123
|
+
* endpoint: "/users/{id}",
|
|
124
|
+
* host: "api.example.com",
|
|
125
|
+
* method: "GET"
|
|
126
|
+
* });
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ## RESTful CRUD operations
|
|
130
|
+
*
|
|
131
|
+
* Create a complete set of CRUD operations for a resource
|
|
132
|
+
*
|
|
133
|
+
* const createUserOp = await APIGatewayOperation("create-user", {
|
|
134
|
+
* zone: myZone,
|
|
135
|
+
* endpoint: "/users",
|
|
136
|
+
* host: "api.example.com",
|
|
137
|
+
* method: "POST"
|
|
138
|
+
* });
|
|
139
|
+
*
|
|
140
|
+
* const updateUserOp = await APIGatewayOperation("update-user", {
|
|
141
|
+
* zone: myZone,
|
|
142
|
+
* endpoint: "/users/{id}",
|
|
143
|
+
* host: "api.example.com",
|
|
144
|
+
* method: "PUT"
|
|
145
|
+
* });
|
|
146
|
+
*
|
|
147
|
+
* const deleteUserOp = await APIGatewayOperation("delete-user", {
|
|
148
|
+
* zone: myZone,
|
|
149
|
+
* endpoint: "/users/{id}",
|
|
150
|
+
* host: "api.example.com",
|
|
151
|
+
* method: "DELETE"
|
|
152
|
+
* });
|
|
153
|
+
*
|
|
154
|
+
* @see https://developers.cloudflare.com/api/resources/api_gateway/subresources/operations/
|
|
155
|
+
* @see https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/
|
|
156
|
+
*/
|
|
157
|
+
export const APIGatewayOperation = Resource(
|
|
158
|
+
"cloudflare::APIGatewayOperation",
|
|
159
|
+
async function (
|
|
160
|
+
this: Context<APIGatewayOperation>,
|
|
161
|
+
_id: string,
|
|
162
|
+
props: APIGatewayOperationProps,
|
|
163
|
+
): Promise<APIGatewayOperation> {
|
|
164
|
+
const api = await createCloudflareApi(props);
|
|
165
|
+
|
|
166
|
+
// Resolve zone ID and name
|
|
167
|
+
const zoneId = typeof props.zone === "string" ? props.zone : props.zone.id;
|
|
168
|
+
const zoneName =
|
|
169
|
+
typeof props.zone === "string" ? props.zone : props.zone.name;
|
|
170
|
+
|
|
171
|
+
if (this.phase === "delete") {
|
|
172
|
+
if (this.output?.operationId) {
|
|
173
|
+
await deleteOperation(api, zoneId, this.output.operationId);
|
|
174
|
+
}
|
|
175
|
+
return this.destroy();
|
|
176
|
+
}
|
|
177
|
+
let operationId: string;
|
|
178
|
+
if (this.phase === "update") {
|
|
179
|
+
if (
|
|
180
|
+
props.endpoint !== this.output?.endpoint ||
|
|
181
|
+
props.host !== this.output?.host ||
|
|
182
|
+
props.method !== this.output?.method
|
|
183
|
+
) {
|
|
184
|
+
// delete and then re-create (cloudflare doesn't allow updating these properties)
|
|
185
|
+
this.replace(true);
|
|
186
|
+
}
|
|
187
|
+
if (props.mitigation !== this.output?.action) {
|
|
188
|
+
// we can update the mitigation action
|
|
189
|
+
await updateOperationSettings(api, zoneId, this.output.operationId, {
|
|
190
|
+
mitigation_action: props.mitigation ?? null,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
operationId = this.output.operationId;
|
|
194
|
+
} else {
|
|
195
|
+
const operation = await createOperation(api, zoneId, props);
|
|
196
|
+
operationId = operation.operation_id;
|
|
197
|
+
|
|
198
|
+
if (props.mitigation) {
|
|
199
|
+
await updateOperationSettings(api, zoneId, operationId, {
|
|
200
|
+
mitigation_action: props.mitigation ?? "none",
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return this({
|
|
206
|
+
zoneId,
|
|
207
|
+
zoneName,
|
|
208
|
+
operationId,
|
|
209
|
+
endpoint: props.endpoint,
|
|
210
|
+
host: props.host,
|
|
211
|
+
method: props.method.toUpperCase(),
|
|
212
|
+
action: props.mitigation ?? null,
|
|
213
|
+
});
|
|
214
|
+
},
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
async function createOperation(
|
|
218
|
+
api: CloudflareApi,
|
|
219
|
+
zoneId: string,
|
|
220
|
+
props: APIGatewayOperationProps,
|
|
221
|
+
) {
|
|
222
|
+
// Create the operation
|
|
223
|
+
const response = await api.post(
|
|
224
|
+
`/zones/${zoneId}/api_gateway/operations/item`,
|
|
225
|
+
{
|
|
226
|
+
endpoint: props.endpoint,
|
|
227
|
+
host: props.host,
|
|
228
|
+
method: props.method.toUpperCase(),
|
|
229
|
+
},
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
if (!response.ok) {
|
|
233
|
+
await handleApiError(
|
|
234
|
+
response,
|
|
235
|
+
"creating",
|
|
236
|
+
"operation",
|
|
237
|
+
`${props.method} ${props.endpoint}`,
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const data = (await response.json()) as {
|
|
242
|
+
result: {
|
|
243
|
+
operation_id: string;
|
|
244
|
+
endpoint: string;
|
|
245
|
+
host: string;
|
|
246
|
+
method: string;
|
|
247
|
+
last_updated: string;
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
return data.result;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function deleteOperation(
|
|
255
|
+
api: CloudflareApi,
|
|
256
|
+
zoneId: string,
|
|
257
|
+
operationId: string,
|
|
258
|
+
) {
|
|
259
|
+
const deleteResponse = await api.delete(
|
|
260
|
+
`/zones/${zoneId}/api_gateway/operations/${operationId}`,
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
if (!deleteResponse.ok && deleteResponse.status !== 404) {
|
|
264
|
+
await handleApiError(deleteResponse, "deleting", "operation", operationId);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Update validation settings for a specific operation
|
|
270
|
+
*/
|
|
271
|
+
async function updateOperationSettings(
|
|
272
|
+
api: CloudflareApi,
|
|
273
|
+
zoneId: string,
|
|
274
|
+
operationId: string,
|
|
275
|
+
params: {
|
|
276
|
+
mitigation_action: APIMitigation;
|
|
277
|
+
},
|
|
278
|
+
): Promise<void> {
|
|
279
|
+
const response = await api.put(
|
|
280
|
+
`/zones/${zoneId}/schema_validation/settings/operations/${operationId}`,
|
|
281
|
+
params,
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
if (!response.ok) {
|
|
285
|
+
await handleApiError(
|
|
286
|
+
response,
|
|
287
|
+
"updating",
|
|
288
|
+
"operation settings",
|
|
289
|
+
operationId,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface CloudflareOperation {
|
|
295
|
+
operation_id: string;
|
|
296
|
+
method: string;
|
|
297
|
+
host: string;
|
|
298
|
+
endpoint: string;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export async function getOperations(
|
|
302
|
+
api: CloudflareApi,
|
|
303
|
+
zoneId: string,
|
|
304
|
+
): Promise<CloudflareOperation[]> {
|
|
305
|
+
const response = await api.get(`/zones/${zoneId}/api_gateway/operations`);
|
|
306
|
+
|
|
307
|
+
if (!response.ok) {
|
|
308
|
+
await handleApiError(response, "getting", "operations");
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return ((await response.json()) as { result: CloudflareOperation[] }).result;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export async function getOperationSchemaValidationSetting(
|
|
315
|
+
api: CloudflareApi,
|
|
316
|
+
zoneId: string,
|
|
317
|
+
operationId: string,
|
|
318
|
+
) {
|
|
319
|
+
const response = await api.get(
|
|
320
|
+
`/zones/${zoneId}/schema_validation/settings/operations/${operationId}`,
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
if (!response.ok) {
|
|
324
|
+
await handleApiError(
|
|
325
|
+
response,
|
|
326
|
+
"getting",
|
|
327
|
+
"operation mitigation status",
|
|
328
|
+
operationId,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const data = (await response.json()) as {
|
|
333
|
+
result: {
|
|
334
|
+
mitigation_action: APIMitigation;
|
|
335
|
+
operation_id: string;
|
|
336
|
+
};
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
return data.result;
|
|
340
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OpenAPIV3 } from "openapi-types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Specifies the mitigation action to apply when a request does not conform to
|
|
5
|
+
* the schema for this operation:
|
|
6
|
+
* - `"log"`: Log the request.
|
|
7
|
+
* - `"block"`: Deny access to the site.
|
|
8
|
+
* - `"none"`: Skip mitigation for this operation.
|
|
9
|
+
* - `null`: Clear any mitigation action.
|
|
10
|
+
*/
|
|
11
|
+
export type APIMitigation = "none" | "log" | "block" | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Mitigation actions for a given API schema.
|
|
15
|
+
*/
|
|
16
|
+
export type APIMitigations<S extends OpenAPIV3.Document> = {
|
|
17
|
+
[path in keyof S["paths"]]?:
|
|
18
|
+
| APIMitigation
|
|
19
|
+
| {
|
|
20
|
+
[method in keyof S["paths"][path]]?: APIMitigation;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { CloudflareApiError } from "./api-error.ts";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Cloudflare API response format
|
|
3
5
|
*/
|
|
@@ -15,7 +17,7 @@ export interface CloudflareApiResponse<T> {
|
|
|
15
17
|
/**
|
|
16
18
|
* Error details if success is false
|
|
17
19
|
*/
|
|
18
|
-
errors:
|
|
20
|
+
errors: CloudflareApiErrorPayload[];
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Response messages
|
|
@@ -37,7 +39,7 @@ export interface CloudflareApiResponse<T> {
|
|
|
37
39
|
/**
|
|
38
40
|
* Cloudflare API error format
|
|
39
41
|
*/
|
|
40
|
-
export interface
|
|
42
|
+
export interface CloudflareApiErrorPayload {
|
|
41
43
|
/**
|
|
42
44
|
* Error code
|
|
43
45
|
*/
|
|
@@ -89,8 +91,10 @@ export async function extractCloudflareResult<T>(
|
|
|
89
91
|
if (json.success) {
|
|
90
92
|
return json.result;
|
|
91
93
|
} else {
|
|
92
|
-
const error = new
|
|
94
|
+
const error = new CloudflareApiError(
|
|
93
95
|
`Failed to ${label} (${response.status} ${response.statusText}):\n${json.errors.map((e) => `- [${e.code}] ${e.message}${e.documentation_url ? ` (${e.documentation_url})` : ""}`).join("\n")}`,
|
|
96
|
+
response,
|
|
97
|
+
json.errors,
|
|
94
98
|
);
|
|
95
99
|
Error.captureStackTrace(error, extractCloudflareResult);
|
|
96
100
|
Object.assign(error, {
|