@ontemper/sdk 0.0.0 → 0.1.0-rc.1

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 CHANGED
@@ -1,3 +1,152 @@
1
- # @ontemper/sdk
1
+ # `@temper/workflow`
2
2
 
3
- Placeholder. Temper publishes the workflow SDK here from CI. Pin an exact version.
3
+ Build a Temper workflow with Effect HTTP API contracts. The SDK creates a Web handler. Temper and the local CLI call the same `fetch(Request, InvocationContext)` method.
4
+
5
+ ## Define a workflow
6
+
7
+ ```ts
8
+ import { Effect, Schema } from 'effect';
9
+ import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';
10
+ import { Invocation, Trigger, workflow } from '@temper/workflow';
11
+
12
+ const SyncResult = Schema.Struct({ executionId: Schema.String });
13
+
14
+ const SyncGroup = HttpApiGroup.make('sync').add(
15
+ HttpApiEndpoint.post('run', '/sync', {
16
+ payload: Schema.Struct({ key: Schema.String }),
17
+ success: SyncResult,
18
+ }).annotate(Trigger, { kind: 'http' }),
19
+ );
20
+
21
+ const Api = HttpApi.make('example-workflow').add(SyncGroup);
22
+
23
+ const Handlers = HttpApiBuilder.group(Api, 'sync', (handlers) =>
24
+ handlers.handle('run', ({ payload }) =>
25
+ Effect.gen(function* () {
26
+ const invocation = yield* Invocation;
27
+ return { executionId: invocation.executionId };
28
+ }),
29
+ ),
30
+ );
31
+
32
+ export default workflow({ api: Api, handlers: Handlers });
33
+ ```
34
+
35
+ Every endpoint must have a `Trigger` annotation. Supported kinds are `http`, `schedule`, `manual`, and `internal`. Module construction fails when an endpoint has no annotation or carries a default that does not belong to its kind.
36
+
37
+ Kinds accept optional defaults that deploy seeds into stored platform records when none exist; a stored record edited later always wins:
38
+
39
+ ```ts
40
+ .annotate(Trigger, { kind: 'http', response: 'ack' })
41
+ .annotate(Trigger, { kind: 'schedule', cron: '*/10 * * * *', timezone: 'UTC' })
42
+ ```
43
+
44
+ A manifest-created Schedule is disabled. Verify the deployed route and its bindings, then enable it
45
+ through the Schedule surface. Deploying source MUST NOT start external work by itself.
46
+
47
+ Customer code does not start a listener. It exports the workflow module.
48
+
49
+ ## Run locally
50
+
51
+ ```sh
52
+ temper-workflow dev --entrypoint src/index.ts --host 127.0.0.1 --port 3051
53
+ ```
54
+
55
+ The CLI rebuilds and reloads the workflow when a file in the entrypoint directory changes. It closes the old workflow after a successful reload.
56
+
57
+ Run compiled JavaScript in a trusted host:
58
+
59
+ ```sh
60
+ temper-workflow serve --entrypoint dist/index.js --host 0.0.0.0 --port 3051
61
+ ```
62
+
63
+ The `serve` command loads once. It does not rebuild or watch files.
64
+
65
+ Invoke one request without a listener:
66
+
67
+ ```sh
68
+ temper-workflow invoke --entrypoint src/index.ts --method POST --path /sync --body '{"key":"value"}'
69
+ ```
70
+
71
+ ## Invocation context
72
+
73
+ `fetch(request, context)` receives the exact object the Firecracker guest builds:
74
+
75
+ ```ts
76
+ type InvocationContext = {
77
+ workflowId: string;
78
+ deploymentId: string;
79
+ executionId: string;
80
+ runId: string; // durable Run identity
81
+ attempt: number; // 1-based
82
+ triggerKind: 'http' | 'schedule' | 'manual' | 'agent' | 'as2' | 'sftp' | 'kafka' | 'child';
83
+ deadline: number; // epoch milliseconds
84
+ token: string; // run-scoped platform token
85
+ };
86
+ ```
87
+
88
+ The SDK owns three runtime behaviours around every handler:
89
+
90
+ 1. Logs: every `Effect.log*` call becomes one JSON line on stdout with `level`, `message`, `runId`,
91
+ `executionId`, `attempt`, and `traceparent`.
92
+ 2. Deadline: when `context.deadline` passes, the handler fiber is interrupted, finalizers run, and the
93
+ response is `504 { _tag: 'InvocationDeadlineExceeded' }`.
94
+ 3. Headers: platform `x-temper-*` request headers are removed before the handler runs.
95
+
96
+ ## Invoke in a test
97
+
98
+ ```ts
99
+ import { invoke, testInvocation } from '@temper/workflow/testing';
100
+ import workflowModule from '../src/index.js';
101
+
102
+ const response = await invoke(workflowModule, {
103
+ request: new Request('http://localhost/sync', {
104
+ method: 'POST',
105
+ headers: { 'content-type': 'application/json' },
106
+ body: JSON.stringify({ key: 'value' }),
107
+ }),
108
+ context: testInvocation({ runId: 'run-1' }),
109
+ });
110
+ ```
111
+
112
+ `testInvocation()` fills every field with a stable default and no deadline.
113
+
114
+ ## Versions
115
+
116
+ CI publishes every version to npm as `@ontemper/sdk`; nobody publishes by hand. Workflow code keeps
117
+ importing `@temper/workflow` through an npm alias. `sdk/workflow/package.json` holds a plain
118
+ `x.y.z` base, and CI adds the suffix: `x.y.z-pr.<N>.<sha>` previews under `pr-<N>`, `x.y.z-rc.<N>`
119
+ release candidates under `next`, and `x.y.z` under `latest`. Pin one exact version:
120
+
121
+ ```sh
122
+ npm install --save-exact @temper/workflow@npm:@ontemper/sdk@<version>
123
+ ```
124
+
125
+ A published version never changes. Until the first release candidate exists, the workflow template
126
+ and the examples install a vendored canary tarball.
127
+
128
+ ## Develop and release
129
+
130
+ Work locally first; a pull request preview is for a dev stack only.
131
+
132
+ | Loop | Command |
133
+ | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
134
+ | Unit tests | `pnpm --filter @temper/workflow test` |
135
+ | Every example against your change | `pnpm --dir sdk/workflow pack --pack-destination /tmp/sdk`, then `WORKFLOW_SDK_TARBALL=/tmp/sdk/<file>.tgz bash scripts/check-workflow-examples.sh` |
136
+ | Another workflow repository | `npm install @temper/workflow@file:/tmp/sdk/<file>.tgz` |
137
+ | A dev stack | Open a pull request into `stg`; CI publishes `x.y.z-pr.<N>.<sha>` in about 5 minutes. Deploy it with `scripts/seed-example-workflow.ts --sdk-version <version>` |
138
+
139
+ Before the change merges, raise the base version in `package.json` and `SDK_VERSION` in `src/Manifest.ts`
140
+ to the same `x.y.z`; `scripts/check-sdk-consistency.ts` fails if they differ. CI refuses to release a
141
+ base that is already stable on npm.
142
+
143
+ | Change | Base version |
144
+ | ------------------------------------------- | ------------------------ |
145
+ | Bug fix | patch: `0.2.0` → `0.2.1` |
146
+ | New feature or breaking change (before 1.0) | minor: `0.2.1` → `0.3.0` |
147
+
148
+ Raise `RUNTIME_API_VERSION` only when the SDK needs a changed platform runtime protocol.
149
+
150
+ Merging to `stg` publishes a release candidate and opens a pin pull request for the template and
151
+ examples. Promoting to `prod` publishes the stable version after an approval in the `sdk-stable`
152
+ environment.
@@ -0,0 +1,26 @@
1
+ import { Context } from 'effect';
2
+ /** Who admitted this invocation. Mirrors the platform `RunTriggerKind`; `http` is the guest default. */
3
+ export type InvocationTriggerKind = 'http' | 'schedule' | 'manual' | 'agent' | 'as2' | 'sftp' | 'kafka' | 'child';
4
+ /**
5
+ * The exact object the Firecracker guest passes as the second `fetch` argument.
6
+ * Fields are additive only: the platform may append, never rename or remove.
7
+ */
8
+ export interface InvocationContext {
9
+ readonly workflowId: string;
10
+ readonly deploymentId: string;
11
+ readonly executionId: string;
12
+ /** Durable Run identity. Empty when a host predates unified Run admission. */
13
+ readonly runId: string;
14
+ /** 1-based attempt counter for this Run. */
15
+ readonly attempt: number;
16
+ readonly triggerKind: InvocationTriggerKind;
17
+ /** Absolute epoch milliseconds. The SDK interrupts the handler fiber when it passes. */
18
+ readonly deadline: number;
19
+ /** Run-scoped platform token for AS2, EDI, and Resource calls. Empty outside a platform host. */
20
+ readonly token: string;
21
+ }
22
+ declare const Invocation_base: Context.ServiceClass<Invocation, "@temper/workflow/Invocation", InvocationContext>;
23
+ export declare class Invocation extends Invocation_base {
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=Invocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Invocation.d.ts","sourceRoot":"","sources":["../src/Invocation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,wGAAwG;AACxG,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAElH;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC;IAC5C,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iGAAiG;IACjG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;;AAED,qBAAa,UAAW,SAAQ,eAA+E;CAAG"}
@@ -0,0 +1,4 @@
1
+ import { Context } from 'effect';
2
+ export class Invocation extends Context.Service()('@temper/workflow/Invocation') {
3
+ }
4
+ //# sourceMappingURL=Invocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Invocation.js","sourceRoot":"","sources":["../src/Invocation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAwBjC,MAAM,OAAO,UAAW,SAAQ,OAAO,CAAC,OAAO,EAAiC,CAAC,6BAA6B,CAAC;CAAG"}
@@ -0,0 +1,5 @@
1
+ import { Logger } from 'effect';
2
+ export declare const writeStdoutLine: (line: string) => void;
3
+ /** Replaces the default console logger for every workflow request fiber. */
4
+ export declare const makeWorkflowLoggers: (writeLine: (line: string) => void) => ReadonlySet<Logger.Logger<unknown, unknown>>;
5
+ //# sourceMappingURL=Logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAc,MAAM,QAAQ,CAAC;AA0CnD,eAAO,MAAM,eAAe,SAAU,MAAM,KAAG,IAE9C,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,cAAe,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAK/G,CAAC"}
package/dist/Logger.js ADDED
@@ -0,0 +1,46 @@
1
+ import { Cause, Logger, References } from 'effect';
2
+ const levelOf = (logLevel) => {
3
+ switch (logLevel) {
4
+ case 'Fatal':
5
+ return 'fatal';
6
+ case 'Error':
7
+ return 'error';
8
+ case 'Warn':
9
+ return 'warn';
10
+ case 'Info':
11
+ return 'info';
12
+ default:
13
+ return 'debug';
14
+ }
15
+ };
16
+ /**
17
+ * One JSON object per line on stdout, in the shape the Firecracker guest and the
18
+ * legacy `unnbound-logger-sdk` ingestion read: lowercase `level`, `message`, run identity,
19
+ * and log annotations as top-level keys. The middleware annotates every handler with its
20
+ * invocation, so handlers only call `Effect.log*`. The first log argument is the message text;
21
+ * further arguments land in `details`. Fixed keys win over annotations.
22
+ */
23
+ const workflowLineLogger = Logger.make(({ cause, date, fiber, logLevel, message }) => {
24
+ const messages = Array.isArray(message) ? message : [message];
25
+ const [head, ...rest] = messages;
26
+ return JSON.stringify({
27
+ ...fiber.getRef(References.CurrentLogAnnotations),
28
+ level: levelOf(logLevel),
29
+ message: String(head),
30
+ logId: crypto.randomUUID(),
31
+ timestamp: date.toISOString(),
32
+ source: 'workflow',
33
+ details: rest.length > 0 ? rest : undefined,
34
+ cause: cause.reasons.length > 0 ? Cause.pretty(cause) : undefined,
35
+ });
36
+ });
37
+ export const writeStdoutLine = (line) => {
38
+ process.stdout.write(`${line}\n`);
39
+ };
40
+ /** Replaces the default console logger for every workflow request fiber. */
41
+ export const makeWorkflowLoggers = (writeLine) => new Set([
42
+ Logger.make((options) => {
43
+ writeLine(workflowLineLogger.log(options));
44
+ }),
45
+ ]);
46
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAKnD,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAoB,EAAE;IACrD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAkB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;IACpG,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC;IACjC,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,qBAAqB,CAAC;QACjD,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE;QAC1B,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE;QAC7B,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC3C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;KAClE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAQ,EAAE;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,SAAiC,EAAgD,EAAE,CACrH,IAAI,GAAG,CAAC;IACN,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACtB,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC;CACH,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { HttpApi, type HttpApiGroup } from 'effect/unstable/httpapi';
2
+ import { TriggerMetadata } from './Trigger.js';
3
+ export declare const SDK_VERSION = "0.1.0-rc.1";
4
+ export declare const RUNTIME_API_VERSION = 1;
5
+ export interface WorkflowManifestEndpoint {
6
+ readonly group: string;
7
+ readonly name: string;
8
+ readonly method: string;
9
+ readonly path: string;
10
+ readonly trigger: TriggerMetadata;
11
+ }
12
+ export interface WorkflowManifest {
13
+ readonly version: 1;
14
+ readonly sdkVersion: typeof SDK_VERSION;
15
+ readonly runtimeApiVersion: typeof RUNTIME_API_VERSION;
16
+ readonly apiId: string;
17
+ readonly endpoints: ReadonlyArray<WorkflowManifestEndpoint>;
18
+ }
19
+ export declare const makeManifest: <Id extends string, Groups extends HttpApiGroup.Constraint>(api: HttpApi.HttpApi<Id, Groups>) => WorkflowManifest;
20
+ //# sourceMappingURL=Manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Manifest.d.ts","sourceRoot":"","sources":["../src/Manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAW,eAAe,EAAE,MAAM,cAAc,CAAC;AAIxD,eAAO,MAAM,WAAW,eAAe,CAAC;AACxC,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,OAAO,WAAW,CAAC;IACxC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,mBAAmB,CAAC;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,wBAAwB,CAAC,CAAC;CAC7D;AAUD,eAAO,MAAM,YAAY,GAAI,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU,OAC/E,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,KAC/B,gBA+BF,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { Context, Option, Schema } from 'effect';
2
+ import { HttpApi } from 'effect/unstable/httpapi';
3
+ import { Trigger, TriggerMetadata } from './Trigger.js';
4
+ const decodeTrigger = Schema.decodeUnknownSync(TriggerMetadata, { onExcessProperty: 'error' });
5
+ export const SDK_VERSION = '0.1.0-rc.1';
6
+ export const RUNTIME_API_VERSION = 1;
7
+ const compareText = (left, right) => (left < right ? -1 : left > right ? 1 : 0);
8
+ const compareEndpoints = (left, right) => compareText(left.group, right.group) ||
9
+ compareText(left.name, right.name) ||
10
+ compareText(left.method, right.method) ||
11
+ compareText(left.path, right.path);
12
+ export const makeManifest = (api) => {
13
+ const endpoints = [];
14
+ HttpApi.reflect(api, {
15
+ onGroup() { },
16
+ onEndpoint({ endpoint, group }) {
17
+ const trigger = Option.getOrUndefined(Context.getOption(endpoint.annotations, Trigger));
18
+ if (trigger === undefined) {
19
+ throw new Error(`Endpoint ${group.identifier}.${endpoint.identifier} must have a Trigger annotation.`);
20
+ }
21
+ endpoints.push(Object.freeze({
22
+ group: group.identifier,
23
+ name: endpoint.identifier,
24
+ method: endpoint.method,
25
+ path: endpoint.path,
26
+ // Validated so a typo in a default never reaches the deploy that seeds records from it.
27
+ trigger: Object.freeze(decodeTrigger(trigger)),
28
+ }));
29
+ },
30
+ });
31
+ endpoints.sort(compareEndpoints);
32
+ return Object.freeze({
33
+ version: 1,
34
+ sdkVersion: SDK_VERSION,
35
+ runtimeApiVersion: RUNTIME_API_VERSION,
36
+ apiId: api.identifier,
37
+ endpoints: Object.freeze(endpoints),
38
+ });
39
+ };
40
+ //# sourceMappingURL=Manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Manifest.js","sourceRoot":"","sources":["../src/Manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,OAAO,EAAqB,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,aAAa,GAAG,MAAM,CAAC,iBAAiB,CAAC,eAAe,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC;AAE/F,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC;AACxC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAkBrC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExG,MAAM,gBAAgB,GAAG,CAAC,IAA8B,EAAE,KAA+B,EAAU,EAAE,CACnG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IACpC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IAClC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACtC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,GAAgC,EACd,EAAE;IACpB,MAAM,SAAS,GAAoC,EAAE,CAAC;IAEtD,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;QACnB,OAAO,KAAI,CAAC;QACZ,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;YAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;YACxF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,YAAY,KAAK,CAAC,UAAU,IAAI,QAAQ,CAAC,UAAU,kCAAkC,CAAC,CAAC;YACzG,CAAC;YACD,SAAS,CAAC,IAAI,CACZ,MAAM,CAAC,MAAM,CAAC;gBACZ,KAAK,EAAE,KAAK,CAAC,UAAU;gBACvB,IAAI,EAAE,QAAQ,CAAC,UAAU;gBACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,wFAAwF;gBACxF,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;aAC/C,CAAC,CACH,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,WAAW;QACvB,iBAAiB,EAAE,mBAAmB;QACtC,KAAK,EAAE,GAAG,CAAC,UAAU;QACrB,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;KACpC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { HttpRouter } from 'effect/unstable/http';
2
+ /** Wire body of the SDK-owned 504 when `InvocationContext.deadline` passes. */
3
+ export interface DeadlineExceededBody {
4
+ readonly _tag: 'InvocationDeadlineExceeded';
5
+ readonly runId: string;
6
+ readonly executionId: string;
7
+ readonly deadline: string;
8
+ }
9
+ export declare const InvocationMiddlewareLive: import("effect/Layer").Layer<never, never, HttpRouter.HttpRouter>;
10
+ //# sourceMappingURL=Middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Middleware.d.ts","sourceRoot":"","sources":["../src/Middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAC;AAGzF,+EAA+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAgDD,eAAO,MAAM,wBAAwB,mEAAyE,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { Context, Duration, Effect } from 'effect';
2
+ import { HttpRouter, HttpServerRequest, HttpServerResponse } from 'effect/unstable/http';
3
+ import { Invocation } from './Invocation.js';
4
+ const deadlineResponse = (invocation) => Effect.logError('workflow.invocation_deadline_exceeded').pipe(Effect.as(HttpServerResponse.jsonUnsafe({
5
+ _tag: 'InvocationDeadlineExceeded',
6
+ runId: invocation.runId,
7
+ executionId: invocation.executionId,
8
+ deadline: new Date(invocation.deadline).toISOString(),
9
+ }, { status: 504 })));
10
+ /**
11
+ * Every handler runs under the invocation identity and its deadline.
12
+ * Logs carry run correlation; the fiber is interrupted, with finalizers, when the deadline passes.
13
+ */
14
+ const withInvocation = (effect) => Effect.withFiber((fiber) => {
15
+ const invocation = Context.getUnsafe(fiber.context, Invocation);
16
+ const request = Context.getUnsafe(fiber.context, HttpServerRequest.HttpServerRequest);
17
+ const traceparent = request.headers.traceparent;
18
+ const annotations = {
19
+ workflowId: invocation.workflowId,
20
+ deploymentId: invocation.deploymentId,
21
+ executionId: invocation.executionId,
22
+ runId: invocation.runId,
23
+ attempt: invocation.attempt,
24
+ triggerKind: invocation.triggerKind,
25
+ traceparent,
26
+ };
27
+ if (!Number.isFinite(invocation.deadline))
28
+ return effect.pipe(Effect.annotateLogs(annotations));
29
+ const remaining = Math.max(0, invocation.deadline - Date.now());
30
+ return effect.pipe(Effect.timeoutOrElse({
31
+ duration: Duration.millis(remaining),
32
+ orElse: () => deadlineResponse(invocation),
33
+ }), Effect.annotateLogs(annotations));
34
+ });
35
+ export const InvocationMiddlewareLive = HttpRouter.use((router) => router.addGlobalMiddleware(withInvocation));
36
+ //# sourceMappingURL=Middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Middleware.js","sourceRoot":"","sources":["../src/Middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAU7C,MAAM,gBAAgB,GAAG,CAAC,UAAiC,EAAE,EAAE,CAC7D,MAAM,CAAC,QAAQ,CAAC,uCAAuC,CAAC,CAAC,IAAI,CAC3D,MAAM,CAAC,EAAE,CACP,kBAAkB,CAAC,UAAU,CAC3B;IACE,IAAI,EAAE,4BAA4B;IAClC,KAAK,EAAE,UAAU,CAAC,KAAK;IACvB,WAAW,EAAE,UAAU,CAAC,WAAW;IACnC,QAAQ,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE;CACvB,EAChC,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CACF,CACF,CAAC;AAEJ;;;GAGG;AACH,MAAM,cAAc,GAAG,CACrB,MAAkE,EACN,EAAE,CAC9D,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;IACzB,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IACtF,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;IAChD,MAAM,WAAW,GAAG;QAClB,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,YAAY,EAAE,UAAU,CAAC,YAAY;QACrC,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,WAAW;KACZ,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;IAChG,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC,IAAI,CAChB,MAAM,CAAC,aAAa,CAAC;QACnB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;QACpC,MAAM,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC;KAC3C,CAAC,EACF,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CACjC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { Context, Schema } from 'effect';
2
+ export declare const TriggerKind: Schema.Literals<readonly ["http", "schedule", "manual", "internal"]>;
3
+ export type TriggerKind = typeof TriggerKind.Type;
4
+ export declare const ResponsePolicy: Schema.Literals<readonly ["wait", "ack"]>;
5
+ export type ResponsePolicy = typeof ResponsePolicy.Type;
6
+ /**
7
+ * How the platform invokes one route. `kind` is the contract; the other fields are DEFAULTS that
8
+ * deploy seeds into the stored Trigger and Schedule records when none exist. A stored record edited
9
+ * through the product or the Temper agent always wins afterwards; deploy reports the drift.
10
+ */
11
+ export declare const TriggerMetadata: Schema.Union<readonly [Schema.Struct<{
12
+ readonly kind: Schema.Literal<"http">;
13
+ /** Default response policy for the stored Trigger: `wait` returns the handler response, `ack` returns 202. */
14
+ readonly response: Schema.optional<Schema.Literals<readonly ["wait", "ack"]>>;
15
+ }>, Schema.Struct<{
16
+ readonly kind: Schema.Literal<"schedule">;
17
+ /** Default cadence for the stored Schedule; five-field cron. Without it deploy warns until a Schedule exists. */
18
+ readonly cron: Schema.optional<Schema.String>;
19
+ /** IANA timezone for `cron`; the platform default is UTC. */
20
+ readonly timezone: Schema.optional<Schema.String>;
21
+ }>, Schema.Struct<{
22
+ readonly kind: Schema.Literal<"manual">;
23
+ }>, Schema.Struct<{
24
+ readonly kind: Schema.Literal<"internal">;
25
+ }>]>;
26
+ export type TriggerMetadata = typeof TriggerMetadata.Type;
27
+ declare const Trigger_base: Context.ServiceClass<Trigger, "@temper/workflow/Trigger", {
28
+ readonly kind: "http";
29
+ readonly response?: "ack" | "wait" | undefined;
30
+ } | {
31
+ readonly kind: "schedule";
32
+ readonly cron?: string | undefined;
33
+ readonly timezone?: string | undefined;
34
+ } | {
35
+ readonly kind: "manual";
36
+ } | {
37
+ readonly kind: "internal";
38
+ }>;
39
+ export declare class Trigger extends Trigger_base {
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=Trigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Trigger.d.ts","sourceRoot":"","sources":["../src/Trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,eAAO,MAAM,WAAW,sEAA8D,CAAC;AACvF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAC;AAElD,eAAO,MAAM,cAAc,2CAAmC,CAAC;AAC/D,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;IAGxB,8GAA8G;;;;IAK9G,iHAAiH;;IAEjH,6DAA6D;;;;;;IAK/D,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;;;;;;;;;;;;;AAE1D,qBAAa,OAAQ,SAAQ,YAAuE;CAAG"}
@@ -0,0 +1,27 @@
1
+ import { Context, Schema } from 'effect';
2
+ export const TriggerKind = Schema.Literals(['http', 'schedule', 'manual', 'internal']);
3
+ export const ResponsePolicy = Schema.Literals(['wait', 'ack']);
4
+ /**
5
+ * How the platform invokes one route. `kind` is the contract; the other fields are DEFAULTS that
6
+ * deploy seeds into the stored Trigger and Schedule records when none exist. A stored record edited
7
+ * through the product or the Temper agent always wins afterwards; deploy reports the drift.
8
+ */
9
+ export const TriggerMetadata = Schema.Union([
10
+ Schema.Struct({
11
+ kind: Schema.Literal('http'),
12
+ /** Default response policy for the stored Trigger: `wait` returns the handler response, `ack` returns 202. */
13
+ response: Schema.optional(ResponsePolicy),
14
+ }),
15
+ Schema.Struct({
16
+ kind: Schema.Literal('schedule'),
17
+ /** Default cadence for the stored Schedule; five-field cron. Without it deploy warns until a Schedule exists. */
18
+ cron: Schema.optional(Schema.String),
19
+ /** IANA timezone for `cron`; the platform default is UTC. */
20
+ timezone: Schema.optional(Schema.String),
21
+ }),
22
+ Schema.Struct({ kind: Schema.Literal('manual') }),
23
+ Schema.Struct({ kind: Schema.Literal('internal') }),
24
+ ]);
25
+ export class Trigger extends Context.Service()('@temper/workflow/Trigger') {
26
+ }
27
+ //# sourceMappingURL=Trigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Trigger.js","sourceRoot":"","sources":["../src/Trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAGvF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAG/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1C,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC5B,8GAA8G;QAC9G,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;KAC1C,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QAChC,iHAAiH;QACjH,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;QACpC,6DAA6D;QAC7D,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;KACzC,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IACjD,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;CACpD,CAAC,CAAC;AAGH,MAAM,OAAO,OAAQ,SAAQ,OAAO,CAAC,OAAO,EAA4B,CAAC,0BAA0B,CAAC;CAAG"}
@@ -0,0 +1,19 @@
1
+ import { Layer } from 'effect';
2
+ import { HttpRouter } from 'effect/unstable/http';
3
+ import { type HttpApi, type HttpApiGroup } from 'effect/unstable/httpapi';
4
+ import { Invocation, type InvocationContext } from './Invocation.js';
5
+ import { type WorkflowManifest } from './Manifest.js';
6
+ export interface WorkflowModule<Api extends HttpApi.Constraint = HttpApi.Constraint> {
7
+ readonly api: Api;
8
+ readonly manifest: WorkflowManifest;
9
+ readonly fetch: (request: Request, context: InvocationContext) => Promise<Response>;
10
+ readonly dispose: () => Promise<void>;
11
+ }
12
+ export interface WorkflowOptions<Id extends string, Groups extends HttpApiGroup.Constraint> {
13
+ readonly api: HttpApi.HttpApi<Id, Groups>;
14
+ readonly handlers: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, never, HttpRouter.Request.From<'Requires', Invocation>>;
15
+ /** Receives one JSON log line per `Effect.log*` call. Defaults to stdout, which the platform reads. */
16
+ readonly writeLog?: (line: string) => void;
17
+ }
18
+ export declare const workflow: <Id extends string, Groups extends HttpApiGroup.Constraint>(options: WorkflowOptions<Id, Groups>) => WorkflowModule<HttpApi.HttpApi<Id, Groups>>;
19
+ //# sourceMappingURL=Workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Workflow.d.ts","sourceRoot":"","sources":["../src/Workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,EAAoB,MAAM,QAAQ,CAAC;AACtE,OAAO,EAAsB,UAAU,EAAkC,MAAM,sBAAsB,CAAC;AACtG,OAAO,EAAkB,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAkBpE,MAAM,WAAW,cAAc,CAAC,GAAG,SAAS,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU;IACjF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU;IACxF,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAC5B,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,EAClC,KAAK,EACL,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAChD,CAAC;IACF,uGAAuG;IACvG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAWD,eAAO,MAAM,QAAQ,GAAI,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU,WACvE,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,KACnC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAyB5C,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { Context, FileSystem, Layer, Path, References } from 'effect';
2
+ import { Etag, HttpPlatform, HttpRouter, HttpServer, HttpServerResponse } from 'effect/unstable/http';
3
+ import { HttpApiBuilder } from 'effect/unstable/httpapi';
4
+ import { Invocation } from './Invocation.js';
5
+ import { makeWorkflowLoggers, writeStdoutLine } from './Logger.js';
6
+ import { makeManifest } from './Manifest.js';
7
+ import { InvocationMiddlewareLive } from './Middleware.js';
8
+ /**
9
+ * Kubernetes probes every workflow pod on `GET /healthcheck` (startup, liveness, readiness). The
10
+ * runtime owns that route so a migrated workflow cannot crash-loop by omitting it. It is composed
11
+ * onto the router ahead of the user API, so it is served regardless of the user's `Api` and never
12
+ * appears in the manifest.
13
+ */
14
+ const PlatformRoutes = HttpRouter.add('GET', '/healthcheck', HttpServerResponse.jsonUnsafe({ status: 'ok' }));
15
+ const InMemoryHttpPlatform = Layer.mergeAll(HttpPlatform.layer.pipe(Layer.provide(FileSystem.layerNoop({}))), FileSystem.layerNoop({}), Path.layer, Etag.layerWeak);
16
+ /** Platform run metadata travels in `context`; the header copies are removed so handlers cannot drift onto them. */
17
+ const stripPlatformHeaders = (request) => {
18
+ const names = [];
19
+ request.headers.forEach((_value, name) => {
20
+ if (name.startsWith('x-temper-'))
21
+ names.push(name);
22
+ });
23
+ for (const name of names)
24
+ request.headers.delete(name);
25
+ };
26
+ export const workflow = (options) => {
27
+ const manifest = makeManifest(options.api);
28
+ const appLayer = Layer.mergeAll(PlatformRoutes, HttpApiBuilder.layer(options.api).pipe(Layer.provide(options.handlers)), InvocationMiddlewareLive).pipe(Layer.provide(HttpServer.layerServices), Layer.provide(InMemoryHttpPlatform));
29
+ const web = HttpRouter.toWebHandler(appLayer, { disableLogger: true });
30
+ // SAFETY: WorkflowOptions accepts a complete handler layer whose only request service is Invocation.
31
+ const handler = web.handler;
32
+ const loggers = makeWorkflowLoggers(options.writeLog ?? writeStdoutLine);
33
+ return Object.freeze({
34
+ api: options.api,
35
+ manifest,
36
+ fetch: (request, invocation) => {
37
+ stripPlatformHeaders(request);
38
+ // Loggers ride on the request context so middleware and handlers share them.
39
+ return handler(request, Context.make(Invocation, invocation).pipe(Context.add(References.CurrentLoggers, loggers)));
40
+ },
41
+ dispose: web.dispose,
42
+ });
43
+ };
44
+ //# sourceMappingURL=Workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Workflow.js","sourceRoot":"","sources":["../src/Workflow.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ export declare const runCli: (arguments_: ReadonlyArray<string>) => Promise<void>;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAyTA,eAAO,MAAM,MAAM,eAAsB,aAAa,CAAC,MAAM,CAAC,KAAG,OAAO,CAAC,IAAI,CAK5E,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env bun
2
+ import { execFile } from 'node:child_process';
3
+ import { watch } from 'node:fs';
4
+ import { mkdtemp, rm } from 'node:fs/promises';
5
+ import { createServer } from 'node:http';
6
+ import { tmpdir } from 'node:os';
7
+ import { dirname, join, resolve } from 'node:path';
8
+ import { fileURLToPath, pathToFileURL } from 'node:url';
9
+ const usage = `Usage:
10
+ temper-workflow dev --entrypoint <file> [--host 127.0.0.1] [--port 3051]
11
+ temper-workflow serve --entrypoint <file> [--host 0.0.0.0] [--port 3051]
12
+ temper-workflow invoke --entrypoint <file> [--method POST] [--path /] [--body <text>]
13
+ `;
14
+ const fail = (message) => {
15
+ throw new Error(`${message}\n\n${usage}`);
16
+ };
17
+ const parseCommand = (value) => {
18
+ if (value === 'dev' || value === 'invoke' || value === 'serve')
19
+ return value;
20
+ return fail('Use dev, serve, or invoke.');
21
+ };
22
+ const optionValue = (arguments_, name) => {
23
+ const index = arguments_.indexOf(name);
24
+ if (index === -1)
25
+ return undefined;
26
+ const value = arguments_[index + 1];
27
+ if (value === undefined || value.startsWith('--'))
28
+ fail(`Missing value for ${name}.`);
29
+ return value;
30
+ };
31
+ const parseArguments = (arguments_) => {
32
+ const command = parseCommand(arguments_[0]);
33
+ const entrypoint = optionValue(arguments_, '--entrypoint') ?? fail('Missing --entrypoint.');
34
+ const host = optionValue(arguments_, '--host') ?? (command === 'serve' ? '0.0.0.0' : '127.0.0.1');
35
+ if (command === 'dev' && host !== '127.0.0.1' && host !== 'localhost' && host !== '::1') {
36
+ fail('The dev listener must use a localhost address.');
37
+ }
38
+ const portText = optionValue(arguments_, '--port') ?? process.env.PORT ?? '3051';
39
+ const port = Number(portText);
40
+ if (!Number.isInteger(port) || port < 0 || port > 65_535)
41
+ fail('--port must be between 0 and 65535.');
42
+ const path = optionValue(arguments_, '--path') ?? '/';
43
+ if (!path.startsWith('/'))
44
+ fail('--path must start with /.');
45
+ return {
46
+ command,
47
+ entrypoint: resolve(entrypoint),
48
+ host,
49
+ port,
50
+ method: (optionValue(arguments_, '--method') ?? 'POST').toUpperCase(),
51
+ path,
52
+ body: optionValue(arguments_, '--body'),
53
+ };
54
+ };
55
+ const importWorkflowModule = async (url) => {
56
+ // SAFETY: a dynamic module namespace is checked for its required default export before use.
57
+ return (await import(url));
58
+ };
59
+ const moduleFromImport = (imported, entrypoint) => {
60
+ if (imported.default === undefined)
61
+ return fail(`${entrypoint} must export a default workflow.`);
62
+ return imported.default;
63
+ };
64
+ const buildEntrypoint = (entrypoint, output) => {
65
+ const build = Promise.withResolvers();
66
+ execFile(process.execPath, [
67
+ 'build',
68
+ entrypoint,
69
+ '--target',
70
+ 'bun',
71
+ '--format',
72
+ 'esm',
73
+ '--outfile',
74
+ output,
75
+ // SSH2 falls back to Node crypto when its optional native addons are absent.
76
+ '--external',
77
+ '*/sshcrypto.node',
78
+ '--external',
79
+ '*/cpufeatures.node',
80
+ ], { encoding: 'utf8' }, (error, _stdout, stderr) => {
81
+ if (error === null) {
82
+ build.resolve(undefined);
83
+ return;
84
+ }
85
+ build.reject(new Error(`Workflow build failed.\n${stderr.trim()}`));
86
+ });
87
+ return build.promise;
88
+ };
89
+ const loadWorkflow = async (entrypoint) => {
90
+ const directory = await mkdtemp(join(tmpdir(), 'temper-workflow-'));
91
+ const output = join(directory, 'workflow.mjs');
92
+ try {
93
+ await buildEntrypoint(entrypoint, output);
94
+ const imported = await importWorkflowModule(pathToFileURL(output).href);
95
+ const module = moduleFromImport(imported, entrypoint);
96
+ return {
97
+ module,
98
+ dispose: async () => {
99
+ try {
100
+ await module.dispose();
101
+ }
102
+ finally {
103
+ await rm(directory, { recursive: true, force: true });
104
+ }
105
+ },
106
+ };
107
+ }
108
+ catch (error) {
109
+ await rm(directory, { recursive: true, force: true });
110
+ throw error;
111
+ }
112
+ };
113
+ const loadBuiltWorkflow = async (entrypoint) => {
114
+ const imported = await importWorkflowModule(pathToFileURL(entrypoint).href);
115
+ const module = moduleFromImport(imported, entrypoint);
116
+ return { module, dispose: module.dispose };
117
+ };
118
+ /** Mirrors the Firecracker guest's 115 s request deadline so local runs surface the same interruption. */
119
+ const LOCAL_DEADLINE_MS = 115_000;
120
+ const invocationFor = (module, triggerKind) => ({
121
+ workflowId: module.manifest.apiId,
122
+ deploymentId: 'local',
123
+ executionId: crypto.randomUUID(),
124
+ runId: crypto.randomUUID(),
125
+ attempt: 1,
126
+ triggerKind,
127
+ deadline: Date.now() + LOCAL_DEADLINE_MS,
128
+ token: '',
129
+ });
130
+ const readRequestBody = async (request) => {
131
+ if (request.method === 'GET' || request.method === 'HEAD')
132
+ return undefined;
133
+ const chunks = [];
134
+ // SAFETY: no request encoding is configured, so IncomingMessage yields Buffer chunks.
135
+ for await (const chunk of request) {
136
+ chunks.push(chunk);
137
+ }
138
+ if (chunks.length === 0)
139
+ return undefined;
140
+ const bytes = Buffer.concat(chunks);
141
+ const body = new ArrayBuffer(bytes.length);
142
+ new Uint8Array(body).set(bytes);
143
+ return body;
144
+ };
145
+ const toWebRequest = async (request, host) => {
146
+ const headers = new Headers();
147
+ let index = 0;
148
+ while (index < request.rawHeaders.length) {
149
+ headers.append(request.rawHeaders[index], request.rawHeaders[index + 1]);
150
+ index += 2;
151
+ }
152
+ return new Request(`http://${request.headers.host ?? host}${request.url ?? '/'}`, {
153
+ method: request.method,
154
+ headers,
155
+ body: await readRequestBody(request),
156
+ });
157
+ };
158
+ const sendWebResponse = async (response, outgoing) => {
159
+ for (const [name, value] of response.headers) {
160
+ if (name !== 'set-cookie')
161
+ outgoing.setHeader(name, value);
162
+ }
163
+ const cookies = response.headers.getSetCookie();
164
+ if (cookies.length > 0)
165
+ outgoing.setHeader('set-cookie', cookies);
166
+ outgoing.statusCode = response.status;
167
+ outgoing.statusMessage = response.statusText;
168
+ if (response.body === null) {
169
+ outgoing.end();
170
+ return;
171
+ }
172
+ const reader = response.body.getReader();
173
+ try {
174
+ while (true) {
175
+ const item = await reader.read();
176
+ if (item.done)
177
+ break;
178
+ if (!outgoing.write(item.value)) {
179
+ const drained = Promise.withResolvers();
180
+ outgoing.once('drain', () => drained.resolve(undefined));
181
+ await drained.promise;
182
+ }
183
+ }
184
+ }
185
+ finally {
186
+ reader.releaseLock();
187
+ }
188
+ outgoing.end();
189
+ };
190
+ const runServer = async (options, loader, reload) => {
191
+ let current = await loader(options.entrypoint);
192
+ let reloadTimer;
193
+ let stopping = false;
194
+ let reloadWork = Promise.resolve();
195
+ const watcher = reload
196
+ ? watch(dirname(options.entrypoint), { recursive: true }, () => {
197
+ clearTimeout(reloadTimer);
198
+ reloadTimer = setTimeout(() => {
199
+ reloadWork = reloadWork
200
+ .then(async () => {
201
+ const next = await loader(options.entrypoint);
202
+ if (stopping) {
203
+ await next.dispose();
204
+ return;
205
+ }
206
+ const previous = current;
207
+ current = next;
208
+ await previous.dispose();
209
+ process.stderr.write('Workflow reloaded.\n');
210
+ })
211
+ .catch((error) => {
212
+ process.stderr.write(`Reload failed: ${String(error)}\n`);
213
+ });
214
+ }, 40);
215
+ })
216
+ : undefined;
217
+ const server = createServer((request, response) => {
218
+ void toWebRequest(request, options.host)
219
+ .then((webRequest) => {
220
+ const active = current.module;
221
+ return active.fetch(webRequest, invocationFor(active, 'http'));
222
+ })
223
+ .then((webResponse) => sendWebResponse(webResponse, response))
224
+ .catch((error) => {
225
+ response.statusCode = 500;
226
+ response.end('Workflow request failed.');
227
+ process.stderr.write(`${String(error)}\n`);
228
+ });
229
+ });
230
+ const listening = Promise.withResolvers();
231
+ server.once('error', listening.reject);
232
+ server.listen(options.port, options.host, () => listening.resolve(undefined));
233
+ try {
234
+ await listening.promise;
235
+ const address = server.address();
236
+ if (address === null)
237
+ throw new Error('Workflow listener has no address.');
238
+ // SAFETY: this server listens on a numeric TCP port, never a Unix socket path.
239
+ const port = address.port;
240
+ process.stderr.write(`Workflow listening on http://${options.host}:${port}\n`);
241
+ const shutdown = Promise.withResolvers();
242
+ process.once('SIGINT', () => shutdown.resolve(undefined));
243
+ process.once('SIGTERM', () => shutdown.resolve(undefined));
244
+ await shutdown.promise;
245
+ }
246
+ finally {
247
+ stopping = true;
248
+ watcher?.close();
249
+ clearTimeout(reloadTimer);
250
+ await reloadWork;
251
+ if (server.listening) {
252
+ const closed = Promise.withResolvers();
253
+ server.close((error) => (error === undefined ? closed.resolve(undefined) : closed.reject(error)));
254
+ await closed.promise;
255
+ }
256
+ await current.dispose();
257
+ }
258
+ };
259
+ const runDev = (options) => runServer(options, loadWorkflow, true);
260
+ const runServe = (options) => runServer(options, loadBuiltWorkflow, false);
261
+ const runInvoke = async (options) => {
262
+ const loaded = await loadWorkflow(options.entrypoint);
263
+ try {
264
+ const headers = new Headers();
265
+ if (options.body !== undefined)
266
+ headers.set('content-type', 'application/json');
267
+ const response = await loaded.module.fetch(new Request(`http://127.0.0.1${options.path}`, {
268
+ method: options.method,
269
+ headers,
270
+ body: options.method === 'GET' || options.method === 'HEAD' ? undefined : options.body,
271
+ }), invocationFor(loaded.module, 'manual'));
272
+ process.stdout.write(new Uint8Array(await response.arrayBuffer()));
273
+ if (!response.ok)
274
+ process.exitCode = 1;
275
+ }
276
+ finally {
277
+ await loaded.dispose();
278
+ }
279
+ };
280
+ export const runCli = async (arguments_) => {
281
+ const options = parseArguments(arguments_);
282
+ if (options.command === 'dev')
283
+ return runDev(options);
284
+ if (options.command === 'serve')
285
+ return runServe(options);
286
+ return runInvoke(options);
287
+ };
288
+ const isMain = import.meta.main ?? resolve(process.argv[1] ?? '') === fileURLToPath(import.meta.url);
289
+ if (isMain) {
290
+ runCli(process.argv.slice(2)).catch((error) => {
291
+ process.stderr.write(`${String(error)}\n`);
292
+ process.exitCode = 1;
293
+ });
294
+ }
295
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { Invocation, type InvocationContext, type InvocationTriggerKind } from './Invocation.js';
2
+ export { type DeadlineExceededBody } from './Middleware.js';
3
+ export { makeManifest, RUNTIME_API_VERSION, SDK_VERSION, type WorkflowManifest, type WorkflowManifestEndpoint, } from './Manifest.js';
4
+ export { ResponsePolicy, Trigger, TriggerKind, TriggerMetadata } from './Trigger.js';
5
+ export { workflow, type WorkflowModule, type WorkflowOptions } from './Workflow.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { Invocation } from './Invocation.js';
2
+ export {} from './Middleware.js';
3
+ export { makeManifest, RUNTIME_API_VERSION, SDK_VERSION, } from './Manifest.js';
4
+ export { ResponsePolicy, Trigger, TriggerKind, TriggerMetadata } from './Trigger.js';
5
+ export { workflow } from './Workflow.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsD,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAA6B,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,WAAW,GAGZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,QAAQ,EAA6C,MAAM,eAAe,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { InvocationContext } from './Invocation.js';
2
+ import type { WorkflowModule } from './Workflow.js';
3
+ export interface InvokeOptions {
4
+ readonly request: Request;
5
+ readonly context: InvocationContext;
6
+ }
7
+ /** A complete invocation for tests. Override only the fields the test observes. */
8
+ export declare const testInvocation: (overrides?: Partial<InvocationContext>) => InvocationContext;
9
+ export declare const invoke: (module: WorkflowModule, options: InvokeOptions) => Promise<Response>;
10
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC;AAED,mFAAmF;AACnF,eAAO,MAAM,cAAc,eAAe,OAAO,CAAC,iBAAiB,CAAC,KAAQ,iBAU1E,CAAC;AAEH,eAAO,MAAM,MAAM,WAAY,cAAc,WAAW,aAAa,KAAG,OAAO,CAAC,QAAQ,CACxC,CAAC"}
@@ -0,0 +1,14 @@
1
+ /** A complete invocation for tests. Override only the fields the test observes. */
2
+ export const testInvocation = (overrides = {}) => ({
3
+ workflowId: 'workflow-test',
4
+ deploymentId: 'deployment-test',
5
+ executionId: 'execution-test',
6
+ runId: 'run-test',
7
+ attempt: 1,
8
+ triggerKind: 'http',
9
+ deadline: Number.POSITIVE_INFINITY,
10
+ token: '',
11
+ ...overrides,
12
+ });
13
+ export const invoke = (module, options) => module.fetch(options.request, options.context);
14
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAQA,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAAS,GAA+B,EAAE,EAAqB,EAAE,CAAC,CAAC;IAChG,UAAU,EAAE,eAAe;IAC3B,YAAY,EAAE,iBAAiB;IAC/B,WAAW,EAAE,gBAAgB;IAC7B,KAAK,EAAE,UAAU;IACjB,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,MAAM;IACnB,QAAQ,EAAE,MAAM,CAAC,iBAAiB;IAClC,KAAK,EAAE,EAAE;IACT,GAAG,SAAS;CACb,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAsB,EAAE,OAAsB,EAAqB,EAAE,CAC1F,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,56 @@
1
1
  {
2
2
  "name": "@ontemper/sdk",
3
- "version": "0.0.0",
4
- "description": "Placeholder. Temper publishes the workflow SDK here from CI with provenance.",
5
- "repository": { "type": "git", "url": "git+https://github.com/ontemper/temper.git", "directory": "sdk/workflow" },
3
+ "version": "0.1.0-rc.1",
4
+ "description": "Effect workflow SDK for Temper.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/ontemper/temper.git",
8
+ "directory": "sdk/workflow"
9
+ },
10
+ "type": "module",
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./testing": {
19
+ "types": "./dist/testing.d.ts",
20
+ "default": "./dist/testing.js"
21
+ }
22
+ },
23
+ "bin": {
24
+ "temper-workflow": "./dist/cli.js"
25
+ },
26
+ "files": [
27
+ "dist/**/*",
28
+ "README.md"
29
+ ],
30
+ "engines": {
31
+ "bun": ">=1.3.0",
32
+ "node": ">=22.0.0"
33
+ },
34
+ "peerDependencies": {
35
+ "effect": "4.0.0-rc.115"
36
+ },
37
+ "devDependencies": {
38
+ "@types/bun": "1.4.1",
39
+ "@types/node": "26.4.1",
40
+ "@types/ssh2": "1.15.5",
41
+ "effect": "4.0.0-rc.115",
42
+ "ssh2": "1.17.0",
43
+ "vitest": "^4.0.15"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
6
48
  "license": "MIT",
7
- "files": ["README.md"]
8
- }
49
+ "sideEffects": false,
50
+ "gitHead": "6f4fb95e33204828fac9245d75bfeddc6b5e8fbe",
51
+ "scripts": {
52
+ "build": "tsc -p tsconfig.json",
53
+ "test": "vitest run",
54
+ "typecheck": "tsc -p tsconfig.json --noEmit"
55
+ }
56
+ }