alchemy 2.0.0-beta.3 → 2.0.0-beta.test-export-fix-3
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-effect.js → alchemy.js} +172 -172
- package/bin/alchemy.js.map +1 -0
- package/bin/{alchemy-effect.sh → alchemy.sh} +2 -2
- package/lib/cli/index.js +169 -169
- package/lib/cli/index.js.map +1 -1
- package/package.json +60 -61
- package/src/AWS/AGENTS.md +10 -10
- package/src/AWS/Assets.ts +1 -1
- package/src/AWS/Credentials.ts +0 -1
- package/src/AWS/DynamoDB/Table.ts +63 -10
- package/src/AWS/EC2/hosted.ts +1 -1
- package/src/AWS/ECS/Task.ts +1 -1
- package/src/AWS/Kinesis/Stream.ts +44 -8
- package/src/AWS/Lambda/Function.ts +218 -10
- package/src/AWS/S3/Bucket.ts +26 -19
- package/src/AWS/S3/BucketNotifications.ts +1 -1
- package/src/AWS/SNS/Topic.ts +47 -10
- package/src/AWS/SQS/Queue.ts +66 -0
- package/src/Cloudflare/Container/ContainerApplication.ts +3 -3
- package/src/Cloudflare/Container/ContainerBinding.ts +2 -4
- package/src/Cloudflare/Container/StartContainer.ts +1 -1
- package/src/Cloudflare/Providers.ts +1 -6
- package/src/Cloudflare/R2/R2Bucket.ts +2 -2
- package/src/Cloudflare/Website/StaticSite.ts +22 -6
- package/src/Cloudflare/Website/Vite.ts +15 -5
- package/src/Cloudflare/Workers/Assets.ts +170 -207
- package/src/Cloudflare/Workers/DurableObjectNamespace.ts +230 -370
- package/src/Cloudflare/Workers/DurableObjectState.ts +63 -0
- package/src/Cloudflare/Workers/DurableObjectStorage.ts +256 -0
- package/src/Cloudflare/Workers/InferEnv.ts +11 -7
- package/src/Cloudflare/Workers/Rpc.ts +13 -2
- package/src/Cloudflare/Workers/ScheduledEvents.ts +185 -0
- package/src/Cloudflare/Workers/WebSocket.ts +1 -1
- package/src/Cloudflare/Workers/Worker.ts +95 -43
- package/src/Cloudflare/Workers/index.ts +3 -0
- package/src/Construct.ts +2 -2
- package/src/GitHub/Secret.ts +52 -7
- package/src/GitHub/Variable.ts +45 -2
- package/src/Kubernetes/client.ts +2 -2
- package/src/Output.ts +1 -1
- package/src/Platform.ts +1 -1
- package/src/Test/Vitest.ts +4 -3
- package/src/Util/PlatformServices.ts +21 -0
- package/src/Util/dedent.ts +4 -1
- package/bin/alchemy-effect.js.map +0 -1
- package/src/Daemon/Client.ts +0 -116
- package/src/Daemon/Config.ts +0 -28
- package/src/Daemon/Errors.ts +0 -48
- package/src/Daemon/Lock.ts +0 -162
- package/src/Daemon/ProcessRegistry.ts +0 -284
- package/src/Daemon/RpcSchema.ts +0 -43
- package/src/Daemon/RpcServer.ts +0 -231
- package/src/Daemon/index.ts +0 -27
- package/src/Spawn.ts +0 -23
- /package/bin/{alchemy-effect.ts → alchemy.ts} +0 -0
|
@@ -116,25 +116,233 @@ export type FunctionShape = Main<FunctionServices>;
|
|
|
116
116
|
* An AWS Lambda host resource that combines code bundling, IAM role
|
|
117
117
|
* provisioning, and runtime binding collection.
|
|
118
118
|
*
|
|
119
|
-
* `Function` is the canonical runtime host for AWS.
|
|
120
|
-
*
|
|
121
|
-
* execution
|
|
119
|
+
* `Function` is the canonical runtime host for AWS. Alchemy automatically
|
|
120
|
+
* bundles your TypeScript entry module with Rolldown, creates an IAM
|
|
121
|
+
* execution role, and uploads the zip artifact. On subsequent deploys, the
|
|
122
|
+
* function is only updated when the bundle hash changes.
|
|
122
123
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
124
|
+
* There are two ways to define a Lambda Function:
|
|
125
|
+
*
|
|
126
|
+
* - **Async** — plain handler export, no Effect runtime in the bundle.
|
|
127
|
+
* - **Effect** — Effect implementation with typed bindings and event sources.
|
|
128
|
+
*
|
|
129
|
+
* See the {@link https://alchemy.run/guides/async-lambda | Async Lambda Guide}
|
|
130
|
+
* for plain handler patterns, or the
|
|
131
|
+
* {@link https://alchemy.run/guides/lambda | Effect Lambda Guide}
|
|
132
|
+
* for the full Effect-based approach with bindings, event sources, and sinks.
|
|
133
|
+
*
|
|
134
|
+
* @section Async Functions
|
|
135
|
+
* Point `main` at a file that exports a standard Lambda handler. No
|
|
136
|
+
* Effect runtime is included in the bundle. Useful when migrating
|
|
137
|
+
* existing Lambda functions or when you don't need Effect.
|
|
138
|
+
*
|
|
139
|
+
* @example Defining an async Lambda in your stack
|
|
125
140
|
* ```typescript
|
|
126
|
-
*
|
|
127
|
-
*
|
|
141
|
+
* // alchemy.run.ts
|
|
142
|
+
* import * as AWS from "alchemy/AWS";
|
|
143
|
+
*
|
|
144
|
+
* const func = yield* AWS.Lambda.Function("ApiFunction", {
|
|
145
|
+
* main: "./src/handler.ts",
|
|
146
|
+
* url: true,
|
|
128
147
|
* });
|
|
129
148
|
* ```
|
|
130
149
|
*
|
|
150
|
+
* @example Writing the async handler
|
|
151
|
+
* ```typescript
|
|
152
|
+
* // src/handler.ts
|
|
153
|
+
* export const handler = async (event: any) => {
|
|
154
|
+
* return {
|
|
155
|
+
* statusCode: 200,
|
|
156
|
+
* body: JSON.stringify({ message: "Hello from Lambda!" }),
|
|
157
|
+
* };
|
|
158
|
+
* };
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @section Effect Functions
|
|
162
|
+
* Pass the Effect implementation as the third argument. Bindings
|
|
163
|
+
* attach IAM permissions and environment variables at deploy time,
|
|
164
|
+
* while the runtime execution context collects listeners and exports.
|
|
165
|
+
*
|
|
166
|
+
* @example Effect Function with HTTP handler
|
|
167
|
+
* ```typescript
|
|
168
|
+
* export default class ApiFunction extends AWS.Lambda.Function<ApiFunction>()(
|
|
169
|
+
* "ApiFunction",
|
|
170
|
+
* { main: import.meta.filename, url: true },
|
|
171
|
+
* Effect.gen(function* () {
|
|
172
|
+
* // init: bind resources
|
|
173
|
+
* const getItem = yield* DynamoDB.GetItem.bind(table);
|
|
174
|
+
*
|
|
175
|
+
* return {
|
|
176
|
+
* // runtime: use them
|
|
177
|
+
* fetch: Effect.gen(function* () {
|
|
178
|
+
* const request = yield* HttpServerRequest;
|
|
179
|
+
* const url = new URL(request.url);
|
|
180
|
+
* const id = url.searchParams.get("id");
|
|
181
|
+
* const result = yield* getItem({ Key: { pk: { S: id! } } });
|
|
182
|
+
* return yield* HttpServerResponse.json(result.Item);
|
|
183
|
+
* }),
|
|
184
|
+
* };
|
|
185
|
+
* }),
|
|
186
|
+
* ) {}
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* @section Configuration
|
|
131
190
|
* @example Function with URL
|
|
132
191
|
* ```typescript
|
|
133
|
-
* const func = yield* Function("ApiFunction", {
|
|
134
|
-
* main: "./src/
|
|
192
|
+
* const func = yield* AWS.Lambda.Function("ApiFunction", {
|
|
193
|
+
* main: "./src/handler.ts",
|
|
135
194
|
* url: true,
|
|
136
195
|
* });
|
|
137
196
|
* ```
|
|
197
|
+
*
|
|
198
|
+
* @example Function in a VPC
|
|
199
|
+
* ```typescript
|
|
200
|
+
* const func = yield* AWS.Lambda.Function("VpcFunction", {
|
|
201
|
+
* main: "./src/handler.ts",
|
|
202
|
+
* vpc: {
|
|
203
|
+
* subnetIds: ["subnet-abc123", "subnet-def456"],
|
|
204
|
+
* securityGroupIds: ["sg-xyz789"],
|
|
205
|
+
* },
|
|
206
|
+
* });
|
|
207
|
+
* ```
|
|
208
|
+
*
|
|
209
|
+
* @section S3 Bindings
|
|
210
|
+
* Bind S3 operations in the init phase to give the function IAM
|
|
211
|
+
* permissions and inject the bucket name as an environment variable.
|
|
212
|
+
*
|
|
213
|
+
* @example Read and write S3 objects
|
|
214
|
+
* ```typescript
|
|
215
|
+
* // init
|
|
216
|
+
* const getObject = yield* S3.GetObject.bind(bucket);
|
|
217
|
+
* const putObject = yield* S3.PutObject.bind(bucket);
|
|
218
|
+
*
|
|
219
|
+
* return {
|
|
220
|
+
* fetch: Effect.gen(function* () {
|
|
221
|
+
* // runtime
|
|
222
|
+
* yield* putObject({ Key: "hello.txt", Body: "Hello!" });
|
|
223
|
+
* const obj = yield* getObject({ Key: "hello.txt" });
|
|
224
|
+
* return HttpServerResponse.text("OK");
|
|
225
|
+
* }),
|
|
226
|
+
* };
|
|
227
|
+
* ```
|
|
228
|
+
*
|
|
229
|
+
* @section DynamoDB Bindings
|
|
230
|
+
* Bind DynamoDB operations in the init phase to grant table-scoped
|
|
231
|
+
* IAM permissions.
|
|
232
|
+
*
|
|
233
|
+
* @example Get and put items
|
|
234
|
+
* ```typescript
|
|
235
|
+
* // init
|
|
236
|
+
* const getItem = yield* DynamoDB.GetItem.bind(table);
|
|
237
|
+
* const putItem = yield* DynamoDB.PutItem.bind(table);
|
|
238
|
+
*
|
|
239
|
+
* return {
|
|
240
|
+
* fetch: Effect.gen(function* () {
|
|
241
|
+
* // runtime
|
|
242
|
+
* yield* putItem({ Item: { pk: { S: "user#1" }, name: { S: "Alice" } } });
|
|
243
|
+
* const result = yield* getItem({ Key: { pk: { S: "user#1" } } });
|
|
244
|
+
* return yield* HttpServerResponse.json(result.Item);
|
|
245
|
+
* }),
|
|
246
|
+
* };
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
249
|
+
* @section SQS Bindings
|
|
250
|
+
* Bind SQS operations in the init phase to send messages to a queue.
|
|
251
|
+
*
|
|
252
|
+
* @example Send a message
|
|
253
|
+
* ```typescript
|
|
254
|
+
* // init
|
|
255
|
+
* const sendMessage = yield* SQS.SendMessage.bind(queue);
|
|
256
|
+
*
|
|
257
|
+
* return {
|
|
258
|
+
* fetch: Effect.gen(function* () {
|
|
259
|
+
* // runtime
|
|
260
|
+
* yield* sendMessage({
|
|
261
|
+
* MessageBody: JSON.stringify({ orderId: "123" }),
|
|
262
|
+
* });
|
|
263
|
+
* return HttpServerResponse.text("Queued");
|
|
264
|
+
* }),
|
|
265
|
+
* };
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @section SNS Bindings
|
|
269
|
+
* Bind SNS operations in the init phase to publish messages to a
|
|
270
|
+
* topic.
|
|
271
|
+
*
|
|
272
|
+
* @example Publish a notification
|
|
273
|
+
* ```typescript
|
|
274
|
+
* // init
|
|
275
|
+
* const publish = yield* SNS.Publish.bind(topic);
|
|
276
|
+
*
|
|
277
|
+
* return {
|
|
278
|
+
* fetch: Effect.gen(function* () {
|
|
279
|
+
* // runtime
|
|
280
|
+
* yield* publish({
|
|
281
|
+
* Message: JSON.stringify({ event: "order.created" }),
|
|
282
|
+
* Subject: "OrderCreated",
|
|
283
|
+
* });
|
|
284
|
+
* return HttpServerResponse.text("Published");
|
|
285
|
+
* }),
|
|
286
|
+
* };
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @section Kinesis Bindings
|
|
290
|
+
* Bind Kinesis operations in the init phase to put records into a
|
|
291
|
+
* stream.
|
|
292
|
+
*
|
|
293
|
+
* @example Put a record
|
|
294
|
+
* ```typescript
|
|
295
|
+
* // init
|
|
296
|
+
* const putRecord = yield* Kinesis.PutRecord.bind(stream);
|
|
297
|
+
*
|
|
298
|
+
* return {
|
|
299
|
+
* fetch: Effect.gen(function* () {
|
|
300
|
+
* // runtime
|
|
301
|
+
* yield* putRecord({
|
|
302
|
+
* PartitionKey: "order-123",
|
|
303
|
+
* Data: new TextEncoder().encode(JSON.stringify({ orderId: "123" })),
|
|
304
|
+
* });
|
|
305
|
+
* return HttpServerResponse.text("Sent");
|
|
306
|
+
* }),
|
|
307
|
+
* };
|
|
308
|
+
* ```
|
|
309
|
+
*
|
|
310
|
+
* @section Event Sources
|
|
311
|
+
* Lambda functions can be triggered by event sources like SQS queues,
|
|
312
|
+
* DynamoDB streams, S3 notifications, SNS topics, and Kinesis streams.
|
|
313
|
+
*
|
|
314
|
+
* @example Process SQS messages
|
|
315
|
+
* ```typescript
|
|
316
|
+
* yield* SQS.messages(queue).process(
|
|
317
|
+
* Effect.fn(function* (message) {
|
|
318
|
+
* yield* Effect.log(`Received: ${message.body}`);
|
|
319
|
+
* }),
|
|
320
|
+
* );
|
|
321
|
+
* ```
|
|
322
|
+
*
|
|
323
|
+
* @example Process DynamoDB stream changes
|
|
324
|
+
* ```typescript
|
|
325
|
+
* yield* DynamoDB.streams(table, {
|
|
326
|
+
* StreamViewType: "NEW_AND_OLD_IMAGES",
|
|
327
|
+
* }).process(
|
|
328
|
+
* Effect.fn(function* (record) {
|
|
329
|
+
* yield* Effect.log(`Change: ${record.eventName}`);
|
|
330
|
+
* }),
|
|
331
|
+
* );
|
|
332
|
+
* ```
|
|
333
|
+
*
|
|
334
|
+
* @example Process S3 notifications
|
|
335
|
+
* ```typescript
|
|
336
|
+
* yield* S3.notifications(bucket, {
|
|
337
|
+
* events: ["s3:ObjectCreated:*"],
|
|
338
|
+
* }).subscribe((stream) =>
|
|
339
|
+
* stream.pipe(
|
|
340
|
+
* Stream.runForEach((event) =>
|
|
341
|
+
* Effect.log(`New object: ${event.key}`),
|
|
342
|
+
* ),
|
|
343
|
+
* ),
|
|
344
|
+
* );
|
|
345
|
+
* ```
|
|
138
346
|
*/
|
|
139
347
|
export const Function: Platform<
|
|
140
348
|
Function,
|
|
@@ -433,7 +641,7 @@ export const FunctionProvider = () =>
|
|
|
433
641
|
virtualEntryPlugin(
|
|
434
642
|
(importPath) => `
|
|
435
643
|
import { NodeServices } from "@effect/platform-node";
|
|
436
|
-
import { Stack } from "alchemy
|
|
644
|
+
import { Stack } from "alchemy/Stack";
|
|
437
645
|
import * as Config from "effect/Config";
|
|
438
646
|
import * as ConfigProvider from "effect/ConfigProvider";
|
|
439
647
|
import * as Credentials from "@distilled.cloud/aws/Credentials";
|
package/src/AWS/S3/Bucket.ts
CHANGED
|
@@ -91,7 +91,7 @@ export interface Bucket extends Resource<
|
|
|
91
91
|
* @section Creating a Bucket
|
|
92
92
|
* @example Basic Bucket
|
|
93
93
|
* ```typescript
|
|
94
|
-
* import * as S3 from "alchemy
|
|
94
|
+
* import * as S3 from "alchemy/AWS/S3";
|
|
95
95
|
*
|
|
96
96
|
* const bucket = yield* S3.Bucket("my-bucket", {});
|
|
97
97
|
* ```
|
|
@@ -110,37 +110,44 @@ export interface Bucket extends Resource<
|
|
|
110
110
|
* });
|
|
111
111
|
* ```
|
|
112
112
|
*
|
|
113
|
-
* @section
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* const response = yield* getObject({ Key: "hello.txt" });
|
|
119
|
-
* ```
|
|
113
|
+
* @section Runtime Operations
|
|
114
|
+
* Bind S3 operations in the init phase and use them in runtime
|
|
115
|
+
* handlers. Bindings inject the bucket name and grant scoped IAM
|
|
116
|
+
* permissions automatically.
|
|
120
117
|
*
|
|
121
|
-
* @
|
|
122
|
-
* @example Put an object into a bucket
|
|
118
|
+
* @example Read and write objects
|
|
123
119
|
* ```typescript
|
|
120
|
+
* // init
|
|
121
|
+
* const getObject = yield* S3.GetObject.bind(bucket);
|
|
124
122
|
* const putObject = yield* S3.PutObject.bind(bucket);
|
|
125
123
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
124
|
+
* return {
|
|
125
|
+
* fetch: Effect.gen(function* () {
|
|
126
|
+
* // runtime
|
|
127
|
+
* yield* putObject({
|
|
128
|
+
* Key: "hello.txt",
|
|
129
|
+
* Body: "Hello, World!",
|
|
130
|
+
* ContentType: "text/plain",
|
|
131
|
+
* });
|
|
132
|
+
* const response = yield* getObject({ Key: "hello.txt" });
|
|
133
|
+
* return HttpServerResponse.text("OK");
|
|
134
|
+
* }),
|
|
135
|
+
* };
|
|
131
136
|
* ```
|
|
132
137
|
*
|
|
133
|
-
* @
|
|
134
|
-
* @example Delete an object from a bucket
|
|
138
|
+
* @example Delete an object
|
|
135
139
|
* ```typescript
|
|
140
|
+
* // init
|
|
136
141
|
* const deleteObject = yield* S3.DeleteObject.bind(bucket);
|
|
137
|
-
*
|
|
138
|
-
* yield* deleteObject({ Key: "hello.txt" });
|
|
139
142
|
* ```
|
|
140
143
|
*
|
|
141
144
|
* @section Event Notifications
|
|
145
|
+
* Subscribe to bucket events from the init phase. The subscription
|
|
146
|
+
* and Lambda invoke permissions are created automatically.
|
|
147
|
+
*
|
|
142
148
|
* @example Process object creation events
|
|
143
149
|
* ```typescript
|
|
150
|
+
* // init
|
|
144
151
|
* yield* S3.notifications(bucket, {
|
|
145
152
|
* events: ["s3:ObjectCreated:*"],
|
|
146
153
|
* }).subscribe((stream) =>
|
|
@@ -35,7 +35,7 @@ export interface NotificationsProps<Events extends S3EventType[]> {
|
|
|
35
35
|
* @section Subscribing to Events
|
|
36
36
|
* @example Process all object creation events
|
|
37
37
|
* ```typescript
|
|
38
|
-
* import * as S3 from "alchemy
|
|
38
|
+
* import * as S3 from "alchemy/AWS/S3";
|
|
39
39
|
*
|
|
40
40
|
* yield* S3.notifications(bucket, {
|
|
41
41
|
* events: ["s3:ObjectCreated:*"],
|
package/src/AWS/SNS/Topic.ts
CHANGED
|
@@ -60,20 +60,30 @@ export interface Topic extends Resource<
|
|
|
60
60
|
* An Amazon SNS topic for fan-out messaging and notifications.
|
|
61
61
|
*
|
|
62
62
|
* `Topic` owns the SNS topic lifecycle while raw AWS topic attributes remain
|
|
63
|
-
* available through the `attributes` prop so the full core pub/sub surface can
|
|
64
|
-
* configured without waiting on additional typed wrappers.
|
|
63
|
+
* available through the `attributes` prop so the full core pub/sub surface can
|
|
64
|
+
* be configured without waiting on additional typed wrappers. A topic name is
|
|
65
|
+
* auto-generated unless you provide one explicitly.
|
|
65
66
|
*
|
|
66
67
|
* @section Creating Topics
|
|
67
68
|
* @example Standard Topic
|
|
68
69
|
* ```typescript
|
|
69
|
-
*
|
|
70
|
-
*
|
|
70
|
+
* import * as SNS from "alchemy/AWS/SNS";
|
|
71
|
+
*
|
|
72
|
+
* const topic = yield* SNS.Topic("OrdersTopic");
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @example Topic with Display Name
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const topic = yield* SNS.Topic("NotificationsTopic", {
|
|
78
|
+
* attributes: {
|
|
79
|
+
* DisplayName: "App Notifications",
|
|
80
|
+
* },
|
|
71
81
|
* });
|
|
72
82
|
* ```
|
|
73
83
|
*
|
|
74
84
|
* @example FIFO Topic
|
|
75
85
|
* ```typescript
|
|
76
|
-
* const topic = yield* Topic("OrdersFifoTopic", {
|
|
86
|
+
* const topic = yield* SNS.Topic("OrdersFifoTopic", {
|
|
77
87
|
* fifo: true,
|
|
78
88
|
* attributes: {
|
|
79
89
|
* ContentBasedDeduplication: "true",
|
|
@@ -82,14 +92,41 @@ export interface Topic extends Resource<
|
|
|
82
92
|
* ```
|
|
83
93
|
*
|
|
84
94
|
* @section Runtime Publishing
|
|
85
|
-
*
|
|
95
|
+
* Bind publish operations in the init phase and use them in runtime
|
|
96
|
+
* handlers.
|
|
97
|
+
*
|
|
98
|
+
* @example Publish from a handler
|
|
86
99
|
* ```typescript
|
|
100
|
+
* // init
|
|
87
101
|
* const publish = yield* SNS.Publish.bind(topic);
|
|
88
102
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
103
|
+
* return {
|
|
104
|
+
* fetch: Effect.gen(function* () {
|
|
105
|
+
* // runtime
|
|
106
|
+
* yield* publish({
|
|
107
|
+
* Message: JSON.stringify({ orderId: "123" }),
|
|
108
|
+
* Subject: "OrderCreated",
|
|
109
|
+
* });
|
|
110
|
+
* return HttpServerResponse.text("Published");
|
|
111
|
+
* }),
|
|
112
|
+
* };
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @section Subscriptions
|
|
116
|
+
* Subscribe a Lambda function to process messages published to the
|
|
117
|
+
* topic. The subscription and invoke permissions are created
|
|
118
|
+
* automatically.
|
|
119
|
+
*
|
|
120
|
+
* @example Process topic notifications
|
|
121
|
+
* ```typescript
|
|
122
|
+
* // init
|
|
123
|
+
* yield* SNS.notifications(topic).subscribe((stream) =>
|
|
124
|
+
* stream.pipe(
|
|
125
|
+
* Stream.runForEach((message) =>
|
|
126
|
+
* Effect.log(`Received: ${message.Message}`),
|
|
127
|
+
* ),
|
|
128
|
+
* ),
|
|
129
|
+
* );
|
|
93
130
|
* ```
|
|
94
131
|
*/
|
|
95
132
|
export const Topic = Resource<Topic>("AWS.SNS.Topic");
|
package/src/AWS/SQS/Queue.ts
CHANGED
|
@@ -87,6 +87,72 @@ export interface Queue extends Resource<
|
|
|
87
87
|
Providers
|
|
88
88
|
> {}
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* An Amazon SQS queue for reliable, decoupled message processing.
|
|
92
|
+
*
|
|
93
|
+
* `Queue` owns the lifecycle of a standard or FIFO SQS queue. A queue name
|
|
94
|
+
* is auto-generated from the app, stage, and logical ID unless you provide
|
|
95
|
+
* one explicitly. FIFO queues automatically append the `.fifo` suffix.
|
|
96
|
+
*
|
|
97
|
+
* @section Creating Queues
|
|
98
|
+
* @example Standard Queue
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import * as SQS from "alchemy/AWS/SQS";
|
|
101
|
+
*
|
|
102
|
+
* const queue = yield* SQS.Queue("OrdersQueue");
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example FIFO Queue
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const queue = yield* SQS.Queue("OrdersFifoQueue", {
|
|
108
|
+
* fifo: true,
|
|
109
|
+
* contentBasedDeduplication: true,
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @example Queue with Custom Settings
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const queue = yield* SQS.Queue("ProcessingQueue", {
|
|
116
|
+
* visibilityTimeout: 120,
|
|
117
|
+
* messageRetentionPeriod: 86400,
|
|
118
|
+
* receiveMessageWaitTimeSeconds: 20,
|
|
119
|
+
* });
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @section Sending Messages
|
|
123
|
+
* Bind send operations in the init phase and use them in runtime
|
|
124
|
+
* handlers.
|
|
125
|
+
*
|
|
126
|
+
* @example Send a message from a handler
|
|
127
|
+
* ```typescript
|
|
128
|
+
* // init
|
|
129
|
+
* const sendMessage = yield* SQS.SendMessage.bind(queue);
|
|
130
|
+
*
|
|
131
|
+
* return {
|
|
132
|
+
* fetch: Effect.gen(function* () {
|
|
133
|
+
* // runtime
|
|
134
|
+
* yield* sendMessage({
|
|
135
|
+
* MessageBody: JSON.stringify({ orderId: "123" }),
|
|
136
|
+
* });
|
|
137
|
+
* return HttpServerResponse.text("Queued");
|
|
138
|
+
* }),
|
|
139
|
+
* };
|
|
140
|
+
* ```
|
|
141
|
+
*
|
|
142
|
+
* @section Event Sources
|
|
143
|
+
* Process messages from a queue using a Lambda event source mapping.
|
|
144
|
+
* Messages are automatically deleted after successful processing.
|
|
145
|
+
*
|
|
146
|
+
* @example Process queue messages
|
|
147
|
+
* ```typescript
|
|
148
|
+
* // init
|
|
149
|
+
* yield* SQS.messages(queue).process(
|
|
150
|
+
* Effect.fn(function* (message) {
|
|
151
|
+
* yield* Effect.log(`Received: ${message.body}`);
|
|
152
|
+
* }),
|
|
153
|
+
* );
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
90
156
|
export const Queue = Resource<Queue>("AWS.SQS.Queue");
|
|
91
157
|
|
|
92
158
|
export const QueueProvider = () =>
|
|
@@ -483,16 +483,16 @@ ${
|
|
|
483
483
|
runtime === "bun"
|
|
484
484
|
? `
|
|
485
485
|
import { BunServices } from "@effect/platform-bun";
|
|
486
|
-
import { BunHttpServer } from "alchemy
|
|
486
|
+
import { BunHttpServer } from "alchemy/Http";
|
|
487
487
|
const HttpServer = BunHttpServer;
|
|
488
488
|
`
|
|
489
489
|
: `
|
|
490
490
|
import { NodeServices } from "@effect/platform-node";
|
|
491
|
-
import { NodeHttpServer } from "alchemy
|
|
491
|
+
import { NodeHttpServer } from "alchemy/Http";
|
|
492
492
|
const HttpServer = NodeHttpServer;
|
|
493
493
|
`
|
|
494
494
|
}
|
|
495
|
-
import { Stack } from "alchemy
|
|
495
|
+
import { Stack } from "alchemy/Stack";
|
|
496
496
|
import * as Effect from "effect/Effect";
|
|
497
497
|
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
498
498
|
import * as Layer from "effect/Layer";
|
|
@@ -5,10 +5,8 @@ import {
|
|
|
5
5
|
toCloudflareFetcher,
|
|
6
6
|
type Fetcher,
|
|
7
7
|
} from "../Fetcher.ts";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
DurableObjectState,
|
|
11
|
-
} from "../Workers/DurableObjectNamespace.ts";
|
|
8
|
+
import { DurableObjectNamespace } from "../Workers/DurableObjectNamespace.ts";
|
|
9
|
+
import { DurableObjectState } from "../Workers/DurableObjectState.ts";
|
|
12
10
|
import { Worker } from "../Workers/Worker.ts";
|
|
13
11
|
import type { Container } from "./Container.ts";
|
|
14
12
|
import type { ContainerApplication } from "./ContainerApplication.ts";
|
|
@@ -6,7 +6,7 @@ import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
|
|
|
6
6
|
import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
7
7
|
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
|
|
8
8
|
import { type Fetcher } from "../Fetcher.ts";
|
|
9
|
-
import { DurableObjectState } from "../Workers/
|
|
9
|
+
import { DurableObjectState } from "../Workers/DurableObjectState.ts";
|
|
10
10
|
import { type Container, ContainerError } from "./Container.ts";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -10,7 +10,6 @@ import * as Containers from "./Container/index.ts";
|
|
|
10
10
|
import * as D1 from "./D1/index.ts";
|
|
11
11
|
import * as KV from "./KV/index.ts";
|
|
12
12
|
import * as R2 from "./R2/index.ts";
|
|
13
|
-
import * as Assets from "./Workers/Assets.ts";
|
|
14
13
|
import * as Workers from "./Workers/index.ts";
|
|
15
14
|
import * as Workflows from "./Workers/Workflow.ts";
|
|
16
15
|
|
|
@@ -60,11 +59,7 @@ export const providers = () =>
|
|
|
60
59
|
),
|
|
61
60
|
),
|
|
62
61
|
Layer.provideMerge(
|
|
63
|
-
Layer.mergeAll(
|
|
64
|
-
Assets.AssetsProvider(),
|
|
65
|
-
Build.CommandProvider(),
|
|
66
|
-
RandomProvider(),
|
|
67
|
-
),
|
|
62
|
+
Layer.mergeAll(Build.CommandProvider(), RandomProvider()),
|
|
68
63
|
),
|
|
69
64
|
Layer.provideMerge(
|
|
70
65
|
Layer.mergeAll(
|
|
@@ -6,7 +6,7 @@ import { createPhysicalName } from "../../PhysicalName.ts";
|
|
|
6
6
|
import * as Provider from "../../Provider.ts";
|
|
7
7
|
import { Resource } from "../../Resource.ts";
|
|
8
8
|
import { Account } from "../Account.ts";
|
|
9
|
-
import type
|
|
9
|
+
import type * as Cloudflare from "../Providers.ts";
|
|
10
10
|
import { R2BucketBinding } from "./R2BucketBinding.ts";
|
|
11
11
|
|
|
12
12
|
export type R2BucketName = string;
|
|
@@ -44,7 +44,7 @@ export type R2Bucket = Resource<
|
|
|
44
44
|
accountId: string;
|
|
45
45
|
},
|
|
46
46
|
never,
|
|
47
|
-
Providers
|
|
47
|
+
Cloudflare.Providers
|
|
48
48
|
>;
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -3,10 +3,17 @@ import { Command, type CommandProps } from "../../Build/Command.ts";
|
|
|
3
3
|
import type { InputProps } from "../../Input.ts";
|
|
4
4
|
import * as Namespace from "../../Namespace.ts";
|
|
5
5
|
import type { AssetsConfig } from "../Workers/Assets.ts";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Worker,
|
|
8
|
+
type WorkerAssetsConfig,
|
|
9
|
+
type WorkerBindingProps,
|
|
10
|
+
type WorkerProps,
|
|
11
|
+
} from "../Workers/Worker.ts";
|
|
7
12
|
|
|
8
|
-
export interface StaticSiteProps
|
|
9
|
-
extends
|
|
13
|
+
export interface StaticSiteProps<Bindings extends WorkerBindingProps = {}>
|
|
14
|
+
extends
|
|
15
|
+
Omit<WorkerProps<Bindings, WorkerAssetsConfig>, "assets">,
|
|
16
|
+
Omit<CommandProps, "env"> {
|
|
10
17
|
/**
|
|
11
18
|
* Optional configuration for static asset routing behavior.
|
|
12
19
|
* Supports `runWorkerFirst`, `htmlHandling`, `notFoundHandling`, etc.
|
|
@@ -76,12 +83,21 @@ export type StaticSite = ReturnType<typeof StaticSite>;
|
|
|
76
83
|
* });
|
|
77
84
|
* ```
|
|
78
85
|
*/
|
|
79
|
-
export const StaticSite =
|
|
86
|
+
export const StaticSite = <const Bindings extends WorkerBindingProps = {}>(
|
|
87
|
+
id: string,
|
|
88
|
+
props: InputProps<StaticSiteProps<Bindings>>,
|
|
89
|
+
) =>
|
|
80
90
|
Effect.gen(function* () {
|
|
81
91
|
// TODO(sam): local dev/hmr support?
|
|
82
|
-
const build = yield* Command("Build",
|
|
92
|
+
const build = yield* Command("Build", {
|
|
93
|
+
command: props.command,
|
|
94
|
+
cwd: props.cwd,
|
|
95
|
+
memo: props.memo,
|
|
96
|
+
outdir: props.outdir,
|
|
97
|
+
env: props.env,
|
|
98
|
+
});
|
|
83
99
|
|
|
84
|
-
const worker = yield* Worker("Worker", {
|
|
100
|
+
const worker = yield* Worker<Bindings, WorkerAssetsConfig>("Worker", {
|
|
85
101
|
...props,
|
|
86
102
|
assets: {
|
|
87
103
|
path: build.outdir,
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import type { InputProps } from "../../Input.ts";
|
|
2
1
|
import type { MemoOptions } from "../../Build/Memo.ts";
|
|
3
|
-
import {
|
|
2
|
+
import type { InputProps } from "../../Input.ts";
|
|
3
|
+
import {
|
|
4
|
+
Worker,
|
|
5
|
+
type WorkerAssetsConfig,
|
|
6
|
+
type WorkerBindingProps,
|
|
7
|
+
type WorkerProps,
|
|
8
|
+
} from "../Workers/Worker.ts";
|
|
4
9
|
|
|
5
|
-
export interface ViteProps
|
|
10
|
+
export interface ViteProps<
|
|
11
|
+
Bindings extends WorkerBindingProps = {},
|
|
12
|
+
> extends Omit<WorkerProps<Bindings>, "vite" | "main"> {
|
|
6
13
|
/**
|
|
7
14
|
* Root directory passed to Vite's `root` option.
|
|
8
15
|
* Defaults to the current working directory (`process.cwd()`).
|
|
@@ -99,8 +106,11 @@ export interface ViteProps extends Omit<WorkerProps, "vite" | "main"> {
|
|
|
99
106
|
* });
|
|
100
107
|
* ```
|
|
101
108
|
*/
|
|
102
|
-
export const Vite =
|
|
103
|
-
|
|
109
|
+
export const Vite = <const Bindings extends WorkerBindingProps = {}>(
|
|
110
|
+
id: string,
|
|
111
|
+
props: InputProps<ViteProps<Bindings>> = {},
|
|
112
|
+
) =>
|
|
113
|
+
Worker<Bindings, WorkerAssetsConfig>(id, {
|
|
104
114
|
...props,
|
|
105
115
|
main: undefined!,
|
|
106
116
|
vite: {
|