effect-inngest 0.1.3 → 0.3.0-beta.0
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/README.md +89 -67
- package/dist/Client.d.ts +76 -28
- package/dist/Client.js +92 -30
- package/dist/Event.d.ts +43 -0
- package/dist/Event.js +46 -0
- package/dist/Events.d.ts +48 -76
- package/dist/Events.js +18 -23
- package/dist/Function.d.ts +46 -19
- package/dist/Function.js +32 -22
- package/dist/Group.d.ts +19 -8
- package/dist/Group.js +30 -72
- package/dist/HttpApi.d.ts +51 -56
- package/dist/HttpApi.js +38 -21
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -3
- package/dist/internal/checkpoint/Config.d.ts +10 -0
- package/dist/internal/checkpoint/Config.js +29 -0
- package/dist/internal/checkpoint/Error.d.ts +11 -0
- package/dist/internal/checkpoint/Error.js +8 -0
- package/dist/internal/checkpoint/State.d.ts +1 -0
- package/dist/internal/checkpoint/State.js +54 -0
- package/dist/internal/checkpoint.d.ts +2 -0
- package/dist/internal/codec/EventPayload.d.ts +6 -0
- package/dist/internal/codec/EventPayload.js +60 -0
- package/dist/internal/codec/StepResult.js +55 -0
- package/dist/internal/domain/ExecutionInput.d.ts +40 -0
- package/dist/internal/domain/ExecutionInput.js +57 -0
- package/dist/internal/domain/ExecutionSuspension.d.ts +34 -0
- package/dist/internal/domain/ExecutionSuspension.js +64 -0
- package/dist/internal/domain/FunctionDefinition.js +13 -0
- package/dist/internal/domain/Memo.d.ts +22 -0
- package/dist/internal/domain/Memo.js +18 -0
- package/dist/internal/domain/StepCommand.d.ts +79 -0
- package/dist/internal/domain/StepCommand.js +124 -0
- package/dist/internal/domain/StepInfo.d.ts +12 -0
- package/dist/internal/domain/StepInfo.js +10 -0
- package/dist/internal/domain/StepInput.d.ts +10 -0
- package/dist/internal/driver.js +15 -114
- package/dist/internal/errors.d.ts +21 -48
- package/dist/internal/errors.js +9 -44
- package/dist/internal/execution/CheckpointRun.js +25 -0
- package/dist/internal/execution/ExecutionFailure.js +19 -0
- package/dist/internal/execution/ExecutionHeaders.js +58 -0
- package/dist/internal/execution/ExecutionResponse.js +68 -0
- package/dist/internal/execution/ExecutionResult.js +56 -0
- package/dist/internal/execution/ExecutionScope.js +30 -0
- package/dist/internal/execution/HandlerRun.js +16 -0
- package/dist/internal/handler.d.ts +5 -16
- package/dist/internal/handler.js +128 -96
- package/dist/internal/protocol.d.ts +143 -1
- package/dist/internal/protocol.js +333 -138
- package/dist/internal/runtime/CheckpointContext.js +5 -0
- package/dist/internal/runtime/HandlerContext.d.ts +13 -0
- package/dist/internal/runtime/HandlerContext.js +19 -0
- package/dist/internal/runtime/HandlerFiberScope.d.ts +10 -0
- package/dist/internal/runtime/HandlerFiberScope.js +5 -0
- package/dist/internal/runtime/StepCommandBus.d.ts +27 -0
- package/dist/internal/runtime/StepCommandBus.js +76 -0
- package/dist/internal/runtime/StepIdentity.d.ts +27 -0
- package/dist/internal/runtime/StepIdentity.js +46 -0
- package/dist/internal/runtime/StepTools.d.ts +83 -0
- package/dist/internal/runtime/StepTools.js +76 -0
- package/dist/internal/runtime/steps/InvokeStep.js +43 -0
- package/dist/internal/runtime/steps/SendEventStep.js +46 -0
- package/dist/internal/runtime/steps/SleepStep.js +22 -0
- package/dist/internal/runtime/steps/SleepUntilStep.js +22 -0
- package/dist/internal/runtime/steps/StepRun.js +48 -0
- package/dist/internal/runtime/steps/WaitForEventStep.js +27 -0
- package/dist/internal/serve/HttpApp.js +71 -0
- package/dist/internal/serve/Request.js +23 -0
- package/dist/internal/serve/Signature.d.ts +11 -0
- package/dist/internal/serve/Signature.js +123 -0
- package/dist/internal/wire/Duration.js +19 -0
- package/dist/internal/wire/Timestamp.js +14 -0
- package/package.json +34 -22
- package/src/Client.ts +269 -91
- package/src/Event.ts +107 -0
- package/src/Events.ts +50 -30
- package/src/Function.ts +102 -46
- package/src/Group.ts +56 -108
- package/src/HttpApi.ts +40 -30
- package/src/index.ts +21 -11
- package/src/internal/checkpoint/Config.ts +74 -0
- package/src/internal/checkpoint/Error.ts +6 -0
- package/src/internal/checkpoint/State.ts +107 -0
- package/src/internal/checkpoint.ts +3 -0
- package/src/internal/codec/EventPayload.ts +98 -0
- package/src/internal/codec/StepResult.ts +95 -0
- package/src/internal/domain/ExecutionInput.ts +66 -0
- package/src/internal/domain/ExecutionSuspension.ts +79 -0
- package/src/internal/domain/FunctionDefinition.ts +30 -0
- package/src/internal/domain/Memo.ts +28 -0
- package/src/internal/domain/StepCommand.ts +166 -0
- package/src/internal/domain/StepInfo.ts +8 -0
- package/src/internal/domain/StepInput.ts +10 -0
- package/src/internal/driver.ts +27 -185
- package/src/internal/errors.ts +14 -108
- package/src/internal/execution/CheckpointRun.ts +33 -0
- package/src/internal/execution/ExecutionFailure.ts +19 -0
- package/src/internal/execution/ExecutionHeaders.ts +86 -0
- package/src/internal/execution/ExecutionResponse.ts +79 -0
- package/src/internal/execution/ExecutionResult.ts +57 -0
- package/src/internal/execution/ExecutionScope.ts +41 -0
- package/src/internal/execution/HandlerRun.ts +38 -0
- package/src/internal/handler.ts +222 -172
- package/src/internal/protocol.ts +289 -78
- package/src/internal/runtime/CheckpointContext.ts +7 -0
- package/src/internal/runtime/HandlerContext.ts +21 -0
- package/src/internal/runtime/HandlerFiberScope.ts +9 -0
- package/src/internal/runtime/StepCommandBus.ts +129 -0
- package/src/internal/runtime/StepIdentity.ts +67 -0
- package/src/internal/runtime/StepTools.ts +161 -0
- package/src/internal/runtime/steps/InvokeStep.ts +71 -0
- package/src/internal/runtime/steps/SendEventStep.ts +67 -0
- package/src/internal/runtime/steps/SleepStep.ts +34 -0
- package/src/internal/runtime/steps/SleepUntilStep.ts +34 -0
- package/src/internal/runtime/steps/StepRun.ts +95 -0
- package/src/internal/runtime/steps/WaitForEventStep.ts +55 -0
- package/src/internal/serve/HttpApp.ts +123 -0
- package/src/internal/serve/Request.ts +27 -0
- package/src/internal/serve/Signature.ts +170 -0
- package/src/internal/wire/Duration.ts +31 -0
- package/src/internal/wire/Timestamp.ts +11 -0
- package/dist/_virtual/rolldown_runtime.js +0 -18
- package/dist/internal/constants.js +0 -15
- package/dist/internal/driver.d.ts +0 -5
- package/dist/internal/helpers.js +0 -44
- package/dist/internal/interrupts.d.ts +0 -2
- package/dist/internal/interrupts.js +0 -45
- package/dist/internal/memo.js +0 -56
- package/dist/internal/signature.d.ts +0 -18
- package/dist/internal/signature.js +0 -97
- package/dist/internal/step.d.ts +0 -59
- package/dist/internal/step.js +0 -192
- package/src/internal/constants.ts +0 -11
- package/src/internal/helpers.ts +0 -58
- package/src/internal/interrupts.ts +0 -62
- package/src/internal/memo.ts +0 -73
- package/src/internal/signature.ts +0 -158
- package/src/internal/step.ts +0 -394
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StepInfo } from "../domain/StepInfo.js";
|
|
2
|
+
import { StepInput } from "../domain/StepInput.js";
|
|
3
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
4
|
+
|
|
5
|
+
//#region src/internal/runtime/StepIdentity.d.ts
|
|
6
|
+
declare const StepReservation_base: Schema.Class<StepReservation, Schema.Struct<{
|
|
7
|
+
readonly id: Schema.String;
|
|
8
|
+
readonly name: Schema.String;
|
|
9
|
+
readonly effectiveId: Schema.String;
|
|
10
|
+
readonly sequence: Schema.Number;
|
|
11
|
+
readonly rawStepArg: Schema.Unknown;
|
|
12
|
+
}>, {}>;
|
|
13
|
+
declare class StepReservation extends StepReservation_base {}
|
|
14
|
+
declare const StepIdentity_base: Context.ServiceClass<StepIdentity, "effect-inngest/internal/runtime/StepIdentity", {
|
|
15
|
+
readonly reserve: (input: StepInput) => StepReservation;
|
|
16
|
+
readonly resolve: (reservation: StepReservation) => Effect.Effect<StepInfo>;
|
|
17
|
+
}> & {
|
|
18
|
+
readonly make: Effect.Effect<{
|
|
19
|
+
readonly reserve: (input: StepInput) => StepReservation;
|
|
20
|
+
readonly resolve: (reservation: StepReservation) => Effect.Effect<StepInfo>;
|
|
21
|
+
}, never, never>;
|
|
22
|
+
};
|
|
23
|
+
declare class StepIdentity extends StepIdentity_base {
|
|
24
|
+
static readonly layer: Layer.Layer<StepIdentity, never, never>;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { StepIdentity };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { StepInfo } from "../domain/StepInfo.js";
|
|
2
|
+
import { Context, Effect, Encoding, Layer, MutableHashMap, MutableRef, Number, Option, Predicate, Schema } from "effect";
|
|
3
|
+
//#region src/internal/runtime/StepIdentity.ts
|
|
4
|
+
var StepReservation = class extends Schema.Class("effect-inngest/internal/runtime/StepReservation")({
|
|
5
|
+
id: Schema.String,
|
|
6
|
+
name: Schema.String,
|
|
7
|
+
effectiveId: Schema.String,
|
|
8
|
+
sequence: Schema.Number,
|
|
9
|
+
rawStepArg: Schema.Unknown
|
|
10
|
+
}) {};
|
|
11
|
+
var StepIdentity = class extends Context.Service()("effect-inngest/internal/runtime/StepIdentity", { make: Effect.gen(function* () {
|
|
12
|
+
const counts = MutableHashMap.empty();
|
|
13
|
+
const sequence = MutableRef.make(0);
|
|
14
|
+
const textEncoder = new TextEncoder();
|
|
15
|
+
return {
|
|
16
|
+
reserve: (input) => {
|
|
17
|
+
const id = Predicate.isString(input) ? input : input.id;
|
|
18
|
+
const name = Predicate.isString(input) ? input : input.name ?? input.id;
|
|
19
|
+
const currentSequence = MutableRef.getAndUpdate(sequence, Number.increment);
|
|
20
|
+
const repeatIndex = Option.getOrElse(MutableHashMap.get(counts, id), () => 0);
|
|
21
|
+
MutableHashMap.set(counts, id, Number.increment(repeatIndex));
|
|
22
|
+
const effectiveId = repeatIndex > 0 ? `${id}:${repeatIndex}` : id;
|
|
23
|
+
return StepReservation.make({
|
|
24
|
+
id,
|
|
25
|
+
name,
|
|
26
|
+
effectiveId,
|
|
27
|
+
sequence: currentSequence,
|
|
28
|
+
rawStepArg: input
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
resolve: Effect.fnUntraced(function* (reservation) {
|
|
32
|
+
const buffer = yield* Effect.promise(() => globalThis.crypto.subtle.digest("SHA-1", textEncoder.encode(reservation.effectiveId)));
|
|
33
|
+
const hash = Encoding.encodeHex(new Uint8Array(buffer));
|
|
34
|
+
return StepInfo.make({
|
|
35
|
+
id: reservation.id,
|
|
36
|
+
name: reservation.name,
|
|
37
|
+
hash,
|
|
38
|
+
rawStepArg: reservation.rawStepArg
|
|
39
|
+
});
|
|
40
|
+
})
|
|
41
|
+
};
|
|
42
|
+
}) }) {
|
|
43
|
+
static layer = Layer.effect(this, this.make);
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
export { StepIdentity };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { InngestClient, InngestConfig } from "../../Client.js";
|
|
2
|
+
import { EventType } from "../../Event.js";
|
|
3
|
+
import { InngestFunction } from "../../Function.js";
|
|
4
|
+
import { CurrentExecutionInput } from "../domain/ExecutionInput.js";
|
|
5
|
+
import { EventSchema } from "../codec/EventPayload.js";
|
|
6
|
+
import { SendEventError, StepError } from "../errors.js";
|
|
7
|
+
import { StepInput } from "../domain/StepInput.js";
|
|
8
|
+
import { HandlerFiberScope } from "./HandlerFiberScope.js";
|
|
9
|
+
import { StepCommandBus } from "./StepCommandBus.js";
|
|
10
|
+
import { StepIdentity } from "./StepIdentity.js";
|
|
11
|
+
import { Context, Duration, Effect, Layer, Option, Schema } from "effect";
|
|
12
|
+
|
|
13
|
+
//#region src/internal/runtime/StepTools.d.ts
|
|
14
|
+
type JsonSchema<A = unknown> = Schema.Codec<A, unknown, never, never>;
|
|
15
|
+
interface RunOptions<S extends JsonSchema> {
|
|
16
|
+
readonly schema: S;
|
|
17
|
+
}
|
|
18
|
+
interface WaitForEventOptions {
|
|
19
|
+
readonly timeout: Duration.Input;
|
|
20
|
+
readonly if?: string;
|
|
21
|
+
}
|
|
22
|
+
interface InvokeOptionsBase<F extends InngestFunction.Any> {
|
|
23
|
+
readonly function: F;
|
|
24
|
+
readonly user?: Record<string, unknown>;
|
|
25
|
+
readonly v?: string;
|
|
26
|
+
readonly timeout?: Duration.Input;
|
|
27
|
+
}
|
|
28
|
+
type InvokeOptions<F extends InngestFunction.Any> = [InngestFunction.EventPayload<F>] extends [never] ? InvokeOptionsBase<F> : InvokeOptionsBase<F> & {
|
|
29
|
+
readonly data: InngestFunction.EventPayload<F>;
|
|
30
|
+
};
|
|
31
|
+
interface Run {
|
|
32
|
+
<Err, R>(id: StepInput, effect: Effect.Effect<void, Err, R>): Effect.Effect<void, StepError | Err, R>;
|
|
33
|
+
<S extends JsonSchema, Err, R>(id: StepInput, effect: Effect.Effect<Schema.Schema.Type<S>, Err, R>, options: RunOptions<S>): Effect.Effect<Schema.Schema.Type<S>, StepError | Err, R>;
|
|
34
|
+
}
|
|
35
|
+
interface Sleep {
|
|
36
|
+
(id: StepInput, duration: Duration.Input): Effect.Effect<void>;
|
|
37
|
+
}
|
|
38
|
+
interface SleepUntil {
|
|
39
|
+
(id: StepInput, timestamp: Date | number | string): Effect.Effect<void>;
|
|
40
|
+
}
|
|
41
|
+
interface WaitForEvent {
|
|
42
|
+
<E extends EventSchema>(id: StepInput, event: E, options: WaitForEventOptions): Effect.Effect<Option.Option<EventType<E>>, StepError>;
|
|
43
|
+
}
|
|
44
|
+
interface Invoke {
|
|
45
|
+
<F extends InngestFunction.Any>(id: StepInput, options: InvokeOptions<F>): Effect.Effect<InngestFunction.Success<F>, StepError>;
|
|
46
|
+
}
|
|
47
|
+
interface OutgoingEvent {
|
|
48
|
+
readonly name: string;
|
|
49
|
+
readonly data: unknown;
|
|
50
|
+
}
|
|
51
|
+
interface SendEvent {
|
|
52
|
+
(id: StepInput, payload: OutgoingEvent | ReadonlyArray<OutgoingEvent>): Effect.Effect<{
|
|
53
|
+
readonly ids: ReadonlyArray<string>;
|
|
54
|
+
}, SendEventError, InngestClient>;
|
|
55
|
+
}
|
|
56
|
+
declare namespace StepTools {
|
|
57
|
+
interface Service {
|
|
58
|
+
readonly run: Run;
|
|
59
|
+
readonly sleep: Sleep;
|
|
60
|
+
readonly sleepUntil: SleepUntil;
|
|
61
|
+
readonly waitForEvent: WaitForEvent;
|
|
62
|
+
readonly invoke: Invoke;
|
|
63
|
+
readonly sendEvent: SendEvent;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
declare const StepTools_base: Context.ServiceClass<StepTools, "effect-inngest/internal/runtime/StepTools", StepTools.Service>;
|
|
67
|
+
declare class StepTools extends StepTools_base {
|
|
68
|
+
static readonly make: Effect.Effect<{
|
|
69
|
+
run: {
|
|
70
|
+
<Err, R>(id: StepInput, effect: Effect.Effect<void, Err, R>): Effect.Effect<void, StepError | Err, R>;
|
|
71
|
+
<S extends JsonSchema, Err, R>(id: StepInput, effect: Effect.Effect<Schema.Schema.Type<S>, Err, R>, options: RunOptions<S>): Effect.Effect<Schema.Schema.Type<S>, StepError | Err, R>;
|
|
72
|
+
};
|
|
73
|
+
sleep: Sleep;
|
|
74
|
+
sleepUntil: SleepUntil;
|
|
75
|
+
waitForEvent: WaitForEvent;
|
|
76
|
+
invoke: Invoke;
|
|
77
|
+
sendEvent: SendEvent;
|
|
78
|
+
}, never, InngestConfig | CurrentExecutionInput | StepIdentity | StepCommandBus | HandlerFiberScope>;
|
|
79
|
+
static readonly layer: Layer.Layer<StepTools, never, InngestConfig | CurrentExecutionInput | StepIdentity | StepCommandBus | HandlerFiberScope>;
|
|
80
|
+
static readonly live: Layer.Layer<StepTools, never, InngestConfig | CurrentExecutionInput | StepIdentity | HandlerFiberScope>;
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { StepTools };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { InngestConfig } from "../../Client.js";
|
|
2
|
+
import { CurrentExecutionInput } from "../domain/ExecutionInput.js";
|
|
3
|
+
import { CurrentCheckpoint } from "./CheckpointContext.js";
|
|
4
|
+
import { HandlerFiberScope } from "./HandlerFiberScope.js";
|
|
5
|
+
import { StepCommandBus } from "./StepCommandBus.js";
|
|
6
|
+
import { StepIdentity } from "./StepIdentity.js";
|
|
7
|
+
import { invoke } from "./steps/InvokeStep.js";
|
|
8
|
+
import { sendEvent } from "./steps/SendEventStep.js";
|
|
9
|
+
import { sleep } from "./steps/SleepStep.js";
|
|
10
|
+
import { sleepUntil } from "./steps/SleepUntilStep.js";
|
|
11
|
+
import { run } from "./steps/StepRun.js";
|
|
12
|
+
import { waitForEvent } from "./steps/WaitForEventStep.js";
|
|
13
|
+
import { Context, Effect, Layer, Predicate, pipe } from "effect";
|
|
14
|
+
//#region src/internal/runtime/StepTools.ts
|
|
15
|
+
var StepTools = class extends Context.Service()("effect-inngest/internal/runtime/StepTools") {
|
|
16
|
+
static make = Effect.gen(function* () {
|
|
17
|
+
const input = yield* CurrentExecutionInput;
|
|
18
|
+
const checkpoint = yield* CurrentCheckpoint;
|
|
19
|
+
const config = yield* InngestConfig;
|
|
20
|
+
const identity = yield* StepIdentity;
|
|
21
|
+
const bus = yield* StepCommandBus;
|
|
22
|
+
const handlerFiberScope = yield* HandlerFiberScope;
|
|
23
|
+
const runtime = pipe(Context.make(StepIdentity, identity), Context.add(StepCommandBus, bus), Context.add(CurrentExecutionInput, input), Context.add(CurrentCheckpoint, checkpoint), Context.add(InngestConfig, config), Context.add(HandlerFiberScope, handlerFiberScope));
|
|
24
|
+
function run$1(id, effect, options) {
|
|
25
|
+
if (Predicate.isNotUndefined(options)) return run({
|
|
26
|
+
input,
|
|
27
|
+
id: identity.reserve(id),
|
|
28
|
+
effect,
|
|
29
|
+
options
|
|
30
|
+
}).pipe(Effect.provide(runtime));
|
|
31
|
+
return run({
|
|
32
|
+
input,
|
|
33
|
+
id: identity.reserve(id),
|
|
34
|
+
effect
|
|
35
|
+
}).pipe(Effect.provide(runtime));
|
|
36
|
+
}
|
|
37
|
+
const sleep$1 = (id, duration) => sleep({
|
|
38
|
+
input,
|
|
39
|
+
id: identity.reserve(id),
|
|
40
|
+
duration
|
|
41
|
+
}).pipe(Effect.provide(runtime));
|
|
42
|
+
const sleepUntil$1 = (id, timestamp) => sleepUntil({
|
|
43
|
+
input,
|
|
44
|
+
id: identity.reserve(id),
|
|
45
|
+
timestamp
|
|
46
|
+
}).pipe(Effect.provide(runtime));
|
|
47
|
+
const waitForEvent$1 = (id, event, options) => waitForEvent({
|
|
48
|
+
input,
|
|
49
|
+
id: identity.reserve(id),
|
|
50
|
+
event,
|
|
51
|
+
options
|
|
52
|
+
}).pipe(Effect.provide(runtime));
|
|
53
|
+
const invoke$1 = (id, options) => invoke({
|
|
54
|
+
input,
|
|
55
|
+
id: identity.reserve(id),
|
|
56
|
+
options
|
|
57
|
+
}).pipe(Effect.provide(runtime));
|
|
58
|
+
const sendEvent$1 = (id, payload) => sendEvent({
|
|
59
|
+
input,
|
|
60
|
+
id: identity.reserve(id),
|
|
61
|
+
payload
|
|
62
|
+
}).pipe(Effect.provide(runtime));
|
|
63
|
+
return {
|
|
64
|
+
run: run$1,
|
|
65
|
+
sleep: sleep$1,
|
|
66
|
+
sleepUntil: sleepUntil$1,
|
|
67
|
+
waitForEvent: waitForEvent$1,
|
|
68
|
+
invoke: invoke$1,
|
|
69
|
+
sendEvent: sendEvent$1
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
static layer = Layer.effect(this, this.make);
|
|
73
|
+
static live = this.layer.pipe(Layer.provide(StepCommandBus.layer));
|
|
74
|
+
};
|
|
75
|
+
//#endregion
|
|
76
|
+
export { StepTools };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { InngestDuration } from "../../wire/Duration.js";
|
|
2
|
+
import { InngestConfig } from "../../../Client.js";
|
|
3
|
+
import { StepError } from "../../errors.js";
|
|
4
|
+
import { InvokeFunction } from "../../domain/StepCommand.js";
|
|
5
|
+
import { StepCommandBus } from "../StepCommandBus.js";
|
|
6
|
+
import { StepIdentity } from "../StepIdentity.js";
|
|
7
|
+
import { decodeMemo } from "../../codec/StepResult.js";
|
|
8
|
+
import { Duration, Effect, Match, Predicate, Schema } from "effect";
|
|
9
|
+
//#region src/internal/runtime/steps/InvokeStep.ts
|
|
10
|
+
const invoke = (args) => Effect.gen(function* () {
|
|
11
|
+
const config = yield* InngestConfig;
|
|
12
|
+
const identity = yield* StepIdentity;
|
|
13
|
+
const bus = yield* StepCommandBus;
|
|
14
|
+
const info = yield* identity.resolve(args.id);
|
|
15
|
+
const memo = args.input.memoForStep(info);
|
|
16
|
+
return yield* Match.value(memo).pipe(Match.tag("MemoData", ({ data }) => decodeMemo(Schema.toCodecJson(args.options.function.success), info.id)(data)), Match.tag("MemoError", ({ error }) => Effect.fail(StepError.make({
|
|
17
|
+
stepId: info.id,
|
|
18
|
+
message: Predicate.hasProperty(error, "message") ? String(error.message) : "Invoke failed",
|
|
19
|
+
cause: error
|
|
20
|
+
}))), Match.tag("MemoTimeout", () => Effect.fail(StepError.make({
|
|
21
|
+
stepId: info.id,
|
|
22
|
+
message: "Invoke timed out",
|
|
23
|
+
noRetry: true
|
|
24
|
+
}))), Match.tag("MemoInput", () => Effect.succeed(void 0)), Match.tag("MemoNone", () => Effect.gen(function* () {
|
|
25
|
+
if (!args.input.shouldExecuteStep(info)) return yield* Effect.void;
|
|
26
|
+
const event = Predicate.hasProperty(args.options, "data") ? args.options.data : void 0;
|
|
27
|
+
const data = Predicate.isObject(event) && Predicate.hasProperty(event, "data") ? event.data : event;
|
|
28
|
+
yield* bus.suspend(InvokeFunction.make({
|
|
29
|
+
info,
|
|
30
|
+
sequence: args.id.sequence,
|
|
31
|
+
functionId: `${config.id}-${args.options.function._tag}`,
|
|
32
|
+
payload: {
|
|
33
|
+
data,
|
|
34
|
+
...Predicate.isNotUndefined(args.options.user) ? { user: args.options.user } : {},
|
|
35
|
+
...Predicate.isNotUndefined(args.options.v) ? { v: args.options.v } : {}
|
|
36
|
+
},
|
|
37
|
+
timeout: args.options.timeout ? Schema.encodeSync(InngestDuration)(Duration.fromInputUnsafe(args.options.timeout)) : void 0
|
|
38
|
+
}));
|
|
39
|
+
return yield* Effect.void;
|
|
40
|
+
})), Match.exhaustive);
|
|
41
|
+
});
|
|
42
|
+
//#endregion
|
|
43
|
+
export { invoke };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { InngestClient } from "../../../Client.js";
|
|
2
|
+
import { SendEventError } from "../../errors.js";
|
|
3
|
+
import { SendEventPlanned, SendEventResult } from "../../domain/StepCommand.js";
|
|
4
|
+
import { StepCommandBus } from "../StepCommandBus.js";
|
|
5
|
+
import { StepIdentity } from "../StepIdentity.js";
|
|
6
|
+
import { Array, Effect, Match, Predicate, Schema } from "effect";
|
|
7
|
+
//#region src/internal/runtime/steps/SendEventStep.ts
|
|
8
|
+
const SendEventMemoData = Schema.Struct({ ids: Schema.Array(Schema.String) });
|
|
9
|
+
const sendEventDecodeError = (error) => SendEventError.make({
|
|
10
|
+
message: `Invalid sendEvent memo data: ${Predicate.hasProperty(error, "message") ? String(error.message) : String(error)}`,
|
|
11
|
+
events: []
|
|
12
|
+
});
|
|
13
|
+
const sendEvent = (args) => Effect.gen(function* () {
|
|
14
|
+
const identity = yield* StepIdentity;
|
|
15
|
+
const bus = yield* StepCommandBus;
|
|
16
|
+
const info = yield* identity.resolve(args.id);
|
|
17
|
+
const memo = args.input.memoForStep(info);
|
|
18
|
+
return yield* Match.value(memo).pipe(Match.tag("MemoData", ({ data }) => Schema.decodeUnknownEffect(SendEventMemoData)(data).pipe(Effect.mapError(sendEventDecodeError))), Match.tag("MemoError", () => Effect.fail(SendEventError.make({
|
|
19
|
+
message: "SendEvent failed",
|
|
20
|
+
events: []
|
|
21
|
+
}))), Match.tag("MemoTimeout", () => Effect.fail(SendEventError.make({
|
|
22
|
+
message: "SendEvent timed out",
|
|
23
|
+
events: []
|
|
24
|
+
}))), Match.tag("MemoInput", () => Effect.succeed({ ids: [] })), Match.tag("MemoNone", () => Effect.gen(function* () {
|
|
25
|
+
if (!args.input.shouldExecuteStep(info)) return { ids: [] };
|
|
26
|
+
const planned = SendEventPlanned.make({
|
|
27
|
+
info,
|
|
28
|
+
sequence: args.id.sequence
|
|
29
|
+
});
|
|
30
|
+
if (args.input.shouldPlanStep(info)) {
|
|
31
|
+
yield* bus.plan(planned);
|
|
32
|
+
return { ids: [] };
|
|
33
|
+
}
|
|
34
|
+
if (yield* bus.planCheckpointedFork(planned)) return { ids: [] };
|
|
35
|
+
const events = Array.ensure(args.payload);
|
|
36
|
+
const result = yield* InngestClient.use((client) => client.sendEvent(events));
|
|
37
|
+
yield* bus.complete(SendEventResult.make({
|
|
38
|
+
info,
|
|
39
|
+
data: { ids: [...result.ids] },
|
|
40
|
+
rawPayload: Array.isArray(args.payload) ? events : events[0]
|
|
41
|
+
}));
|
|
42
|
+
return result;
|
|
43
|
+
})), Match.exhaustive);
|
|
44
|
+
});
|
|
45
|
+
//#endregion
|
|
46
|
+
export { sendEvent };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { InngestDuration } from "../../wire/Duration.js";
|
|
2
|
+
import { Sleep } from "../../domain/StepCommand.js";
|
|
3
|
+
import { StepCommandBus } from "../StepCommandBus.js";
|
|
4
|
+
import { StepIdentity } from "../StepIdentity.js";
|
|
5
|
+
import { Duration, Effect, Predicate, Schema } from "effect";
|
|
6
|
+
//#region src/internal/runtime/steps/SleepStep.ts
|
|
7
|
+
const sleep = (args) => Effect.gen(function* () {
|
|
8
|
+
const identity = yield* StepIdentity;
|
|
9
|
+
const bus = yield* StepCommandBus;
|
|
10
|
+
const info = yield* identity.resolve(args.id);
|
|
11
|
+
const memo = args.input.memoForStep(info);
|
|
12
|
+
if (!Predicate.isTagged(memo, "MemoNone") || !args.input.shouldExecuteStep(info)) return;
|
|
13
|
+
const command = Sleep.make({
|
|
14
|
+
info,
|
|
15
|
+
sequence: args.id.sequence,
|
|
16
|
+
duration: Schema.encodeSync(InngestDuration)(Duration.fromInputUnsafe(args.duration))
|
|
17
|
+
});
|
|
18
|
+
if (yield* bus.planCheckpointedFork(command)) return;
|
|
19
|
+
return yield* bus.suspend(command);
|
|
20
|
+
});
|
|
21
|
+
//#endregion
|
|
22
|
+
export { sleep };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Sleep } from "../../domain/StepCommand.js";
|
|
2
|
+
import { StepCommandBus } from "../StepCommandBus.js";
|
|
3
|
+
import { StepIdentity } from "../StepIdentity.js";
|
|
4
|
+
import { InngestTimestamp } from "../../wire/Timestamp.js";
|
|
5
|
+
import { Effect, Predicate, Schema } from "effect";
|
|
6
|
+
//#region src/internal/runtime/steps/SleepUntilStep.ts
|
|
7
|
+
const sleepUntil = (args) => Effect.gen(function* () {
|
|
8
|
+
const identity = yield* StepIdentity;
|
|
9
|
+
const bus = yield* StepCommandBus;
|
|
10
|
+
const info = yield* identity.resolve(args.id);
|
|
11
|
+
const memo = args.input.memoForStep(info);
|
|
12
|
+
if (!Predicate.isTagged(memo, "MemoNone") || !args.input.shouldExecuteStep(info)) return;
|
|
13
|
+
const command = Sleep.make({
|
|
14
|
+
info,
|
|
15
|
+
sequence: args.id.sequence,
|
|
16
|
+
duration: Schema.decodeUnknownSync(InngestTimestamp)(args.timestamp)
|
|
17
|
+
});
|
|
18
|
+
if (yield* bus.planCheckpointedFork(command)) return;
|
|
19
|
+
return yield* bus.suspend(command);
|
|
20
|
+
});
|
|
21
|
+
//#endregion
|
|
22
|
+
export { sleepUntil };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { StepRunError, StepRunPlanned, StepRunResult, stepRunFailureForAttempt } from "../../domain/StepCommand.js";
|
|
2
|
+
import { StepCommandBus } from "../StepCommandBus.js";
|
|
3
|
+
import { StepIdentity } from "../StepIdentity.js";
|
|
4
|
+
import { decodeStepRunMemo, encodeStepRunMemo, failStepRunMemoError, failStepRunMemoTimeout, failUnexpectedStepRunMemoInput } from "../../codec/StepResult.js";
|
|
5
|
+
import { Effect, Match, Option, Schema } from "effect";
|
|
6
|
+
//#region src/internal/runtime/steps/StepRun.ts
|
|
7
|
+
function run(args) {
|
|
8
|
+
const memoCodec = args.options ? Option.some(Schema.toCodecJson(args.options.schema)) : Option.none();
|
|
9
|
+
return Effect.gen(function* () {
|
|
10
|
+
const identity = yield* StepIdentity;
|
|
11
|
+
const bus = yield* StepCommandBus;
|
|
12
|
+
const info = yield* identity.resolve(args.id);
|
|
13
|
+
const memo = args.input.memoForStep(info);
|
|
14
|
+
return yield* Match.value(memo).pipe(Match.tag("MemoData", ({ data }) => decodeStepRunMemo(memoCodec, info.id)(data)), Match.tag("MemoError", ({ error }) => failStepRunMemoError(info.id, error)), Match.tag("MemoTimeout", () => failStepRunMemoTimeout(info.id)), Match.tag("MemoInput", ({ input }) => failUnexpectedStepRunMemoInput(info.id, input)), Match.tag("MemoNone", () => Effect.gen(function* () {
|
|
15
|
+
if (!args.input.shouldExecuteStep(info)) return yield* Effect.void;
|
|
16
|
+
const planned = StepRunPlanned.make({
|
|
17
|
+
info,
|
|
18
|
+
sequence: args.id.sequence
|
|
19
|
+
});
|
|
20
|
+
if (args.input.shouldPlanStep(info)) {
|
|
21
|
+
yield* bus.plan(planned);
|
|
22
|
+
return yield* Effect.void;
|
|
23
|
+
}
|
|
24
|
+
if (yield* bus.planCheckpointedRunBoundary(planned)) return yield* Effect.void;
|
|
25
|
+
return yield* args.effect.pipe(Effect.matchEffect({
|
|
26
|
+
onFailure: (error) => bus.fail(stepRunFailureForAttempt({
|
|
27
|
+
info,
|
|
28
|
+
error,
|
|
29
|
+
attempt: args.input.run.attempt,
|
|
30
|
+
maxAttempts: args.input.run.maxAttempts
|
|
31
|
+
})),
|
|
32
|
+
onSuccess: (value) => Effect.gen(function* () {
|
|
33
|
+
const data = yield* encodeStepRunMemo(memoCodec, info.id)(value);
|
|
34
|
+
yield* bus.complete(StepRunResult.make({
|
|
35
|
+
info,
|
|
36
|
+
data
|
|
37
|
+
}));
|
|
38
|
+
return yield* decodeStepRunMemo(memoCodec, info.id)(data);
|
|
39
|
+
})
|
|
40
|
+
}), Effect.catchDefect((defect) => bus.fail(StepRunError.make({
|
|
41
|
+
info,
|
|
42
|
+
error: defect
|
|
43
|
+
}))));
|
|
44
|
+
})), Match.exhaustive);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { run };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InngestDuration } from "../../wire/Duration.js";
|
|
2
|
+
import { WaitForEvent } from "../../domain/StepCommand.js";
|
|
3
|
+
import { StepCommandBus } from "../StepCommandBus.js";
|
|
4
|
+
import { StepIdentity } from "../StepIdentity.js";
|
|
5
|
+
import { failMemoDecode, mapMemoDecodeError } from "../../codec/StepResult.js";
|
|
6
|
+
import { decodeMemoData } from "../../codec/EventPayload.js";
|
|
7
|
+
import { Duration, Effect, Match, Option, Schema } from "effect";
|
|
8
|
+
//#region src/internal/runtime/steps/WaitForEventStep.ts
|
|
9
|
+
const waitForEvent = (args) => Effect.gen(function* () {
|
|
10
|
+
const identity = yield* StepIdentity;
|
|
11
|
+
const bus = yield* StepCommandBus;
|
|
12
|
+
const info = yield* identity.resolve(args.id);
|
|
13
|
+
const memo = args.input.memoForStep(info);
|
|
14
|
+
return yield* Match.value(memo).pipe(Match.tag("MemoData", ({ data }) => decodeMemoData(args.event)(data).pipe(mapMemoDecodeError(info.id), Effect.map(Option.some))), Match.tag("MemoTimeout", () => Effect.succeed(Option.none())), Match.tag("MemoError", ({ error }) => failMemoDecode(info.id, error)), Match.tag("MemoInput", ({ input }) => failMemoDecode(info.id, input)), Match.tag("MemoNone", () => Effect.gen(function* () {
|
|
15
|
+
if (!args.input.shouldExecuteStep(info)) return Option.none();
|
|
16
|
+
yield* bus.suspend(WaitForEvent.make({
|
|
17
|
+
info,
|
|
18
|
+
sequence: args.id.sequence,
|
|
19
|
+
event: args.event.identifier,
|
|
20
|
+
timeout: Schema.encodeSync(InngestDuration)(Duration.fromInputUnsafe(args.options.timeout)),
|
|
21
|
+
if: args.options.if
|
|
22
|
+
}));
|
|
23
|
+
return Option.none();
|
|
24
|
+
})), Match.exhaustive);
|
|
25
|
+
});
|
|
26
|
+
//#endregion
|
|
27
|
+
export { waitForEvent };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Headers } from "../protocol.js";
|
|
2
|
+
import { SignatureLive } from "./Signature.js";
|
|
3
|
+
import { handleExecution, handleIntrospection, handleRegistration, verifyAndParseRequestBody } from "../handler.js";
|
|
4
|
+
import { Effect, Option, Predicate, Schema } from "effect";
|
|
5
|
+
import "effect/unstable/http/HttpClient";
|
|
6
|
+
import * as HttpEffect from "effect/unstable/http/HttpEffect";
|
|
7
|
+
import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
8
|
+
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
|
|
9
|
+
import * as UrlParams from "effect/unstable/http/UrlParams";
|
|
10
|
+
Schema.TaggedErrorClass()("MethodNotAllowed", { method: Schema.String });
|
|
11
|
+
Schema.TaggedErrorClass()("InvalidQueryParams", { message: Schema.String });
|
|
12
|
+
const toHttpApp = (group) => Effect.gen(function* () {
|
|
13
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
14
|
+
const method = request.method;
|
|
15
|
+
const requestUrl = Option.match(HttpServerRequest.toURL(request), {
|
|
16
|
+
onNone: () => request.url,
|
|
17
|
+
onSome: (url) => url.toString()
|
|
18
|
+
});
|
|
19
|
+
if (method === "GET") {
|
|
20
|
+
const result = yield* handleIntrospection(group, requestUrl);
|
|
21
|
+
return yield* HttpServerResponse.json(result.body, {
|
|
22
|
+
status: result.status,
|
|
23
|
+
headers: result.headers
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (method === "PUT") {
|
|
27
|
+
const result = yield* handleRegistration(group, requestUrl);
|
|
28
|
+
return yield* HttpServerResponse.json(result.body, {
|
|
29
|
+
status: result.status,
|
|
30
|
+
headers: result.headers
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (method === "POST") {
|
|
34
|
+
const url = yield* Option.match(HttpServerRequest.toURL(request), {
|
|
35
|
+
onNone: () => Effect.fail(HttpServerResponse.jsonUnsafe({ error: "Unable to parse request URL" }, {
|
|
36
|
+
status: 400,
|
|
37
|
+
headers: { [Headers.NoRetry]: "true" }
|
|
38
|
+
})),
|
|
39
|
+
onSome: (u) => Effect.succeed(u)
|
|
40
|
+
});
|
|
41
|
+
const ExecuteParamsSchema = UrlParams.schemaRecord.pipe(Schema.decodeTo(Schema.Struct({
|
|
42
|
+
fnId: Schema.String,
|
|
43
|
+
stepId: Schema.optional(Schema.String)
|
|
44
|
+
})));
|
|
45
|
+
const params = yield* Schema.decodeUnknownEffect(ExecuteParamsSchema)(UrlParams.fromInput(url.searchParams)).pipe(Effect.catch((error) => Effect.fail(HttpServerResponse.jsonUnsafe({ error: `Missing or invalid fnId query parameter: ${String(error)}` }, {
|
|
46
|
+
status: 400,
|
|
47
|
+
headers: { [Headers.NoRetry]: "true" }
|
|
48
|
+
}))));
|
|
49
|
+
const body = yield* verifyAndParseRequestBody(request).pipe(Effect.provide(SignatureLive), Effect.catch((error) => Effect.fail(HttpServerResponse.jsonUnsafe({ error: error.message }, {
|
|
50
|
+
status: Predicate.isTagged(error, "SignatureError") ? 401 : 400,
|
|
51
|
+
headers: { [Headers.NoRetry]: "true" }
|
|
52
|
+
}))));
|
|
53
|
+
const result = yield* handleExecution({
|
|
54
|
+
group,
|
|
55
|
+
fnId: params.fnId,
|
|
56
|
+
urlStepId: params.stepId,
|
|
57
|
+
body
|
|
58
|
+
});
|
|
59
|
+
return yield* HttpServerResponse.json(result.body, {
|
|
60
|
+
status: result.status,
|
|
61
|
+
headers: result.headers
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return yield* HttpServerResponse.json({ error: `Method ${method} not allowed` }, { status: 405 });
|
|
65
|
+
}).pipe(Effect.catchCause((cause) => HttpServerResponse.json({
|
|
66
|
+
error: "Internal server error",
|
|
67
|
+
cause: String(cause)
|
|
68
|
+
}, { status: 500 }).pipe(Effect.orDie)));
|
|
69
|
+
const toWebHandler = (args) => HttpEffect.toWebHandlerLayer(toHttpApp(args.group), args.options.layer);
|
|
70
|
+
//#endregion
|
|
71
|
+
export { toHttpApp, toWebHandler };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Headers as Headers$1 } from "../protocol.js";
|
|
2
|
+
import { Signature, SignatureHeader, SignedPayload } from "./Signature.js";
|
|
3
|
+
import { Effect, Function, Option, Schema } from "effect";
|
|
4
|
+
import "effect/unstable/http/HttpServerRequest";
|
|
5
|
+
import * as Headers from "effect/unstable/http/Headers";
|
|
6
|
+
//#region src/internal/serve/Request.ts
|
|
7
|
+
const verifySignature = Function.dual(2, (body, request) => Effect.gen(function* () {
|
|
8
|
+
const sig = yield* Signature;
|
|
9
|
+
const signature = yield* Option.match(Headers.get(request.headers, Headers$1.Signature), {
|
|
10
|
+
onNone: () => Effect.succeed(Option.none()),
|
|
11
|
+
onSome: (header) => SignatureHeader.decode(header).pipe(Effect.map(Option.some))
|
|
12
|
+
});
|
|
13
|
+
yield* sig.verify(SignedPayload.make({
|
|
14
|
+
body,
|
|
15
|
+
signature
|
|
16
|
+
}));
|
|
17
|
+
}));
|
|
18
|
+
const schemaBodyJson = (schema) => (body) => {
|
|
19
|
+
const bodyText = new TextDecoder().decode(body);
|
|
20
|
+
return Schema.decodeUnknownEffect(Schema.fromJsonString(schema))(bodyText);
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { schemaBodyJson, verifySignature };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Option, Schema } from "effect";
|
|
2
|
+
import * as _$effect_Cause0 from "effect/Cause";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/serve/Signature.d.ts
|
|
5
|
+
declare const SignatureError_base: Schema.Class<SignatureError, Schema.TaggedStruct<"SignatureError", {
|
|
6
|
+
readonly reason: Schema.Literals<readonly ["missing_header", "invalid_format", "expired", "invalid_signature", "missing_signing_key"]>;
|
|
7
|
+
readonly message: Schema.String;
|
|
8
|
+
}>, _$effect_Cause0.YieldableError>;
|
|
9
|
+
declare class SignatureError extends SignatureError_base {}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SignatureError };
|