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
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import type { OpenAPIV3 } from "openapi-types";
|
|
2
|
+
import * as yaml from "yaml";
|
|
3
|
+
import type { Context } from "../context.ts";
|
|
4
|
+
import { Resource } from "../resource.ts";
|
|
5
|
+
import { CloudflareApiError, handleApiError } from "./api-error.ts";
|
|
6
|
+
import {
|
|
7
|
+
createCloudflareApi,
|
|
8
|
+
type CloudflareApi,
|
|
9
|
+
type CloudflareApiOptions,
|
|
10
|
+
} from "./api.ts";
|
|
11
|
+
import type { Zone } from "./zone.ts";
|
|
12
|
+
import { findZoneForHostname } from "./zone.ts";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Properties for creating or updating a Schema
|
|
16
|
+
*/
|
|
17
|
+
export interface APISchemaProps<S extends OpenAPIV3.Document>
|
|
18
|
+
extends CloudflareApiOptions {
|
|
19
|
+
/**
|
|
20
|
+
* The zone to upload the schema to
|
|
21
|
+
*/
|
|
22
|
+
zone: string | Zone;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* OpenAPI v3.0.x schema content (YAML string, JSON string, or OpenAPI object)
|
|
26
|
+
* Provide either this or schemaFile
|
|
27
|
+
*
|
|
28
|
+
* Note: Cloudflare only supports OpenAPI v3.0.x, not v3.1
|
|
29
|
+
*/
|
|
30
|
+
schema: S;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Name for the schema
|
|
34
|
+
* @default resource id
|
|
35
|
+
*/
|
|
36
|
+
name?: string;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Enable validation immediately after upload
|
|
40
|
+
*
|
|
41
|
+
* Warning: will trigger a replace when disabling validation.
|
|
42
|
+
*
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
enabled?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* APISchema resource attributes.
|
|
50
|
+
*/
|
|
51
|
+
export interface APISchema<S extends OpenAPIV3.Document = OpenAPIV3.Document>
|
|
52
|
+
extends Resource<"cloudflare::APISchema"> {
|
|
53
|
+
/**
|
|
54
|
+
* Schema ID
|
|
55
|
+
*/
|
|
56
|
+
id: string;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Name for the schema
|
|
60
|
+
*/
|
|
61
|
+
name: string;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The API Schema
|
|
65
|
+
*/
|
|
66
|
+
schema: S;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Source of the schema
|
|
70
|
+
*/
|
|
71
|
+
source: string;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Whether validation is enabled
|
|
75
|
+
*/
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Cloudflare API Gateway Schema manages OpenAPI v3 schemas for API validation.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ## Basic schema upload with inline YAML
|
|
84
|
+
*
|
|
85
|
+
* const apiSchema = await APISchema("my-api-schema", {
|
|
86
|
+
* zone: myZone,
|
|
87
|
+
* name: "my-api-v1"
|
|
88
|
+
* schema: `
|
|
89
|
+
* openapi: 3.0.0
|
|
90
|
+
* info:
|
|
91
|
+
* title: My API
|
|
92
|
+
* version: 1.0.0
|
|
93
|
+
* servers:
|
|
94
|
+
* - url: https://api.example.com
|
|
95
|
+
* paths:
|
|
96
|
+
* /users:
|
|
97
|
+
* get:
|
|
98
|
+
* operationId: getUsers
|
|
99
|
+
* responses:
|
|
100
|
+
* '200':
|
|
101
|
+
* description: Success
|
|
102
|
+
* `,
|
|
103
|
+
* });
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ## Schema upload from file
|
|
107
|
+
*
|
|
108
|
+
* const fileSchema = await APISchema("api-schema-from-file", {
|
|
109
|
+
* zone: "example.com",
|
|
110
|
+
* schemaFile: "./openapi.yaml",
|
|
111
|
+
* name: "production-api-v2",
|
|
112
|
+
* enabled: false // Upload but don't enable validation yet
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ## Schema with typed OpenAPI object
|
|
117
|
+
*
|
|
118
|
+
* import type { OpenAPIV3 } from "openapi-types";
|
|
119
|
+
*
|
|
120
|
+
* const typedSchema: OpenAPIV3.Document = {
|
|
121
|
+
* openapi: "3.0.0",
|
|
122
|
+
* info: { title: "Typed API", version: "1.0.0" },
|
|
123
|
+
* paths: {
|
|
124
|
+
* "/health": {
|
|
125
|
+
* get: {
|
|
126
|
+
* operationId: "healthCheck",
|
|
127
|
+
* responses: { "200": { description: "OK" } }
|
|
128
|
+
* }
|
|
129
|
+
* }
|
|
130
|
+
* }
|
|
131
|
+
* };
|
|
132
|
+
*
|
|
133
|
+
* const schema = await APISchema("typed-schema", {
|
|
134
|
+
* zone: myZone,
|
|
135
|
+
* schema: typedSchema
|
|
136
|
+
* });
|
|
137
|
+
*/
|
|
138
|
+
export const APISchema = Resource("cloudflare::APISchema", async function <
|
|
139
|
+
S extends OpenAPIV3.Document,
|
|
140
|
+
>(this: Context<APISchema<S>>, id: string, props: APISchemaProps<S>): Promise<
|
|
141
|
+
APISchema<S>
|
|
142
|
+
> {
|
|
143
|
+
const api = await createCloudflareApi(props);
|
|
144
|
+
|
|
145
|
+
// Resolve zone ID and name
|
|
146
|
+
const zoneId =
|
|
147
|
+
typeof props.zone === "string"
|
|
148
|
+
? (await findZoneForHostname(api, props.zone)).zoneId
|
|
149
|
+
: props.zone.id;
|
|
150
|
+
|
|
151
|
+
if (this.phase === "delete") {
|
|
152
|
+
if (this.output?.id) {
|
|
153
|
+
await deleteSchema(api, zoneId, this.output.id);
|
|
154
|
+
}
|
|
155
|
+
return this.destroy();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Load schema content
|
|
159
|
+
const parsedSchema = props.schema;
|
|
160
|
+
|
|
161
|
+
let schemaDetails: CloudflareSchemaDetails;
|
|
162
|
+
|
|
163
|
+
if (this.phase === "update" && this.output?.id) {
|
|
164
|
+
// Check if we need to replace due to name, schema content change, or disabling validation
|
|
165
|
+
if (
|
|
166
|
+
props.name !== this.output.name ||
|
|
167
|
+
JSON.stringify(parsedSchema) !== JSON.stringify(this.output.schema) ||
|
|
168
|
+
(this.output.enabled === true && props.enabled === false)
|
|
169
|
+
) {
|
|
170
|
+
// Name, schema content changed, or trying to disable validation - need to replace
|
|
171
|
+
this.replace();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Update existing schema (can only update validation_enabled)
|
|
175
|
+
schemaDetails = await updateSchema(api, zoneId, this.output.id, {
|
|
176
|
+
validation_enabled: props.enabled !== false,
|
|
177
|
+
});
|
|
178
|
+
} else {
|
|
179
|
+
// Create new schema
|
|
180
|
+
schemaDetails = await uploadSchema(api, zoneId, {
|
|
181
|
+
file: yaml.stringify(parsedSchema),
|
|
182
|
+
name: props.name || id,
|
|
183
|
+
validation_enabled: props.enabled !== false,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return this({
|
|
188
|
+
id: schemaDetails.id,
|
|
189
|
+
name: schemaDetails.name,
|
|
190
|
+
schema: parsedSchema as any,
|
|
191
|
+
source: schemaDetails.source,
|
|
192
|
+
enabled: schemaDetails.validationEnabled,
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// API helper functions
|
|
197
|
+
|
|
198
|
+
interface CloudflareSchemaDetails {
|
|
199
|
+
id: string;
|
|
200
|
+
name: string;
|
|
201
|
+
source: string;
|
|
202
|
+
validationEnabled: boolean;
|
|
203
|
+
createdAt: string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
interface CloudflareSchema {
|
|
207
|
+
schema_id: string;
|
|
208
|
+
name: string;
|
|
209
|
+
kind: string;
|
|
210
|
+
source: string;
|
|
211
|
+
validation_enabled: boolean;
|
|
212
|
+
created_at: string;
|
|
213
|
+
size?: number;
|
|
214
|
+
is_learned?: boolean;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function uploadSchema(
|
|
218
|
+
api: CloudflareApi,
|
|
219
|
+
zoneId: string,
|
|
220
|
+
params: {
|
|
221
|
+
file: string;
|
|
222
|
+
name: string;
|
|
223
|
+
validation_enabled?: boolean;
|
|
224
|
+
},
|
|
225
|
+
): Promise<CloudflareSchemaDetails> {
|
|
226
|
+
const body = {
|
|
227
|
+
source: params.file,
|
|
228
|
+
name: params.name,
|
|
229
|
+
kind: "openapi_v3",
|
|
230
|
+
validation_enabled: params.validation_enabled ?? true,
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const response = await api.post(
|
|
234
|
+
`/zones/${zoneId}/schema_validation/schemas`,
|
|
235
|
+
body,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (!response.ok) {
|
|
239
|
+
await handleApiError(response, "uploading", "schema", params.name);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const data = (await response.json()) as {
|
|
243
|
+
result: CloudflareSchema;
|
|
244
|
+
};
|
|
245
|
+
return {
|
|
246
|
+
id: data.result.schema_id,
|
|
247
|
+
name: data.result.name,
|
|
248
|
+
source: data.result.source,
|
|
249
|
+
validationEnabled: data.result.validation_enabled,
|
|
250
|
+
createdAt: data.result.created_at,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function updateSchema(
|
|
255
|
+
api: CloudflareApi,
|
|
256
|
+
zoneId: string,
|
|
257
|
+
schemaId: string,
|
|
258
|
+
params: {
|
|
259
|
+
validation_enabled: boolean;
|
|
260
|
+
},
|
|
261
|
+
): Promise<CloudflareSchemaDetails> {
|
|
262
|
+
const response = await api.patch(
|
|
263
|
+
`/zones/${zoneId}/schema_validation/schemas/${schemaId}`,
|
|
264
|
+
params,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
if (!response.ok) {
|
|
268
|
+
await handleApiError(response, "updating", "schema", schemaId);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const data = (await response.json()) as { result: CloudflareSchema };
|
|
272
|
+
return {
|
|
273
|
+
id: data.result.schema_id,
|
|
274
|
+
name: data.result.name,
|
|
275
|
+
source: data.result.source,
|
|
276
|
+
validationEnabled: data.result.validation_enabled,
|
|
277
|
+
createdAt: data.result.created_at,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export async function deleteSchema(
|
|
282
|
+
api: CloudflareApi,
|
|
283
|
+
zoneId: string,
|
|
284
|
+
schemaId: string,
|
|
285
|
+
): Promise<void> {
|
|
286
|
+
const response = await api.delete(
|
|
287
|
+
`/zones/${zoneId}/schema_validation/schemas/${schemaId}`,
|
|
288
|
+
);
|
|
289
|
+
const data = (await response.json()) as {
|
|
290
|
+
success: boolean;
|
|
291
|
+
errors: {
|
|
292
|
+
code: number;
|
|
293
|
+
message: string;
|
|
294
|
+
}[];
|
|
295
|
+
};
|
|
296
|
+
if (response.status === 404) {
|
|
297
|
+
return;
|
|
298
|
+
} else if (response.status === 400 && data.errors[0].code === 19400) {
|
|
299
|
+
// Bad request: schema with this ID does not exist
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
await handleApiError(response, "deleting", "schema", schemaId);
|
|
305
|
+
} else if (!data.success) {
|
|
306
|
+
throw new CloudflareApiError(data.errors[0].message, response);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get schema details
|
|
312
|
+
*/
|
|
313
|
+
export async function getSchema(
|
|
314
|
+
api: CloudflareApi,
|
|
315
|
+
zoneId: string,
|
|
316
|
+
schemaId: string,
|
|
317
|
+
): Promise<CloudflareSchemaDetails | null> {
|
|
318
|
+
const response = await api.get(
|
|
319
|
+
`/zones/${zoneId}/schema_validation/schemas/${schemaId}`,
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
if (response.status === 404) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (!response.ok) {
|
|
327
|
+
await handleApiError(response, "getting", "schema", schemaId);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const data = (await response.json()) as { result: CloudflareSchema };
|
|
331
|
+
return {
|
|
332
|
+
id: data.result.schema_id,
|
|
333
|
+
name: data.result.name,
|
|
334
|
+
source: data.result.source,
|
|
335
|
+
validationEnabled: data.result.validation_enabled,
|
|
336
|
+
createdAt: data.result.created_at,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* List all schemas in a zone
|
|
342
|
+
*/
|
|
343
|
+
export async function listSchemas(
|
|
344
|
+
api: CloudflareApi,
|
|
345
|
+
zoneId: string,
|
|
346
|
+
): Promise<CloudflareSchemaDetails[]> {
|
|
347
|
+
const response = await api.get(`/zones/${zoneId}/schema_validation/schemas`);
|
|
348
|
+
|
|
349
|
+
if (!response.ok) {
|
|
350
|
+
await handleApiError(response, "listing", "schemas", zoneId);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const data = (await response.json()) as {
|
|
354
|
+
result: CloudflareSchema[];
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
return data.result.map((schema) => ({
|
|
358
|
+
id: schema.schema_id,
|
|
359
|
+
name: schema.name,
|
|
360
|
+
source: schema.source,
|
|
361
|
+
validationEnabled: schema.validation_enabled,
|
|
362
|
+
createdAt: schema.created_at,
|
|
363
|
+
}));
|
|
364
|
+
}
|