alchemy 0.84.0 → 0.85.1
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/bin/alchemy.js +32 -23
- package/lib/cloudflare/account-api-token.d.ts +5 -0
- package/lib/cloudflare/account-api-token.d.ts.map +1 -1
- package/lib/cloudflare/account-api-token.js +13 -2
- package/lib/cloudflare/account-api-token.js.map +1 -1
- package/lib/cloudflare/ai-crawler.d.ts +27 -0
- package/lib/cloudflare/ai-crawler.d.ts.map +1 -0
- package/lib/cloudflare/ai-crawler.js +75 -0
- package/lib/cloudflare/ai-crawler.js.map +1 -0
- package/lib/cloudflare/ai-search-token.d.ts +150 -0
- package/lib/cloudflare/ai-search-token.d.ts.map +1 -0
- package/lib/cloudflare/ai-search-token.js +171 -0
- package/lib/cloudflare/ai-search-token.js.map +1 -0
- package/lib/cloudflare/ai-search.d.ts +397 -0
- package/lib/cloudflare/ai-search.d.ts.map +1 -0
- package/lib/cloudflare/ai-search.js +307 -0
- package/lib/cloudflare/ai-search.js.map +1 -0
- package/lib/cloudflare/api-error.d.ts +11 -0
- package/lib/cloudflare/api-error.d.ts.map +1 -1
- package/lib/cloudflare/api-error.js +11 -0
- package/lib/cloudflare/api-error.js.map +1 -1
- package/lib/cloudflare/api.js +1 -1
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/auth.d.ts +3 -2
- package/lib/cloudflare/auth.d.ts.map +1 -1
- package/lib/cloudflare/auth.js +17 -14
- package/lib/cloudflare/auth.js.map +1 -1
- package/lib/cloudflare/bindings.d.ts +12 -2
- package/lib/cloudflare/bindings.d.ts.map +1 -1
- package/lib/cloudflare/bindings.js.map +1 -1
- package/lib/cloudflare/bound.d.ts +2 -1
- package/lib/cloudflare/bound.d.ts.map +1 -1
- package/lib/cloudflare/bucket-custom-domain.d.ts.map +1 -1
- package/lib/cloudflare/bucket-custom-domain.js +4 -2
- package/lib/cloudflare/bucket-custom-domain.js.map +1 -1
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +8 -2
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/d1-database.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.js +9 -1
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/cloudflare/index.d.ts +4 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +4 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.js +15 -0
- package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.d.ts +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +41 -3
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
- package/lib/cloudflare/permission-groups.d.ts +5 -0
- package/lib/cloudflare/permission-groups.d.ts.map +1 -1
- package/lib/cloudflare/permission-groups.js +6 -0
- package/lib/cloudflare/permission-groups.js.map +1 -1
- package/lib/cloudflare/vpc-service.d.ts +288 -0
- package/lib/cloudflare/vpc-service.d.ts.map +1 -0
- package/lib/cloudflare/vpc-service.js +238 -0
- package/lib/cloudflare/vpc-service.js.map +1 -0
- package/lib/cloudflare/worker-metadata.d.ts +1 -0
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +8 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +9 -0
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +9 -0
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/planetscale/api/sdk.gen.d.ts +874 -190
- package/lib/planetscale/api/sdk.gen.d.ts.map +1 -1
- package/lib/planetscale/api/sdk.gen.js +1250 -306
- package/lib/planetscale/api/sdk.gen.js.map +1 -1
- package/lib/planetscale/api/types.gen.d.ts +8241 -4128
- package/lib/planetscale/api/types.gen.d.ts.map +1 -1
- package/lib/planetscale/branch.js +4 -4
- package/lib/planetscale/branch.js.map +1 -1
- package/lib/planetscale/database.d.ts +43 -24
- package/lib/planetscale/database.d.ts.map +1 -1
- package/lib/planetscale/database.js +39 -18
- package/lib/planetscale/database.js.map +1 -1
- package/lib/planetscale/default-role.d.ts +51 -0
- package/lib/planetscale/default-role.d.ts.map +1 -0
- package/lib/planetscale/default-role.js +100 -0
- package/lib/planetscale/default-role.js.map +1 -0
- package/lib/planetscale/index.d.ts +1 -0
- package/lib/planetscale/index.d.ts.map +1 -1
- package/lib/planetscale/index.js +1 -0
- package/lib/planetscale/index.js.map +1 -1
- package/lib/planetscale/organization.js +1 -1
- package/lib/planetscale/organization.js.map +1 -1
- package/lib/planetscale/role.d.ts +1 -1
- package/lib/planetscale/role.d.ts.map +1 -1
- package/lib/planetscale/role.js +1 -1
- package/lib/planetscale/role.js.map +1 -1
- package/lib/planetscale/utils.d.ts +1 -1
- package/lib/planetscale/utils.d.ts.map +1 -1
- package/lib/planetscale/utils.js +9 -10
- package/lib/planetscale/utils.js.map +1 -1
- package/lib/scope.d.ts +1 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +10 -5
- package/lib/scope.js.map +1 -1
- package/lib/state/sqlite-state-store.js +2 -0
- package/lib/state/sqlite-state-store.js.map +1 -1
- package/lib/test/bun.d.ts +17 -0
- package/lib/test/bun.d.ts.map +1 -1
- package/lib/test/bun.js +1 -0
- package/lib/test/bun.js.map +1 -1
- package/lib/test/vitest.d.ts +17 -0
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +3 -0
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/snake-to-camel.d.ts +21 -0
- package/lib/util/snake-to-camel.d.ts.map +1 -0
- package/lib/util/snake-to-camel.js +34 -0
- package/lib/util/snake-to-camel.js.map +1 -0
- package/package.json +2 -2
- package/src/cloudflare/account-api-token.ts +23 -6
- package/src/cloudflare/ai-crawler.ts +89 -0
- package/src/cloudflare/ai-search-token.ts +324 -0
- package/src/cloudflare/ai-search.ts +952 -0
- package/src/cloudflare/api-error.ts +19 -0
- package/src/cloudflare/api.ts +1 -1
- package/src/cloudflare/auth.ts +17 -14
- package/src/cloudflare/bindings.ts +15 -2
- package/src/cloudflare/bound.ts +6 -3
- package/src/cloudflare/bucket-custom-domain.ts +4 -1
- package/src/cloudflare/bucket.ts +9 -2
- package/src/cloudflare/d1-database.ts +11 -4
- package/src/cloudflare/index.ts +4 -0
- package/src/cloudflare/miniflare/build-worker-options.ts +30 -18
- package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +47 -2
- package/src/cloudflare/permission-groups.ts +6 -0
- package/src/cloudflare/vpc-service.ts +466 -0
- package/src/cloudflare/worker-metadata.ts +8 -0
- package/src/cloudflare/worker.ts +9 -0
- package/src/cloudflare/wrangler.json.ts +8 -0
- package/src/planetscale/api/sdk.gen.ts +2331 -987
- package/src/planetscale/api/types.gen.ts +8980 -4574
- package/src/planetscale/branch.ts +4 -4
- package/src/planetscale/database.ts +87 -46
- package/src/planetscale/default-role.ts +162 -0
- package/src/planetscale/index.ts +1 -0
- package/src/planetscale/organization.ts +1 -1
- package/src/planetscale/role.ts +3 -2
- package/src/planetscale/utils.ts +10 -10
- package/src/scope.ts +14 -5
- package/src/state/sqlite-state-store.ts +2 -0
- package/src/test/bun.ts +25 -0
- package/src/test/vitest.ts +33 -0
- package/src/util/snake-to-camel.ts +59 -0
- package/workers/tunnel-proxy.js +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { CloudflareApiErrorPayload } from "./api-response";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Custom error class for Cloudflare API errors
|
|
3
5
|
* Includes HTTP status information from the Response
|
|
@@ -66,3 +68,20 @@ export async function handleApiError(
|
|
|
66
68
|
}: ${errors.map((error) => `${error.code}: ${error.message}`).join(", ")}`;
|
|
67
69
|
throw new CloudflareApiError(errorMessage, response, errors);
|
|
68
70
|
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Helper function to check if an error is a Cloudflare API error.
|
|
74
|
+
* Optional match criteria can be provided to check for a specific HTTP status code or error code.
|
|
75
|
+
*/
|
|
76
|
+
export function isCloudflareApiError(
|
|
77
|
+
error: unknown,
|
|
78
|
+
match: { status?: number; code?: number } = {},
|
|
79
|
+
): error is CloudflareApiError & { errorData: CloudflareApiErrorPayload[] } {
|
|
80
|
+
return (
|
|
81
|
+
error instanceof CloudflareApiError &&
|
|
82
|
+
(match.status === undefined || error.status === match.status) &&
|
|
83
|
+
(match.code === undefined ||
|
|
84
|
+
(Array.isArray(error.errorData) &&
|
|
85
|
+
error.errorData.some((e) => "code" in e && e.code === match.code)))
|
|
86
|
+
);
|
|
87
|
+
}
|
package/src/cloudflare/api.ts
CHANGED
package/src/cloudflare/auth.ts
CHANGED
|
@@ -75,8 +75,9 @@ export namespace CloudflareAuth {
|
|
|
75
75
|
"queues:write": "See and change Cloudflare Queues settings and data",
|
|
76
76
|
"r2_catalog:write": "Grants write level access to R2 Data Catalog",
|
|
77
77
|
"radar:read": "Grants access to read Cloudflare Radar data",
|
|
78
|
-
"
|
|
79
|
-
"
|
|
78
|
+
"ai-search:read": "Grants read level access to AI Search",
|
|
79
|
+
"ai-search:write": "Grants write level access to AI Search",
|
|
80
|
+
"ai-search:run": "Grants run level access to AI Search",
|
|
80
81
|
"secrets_store:read": "Grants read level access to Secrets Store",
|
|
81
82
|
"secrets_store:write": "Grants write level access to Secrets Store",
|
|
82
83
|
"ssl_certs:write":
|
|
@@ -120,24 +121,26 @@ export namespace CloudflareAuth {
|
|
|
120
121
|
export type Scope = keyof typeof ALL_SCOPES;
|
|
121
122
|
export const DEFAULT_SCOPES = [
|
|
122
123
|
"account:read",
|
|
124
|
+
"ai-search:write",
|
|
125
|
+
"ai-search:run",
|
|
126
|
+
"ai:write",
|
|
127
|
+
"cloudchamber:write",
|
|
128
|
+
"connectivity:admin",
|
|
129
|
+
"containers:write",
|
|
130
|
+
"d1:write",
|
|
131
|
+
"pages:write",
|
|
132
|
+
"pipelines:write",
|
|
133
|
+
"queues:write",
|
|
134
|
+
"secrets_store:write",
|
|
135
|
+
"ssl_certs:write",
|
|
123
136
|
"user:read",
|
|
124
|
-
"
|
|
137
|
+
"vectorize:write",
|
|
125
138
|
"workers_kv:write",
|
|
126
139
|
"workers_routes:write",
|
|
127
140
|
"workers_scripts:write",
|
|
128
141
|
"workers_tail:read",
|
|
129
|
-
"
|
|
130
|
-
"pages:write",
|
|
142
|
+
"workers:write",
|
|
131
143
|
"zone:read",
|
|
132
|
-
"ssl_certs:write",
|
|
133
|
-
"ai:write",
|
|
134
|
-
"queues:write",
|
|
135
|
-
"pipelines:write",
|
|
136
|
-
"secrets_store:write",
|
|
137
|
-
"containers:write",
|
|
138
|
-
"cloudchamber:write",
|
|
139
|
-
"vectorize:write",
|
|
140
|
-
"connectivity:admin",
|
|
141
144
|
];
|
|
142
145
|
|
|
143
146
|
/**
|
|
@@ -26,6 +26,7 @@ import type { SecretRef as CloudflareSecretRef } from "./secret-ref.ts";
|
|
|
26
26
|
import type { Secret as CloudflareSecret } from "./secret.ts";
|
|
27
27
|
import type { VectorizeIndex } from "./vectorize-index.ts";
|
|
28
28
|
import type { VersionMetadata } from "./version-metadata.ts";
|
|
29
|
+
import type { VpcService } from "./vpc-service.ts";
|
|
29
30
|
import type { WorkerLoader } from "./worker-loader.ts";
|
|
30
31
|
import type { WorkerRef } from "./worker-ref.ts";
|
|
31
32
|
import type { WorkerStub } from "./worker-stub.ts";
|
|
@@ -82,7 +83,8 @@ export type Binding =
|
|
|
82
83
|
| BrowserRendering
|
|
83
84
|
| VersionMetadata
|
|
84
85
|
| Self
|
|
85
|
-
| Json
|
|
86
|
+
| Json
|
|
87
|
+
| VpcService;
|
|
86
88
|
|
|
87
89
|
export type Self<
|
|
88
90
|
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
@@ -143,7 +145,8 @@ export type WorkerBindingSpec =
|
|
|
143
145
|
| WorkerBindingVersionMetadata
|
|
144
146
|
| WorkerBindingWasmModule
|
|
145
147
|
| WorkerBindingWorkerLoader
|
|
146
|
-
| WorkerBindingWorkflow
|
|
148
|
+
| WorkerBindingWorkflow
|
|
149
|
+
| WorkerBindingVpcService;
|
|
147
150
|
|
|
148
151
|
/**
|
|
149
152
|
* AI binding type
|
|
@@ -499,6 +502,16 @@ export interface WorkerBindingWorkflow {
|
|
|
499
502
|
script_name?: string;
|
|
500
503
|
}
|
|
501
504
|
|
|
505
|
+
export interface WorkerBindingVpcService {
|
|
506
|
+
/** The name of the binding */
|
|
507
|
+
name: string;
|
|
508
|
+
/** Type identifier for VPC Service binding */
|
|
509
|
+
type: "vpc_service";
|
|
510
|
+
/** VPC Service name */
|
|
511
|
+
service_name: string;
|
|
512
|
+
service_id: string;
|
|
513
|
+
}
|
|
514
|
+
|
|
502
515
|
/**
|
|
503
516
|
* Images binding type
|
|
504
517
|
*/
|
package/src/cloudflare/bound.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type { SecretRef as CloudflareSecretRef } from "./secret-ref.ts";
|
|
|
20
20
|
import type { Secret as CloudflareSecret } from "./secret.ts";
|
|
21
21
|
import type { VectorizeIndex as _VectorizeIndex } from "./vectorize-index.ts";
|
|
22
22
|
import type { VersionMetadata as _VersionMetadata } from "./version-metadata.ts";
|
|
23
|
+
import type { VpcService as _VpcService } from "./vpc-service.ts";
|
|
23
24
|
import type { WorkerLoader as _WorkerLoader } from "./worker-loader.ts";
|
|
24
25
|
import type { WorkerRef } from "./worker-ref.ts";
|
|
25
26
|
import type { WorkerStub } from "./worker-stub.ts";
|
|
@@ -105,6 +106,8 @@ export type Bound<T extends Binding> =
|
|
|
105
106
|
Obj &
|
|
106
107
|
Rpc.DurableObjectBranded
|
|
107
108
|
>
|
|
108
|
-
: T extends
|
|
109
|
-
?
|
|
110
|
-
:
|
|
109
|
+
: T extends _VpcService
|
|
110
|
+
? Fetcher
|
|
111
|
+
: T extends undefined
|
|
112
|
+
? undefined
|
|
113
|
+
: Service;
|
|
@@ -100,6 +100,8 @@ export type R2BucketCustomDomain = {
|
|
|
100
100
|
minTLS?: "1.0" | "1.1" | "1.2" | "1.3" | (string & {});
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
+
const DEV_NOOP_ZONE = "noop-zone";
|
|
104
|
+
|
|
103
105
|
export const R2BucketCustomDomain = Resource(
|
|
104
106
|
"cloudflare::R2BucketCustomDomain",
|
|
105
107
|
async function (
|
|
@@ -114,7 +116,7 @@ export const R2BucketCustomDomain = Resource(
|
|
|
114
116
|
zoneId:
|
|
115
117
|
typeof props.zone === "string"
|
|
116
118
|
? props.zone
|
|
117
|
-
: (props.zone?.id ??
|
|
119
|
+
: (props.zone?.id ?? DEV_NOOP_ZONE),
|
|
118
120
|
ciphers: props.ciphers,
|
|
119
121
|
minTLS: props.minTLS,
|
|
120
122
|
};
|
|
@@ -158,6 +160,7 @@ export const R2BucketCustomDomain = Resource(
|
|
|
158
160
|
}
|
|
159
161
|
case "update": {
|
|
160
162
|
if (
|
|
163
|
+
this.output.zoneId !== DEV_NOOP_ZONE && // dev mode placeholder should not trigger replacement
|
|
161
164
|
diff(this.output, payload).some(
|
|
162
165
|
(property) => property === "domain" || property === "zoneId",
|
|
163
166
|
)
|
package/src/cloudflare/bucket.ts
CHANGED
|
@@ -689,6 +689,13 @@ const _R2Bucket = Resource(
|
|
|
689
689
|
|
|
690
690
|
if (this.phase === "delete") {
|
|
691
691
|
if (props.delete !== false) {
|
|
692
|
+
// Use bucket's actual jurisdiction from output, falling back to props
|
|
693
|
+
// This ensures EU/FedRAMP buckets are correctly addressed during cleanup
|
|
694
|
+
const deleteProps: BucketProps = {
|
|
695
|
+
...props,
|
|
696
|
+
jurisdiction: this.output?.jurisdiction ?? props.jurisdiction,
|
|
697
|
+
};
|
|
698
|
+
|
|
692
699
|
if (this.output?.catalog) {
|
|
693
700
|
await disableDataCatalog(api, bucketName);
|
|
694
701
|
}
|
|
@@ -696,9 +703,9 @@ const _R2Bucket = Resource(
|
|
|
696
703
|
await deleteMiniflareBinding(this.scope, "r2", this.output.dev.id);
|
|
697
704
|
}
|
|
698
705
|
if (props.empty) {
|
|
699
|
-
await emptyBucket(api, bucketName,
|
|
706
|
+
await emptyBucket(api, bucketName, deleteProps);
|
|
700
707
|
}
|
|
701
|
-
await deleteBucket(api, bucketName,
|
|
708
|
+
await deleteBucket(api, bucketName, deleteProps);
|
|
702
709
|
}
|
|
703
710
|
return this.destroy();
|
|
704
711
|
}
|
|
@@ -540,10 +540,17 @@ export async function deleteDatabase(
|
|
|
540
540
|
api: CloudflareApi,
|
|
541
541
|
databaseId: string,
|
|
542
542
|
): Promise<void> {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
543
|
+
try {
|
|
544
|
+
await extractCloudflareResult(
|
|
545
|
+
`delete D1 database "${databaseId}"`,
|
|
546
|
+
api.delete(`/accounts/${api.accountId}/d1/database/${databaseId}`),
|
|
547
|
+
);
|
|
548
|
+
} catch (error) {
|
|
549
|
+
if (error instanceof CloudflareApiError && error.status === 404) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
throw error;
|
|
553
|
+
}
|
|
547
554
|
}
|
|
548
555
|
|
|
549
556
|
/**
|
package/src/cloudflare/index.ts
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
export * from "./account-api-token.ts";
|
|
4
4
|
export * from "./account-id.ts";
|
|
5
|
+
export * from "./ai-crawler.ts";
|
|
5
6
|
export * from "./ai-gateway.ts";
|
|
7
|
+
export * from "./ai-search-token.ts";
|
|
8
|
+
export * from "./ai-search.ts";
|
|
6
9
|
export * from "./ai.ts";
|
|
7
10
|
export * from "./analytics-engine.ts";
|
|
8
11
|
export * from "./api-error.ts";
|
|
@@ -70,6 +73,7 @@ export * from "./vectorize-index.ts";
|
|
|
70
73
|
export * from "./vectorize-metadata-index.ts";
|
|
71
74
|
export * from "./version-metadata.ts";
|
|
72
75
|
export * from "./vite/vite.ts";
|
|
76
|
+
export * from "./vpc-service.ts";
|
|
73
77
|
export * from "./warp-default-profile.ts";
|
|
74
78
|
export * from "./warp-device-profile.ts";
|
|
75
79
|
export * from "./website.ts";
|
|
@@ -31,29 +31,26 @@ export interface MiniflareWorkerInput {
|
|
|
31
31
|
cwd: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
type RemoteOnlyBindingType =
|
|
35
|
-
| "ai"
|
|
36
|
-
| "browser"
|
|
37
|
-
| "dispatch_namespace"
|
|
38
|
-
| "mtls_certificate"
|
|
39
|
-
| "vectorize";
|
|
40
|
-
type RemoteOptionalBindingType =
|
|
41
|
-
| "d1"
|
|
42
|
-
| "images"
|
|
43
|
-
| "kv_namespace"
|
|
44
|
-
| "queue"
|
|
45
|
-
| "r2_bucket";
|
|
46
|
-
|
|
47
34
|
type RemoteBinding =
|
|
35
|
+
// Supported remote bindings that are NOT a fetcher require the `raw` flag.
|
|
48
36
|
| (Extract<
|
|
49
37
|
WorkerBindingSpec,
|
|
50
38
|
{
|
|
51
|
-
type:
|
|
39
|
+
type:
|
|
40
|
+
| "ai"
|
|
41
|
+
| "browser"
|
|
42
|
+
| "dispatch_namespace"
|
|
43
|
+
| "mtls_certificate"
|
|
44
|
+
| "vectorize"
|
|
45
|
+
| "d1"
|
|
46
|
+
| "images"
|
|
47
|
+
| "kv_namespace"
|
|
48
|
+
| "queue"
|
|
49
|
+
| "r2_bucket";
|
|
52
50
|
}
|
|
53
|
-
> & {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
| WorkerBindingService;
|
|
51
|
+
> & { raw: true })
|
|
52
|
+
// Fetcher type bindings do not require the `raw` flag and will throw an error if it is present.
|
|
53
|
+
| Extract<WorkerBindingSpec, { type: "service" | "vpc_service" }>;
|
|
57
54
|
|
|
58
55
|
type BaseWorkerOptions = {
|
|
59
56
|
[K in keyof miniflare.WorkerOptions]: K extends
|
|
@@ -324,6 +321,15 @@ export const buildWorkerOptions = async (
|
|
|
324
321
|
};
|
|
325
322
|
break;
|
|
326
323
|
}
|
|
324
|
+
case "vpc_service": {
|
|
325
|
+
remoteBindings.push({
|
|
326
|
+
type: "vpc_service",
|
|
327
|
+
name: key,
|
|
328
|
+
service_name: binding.name,
|
|
329
|
+
service_id: binding.serviceId,
|
|
330
|
+
});
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
327
333
|
case "worker_loader": {
|
|
328
334
|
(options.workerLoaders ??= {})[key] = {};
|
|
329
335
|
break;
|
|
@@ -447,6 +453,12 @@ export const buildWorkerOptions = async (
|
|
|
447
453
|
remoteProxyConnectionString: remoteProxy.connectionString,
|
|
448
454
|
};
|
|
449
455
|
break;
|
|
456
|
+
case "vpc_service":
|
|
457
|
+
(options.vpcServices ??= {})[binding.name] = {
|
|
458
|
+
service_id: binding.service_id,
|
|
459
|
+
remoteProxyConnectionString: remoteProxy.connectionString,
|
|
460
|
+
};
|
|
461
|
+
break;
|
|
450
462
|
default: {
|
|
451
463
|
assertNever(binding);
|
|
452
464
|
}
|
|
@@ -32,10 +32,12 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
32
32
|
|
|
33
33
|
server.on("request", async (req, res) => {
|
|
34
34
|
try {
|
|
35
|
-
const response = await handleFetch(req);
|
|
35
|
+
const response = await handleFetch(req, res);
|
|
36
36
|
writeMiniflareResponseToNode(response, res);
|
|
37
37
|
} catch (error) {
|
|
38
|
-
|
|
38
|
+
if (!(error instanceof DOMException && error.name === "AbortError")) {
|
|
39
|
+
console.error(error);
|
|
40
|
+
}
|
|
39
41
|
const response = MiniflareWorkerProxyError.fromUnknown(error).toResponse(
|
|
40
42
|
options.mode,
|
|
41
43
|
);
|
|
@@ -45,6 +47,7 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
45
47
|
|
|
46
48
|
const handleFetch = async (
|
|
47
49
|
req: http.IncomingMessage,
|
|
50
|
+
res: http.ServerResponse,
|
|
48
51
|
): Promise<miniflare.Response> => {
|
|
49
52
|
const info = parseIncomingMessage(req);
|
|
50
53
|
options.transformRequest?.(info);
|
|
@@ -60,12 +63,14 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
60
63
|
info.url.pathname = "/cdn-cgi/handler/scheduled";
|
|
61
64
|
}
|
|
62
65
|
|
|
66
|
+
const signal = getDisconnectSignal(req, res);
|
|
63
67
|
const request = new miniflare.Request(info.url, {
|
|
64
68
|
method: info.method,
|
|
65
69
|
headers: info.headers,
|
|
66
70
|
body: info.body,
|
|
67
71
|
redirect: info.redirect,
|
|
68
72
|
duplex: info.duplex,
|
|
73
|
+
signal,
|
|
69
74
|
});
|
|
70
75
|
return await options.miniflare.dispatchFetch(request);
|
|
71
76
|
};
|
|
@@ -114,6 +119,46 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
114
119
|
};
|
|
115
120
|
}
|
|
116
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Creates an abort signal that is triggered when the downstream client
|
|
124
|
+
* disconnects before the response is fully written.
|
|
125
|
+
*
|
|
126
|
+
* This signal should be forwarded to Miniflare dispatch so Worker `req.signal`
|
|
127
|
+
* listeners can observe local client cancellation.
|
|
128
|
+
*/
|
|
129
|
+
function getDisconnectSignal(
|
|
130
|
+
req: http.IncomingMessage,
|
|
131
|
+
res: http.ServerResponse,
|
|
132
|
+
): AbortSignal {
|
|
133
|
+
const controller = new AbortController();
|
|
134
|
+
const onAbort = () => {
|
|
135
|
+
if (!controller.signal.aborted) {
|
|
136
|
+
controller.abort();
|
|
137
|
+
}
|
|
138
|
+
cleanup();
|
|
139
|
+
};
|
|
140
|
+
const onClose = () => {
|
|
141
|
+
if (!res.writableEnded) {
|
|
142
|
+
onAbort();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
cleanup();
|
|
146
|
+
};
|
|
147
|
+
const cleanup = () => {
|
|
148
|
+
req.off("aborted", onAbort);
|
|
149
|
+
req.socket?.off("close", onClose);
|
|
150
|
+
res.off("close", onClose);
|
|
151
|
+
res.off("finish", cleanup);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
req.on("aborted", onAbort);
|
|
155
|
+
req.socket?.on("close", onClose);
|
|
156
|
+
res.on("close", onClose);
|
|
157
|
+
res.on("finish", cleanup);
|
|
158
|
+
|
|
159
|
+
return controller.signal;
|
|
160
|
+
}
|
|
161
|
+
|
|
117
162
|
/**
|
|
118
163
|
* Listens on the given port, retrying on the next port if the port is already in use.
|
|
119
164
|
*/
|
|
@@ -98,6 +98,12 @@ export const PERMISSION_GROUPS = [
|
|
|
98
98
|
description: "Grants access to reading AI Gateways",
|
|
99
99
|
scopes: ["com.cloudflare.api.account"],
|
|
100
100
|
},
|
|
101
|
+
{
|
|
102
|
+
id: "9e9b428a0bcd46fd80e580b46a69963c",
|
|
103
|
+
name: "AI Search Index Engine",
|
|
104
|
+
description: "Grants access to run AI Search Index Engine",
|
|
105
|
+
scopes: ["com.cloudflare.api.account"],
|
|
106
|
+
},
|
|
101
107
|
{
|
|
102
108
|
id: "644535f4ed854494a59cb289d634b257",
|
|
103
109
|
name: "AI Gateway Run",
|