effect-inngest 0.1.2 → 0.2.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/dist/Client.d.ts +55 -24
- package/dist/Client.js +84 -25
- package/dist/Events.d.ts +36 -61
- package/dist/Events.js +5 -13
- package/dist/Function.d.ts +35 -15
- package/dist/Function.js +14 -8
- package/dist/Group.d.ts +5 -4
- package/dist/Group.js +26 -24
- package/dist/HttpApi.d.ts +49 -54
- package/dist/HttpApi.js +32 -17
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/index.js +1 -2
- package/dist/internal/checkpoint.d.ts +32 -0
- package/dist/internal/checkpoint.js +112 -0
- package/dist/internal/constants.js +1 -2
- package/dist/internal/driver.d.ts +1 -5
- package/dist/internal/driver.js +164 -52
- package/dist/internal/errors.d.ts +20 -27
- package/dist/internal/errors.js +29 -15
- package/dist/internal/handler.d.ts +4 -13
- package/dist/internal/handler.js +70 -43
- package/dist/internal/helpers.js +12 -9
- package/dist/internal/interrupts.d.ts +1 -2
- package/dist/internal/interrupts.js +1 -3
- package/dist/internal/memo.js +22 -20
- package/dist/internal/protocol.d.ts +28 -1
- package/dist/internal/protocol.js +84 -52
- package/dist/internal/signature.d.ts +5 -9
- package/dist/internal/signature.js +34 -18
- package/dist/internal/step.d.ts +5 -11
- package/dist/internal/step.js +48 -32
- package/package.json +26 -21
- package/src/Client.ts +244 -68
- package/src/Events.ts +3 -3
- package/src/Function.ts +52 -15
- package/src/Group.ts +39 -26
- package/src/HttpApi.ts +38 -27
- package/src/internal/checkpoint.ts +218 -0
- package/src/internal/driver.ts +241 -93
- package/src/internal/errors.ts +21 -14
- package/src/internal/handler.ts +185 -142
- package/src/internal/helpers.ts +9 -9
- package/src/internal/memo.ts +48 -33
- package/src/internal/protocol.ts +89 -45
- package/src/internal/signature.ts +76 -58
- package/src/internal/step.ts +83 -32
- package/dist/_virtual/rolldown_runtime.js +0 -18
package/dist/Function.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { __exportAll } from "./_virtual/
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { timeStr } from "./internal/helpers.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { resolveConfig, toRegistration } from "./internal/checkpoint.js";
|
|
4
|
+
import { Array, Predicate } from "effect";
|
|
5
|
+
import { pipeArguments } from "effect/Pipeable";
|
|
5
6
|
//#region src/Function.ts
|
|
6
7
|
/**
|
|
7
8
|
* @since 0.1.0
|
|
@@ -18,10 +19,13 @@ const TypeId = Symbol.for("effect-inngest/Function");
|
|
|
18
19
|
const isEventTrigger = (t) => Predicate.hasProperty(t, "event");
|
|
19
20
|
const Proto = {
|
|
20
21
|
[TypeId]: TypeId,
|
|
22
|
+
pipe() {
|
|
23
|
+
return pipeArguments(this, arguments);
|
|
24
|
+
},
|
|
21
25
|
toRegistration(config) {
|
|
22
26
|
const triggers = [];
|
|
23
27
|
for (const t of this.triggers) if (isEventTrigger(t)) triggers.push({
|
|
24
|
-
event: t.event.
|
|
28
|
+
event: t.event.identifier,
|
|
25
29
|
expression: t.if
|
|
26
30
|
});
|
|
27
31
|
else triggers.push({ cron: t.cron });
|
|
@@ -51,7 +55,7 @@ const Proto = {
|
|
|
51
55
|
period: timeStr(opts.debounce.period),
|
|
52
56
|
timeout: opts.debounce.timeout ? timeStr(opts.debounce.timeout) : void 0
|
|
53
57
|
} : void 0;
|
|
54
|
-
const concurrency = opts.concurrency != null ?
|
|
58
|
+
const concurrency = opts.concurrency != null ? Predicate.isNumber(opts.concurrency) ? [{ limit: opts.concurrency }] : Array.ensure(opts.concurrency).map((c) => ({
|
|
55
59
|
key: c.key,
|
|
56
60
|
limit: c.limit,
|
|
57
61
|
scope: c.scope
|
|
@@ -67,6 +71,8 @@ const Proto = {
|
|
|
67
71
|
key: opts.batchEvents.key
|
|
68
72
|
} : void 0;
|
|
69
73
|
const idempotency = opts.idempotency;
|
|
74
|
+
const resolvedCheckpoint = opts.checkpointing !== void 0 ? resolveConfig(opts.checkpointing, void 0) : void 0;
|
|
75
|
+
const checkpoint = resolvedCheckpoint ? toRegistration(resolvedCheckpoint) : void 0;
|
|
70
76
|
const fnId = `${config.appId}-${this._tag}`;
|
|
71
77
|
const stepUrl = new URL(config.url);
|
|
72
78
|
stepUrl.searchParams.set("fnId", fnId);
|
|
@@ -93,7 +99,8 @@ const Proto = {
|
|
|
93
99
|
priority,
|
|
94
100
|
singleton,
|
|
95
101
|
batchEvents,
|
|
96
|
-
idempotency
|
|
102
|
+
idempotency,
|
|
103
|
+
checkpoint
|
|
97
104
|
};
|
|
98
105
|
}
|
|
99
106
|
};
|
|
@@ -139,6 +146,5 @@ function make(tag, options) {
|
|
|
139
146
|
fn.options = options;
|
|
140
147
|
return fn;
|
|
141
148
|
}
|
|
142
|
-
|
|
143
149
|
//#endregion
|
|
144
|
-
export { Function_exports, TypeId, make };
|
|
150
|
+
export { Function_exports, TypeId, make };
|
package/dist/Group.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { InngestClient } from "./Client.js";
|
|
2
2
|
import { InngestFunction } from "./Function.js";
|
|
3
3
|
import { HandlerContext } from "./internal/step.js";
|
|
4
|
-
import * as HttpApp from "@effect/platform/HttpApp";
|
|
5
|
-
import * as HttpClient from "@effect/platform/HttpClient";
|
|
6
|
-
import * as Context from "effect/Context";
|
|
7
4
|
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
6
|
+
import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
7
|
+
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
|
|
8
|
+
import * as Context from "effect/Context";
|
|
8
9
|
import * as Layer from "effect/Layer";
|
|
9
10
|
|
|
10
11
|
//#region src/Group.d.ts
|
|
@@ -116,7 +117,7 @@ declare const make: <Fns extends ReadonlyArray<InngestFunction.Any>>(...fns: Fns
|
|
|
116
117
|
* )
|
|
117
118
|
* ```
|
|
118
119
|
*/
|
|
119
|
-
declare const toHttpApp: (group: InngestGroup.Any) =>
|
|
120
|
+
declare const toHttpApp: (group: InngestGroup.Any) => Effect.Effect<HttpServerResponse.HttpServerResponse, never, InngestClient | HttpClient.HttpClient | HttpServerRequest.HttpServerRequest>;
|
|
120
121
|
/**
|
|
121
122
|
* Create a standalone web handler from an InngestGroup.
|
|
122
123
|
*
|
package/dist/Group.js
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
import { __exportAll } from "./_virtual/
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { Headers } from "./internal/protocol.js";
|
|
3
3
|
import { SignatureLive } from "./internal/signature.js";
|
|
4
|
+
import "./internal/step.js";
|
|
4
5
|
import { handleExecution, handleIntrospection, handleRegistration, verifyAndParseRequestBody } from "./internal/handler.js";
|
|
5
|
-
import * as HttpApp from "@effect/platform/HttpApp";
|
|
6
|
-
import "@effect/platform/HttpClient";
|
|
7
|
-
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
|
8
|
-
import * as HttpServerResponse from "@effect/platform/HttpServerResponse";
|
|
9
|
-
import * as UrlParams from "@effect/platform/UrlParams";
|
|
10
|
-
import * as Context from "effect/Context";
|
|
11
6
|
import * as Effect from "effect/Effect";
|
|
12
|
-
import * as Layer from "effect/Layer";
|
|
13
7
|
import * as Option from "effect/Option";
|
|
14
8
|
import * as Schema from "effect/Schema";
|
|
15
|
-
|
|
9
|
+
import "effect/unstable/http/HttpClient";
|
|
10
|
+
import * as HttpEffect from "effect/unstable/http/HttpEffect";
|
|
11
|
+
import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
12
|
+
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
|
|
13
|
+
import * as UrlParams from "effect/unstable/http/UrlParams";
|
|
14
|
+
import * as Context from "effect/Context";
|
|
15
|
+
import * as Layer from "effect/Layer";
|
|
16
16
|
//#region src/Group.ts
|
|
17
|
-
/**
|
|
18
|
-
* @since 0.1.0
|
|
19
|
-
*/
|
|
20
17
|
var Group_exports = /* @__PURE__ */ __exportAll({
|
|
21
18
|
TypeId: () => TypeId,
|
|
22
19
|
make: () => make,
|
|
@@ -42,7 +39,7 @@ const Proto = {
|
|
|
42
39
|
context
|
|
43
40
|
});
|
|
44
41
|
}
|
|
45
|
-
return Context.
|
|
42
|
+
return Context.makeUnsafe(contextMap);
|
|
46
43
|
}));
|
|
47
44
|
},
|
|
48
45
|
toLayerHandler(tag, handler) {
|
|
@@ -54,7 +51,7 @@ const Proto = {
|
|
|
54
51
|
handler,
|
|
55
52
|
context
|
|
56
53
|
});
|
|
57
|
-
return Context.
|
|
54
|
+
return Context.makeUnsafe(contextMap);
|
|
58
55
|
}));
|
|
59
56
|
}
|
|
60
57
|
};
|
|
@@ -88,7 +85,7 @@ const make = (...fns) => {
|
|
|
88
85
|
* )
|
|
89
86
|
* ```
|
|
90
87
|
*/
|
|
91
|
-
const toHttpApp =
|
|
88
|
+
const toHttpApp = Effect.fn("InngestGroup.toHttpApp")(function* (group) {
|
|
92
89
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
93
90
|
const method = request.method;
|
|
94
91
|
const requestUrl = Option.match(HttpServerRequest.toURL(request), {
|
|
@@ -110,16 +107,22 @@ const toHttpApp = (group) => Effect.gen(function* () {
|
|
|
110
107
|
});
|
|
111
108
|
}
|
|
112
109
|
if (method === "POST") {
|
|
113
|
-
const url = Option.
|
|
114
|
-
|
|
110
|
+
const url = yield* Option.match(HttpServerRequest.toURL(request), {
|
|
111
|
+
onNone: () => Effect.fail(HttpServerResponse.jsonUnsafe({ error: "Unable to parse request URL" }, {
|
|
112
|
+
status: 400,
|
|
113
|
+
headers: { [Headers.NoRetry]: "true" }
|
|
114
|
+
})),
|
|
115
|
+
onSome: (u) => Effect.succeed(u)
|
|
116
|
+
});
|
|
117
|
+
const ExecuteParamsSchema = UrlParams.schemaRecord.pipe(Schema.decodeTo(Schema.Struct({
|
|
115
118
|
fnId: Schema.String,
|
|
116
119
|
stepId: Schema.optional(Schema.String)
|
|
117
|
-
});
|
|
118
|
-
const params = yield*
|
|
120
|
+
})));
|
|
121
|
+
const params = yield* Schema.decodeUnknownEffect(ExecuteParamsSchema)(UrlParams.fromInput(url.searchParams)).pipe(Effect.catch(() => Effect.fail(HttpServerResponse.jsonUnsafe({ error: "Missing or invalid fnId query parameter" }, {
|
|
119
122
|
status: 400,
|
|
120
123
|
headers: { [Headers.NoRetry]: "true" }
|
|
121
124
|
}))));
|
|
122
|
-
const body = yield* verifyAndParseRequestBody(request).pipe(Effect.provide(SignatureLive), Effect.
|
|
125
|
+
const body = yield* verifyAndParseRequestBody(request).pipe(Effect.provide(SignatureLive), Effect.catch((error) => Effect.fail(HttpServerResponse.jsonUnsafe({ error: error.message }, {
|
|
123
126
|
status: error._tag === "SignatureError" ? 401 : 400,
|
|
124
127
|
headers: { [Headers.NoRetry]: "true" }
|
|
125
128
|
}))));
|
|
@@ -130,7 +133,7 @@ const toHttpApp = (group) => Effect.gen(function* () {
|
|
|
130
133
|
});
|
|
131
134
|
}
|
|
132
135
|
return yield* HttpServerResponse.json({ error: `Method ${method} not allowed` }, { status: 405 });
|
|
133
|
-
}
|
|
136
|
+
}, Effect.catchCause((cause) => HttpServerResponse.json({
|
|
134
137
|
error: "Internal server error",
|
|
135
138
|
cause: String(cause)
|
|
136
139
|
}, { status: 500 }).pipe(Effect.orDie)));
|
|
@@ -158,7 +161,6 @@ const toHttpApp = (group) => Effect.gen(function* () {
|
|
|
158
161
|
* process.on("SIGTERM", dispose)
|
|
159
162
|
* ```
|
|
160
163
|
*/
|
|
161
|
-
const toWebHandler = (group, options) =>
|
|
162
|
-
|
|
164
|
+
const toWebHandler = (group, options) => HttpEffect.toWebHandlerLayer(toHttpApp(group), options.layer);
|
|
163
165
|
//#endregion
|
|
164
|
-
export { Group_exports, TypeId, make, toHttpApp, toWebHandler };
|
|
166
|
+
export { Group_exports, TypeId, make, toHttpApp, toWebHandler };
|
package/dist/HttpApi.d.ts
CHANGED
|
@@ -2,74 +2,69 @@ import { InngestClient } from "./Client.js";
|
|
|
2
2
|
import { InngestGroup } from "./Group.js";
|
|
3
3
|
import { SignatureError } from "./internal/signature.js";
|
|
4
4
|
import { InvalidRequestError } from "./internal/handler.js";
|
|
5
|
-
import * as HttpClient from "@effect/platform/HttpClient";
|
|
6
|
-
import * as Layer from "effect/Layer";
|
|
7
5
|
import * as Schema from "effect/Schema";
|
|
8
|
-
import * as
|
|
9
|
-
import * as
|
|
10
|
-
import * as
|
|
6
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
7
|
+
import * as Layer from "effect/Layer";
|
|
8
|
+
import * as _$effect_Cause0 from "effect/Cause";
|
|
9
|
+
import * as HttpApi from "effect/unstable/httpapi/HttpApi";
|
|
10
|
+
import * as HttpApiEndpoint from "effect/unstable/httpapi/HttpApiEndpoint";
|
|
11
|
+
import * as HttpApiGroup from "effect/unstable/httpapi/HttpApiGroup";
|
|
11
12
|
|
|
12
13
|
//#region src/HttpApi.d.ts
|
|
13
14
|
declare namespace HttpApi_d_exports {
|
|
14
15
|
export { InngestApiGroup, layerGroup };
|
|
15
16
|
}
|
|
16
|
-
declare const FunctionNotFoundError_base: Schema.
|
|
17
|
-
readonly
|
|
18
|
-
}
|
|
19
|
-
message: typeof Schema.String;
|
|
20
|
-
}>;
|
|
17
|
+
declare const FunctionNotFoundError_base: Schema.Class<FunctionNotFoundError, Schema.TaggedStruct<"FunctionNotFoundError", {
|
|
18
|
+
readonly message: Schema.String;
|
|
19
|
+
}>, _$effect_Cause0.YieldableError>;
|
|
21
20
|
declare class FunctionNotFoundError extends FunctionNotFoundError_base {}
|
|
21
|
+
declare const InngestApiGroup_base: HttpApiGroup.HttpApiGroup<"inngest", HttpApiEndpoint.HttpApiEndpoint<"introspect", "GET", "/", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Union<readonly [Schema.Struct<{
|
|
22
|
+
readonly function_count: Schema.Number;
|
|
23
|
+
readonly has_event_key: Schema.Boolean;
|
|
24
|
+
readonly has_signing_key: Schema.Boolean;
|
|
25
|
+
readonly has_signing_key_fallback: Schema.Boolean;
|
|
26
|
+
readonly mode: Schema.Literals<readonly ["cloud", "dev"]>;
|
|
27
|
+
readonly schema_version: Schema.Literal<"2024-05-24">;
|
|
28
|
+
readonly extra: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
29
|
+
readonly authentication_succeeded: Schema.Literal<true>;
|
|
30
|
+
readonly api_origin: Schema.String;
|
|
31
|
+
readonly app_id: Schema.String;
|
|
32
|
+
readonly env: Schema.NullOr<Schema.String>;
|
|
33
|
+
readonly event_api_origin: Schema.String;
|
|
34
|
+
readonly event_key_hash: Schema.NullOr<Schema.String>;
|
|
35
|
+
readonly framework: Schema.String;
|
|
36
|
+
readonly sdk_language: Schema.String;
|
|
37
|
+
readonly sdk_version: Schema.String;
|
|
38
|
+
readonly serve_origin: Schema.NullOr<Schema.String>;
|
|
39
|
+
readonly serve_path: Schema.NullOr<Schema.String>;
|
|
40
|
+
readonly signing_key_fallback_hash: Schema.NullOr<Schema.String>;
|
|
41
|
+
readonly signing_key_hash: Schema.NullOr<Schema.String>;
|
|
42
|
+
}>, Schema.Struct<{
|
|
43
|
+
readonly function_count: Schema.Number;
|
|
44
|
+
readonly has_event_key: Schema.Boolean;
|
|
45
|
+
readonly has_signing_key: Schema.Boolean;
|
|
46
|
+
readonly has_signing_key_fallback: Schema.Boolean;
|
|
47
|
+
readonly mode: Schema.Literals<readonly ["cloud", "dev"]>;
|
|
48
|
+
readonly schema_version: Schema.Literal<"2024-05-24">;
|
|
49
|
+
readonly extra: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
50
|
+
readonly authentication_succeeded: Schema.Union<readonly [Schema.Literal<false>, Schema.Null]>;
|
|
51
|
+
readonly functions: Schema.optionalKey<Schema.$Array<Schema.Unknown>>;
|
|
52
|
+
}>]>>, HttpApiEndpoint.Json<typeof FunctionNotFoundError | typeof InvalidRequestError | typeof SignatureError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"register", "PUT", "/", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
53
|
+
readonly message: Schema.String;
|
|
54
|
+
readonly modified: Schema.Boolean;
|
|
55
|
+
}>>, HttpApiEndpoint.Json<typeof FunctionNotFoundError | typeof InvalidRequestError | typeof SignatureError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"execute", "POST", "/", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
56
|
+
readonly fnId: Schema.String;
|
|
57
|
+
readonly stepId: Schema.optional<Schema.String>;
|
|
58
|
+
}>>, HttpApiEndpoint.Json<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Unknown>, HttpApiEndpoint.Json<typeof FunctionNotFoundError | typeof InvalidRequestError | typeof SignatureError>, never, never>, false>;
|
|
22
59
|
/**
|
|
23
60
|
* @since 0.1.0
|
|
24
61
|
* @category api
|
|
25
62
|
*/
|
|
26
|
-
declare
|
|
27
|
-
readonly function_count: number;
|
|
28
|
-
readonly has_event_key: boolean;
|
|
29
|
-
readonly has_signing_key: boolean;
|
|
30
|
-
readonly has_signing_key_fallback: boolean;
|
|
31
|
-
readonly mode: "cloud" | "dev";
|
|
32
|
-
readonly schema_version: "2024-05-24";
|
|
33
|
-
readonly extra?: {
|
|
34
|
-
readonly [x: string]: unknown;
|
|
35
|
-
} | undefined;
|
|
36
|
-
} & {
|
|
37
|
-
readonly authentication_succeeded: true;
|
|
38
|
-
readonly api_origin: string;
|
|
39
|
-
readonly app_id: string;
|
|
40
|
-
readonly env: string | null;
|
|
41
|
-
readonly event_api_origin: string;
|
|
42
|
-
readonly event_key_hash: string | null;
|
|
43
|
-
readonly framework: string;
|
|
44
|
-
readonly sdk_language: string;
|
|
45
|
-
readonly sdk_version: string;
|
|
46
|
-
readonly serve_origin: string | null;
|
|
47
|
-
readonly serve_path: string | null;
|
|
48
|
-
readonly signing_key_fallback_hash: string | null;
|
|
49
|
-
readonly signing_key_hash: string | null;
|
|
50
|
-
}) | ({
|
|
51
|
-
readonly function_count: number;
|
|
52
|
-
readonly has_event_key: boolean;
|
|
53
|
-
readonly has_signing_key: boolean;
|
|
54
|
-
readonly has_signing_key_fallback: boolean;
|
|
55
|
-
readonly mode: "cloud" | "dev";
|
|
56
|
-
readonly schema_version: "2024-05-24";
|
|
57
|
-
readonly extra?: {
|
|
58
|
-
readonly [x: string]: unknown;
|
|
59
|
-
} | undefined;
|
|
60
|
-
} & {
|
|
61
|
-
readonly authentication_succeeded: false | null;
|
|
62
|
-
readonly functions?: readonly unknown[] | undefined;
|
|
63
|
-
}), never, never, never> | HttpApiEndpoint.HttpApiEndpoint<"register", "PUT", never, never, never, never, {
|
|
64
|
-
readonly message?: string | undefined;
|
|
65
|
-
}, never, never, never> | HttpApiEndpoint.HttpApiEndpoint<"execute", "POST", never, {
|
|
66
|
-
readonly fnId: string;
|
|
67
|
-
readonly stepId?: string | undefined;
|
|
68
|
-
}, never, never, unknown, never, never, never>, FunctionNotFoundError | InvalidRequestError | SignatureError, never, false>;
|
|
63
|
+
declare class InngestApiGroup extends InngestApiGroup_base {}
|
|
69
64
|
/**
|
|
70
65
|
* @since 0.1.0
|
|
71
66
|
* @category layers
|
|
72
67
|
*/
|
|
73
|
-
declare const layerGroup: <ApiId extends string, Groups extends HttpApiGroup.
|
|
68
|
+
declare const layerGroup: <ApiId extends string, Groups extends HttpApiGroup.Any>(api: HttpApi.HttpApi<ApiId, Groups>, group: InngestGroup.Any) => Layer.Layer<HttpApiGroup.ApiGroup<ApiId, "inngest">, never, InngestClient | HttpClient.HttpClient>;
|
|
74
69
|
//#endregion
|
|
75
70
|
export { HttpApi_d_exports, InngestApiGroup, layerGroup };
|
package/dist/HttpApi.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { __exportAll } from "./_virtual/
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { IntrospectionResponse, RegisterResponse } from "./internal/protocol.js";
|
|
3
3
|
import { SignatureError, SignatureLive } from "./internal/signature.js";
|
|
4
4
|
import { InvalidRequestError, handleExecution, handleIntrospection, handleRegistration, verifyAndParseRequestBody } from "./internal/handler.js";
|
|
5
|
-
import "@effect/platform/HttpClient";
|
|
6
|
-
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
|
7
5
|
import * as Effect from "effect/Effect";
|
|
8
|
-
import "effect/Layer";
|
|
9
6
|
import * as Option from "effect/Option";
|
|
10
7
|
import * as Schema from "effect/Schema";
|
|
11
|
-
import "
|
|
12
|
-
import * as
|
|
13
|
-
import * as
|
|
14
|
-
import
|
|
15
|
-
|
|
8
|
+
import "effect/unstable/http/HttpClient";
|
|
9
|
+
import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
10
|
+
import * as Layer from "effect/Layer";
|
|
11
|
+
import "effect/unstable/httpapi/HttpApi";
|
|
12
|
+
import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder";
|
|
13
|
+
import * as HttpApiEndpoint from "effect/unstable/httpapi/HttpApiEndpoint";
|
|
14
|
+
import * as HttpApiGroup from "effect/unstable/httpapi/HttpApiGroup";
|
|
16
15
|
//#region src/HttpApi.ts
|
|
17
16
|
var HttpApi_exports = /* @__PURE__ */ __exportAll({
|
|
18
17
|
InngestApiGroup: () => InngestApiGroup,
|
|
@@ -22,15 +21,30 @@ const ExecuteParams = Schema.Struct({
|
|
|
22
21
|
fnId: Schema.String,
|
|
23
22
|
stepId: Schema.optional(Schema.String)
|
|
24
23
|
});
|
|
25
|
-
var FunctionNotFoundError = class extends Schema.
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
var FunctionNotFoundError = class extends Schema.TaggedErrorClass()("FunctionNotFoundError", { message: Schema.String }) {};
|
|
25
|
+
const CommonErrors = [
|
|
26
|
+
FunctionNotFoundError,
|
|
27
|
+
InvalidRequestError,
|
|
28
|
+
SignatureError
|
|
29
|
+
];
|
|
30
|
+
const IntrospectEndpoint = HttpApiEndpoint.get("introspect", "/", {
|
|
31
|
+
success: IntrospectionResponse,
|
|
32
|
+
error: CommonErrors
|
|
33
|
+
});
|
|
34
|
+
const RegisterEndpoint = HttpApiEndpoint.put("register", "/", {
|
|
35
|
+
success: RegisterResponse,
|
|
36
|
+
error: CommonErrors
|
|
37
|
+
});
|
|
38
|
+
const ExecuteEndpoint = HttpApiEndpoint.post("execute", "/", {
|
|
39
|
+
query: ExecuteParams,
|
|
40
|
+
success: Schema.Unknown,
|
|
41
|
+
error: CommonErrors
|
|
42
|
+
});
|
|
29
43
|
/**
|
|
30
44
|
* @since 0.1.0
|
|
31
45
|
* @category api
|
|
32
46
|
*/
|
|
33
|
-
|
|
47
|
+
var InngestApiGroup = class extends HttpApiGroup.make("inngest").add(IntrospectEndpoint).add(RegisterEndpoint).add(ExecuteEndpoint) {};
|
|
34
48
|
/**
|
|
35
49
|
* @since 0.1.0
|
|
36
50
|
* @category layers
|
|
@@ -40,8 +54,9 @@ const layerGroup = (api, group) => {
|
|
|
40
54
|
onNone: () => req.url,
|
|
41
55
|
onSome: (url) => url.toString()
|
|
42
56
|
});
|
|
43
|
-
return HttpApiBuilder.group(api, "inngest",
|
|
57
|
+
return HttpApiBuilder.group(api, "inngest", Effect.fn(function* (handlers) {
|
|
58
|
+
return handlers.handle("introspect", ({ request }) => handleIntrospection(group, toUrl(request)).pipe(Effect.map((r) => r.body))).handle("register", ({ request }) => handleRegistration(group, toUrl(request)).pipe(Effect.map((r) => r.body))).handleRaw("execute", ({ query, request }) => verifyAndParseRequestBody(request).pipe(Effect.flatMap((payload) => handleExecution(group, query.fnId, query.stepId, payload)), Effect.map((r) => r.body)));
|
|
59
|
+
})).pipe(Layer.provide(SignatureLive));
|
|
44
60
|
};
|
|
45
|
-
|
|
46
61
|
//#endregion
|
|
47
|
-
export { HttpApi_exports, InngestApiGroup, layerGroup };
|
|
62
|
+
export { HttpApi_exports, InngestApiGroup, layerGroup };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll };
|
package/dist/index.js
CHANGED
|
@@ -4,5 +4,4 @@ import { NonRetriableError, RetryAfterError } from "./internal/errors.js";
|
|
|
4
4
|
import { Group_exports } from "./Group.js";
|
|
5
5
|
import { HttpApi_exports } from "./HttpApi.js";
|
|
6
6
|
import { Events_exports } from "./Events.js";
|
|
7
|
-
|
|
8
|
-
export { Client_exports as InngestClient, Events_exports as InngestEvents, Function_exports as InngestFunction, Group_exports as InngestGroup, HttpApi_exports as InngestHttpApi, NonRetriableError, RetryAfterError };
|
|
7
|
+
export { Client_exports as InngestClient, Events_exports as InngestEvents, Function_exports as InngestFunction, Group_exports as InngestGroup, HttpApi_exports as InngestHttpApi, NonRetriableError, RetryAfterError };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as Duration from "effect/Duration";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
import * as _$effect_Cause0 from "effect/Cause";
|
|
4
|
+
|
|
5
|
+
//#region src/internal/checkpoint.d.ts
|
|
6
|
+
declare const CheckpointApiError_base: Schema.Class<CheckpointApiError, Schema.TaggedStruct<"CheckpointApiError", {
|
|
7
|
+
readonly message: Schema.String;
|
|
8
|
+
readonly status: Schema.optionalKey<Schema.Number>;
|
|
9
|
+
}>, _$effect_Cause0.YieldableError>;
|
|
10
|
+
/**
|
|
11
|
+
* Tagged error returned by `InngestClient.checkpointAsync` when the API call
|
|
12
|
+
* fails (network error or non-2xx after retries). The driver and step tools
|
|
13
|
+
* treat this as a graceful-fallback signal — buffered steps are restored to
|
|
14
|
+
* the buffer so they get included in the final 206 response.
|
|
15
|
+
*/
|
|
16
|
+
declare class CheckpointApiError extends CheckpointApiError_base {}
|
|
17
|
+
/**
|
|
18
|
+
* User-facing checkpointing option, accepted on `ClientConfig.checkpointing`
|
|
19
|
+
* and `FunctionOptions.checkpointing`.
|
|
20
|
+
*
|
|
21
|
+
* - `false` disables checkpointing entirely (no API calls; classic 206-per-step).
|
|
22
|
+
* - `true` enables checkpointing with the safe defaults
|
|
23
|
+
* (`bufferedSteps: 1`, `maxInterval: 0`, `maxRuntime: 10 seconds`).
|
|
24
|
+
* - An object lets you tune `bufferedSteps`, `maxInterval`, `maxRuntime`.
|
|
25
|
+
*/
|
|
26
|
+
type CheckpointingOption = boolean | {
|
|
27
|
+
readonly bufferedSteps?: number;
|
|
28
|
+
readonly maxInterval?: Duration.Input;
|
|
29
|
+
readonly maxRuntime?: Duration.Input;
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { CheckpointApiError, CheckpointingOption };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { timeStr } from "./helpers.js";
|
|
2
|
+
import * as Clock from "effect/Clock";
|
|
3
|
+
import * as Duration from "effect/Duration";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Option from "effect/Option";
|
|
6
|
+
import * as Ref from "effect/Ref";
|
|
7
|
+
import * as Result from "effect/Result";
|
|
8
|
+
import * as Schema from "effect/Schema";
|
|
9
|
+
//#region src/internal/checkpoint.ts
|
|
10
|
+
/**
|
|
11
|
+
* Checkpoint configuration + per-execution state for spec §10 async
|
|
12
|
+
* checkpointing.
|
|
13
|
+
*
|
|
14
|
+
* Sync checkpointing (§10.3.2 / §10.4.2) is intentionally out of scope —
|
|
15
|
+
* it requires a durable endpoint primitive the SDK does not yet expose.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Tagged error returned by `InngestClient.checkpointAsync` when the API call
|
|
21
|
+
* fails (network error or non-2xx after retries). The driver and step tools
|
|
22
|
+
* treat this as a graceful-fallback signal — buffered steps are restored to
|
|
23
|
+
* the buffer so they get included in the final 206 response.
|
|
24
|
+
*/
|
|
25
|
+
var CheckpointApiError = class extends Schema.TaggedErrorClass()("CheckpointApiError", {
|
|
26
|
+
message: Schema.String,
|
|
27
|
+
status: Schema.optionalKey(Schema.Number)
|
|
28
|
+
}) {};
|
|
29
|
+
const DEFAULTS = {
|
|
30
|
+
bufferedSteps: 1,
|
|
31
|
+
maxInterval: Duration.millis(0),
|
|
32
|
+
maxRuntime: Duration.seconds(10)
|
|
33
|
+
};
|
|
34
|
+
const normalize = (option) => ({
|
|
35
|
+
bufferedSteps: option.bufferedSteps ?? DEFAULTS.bufferedSteps,
|
|
36
|
+
maxInterval: option.maxInterval !== void 0 ? Duration.fromInputUnsafe(option.maxInterval) : DEFAULTS.maxInterval,
|
|
37
|
+
maxRuntime: option.maxRuntime !== void 0 ? Duration.fromInputUnsafe(option.maxRuntime) : DEFAULTS.maxRuntime
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Resolve final config from function-level + client-level settings.
|
|
41
|
+
*
|
|
42
|
+
* Precedence: function-level explicit > client-level explicit > built-in
|
|
43
|
+
* defaults (default-ON, matching the TS reference SDK).
|
|
44
|
+
*
|
|
45
|
+
* Returns `undefined` if either level explicitly disables checkpointing.
|
|
46
|
+
*/
|
|
47
|
+
const resolveConfig = (fnLevel, clientLevel) => {
|
|
48
|
+
if (fnLevel === false) return void 0;
|
|
49
|
+
if (fnLevel === true) return DEFAULTS;
|
|
50
|
+
if (fnLevel !== void 0) return normalize(fnLevel);
|
|
51
|
+
if (clientLevel === false) return void 0;
|
|
52
|
+
if (clientLevel === true) return DEFAULTS;
|
|
53
|
+
if (clientLevel !== void 0) return normalize(clientLevel);
|
|
54
|
+
return DEFAULTS;
|
|
55
|
+
};
|
|
56
|
+
const toRegistration = (cfg) => ({
|
|
57
|
+
batch_steps: cfg.bufferedSteps,
|
|
58
|
+
batch_interval: timeStr(cfg.maxInterval),
|
|
59
|
+
max_runtime: timeStr(cfg.maxRuntime)
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Construct a `CheckpointState`. Caller supplies a pre-bound `checkpointAsync`
|
|
63
|
+
* callback (typically `(steps) => client.checkpointAsync({runId, fnId, qiId, steps})`),
|
|
64
|
+
* so this module has no dependency on `InngestClient`.
|
|
65
|
+
*/
|
|
66
|
+
const make = (args) => Effect.sync(() => {
|
|
67
|
+
const buffer = Ref.makeUnsafe([]);
|
|
68
|
+
const intervalStartedAt = Ref.makeUnsafe(Option.none());
|
|
69
|
+
const runtimeExceeded = Ref.makeUnsafe(false);
|
|
70
|
+
const maxIntervalMs = Duration.toMillis(args.config.maxInterval);
|
|
71
|
+
const flushInner = Effect.gen(function* () {
|
|
72
|
+
const steps = yield* Ref.modify(buffer, (current) => [current, []]);
|
|
73
|
+
if (steps.length === 0) return;
|
|
74
|
+
const result = yield* Effect.result(args.checkpointAsync(steps));
|
|
75
|
+
if (Result.isFailure(result)) {
|
|
76
|
+
yield* Ref.update(buffer, (current) => [...steps, ...current]);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
yield* Ref.set(intervalStartedAt, Option.none());
|
|
80
|
+
});
|
|
81
|
+
const bufferStep = (op) => Effect.gen(function* () {
|
|
82
|
+
const len = yield* Ref.modify(buffer, (current) => {
|
|
83
|
+
const next = [...current, op];
|
|
84
|
+
return [next.length, next];
|
|
85
|
+
});
|
|
86
|
+
const now = yield* Clock.currentTimeMillis;
|
|
87
|
+
const start = yield* Ref.get(intervalStartedAt);
|
|
88
|
+
if (len >= args.config.bufferedSteps) {
|
|
89
|
+
yield* flushInner;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (Option.isSome(start) && maxIntervalMs > 0 && now - start.value >= maxIntervalMs) {
|
|
93
|
+
yield* flushInner;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (Option.isNone(start) && maxIntervalMs > 0) yield* Ref.set(intervalStartedAt, Option.some(now));
|
|
97
|
+
});
|
|
98
|
+
const drain = Ref.modify(buffer, (current) => [current, []]);
|
|
99
|
+
return {
|
|
100
|
+
config: args.config,
|
|
101
|
+
runId: args.runId,
|
|
102
|
+
fnId: args.fnId,
|
|
103
|
+
qiId: args.qiId,
|
|
104
|
+
bufferStep,
|
|
105
|
+
flush: flushInner,
|
|
106
|
+
drain,
|
|
107
|
+
markRuntimeExceeded: Ref.set(runtimeExceeded, true),
|
|
108
|
+
isRuntimeExceeded: Ref.get(runtimeExceeded)
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
//#endregion
|
|
112
|
+
export { CheckpointApiError, make, resolveConfig, toRegistration };
|