Skip to content

Commit 1d08d19

Browse files
committed
fix: re-work simpler types for plan and apply
1 parent 6adca3c commit 1d08d19

File tree

12 files changed

+92
-223
lines changed

12 files changed

+92
-223
lines changed
Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
import {
2-
Capability,
3-
Policy,
4-
Provider,
5-
Runtime,
6-
type RuntimeHandler,
7-
} from "@alchemy.run/effect";
1+
import { Capability, Policy, Runtime } from "@alchemy.run/effect";
82

9-
import type { Context } from "aws-lambda";
103
export type { Context } from "aws-lambda";
114

125
export interface FunctionProps<Req = any> {
@@ -30,17 +23,7 @@ export type FunctionAttr<Props extends FunctionProps = FunctionProps> = {
3023
};
3124
};
3225

33-
export interface Function<
34-
Handler extends
35-
| RuntimeHandler<[event: any, context: Context]>
36-
| unknown = unknown,
37-
Props extends FunctionProps<RuntimeHandler.Caps<Handler>> | unknown = unknown,
38-
> extends Runtime<"AWS.Lambda.Function", Handler, Props> {
39-
readonly Provider: FunctionProvider;
40-
readonly Instance: Function<this["handler"], this["props"]>;
41-
26+
export interface Function extends Runtime<"AWS.Lambda.Function"> {
4227
readonly attr: FunctionAttr<Extract<this["props"], FunctionProps>>;
4328
}
4429
export const Function = Runtime("AWS.Lambda.Function")<Function>();
45-
46-
export type FunctionProvider = Provider<Function>;

@alchemy.run/effect-aws/src/lambda/serve.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@ export const serve =
2323
},
2424
) =>
2525
<const Props extends Lambda.FunctionProps<Req>>(props: Props) =>
26-
Lambda.Function(id, { handle: fetch })(props);
26+
Lambda.Function(id, { handle: fetch })({
27+
...props,
28+
url: true,
29+
});

@alchemy.run/effect-example/alchemy.run.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import * as AlchemyCLI from "@alchemy.run/effect-cli";
44
import { FetchHttpClient } from "@effect/platform";
55
import { NodeContext } from "@effect/platform-node";
66
import * as Effect from "effect/Effect";
7-
import { MyMonitor } from "./src/component.ts";
8-
import { Api, Consumer } from "./src/index.ts";
7+
import { Api } from "./src/index.ts";
98

109
const plan = Alchemy.plan({
11-
phase: process.argv.includes("--destroy") ? "destroy" : "update",
12-
resources: [Api, Consumer, MyMonitor],
10+
// phase: process.argv.includes("--destroy") ? "destroy" : "update",
11+
phase: "update",
12+
services: [Api],
1313
});
1414

1515
const stack = await plan.pipe(
@@ -25,3 +25,7 @@ const stack = await plan.pipe(
2525
Effect.tap((stack) => Effect.log(stack?.Api.functionUrl)),
2626
Effect.runPromise,
2727
);
28+
29+
if (stack) {
30+
// Effect.log(stack?.Api.functionUrl);
31+
}

@alchemy.run/effect-example/src/api.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,6 @@ import * as Effect from "effect/Effect";
55
import * as S from "effect/Schema";
66
import { Message, Messages } from "./messages.ts";
77

8-
const ___ = Lambda.serve("Api", {
9-
fetch: Effect.fn(function* (event) {
10-
const msg = yield* S.validate(Message)(event.body).pipe(
11-
Effect.catchAll(Effect.die),
12-
);
13-
yield* SQS.sendMessage(Messages, msg).pipe(
14-
Effect.catchAll(() => Effect.void),
15-
);
16-
return {
17-
body: JSON.stringify(null),
18-
};
19-
}),
20-
})({
21-
main: import.meta.filename,
22-
bindings: $(SQS.SendMessage(Messages)),
23-
});
24-
258
export class Api extends Lambda.serve("Api", {
269
fetch: Effect.fn(function* (event) {
2710
const msg = yield* S.validate(Message)(event.body).pipe(

@alchemy.run/effect-example/src/messages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export class Message extends S.Class<Message>("Message")({
66
value: S.String,
77
}) {}
88

9-
export class Messages extends SQS.Queue("messages", {
9+
export class Messages extends SQS.Queue("Messages", {
1010
fifo: true,
1111
schema: Message,
1212
}) {}

@alchemy.run/effect/src/bind.ts

Lines changed: 0 additions & 100 deletions
This file was deleted.

@alchemy.run/effect/src/binding.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,20 @@ export type Binding<
2121
> = {
2222
runtime: Run;
2323
capability: Cap;
24-
tag: BindingTag<Run, Cap, Tag>;
24+
tag: Bind<Run, Cap, Tag>;
2525
};
2626

27-
export interface BindingTag<
28-
Run extends Runtime,
27+
/** Tag for a Service that can bind a Capability to a Runtime */
28+
export interface Bind<
29+
F extends Runtime,
2930
Cap extends Capability,
3031
Tag extends string,
3132
> extends Context.Tag<
32-
`${Run["type"]}(${Cap["type"]}, ${Tag})`,
33+
`${F["type"]}(${Cap["type"]}, ${Tag})`,
3334
BindingService<
34-
Run,
35+
F,
3536
Extract<Extract<Cap["resource"], Resource>["parent"], Resource>,
36-
Run["props"]
37+
F["props"]
3738
>
3839
> {
3940
/** @internal phantom */
@@ -81,7 +82,7 @@ export interface BindingDeclaration<
8182
): Layer<Tag, Err, Req>;
8283
succeed(
8384
service: BindingService<Run["props"], Parameters<F>[0], Parameters<F>[1]>,
84-
): Layer<BindingService<Run["props"], Parameters<F>[0], Parameters<F>[1]>>;
85+
): Layer<Tag>;
8586
};
8687
}
8788

@alchemy.run/effect/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
export * from "./app.ts";
22
export * from "./apply.ts";
33
export * from "./approve.ts";
4-
export * from "./bind.ts";
54
export * from "./binding.ts";
65
export * from "./capability.ts";
76
export * from "./destroy.ts";
@@ -13,4 +12,5 @@ export * from "./policy.ts";
1312
export * from "./provider.ts";
1413
export * from "./resource.ts";
1514
export * from "./runtime.ts";
15+
export * from "./service.ts";
1616
export * as State from "./state.ts";

@alchemy.run/effect/src/plan.ts

Lines changed: 32 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import * as Data from "effect/Data";
22
import * as Effect from "effect/Effect";
33
import util from "node:util";
4-
import { isBound, type Bound } from "./bind.ts";
54
import type { Capability, SerializedCapability } from "./capability.ts";
6-
import type { Phase } from "./phase.ts";
5+
import type { Instance } from "./policy.ts";
76
import { Provider, type ProviderService } from "./provider.ts";
87
import type { Resource } from "./resource.ts";
9-
import type { Runtime } from "./runtime.ts";
8+
import type { Service } from "./service.ts";
109
import { State, type ResourceState } from "./state.ts";
1110

1211
export type PlanError = never;
@@ -139,65 +138,42 @@ export type Replace<R extends Resource> = {
139138
deleteFirst?: boolean;
140139
};
141140

142-
type PlanNode = Bound<any> | Resource;
143-
type PlanGraph = {
144-
[id in string]: PlanNode;
145-
};
146-
type PlanGraphEffect = Effect.Effect<PlanGraph, never, unknown>;
147-
148-
type ApplyAll<
149-
Subgraphs extends PlanGraphEffect[],
150-
Accum extends Record<string, CRUD> = {},
151-
> = Subgraphs extends [
152-
infer Head extends PlanGraphEffect,
153-
...infer Tail extends PlanGraphEffect[],
154-
]
155-
? ApplyAll<
156-
Tail,
157-
Accum & {
158-
[id in keyof Effect.Effect.Success<Head>]: _Apply<
159-
Extract<Effect.Effect.Success<Head>[id], PlanNode>
160-
>;
161-
}
162-
>
163-
: Accum;
164-
165-
type _Apply<Item extends PlanNode> =
166-
Item extends Bound<infer Run extends Runtime<string, any, any>>
167-
? Apply<Run>
168-
: Item extends Resource
169-
? Apply<Item>
170-
: never;
171-
172-
type DerivePlan<
173-
P extends Phase = Phase,
174-
Resources extends PlanGraphEffect[] = PlanGraphEffect[],
175-
> = P extends "update"
176-
?
177-
| {
178-
[k in keyof ApplyAll<Resources>]: ApplyAll<Resources>[k];
179-
}
180-
| {
181-
[k in Exclude<string, keyof ApplyAll<Resources>>]: Delete<Resource>;
182-
}
183-
: {
184-
[k in Exclude<string, keyof ApplyAll<Resources>>]: Delete<Resource>;
185-
};
186-
187141
export type Plan = {
188142
[id in string]: CRUD;
189143
};
190144

191145
export const plan = <
192146
const Phase extends "update" | "destroy",
193-
const Resources extends PlanGraphEffect[],
147+
const Services extends Service[],
194148
>({
195149
phase,
196-
resources,
150+
services,
197151
}: {
198152
phase: Phase;
199-
resources: Resources;
153+
services: Services;
200154
}) => {
155+
type ServiceIDs = Services[number]["id"];
156+
type ServiceHosts = {
157+
[ID in ServiceIDs]: Extract<Services[number], Service<Extract<ID, string>>>;
158+
};
159+
160+
type UpstreamTags = {
161+
[ID in ServiceIDs]: ServiceHosts[ID]["props"]["bindings"]["tags"][number];
162+
}[ServiceIDs];
163+
type UpstreamResources = {
164+
[ID in ServiceIDs]: Extract<
165+
ServiceHosts[ID]["props"]["bindings"]["capabilities"][number]["resource"],
166+
Resource
167+
>;
168+
}[ServiceIDs];
169+
type Graph = {
170+
[ID in ServiceIDs]: Apply<Extract<Instance<ServiceHosts[ID]>, Resource>>;
171+
} & {
172+
[ID in UpstreamResources["id"]]: Apply<
173+
Extract<UpstreamResources, { id: ID }>
174+
>;
175+
};
176+
201177
return Effect.gen(function* () {
202178
const state = yield* State;
203179

@@ -228,7 +204,7 @@ export const plan = <
228204
const updates = (
229205
phase === "update"
230206
? yield* Effect.all(
231-
resources.map((resource) =>
207+
services.map((resource) =>
232208
Effect.flatMap(
233209
resource,
234210
Effect.fn(function* (subgraph: {
@@ -405,9 +381,11 @@ export const plan = <
405381
{} as any,
406382
);
407383
}) as Effect.Effect<
408-
DerivePlan<Phase, Resources>,
384+
{
385+
[ID in keyof Graph]: Graph[ID];
386+
},
409387
never,
410-
Effect.Effect.Context<Resources[number]> | State
388+
UpstreamTags | State
411389
>;
412390
};
413391

@alchemy.run/effect/src/policy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function Policy(...bindings: AnyBinding[]) {
4646
export const declare = <S extends Capability>() =>
4747
Effect.gen(function* () {}) as Effect.Effect<void, never, S>;
4848

49-
type Instance<T> = { id: string } extends T
49+
export type Instance<T> = { id: string } extends T
5050
? T
5151
: T extends new (...args: any) => infer I
5252
? I

0 commit comments

Comments
 (0)