alchemy 0.12.6 → 0.12.8

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.
Files changed (80) hide show
  1. package/lib/cloudflare/ai-gateway.d.ts.map +1 -1
  2. package/lib/cloudflare/ai-gateway.js +1 -2
  3. package/lib/cloudflare/ai-gateway.js.map +1 -1
  4. package/lib/cloudflare/bindings.d.ts +2 -1
  5. package/lib/cloudflare/bindings.d.ts.map +1 -1
  6. package/lib/cloudflare/bound.d.ts +2 -1
  7. package/lib/cloudflare/bound.d.ts.map +1 -1
  8. package/lib/cloudflare/bucket.d.ts +8 -2
  9. package/lib/cloudflare/bucket.d.ts.map +1 -1
  10. package/lib/cloudflare/bucket.js +1 -1
  11. package/lib/cloudflare/bucket.js.map +1 -1
  12. package/lib/cloudflare/d1-database.d.ts +8 -2
  13. package/lib/cloudflare/d1-database.d.ts.map +1 -1
  14. package/lib/cloudflare/d1-database.js +2 -2
  15. package/lib/cloudflare/d1-database.js.map +1 -1
  16. package/lib/cloudflare/event-source.d.ts +26 -0
  17. package/lib/cloudflare/event-source.d.ts.map +1 -0
  18. package/lib/cloudflare/event-source.js +9 -0
  19. package/lib/cloudflare/event-source.js.map +1 -0
  20. package/lib/cloudflare/hyperdrive.d.ts +216 -0
  21. package/lib/cloudflare/hyperdrive.d.ts.map +1 -0
  22. package/lib/cloudflare/hyperdrive.js +184 -0
  23. package/lib/cloudflare/hyperdrive.js.map +1 -0
  24. package/lib/cloudflare/index.d.ts +2 -0
  25. package/lib/cloudflare/index.d.ts.map +1 -1
  26. package/lib/cloudflare/index.js +2 -0
  27. package/lib/cloudflare/index.js.map +1 -1
  28. package/lib/cloudflare/queue-consumer.d.ts +162 -0
  29. package/lib/cloudflare/queue-consumer.d.ts.map +1 -0
  30. package/lib/cloudflare/queue-consumer.js +197 -0
  31. package/lib/cloudflare/queue-consumer.js.map +1 -0
  32. package/lib/cloudflare/queue.d.ts +15 -3
  33. package/lib/cloudflare/queue.d.ts.map +1 -1
  34. package/lib/cloudflare/queue.js +8 -2
  35. package/lib/cloudflare/queue.js.map +1 -1
  36. package/lib/cloudflare/website.d.ts.map +1 -1
  37. package/lib/cloudflare/website.js +8 -10
  38. package/lib/cloudflare/website.js.map +1 -1
  39. package/lib/cloudflare/worker.d.ts +13 -2
  40. package/lib/cloudflare/worker.d.ts.map +1 -1
  41. package/lib/cloudflare/worker.js +75 -3
  42. package/lib/cloudflare/worker.js.map +1 -1
  43. package/lib/cloudflare/wrangler.json.d.ts +13 -3
  44. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  45. package/lib/cloudflare/wrangler.json.js +27 -5
  46. package/lib/cloudflare/wrangler.json.js.map +1 -1
  47. package/lib/neon/api-error.d.ts +31 -0
  48. package/lib/neon/api-error.d.ts.map +1 -0
  49. package/lib/neon/api-error.js +73 -0
  50. package/lib/neon/api-error.js.map +1 -0
  51. package/lib/neon/api.d.ts +70 -0
  52. package/lib/neon/api.d.ts.map +1 -0
  53. package/lib/neon/api.js +128 -0
  54. package/lib/neon/api.js.map +1 -0
  55. package/lib/neon/index.d.ts +4 -0
  56. package/lib/neon/index.d.ts.map +1 -0
  57. package/lib/neon/index.js +4 -0
  58. package/lib/neon/index.js.map +1 -0
  59. package/lib/neon/project.d.ts +345 -0
  60. package/lib/neon/project.d.ts.map +1 -0
  61. package/lib/neon/project.js +305 -0
  62. package/lib/neon/project.js.map +1 -0
  63. package/package.json +2 -1
  64. package/src/cloudflare/ai-gateway.ts +0 -1
  65. package/src/cloudflare/bindings.ts +4 -2
  66. package/src/cloudflare/bound.ts +20 -17
  67. package/src/cloudflare/bucket.ts +9 -2
  68. package/src/cloudflare/d1-database.ts +10 -3
  69. package/src/cloudflare/event-source.ts +33 -0
  70. package/src/cloudflare/hyperdrive.ts +375 -0
  71. package/src/cloudflare/index.ts +2 -0
  72. package/src/cloudflare/queue-consumer.ts +433 -0
  73. package/src/cloudflare/queue.ts +83 -63
  74. package/src/cloudflare/website.ts +9 -13
  75. package/src/cloudflare/worker.ts +109 -5
  76. package/src/cloudflare/wrangler.json.ts +52 -8
  77. package/src/neon/api-error.ts +81 -0
  78. package/src/neon/api.ts +178 -0
  79. package/src/neon/index.ts +3 -0
  80. package/src/neon/project.ts +870 -0
@@ -0,0 +1,305 @@
1
+ import { alchemy } from "../alchemy.js";
2
+ import { Resource } from "../resource.js";
3
+ import { handleApiError } from "./api-error.js";
4
+ import { createNeonApi } from "./api.js";
5
+ /**
6
+ * Creates a Neon serverless PostgreSQL project.
7
+ *
8
+ * @example
9
+ * // Create a basic Neon project with default settings:
10
+ * const project = await NeonProject("my-project", {
11
+ * name: "My Project"
12
+ * });
13
+ *
14
+ * @example
15
+ * // Create a Neon project in a specific region with a specific PostgreSQL version:
16
+ * const euProject = await NeonProject("my-eu-project", {
17
+ * name: "My EU Project",
18
+ * region_id: "aws-eu-west-1",
19
+ * pg_version: 16,
20
+ * apiKey: alchemy.secret(process.env.NEON_API_KEY)
21
+ * });
22
+ *
23
+ * @example
24
+ * // Create a Neon project with a custom default branch name:
25
+ * const devProject = await NeonProject("dev-project", {
26
+ * name: "Development Project",
27
+ * default_branch_name: "development"
28
+ * });
29
+ */
30
+ export const NeonProject = Resource("neon::Project", async function (id, props) {
31
+ const api = createNeonApi(props);
32
+ const projectId = props.existing_project_id || this.output?.id;
33
+ if (this.phase === "delete") {
34
+ try {
35
+ // Check if the project exists before attempting to delete
36
+ if (projectId) {
37
+ const deleteResponse = await api.delete(`/projects/${projectId}`);
38
+ if (!deleteResponse.ok && deleteResponse.status !== 404) {
39
+ await handleApiError(deleteResponse, "delete", "project", id);
40
+ }
41
+ }
42
+ }
43
+ catch (error) {
44
+ console.error(`Error deleting Neon project ${id}:`, error);
45
+ throw error;
46
+ }
47
+ return this.destroy();
48
+ }
49
+ let response;
50
+ try {
51
+ if (this.phase === "update" && projectId) {
52
+ // Update existing project
53
+ // Neon only allows updating the project name
54
+ const projectResponse = await api.patch(`/projects/${projectId}`, {
55
+ project: {
56
+ name: props.name,
57
+ },
58
+ });
59
+ if (!projectResponse.ok) {
60
+ await handleApiError(projectResponse, "update", "project", id);
61
+ }
62
+ const initialData = await projectResponse.json();
63
+ // Reify project properties to get complete data
64
+ response = await getProject(api, projectId, initialData);
65
+ }
66
+ else {
67
+ // Check if a project with this ID already exists
68
+ if (projectId) {
69
+ const getResponse = await api.get(`/projects/${projectId}`);
70
+ if (getResponse.ok) {
71
+ // Project exists, update it
72
+ const projectResponse = await api.patch(`/projects/${projectId}`, {
73
+ project: {
74
+ name: props.name,
75
+ },
76
+ });
77
+ if (!projectResponse.ok) {
78
+ await handleApiError(projectResponse, "update", "project", id);
79
+ }
80
+ const initialData = await projectResponse.json();
81
+ // Reify project properties to get complete data
82
+ response = await getProject(api, projectId, initialData);
83
+ }
84
+ else if (getResponse.status !== 404) {
85
+ // Unexpected error during GET check
86
+ await handleApiError(getResponse, "get", "project", id);
87
+ throw new Error("Failed to check if project exists");
88
+ }
89
+ else {
90
+ // Project doesn't exist, create new
91
+ response = await createNewProject(api, props);
92
+ }
93
+ }
94
+ else {
95
+ // No output ID, create new project
96
+ response = await createNewProject(api, props);
97
+ }
98
+ }
99
+ // Wait for any pending operations to complete
100
+ if (response.operations && response.operations.length > 0) {
101
+ await waitForOperations(api, response.operations);
102
+ }
103
+ // Get the latest project state after operations complete
104
+ if (response.project?.id) {
105
+ // Reify project properties to get complete data
106
+ response = await getProject(api, response.project.id, response);
107
+ }
108
+ return this({
109
+ id: response.project.id,
110
+ name: response.project.name,
111
+ region_id: response.project.region_id,
112
+ pg_version: response.project.pg_version,
113
+ created_at: response.project.created_at,
114
+ updated_at: response.project.updated_at,
115
+ proxy_host: response.project.proxy_host,
116
+ // Pass through the provided props except apiKey (which is sensitive)
117
+ default_endpoint: props.default_endpoint,
118
+ default_branch_name: props.default_branch_name,
119
+ baseUrl: props.baseUrl,
120
+ // Add all available data
121
+ // @ts-ignore - api ensures they're non-empty
122
+ connection_uris: response.connection_uris,
123
+ // @ts-ignore
124
+ roles: response.roles,
125
+ // @ts-ignore
126
+ databases: response.databases,
127
+ // @ts-ignore
128
+ branch: response.branch,
129
+ // @ts-ignore
130
+ endpoints: response.endpoints,
131
+ });
132
+ }
133
+ catch (error) {
134
+ console.error(`Error ${this.phase} Neon project '${id}':`, error);
135
+ throw error;
136
+ }
137
+ });
138
+ /**
139
+ * Helper function to create a new Neon project
140
+ */
141
+ async function createNewProject(api, props) {
142
+ const defaultEndpoint = props.default_endpoint ?? true;
143
+ const projectResponse = await api.post("/projects", {
144
+ project: {
145
+ name: props.name,
146
+ region_id: props.region_id || "aws-us-east-1",
147
+ pg_version: props.pg_version || 15,
148
+ default_endpoint: defaultEndpoint,
149
+ branch: defaultEndpoint
150
+ ? { name: props.default_branch_name || "main" }
151
+ : undefined,
152
+ },
153
+ });
154
+ if (!projectResponse.ok) {
155
+ await handleApiError(projectResponse, "create", "project");
156
+ }
157
+ return (await projectResponse.json());
158
+ }
159
+ /**
160
+ * Helper function to get complete project details by fetching all related data
161
+ *
162
+ * @param api The Neon API client
163
+ * @param projectId The project ID
164
+ * @param initialData Initial project data (optional)
165
+ * @returns Complete project data with all related resources
166
+ */
167
+ async function getProject(api, projectId, initialData = {}) {
168
+ // Get the latest project details
169
+ const updatedData = await getProjectDetails(api, projectId);
170
+ // Start with a copy of the initial data
171
+ let responseData = { ...initialData };
172
+ // Check if we have a branch ID from the initial data
173
+ const branchId = initialData.branch?.id;
174
+ if (branchId) {
175
+ // Get the branch details
176
+ const branchData = await getBranchDetails(api, projectId, branchId);
177
+ // Update with the latest branch data
178
+ responseData.branch = branchData.branch;
179
+ // Also fetch the latest endpoint details for this branch
180
+ const endpointData = await getEndpointDetails(api, projectId, branchId);
181
+ // Update with the latest endpoint data if available
182
+ if (endpointData.endpoints && endpointData.endpoints.length > 0) {
183
+ responseData.endpoints = endpointData.endpoints;
184
+ }
185
+ }
186
+ // Preserve all data from the original response
187
+ // Only update properties that might have changed during operations
188
+ return {
189
+ ...responseData,
190
+ connection_uris: (updatedData.connection_uris || responseData.connection_uris)?.map((uri) => ({
191
+ connection_uri: alchemy.secret(uri.connection_uri),
192
+ connection_parameters: {
193
+ database: uri.connection_parameters.database,
194
+ host: uri.connection_parameters.host,
195
+ port: uri.connection_parameters.port ?? 5432,
196
+ user: uri.connection_parameters.user ?? "neondb_owner",
197
+ password: alchemy.secret(uri.connection_parameters.password),
198
+ },
199
+ })),
200
+ project: updatedData.project,
201
+ branch: updatedData.branch || responseData.branch,
202
+ endpoints: updatedData.endpoints || responseData.endpoints,
203
+ };
204
+ }
205
+ /**
206
+ * Wait for operations to complete
207
+ *
208
+ * @param api The Neon API client
209
+ * @param operations Operations to wait for
210
+ * @throws Error if an operation fails or times out
211
+ * @returns Promise that resolves when all operations complete
212
+ */
213
+ async function waitForOperations(api, operations) {
214
+ const pendingOperations = operations.filter((op) => op.status !== "finished" && op.status !== "failed");
215
+ if (pendingOperations.length === 0) {
216
+ return;
217
+ }
218
+ // Maximum wait time in milliseconds (5 minutes)
219
+ const maxWaitTime = 5 * 60 * 1000;
220
+ // Initial delay between retries in milliseconds
221
+ const initialRetryDelay = 500;
222
+ // Maximum delay between retries
223
+ const maxRetryDelay = 10000;
224
+ // Backoff factor for exponential backoff
225
+ const backoffFactor = 1.5;
226
+ for (const operation of pendingOperations) {
227
+ let totalWaitTime = 0;
228
+ let retryDelay = initialRetryDelay;
229
+ let operationStatus = operation.status;
230
+ while (operationStatus !== "finished" &&
231
+ operationStatus !== "failed" &&
232
+ totalWaitTime < maxWaitTime) {
233
+ // Wait before checking again with exponential backoff
234
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
235
+ totalWaitTime += retryDelay;
236
+ // Increase delay for next retry with exponential backoff, up to max
237
+ retryDelay = Math.min(retryDelay * backoffFactor, maxRetryDelay);
238
+ // Check operation status
239
+ const operationResponse = await api.get(`/projects/${operation.project_id}/operations/${operation.id}`);
240
+ if (operationResponse.ok) {
241
+ const operationData = await operationResponse.json();
242
+ operationStatus = operationData.operation?.status;
243
+ }
244
+ else {
245
+ throw new Error(`Failed to check operation ${operation.id} status: HTTP ${operationResponse.status}`);
246
+ }
247
+ }
248
+ if (operationStatus === "failed") {
249
+ throw new Error(`Operation ${operation.id} (${operation.action}) failed`);
250
+ }
251
+ else if (totalWaitTime >= maxWaitTime) {
252
+ throw new Error(`Timeout waiting for operation ${operation.id} (${operation.action}) to complete`);
253
+ }
254
+ }
255
+ // Explicitly return when all operations are complete
256
+ return;
257
+ }
258
+ /**
259
+ * Get the latest project details
260
+ *
261
+ * @param api The Neon API client
262
+ * @param projectId The project ID
263
+ * @returns Project details including branch and endpoints
264
+ * @throws Error if project details cannot be retrieved
265
+ */
266
+ async function getProjectDetails(api, projectId) {
267
+ const response = await api.get(`/projects/${projectId}`);
268
+ if (!response.ok) {
269
+ throw new Error(`Failed to get project details: HTTP ${response.status}`);
270
+ }
271
+ return (await response.json());
272
+ }
273
+ /**
274
+ * Get the latest branch details
275
+ *
276
+ * @param api The Neon API client
277
+ * @param projectId The project ID
278
+ * @param branchId The branch ID
279
+ * @returns Branch details
280
+ * @throws Error if branch details cannot be retrieved
281
+ */
282
+ async function getBranchDetails(api, projectId, branchId) {
283
+ const response = await api.get(`/projects/${projectId}/branches/${branchId}`);
284
+ if (!response.ok) {
285
+ throw new Error(`Failed to get branch details: HTTP ${response.status}`);
286
+ }
287
+ return (await response.json());
288
+ }
289
+ /**
290
+ * Get the latest endpoint details for a branch
291
+ *
292
+ * @param api The Neon API client
293
+ * @param projectId The project ID
294
+ * @param branchId The branch ID
295
+ * @returns Endpoint details for the branch
296
+ * @throws Error if endpoint details cannot be retrieved
297
+ */
298
+ async function getEndpointDetails(api, projectId, branchId) {
299
+ const response = await api.get(`/projects/${projectId}/branches/${branchId}/endpoints`);
300
+ if (!response.ok) {
301
+ throw new Error(`Failed to get endpoint details: HTTP ${response.status}`);
302
+ }
303
+ return (await response.json());
304
+ }
305
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/neon/project.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy",
3
- "version": "0.12.6",
3
+ "version": "0.12.8",
4
4
  "type": "module",
5
5
  "module": "./lib/index.js",
6
6
  "scripts": {
@@ -21,6 +21,7 @@
21
21
  "./esbuild": "./lib/esbuild/index.js",
22
22
  "./fs": "./lib/fs/index.js",
23
23
  "./github": "./lib/github/index.js",
24
+ "./neon": "./lib/neon/index.js",
24
25
  "./os": "./lib/os/index.js",
25
26
  "./shadcn": "./lib/shadcn/index.js",
26
27
  "./stripe": "./lib/stripe/index.js",
@@ -151,7 +151,6 @@ export interface AiGateway
151
151
  */
152
152
  export const AiGateway = Resource(
153
153
  "cloudflare::AiGateway",
154
- { alwaysUpdate: true }, // AI Gateway PUT updates, so always run update logic
155
154
  async function (
156
155
  this: Context<AiGateway>,
157
156
  id: string,
@@ -9,6 +9,7 @@ import type { Assets } from "./assets.js";
9
9
  import type { R2Bucket } from "./bucket.js";
10
10
  import type { D1Database } from "./d1-database.js";
11
11
  import type { DurableObjectNamespace } from "./durable-object-namespace.js";
12
+ import type { Hyperdrive } from "./hyperdrive.js";
12
13
  import type { KVNamespace } from "./kv-namespace.js";
13
14
  import type { Pipeline } from "./pipeline.js";
14
15
  import type { Queue } from "./queue.js";
@@ -24,9 +25,11 @@ export type Bindings = {
24
25
  * L2 Binding Resources.
25
26
  */
26
27
  export type Binding =
28
+ | AiGateway
27
29
  | Assets
28
30
  | D1Database
29
31
  | DurableObjectNamespace
32
+ | Hyperdrive
30
33
  | KVNamespace
31
34
  | Pipeline
32
35
  | Queue
@@ -35,8 +38,7 @@ export type Binding =
35
38
  | string
36
39
  | VectorizeIndex
37
40
  | Worker
38
- | Workflow
39
- | AiGateway;
41
+ | Workflow;
40
42
 
41
43
  /**
42
44
  * Union type for all Worker binding types (API spec)
@@ -6,6 +6,7 @@ import type { Binding } from "./bindings.js";
6
6
  import type { R2Bucket as _R2Bucket } from "./bucket.js";
7
7
  import type { D1Database as _D1Database } from "./d1-database.js";
8
8
  import type { DurableObjectNamespace as _DurableObjectNamespace } from "./durable-object-namespace.js";
9
+ import type { Hyperdrive as _Hyperdrive } from "./hyperdrive.js";
9
10
  import type { KVNamespace as _KVNamespace } from "./kv-namespace.js";
10
11
  import type { Pipeline as _Pipeline } from "./pipeline.js";
11
12
  import type { Queue as _Queue } from "./queue.js";
@@ -23,20 +24,22 @@ export type Bound<T extends Binding> = T extends _DurableObjectNamespace
23
24
  ? R2Bucket
24
25
  : T extends _AiGateway
25
26
  ? AiGateway
26
- : T extends Secret
27
- ? string
28
- : T extends Assets
29
- ? Service
30
- : T extends _Workflow<infer P>
31
- ? Workflow<P>
32
- : T extends _D1Database
33
- ? D1Database
34
- : T extends _VectorizeIndex
35
- ? VectorizeIndex
36
- : T extends _Queue
37
- ? Queue
38
- : T extends _Pipeline<infer R>
39
- ? Pipeline<R>
40
- : T extends string
41
- ? string
42
- : Service;
27
+ : T extends _Hyperdrive
28
+ ? Hyperdrive
29
+ : T extends Secret
30
+ ? string
31
+ : T extends Assets
32
+ ? Service
33
+ : T extends _Workflow<infer P>
34
+ ? Workflow<P>
35
+ : T extends _D1Database
36
+ ? D1Database
37
+ : T extends _VectorizeIndex
38
+ ? VectorizeIndex
39
+ : T extends _Queue<infer Body>
40
+ ? Queue<Body>
41
+ : T extends _Pipeline<infer R>
42
+ ? Pipeline<R>
43
+ : T extends string
44
+ ? string
45
+ : Service;
@@ -13,8 +13,10 @@ export interface BucketProps {
13
13
  * Name of the bucket
14
14
  * Names can only contain lowercase letters (a-z), numbers (0-9), and hyphens (-)
15
15
  * Cannot begin or end with a hyphen
16
+ *
17
+ * @default - the id of the resource
16
18
  */
17
- name: string;
19
+ name?: string;
18
20
 
19
21
  /**
20
22
  * Optional location hint for the bucket
@@ -90,6 +92,11 @@ export interface R2Bucket
90
92
  */
91
93
  type: "r2_bucket";
92
94
 
95
+ /**
96
+ * The name of the bucket
97
+ */
98
+ name: string;
99
+
93
100
  /**
94
101
  * Location of the bucket
95
102
  */
@@ -150,7 +157,7 @@ export const R2Bucket = Resource(
150
157
  async function (
151
158
  this: Context<R2Bucket>,
152
159
  id: string,
153
- props: BucketProps
160
+ props: BucketProps = {}
154
161
  ): Promise<R2Bucket> {
155
162
  const api = await createCloudflareApi(props);
156
163
  const bucketName = props.name || this.id;
@@ -14,8 +14,10 @@ import { applyMigrations, listMigrationsFiles } from "./d1-migrations.js";
14
14
  export interface D1DatabaseProps extends CloudflareApiOptions {
15
15
  /**
16
16
  * Name of the database
17
+ *
18
+ * @default id
17
19
  */
18
- name: string;
20
+ name?: string;
19
21
 
20
22
  /**
21
23
  * Optional primary location hint for the database
@@ -90,6 +92,11 @@ export type D1Database = Resource<"cloudflare::D1Database"> &
90
92
  */
91
93
  id: string;
92
94
 
95
+ /**
96
+ * The name of the database
97
+ */
98
+ name: string;
99
+
93
100
  /**
94
101
  * File size of the database
95
102
  */
@@ -173,10 +180,10 @@ export const D1DatabaseResource = Resource(
173
180
  async function (
174
181
  this: Context<D1Database>,
175
182
  id: string,
176
- props: D1DatabaseProps
183
+ props: D1DatabaseProps = {}
177
184
  ): Promise<D1Database> {
178
185
  const api = await createCloudflareApi(props);
179
- const databaseName = props.name || id;
186
+ const databaseName = props.name ?? id;
180
187
 
181
188
  if (this.phase === "delete") {
182
189
  console.log("Deleting D1 database:", databaseName);
@@ -0,0 +1,33 @@
1
+ import type { QueueConsumerSettings } from "./queue-consumer.js";
2
+ import type { Queue } from "./queue.js";
3
+
4
+ /**
5
+ * Base interface for event sources that can be bound to a Worker
6
+ */
7
+ export type EventSource = QueueEventSource | Queue;
8
+
9
+ /**
10
+ * Configuration for a Queue as an event source for a Worker
11
+ */
12
+ export interface QueueEventSource {
13
+ /**
14
+ * The queue to consume messages from
15
+ */
16
+ readonly queue: Queue;
17
+
18
+ /**
19
+ * Optional settings for configuring how the Worker consumes the queue
20
+ */
21
+ readonly settings?: QueueConsumerSettings;
22
+ }
23
+
24
+ /**
25
+ * Checks if an event source is a QueueEventSource
26
+ * @param eventSource - The event source to check
27
+ * @returns true if the event source is a QueueEventSource, false otherwise
28
+ */
29
+ export function isQueueEventSource(
30
+ eventSource: any
31
+ ): eventSource is QueueEventSource {
32
+ return "queue" in eventSource;
33
+ }