1import * as AWS from "alchemy/AWS";
2import * as Effect from "effect/Effect";
3import { OrdersTable } from "./infra.ts";
4
5const seedOrders = [
6 { id: "1001", customer: "ada", total: 4250 },
7 { id: "1002", customer: "grace", total: 1799 },
8 { id: "1003", customer: "linus", total: 999 },
9];
10
11/**
12 * A one-shot `AWS.ECS.Task` in the INLINE EFFECT form: props + an init
13 * Effect whose impl returns `{ run }` — a one-shot entry that executes to
14 * completion when the container starts, after which the container exits.
15 *
16 * The Effect program is bundled into a generated image `FROM image`
17 * (`main: import.meta.url` names this module as the entrypoint). The
18 * `AWS.DynamoDB.PutItem` binding injects the table's name into the
19 * container environment and grants `dynamodb:PutItem` on the task role.
20 *
21 * Nothing runs this task on deploy — it is the target of the
22 * `AWS.ECS.RunTask(cluster, SeedTask)` binding the `Api` service exposes at
23 * `POST /api/seed`. A task definition is cluster-independent (mirroring
24 * `AWS::ECS::TaskDefinition`), so the launch cluster is declared where the
25 * launch is bound, not here.
26 */
27export default AWS.ECS.Task(
28 "SeedTask",
29 {
30 main: import.meta.url,
31 // Docker Hub's `oven/bun`; the public.ecr.aws default mirror
32 // rate-limits anonymous pulls during local builds.
33 image: "oven/bun:1",
34 cpu: 256,
35 memory: 512,
36 // Build/run on ARM64 so an image built on an Apple Silicon host matches
37 // the Fargate runtime architecture (Graviton).
38 runtimePlatform: {
39 cpuArchitecture: "ARM64",
40 operatingSystemFamily: "LINUX",
41 },
42 },
43 Effect.gen(function* () {
44 const table = yield* OrdersTable;
45 const putItem = yield* AWS.DynamoDB.PutItem(table);
46
47 return {
48 // One-shot entry: seed the table, log, exit 0.
49 run: Effect.gen(function* () {
50 yield* Effect.forEach(
51 seedOrders,
52 (order) =>
53 putItem({
54 Item: {
55 pk: { S: `order#${order.id}` },
56 customer: { S: order.customer },
57 total: { N: String(order.total) },
58 },
59 }),
60 { discard: true },
61 );
62 yield* Effect.log(`seeded ${seedOrders.length} orders`);
63 }).pipe(Effect.orDie),
64 };
65 }).pipe(Effect.provide(AWS.DynamoDB.PutItemHttp)),
66);