@cellaflow/sdk 0.7.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/cellaflow/v1/common_pb.d.ts +119 -0
- package/dist/cellaflow/v1/common_pb.d.ts.map +1 -0
- package/dist/cellaflow/v1/common_pb.js +166 -0
- package/dist/cellaflow/v1/common_pb.js.map +1 -0
- package/dist/cellaflow/v1/idempotency_pb.d.ts +378 -0
- package/dist/cellaflow/v1/idempotency_pb.d.ts.map +1 -0
- package/dist/cellaflow/v1/idempotency_pb.js +513 -0
- package/dist/cellaflow/v1/idempotency_pb.js.map +1 -0
- package/dist/cellaflow/v1/internal_pb.d.ts +201 -0
- package/dist/cellaflow/v1/internal_pb.d.ts.map +1 -0
- package/dist/cellaflow/v1/internal_pb.js +254 -0
- package/dist/cellaflow/v1/internal_pb.js.map +1 -0
- package/dist/cellaflow/v1/service_connect.d.ts +84 -0
- package/dist/cellaflow/v1/service_connect.d.ts.map +1 -0
- package/dist/cellaflow/v1/service_connect.js +88 -0
- package/dist/cellaflow/v1/service_connect.js.map +1 -0
- package/dist/cellaflow/v1/service_pb.d.ts +172 -0
- package/dist/cellaflow/v1/service_pb.d.ts.map +1 -0
- package/dist/cellaflow/v1/service_pb.js +266 -0
- package/dist/cellaflow/v1/service_pb.js.map +1 -0
- package/dist/client.d.ts +88 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +187 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/serialization.d.ts +18 -0
- package/dist/serialization.d.ts.map +1 -0
- package/dist/serialization.js +41 -0
- package/dist/serialization.js.map +1 -0
- package/package.json +59 -0
- package/src/cellaflow/v1/common_pb.ts +195 -0
- package/src/cellaflow/v1/idempotency_pb.ts +591 -0
- package/src/cellaflow/v1/internal_pb.ts +308 -0
- package/src/cellaflow/v1/service_connect.ts +90 -0
- package/src/cellaflow/v1/service_pb.ts +323 -0
- package/src/client.ts +277 -0
- package/src/index.ts +7 -0
- package/src/serialization.ts +53 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// @generated by protoc-gen-es v1.10.1 with parameter "target=ts,import_extension=.js"
|
|
2
|
+
// @generated from file cellaflow/v1/service.proto (package cellaflow.v1, syntax proto3)
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
// @ts-nocheck
|
|
5
|
+
|
|
6
|
+
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
|
|
7
|
+
import { Message, proto3, protoInt64 } from "@bufbuild/protobuf";
|
|
8
|
+
import { StepResult } from "./common_pb.js";
|
|
9
|
+
import { IdempotencyCommitStatus } from "./idempotency_pb.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @generated from message cellaflow.v1.StartSessionRequest
|
|
13
|
+
*/
|
|
14
|
+
export class StartSessionRequest extends Message<StartSessionRequest> {
|
|
15
|
+
/**
|
|
16
|
+
* @generated from field: string workflow_id = 1;
|
|
17
|
+
*/
|
|
18
|
+
workflowId = "";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @generated from field: string version = 2;
|
|
22
|
+
*/
|
|
23
|
+
version = "";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Optional client-proposed session identifier.
|
|
27
|
+
*
|
|
28
|
+
* @generated from field: optional string session_id = 3;
|
|
29
|
+
*/
|
|
30
|
+
sessionId?: string;
|
|
31
|
+
|
|
32
|
+
constructor(data?: PartialMessage<StartSessionRequest>) {
|
|
33
|
+
super();
|
|
34
|
+
proto3.util.initPartial(data, this);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
38
|
+
static readonly typeName = "cellaflow.v1.StartSessionRequest";
|
|
39
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
40
|
+
{ no: 1, name: "workflow_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
41
|
+
{ no: 2, name: "version", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
42
|
+
{ no: 3, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): StartSessionRequest {
|
|
46
|
+
return new StartSessionRequest().fromBinary(bytes, options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): StartSessionRequest {
|
|
50
|
+
return new StartSessionRequest().fromJson(jsonValue, options);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): StartSessionRequest {
|
|
54
|
+
return new StartSessionRequest().fromJsonString(jsonString, options);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static equals(a: StartSessionRequest | PlainMessage<StartSessionRequest> | undefined, b: StartSessionRequest | PlainMessage<StartSessionRequest> | undefined): boolean {
|
|
58
|
+
return proto3.util.equals(StartSessionRequest, a, b);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @generated from message cellaflow.v1.StartSessionResponse
|
|
64
|
+
*/
|
|
65
|
+
export class StartSessionResponse extends Message<StartSessionResponse> {
|
|
66
|
+
/**
|
|
67
|
+
* @generated from field: string session_id = 1;
|
|
68
|
+
*/
|
|
69
|
+
sessionId = "";
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @generated from field: string version = 2;
|
|
73
|
+
*/
|
|
74
|
+
version = "";
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @generated from field: bool is_recovered = 3;
|
|
78
|
+
*/
|
|
79
|
+
isRecovered = false;
|
|
80
|
+
|
|
81
|
+
constructor(data?: PartialMessage<StartSessionResponse>) {
|
|
82
|
+
super();
|
|
83
|
+
proto3.util.initPartial(data, this);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
87
|
+
static readonly typeName = "cellaflow.v1.StartSessionResponse";
|
|
88
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
89
|
+
{ no: 1, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
90
|
+
{ no: 2, name: "version", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
91
|
+
{ no: 3, name: "is_recovered", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): StartSessionResponse {
|
|
95
|
+
return new StartSessionResponse().fromBinary(bytes, options);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): StartSessionResponse {
|
|
99
|
+
return new StartSessionResponse().fromJson(jsonValue, options);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): StartSessionResponse {
|
|
103
|
+
return new StartSessionResponse().fromJsonString(jsonString, options);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static equals(a: StartSessionResponse | PlainMessage<StartSessionResponse> | undefined, b: StartSessionResponse | PlainMessage<StartSessionResponse> | undefined): boolean {
|
|
107
|
+
return proto3.util.equals(StartSessionResponse, a, b);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @generated from message cellaflow.v1.CommitStepRequest
|
|
113
|
+
*/
|
|
114
|
+
export class CommitStepRequest extends Message<CommitStepRequest> {
|
|
115
|
+
/**
|
|
116
|
+
* @generated from field: string session_id = 1;
|
|
117
|
+
*/
|
|
118
|
+
sessionId = "";
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @generated from field: cellaflow.v1.StepResult step_result = 2;
|
|
122
|
+
*/
|
|
123
|
+
stepResult?: StepResult;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Idempotency lease validation fields
|
|
127
|
+
*
|
|
128
|
+
* @generated from field: optional string idempotency_key = 10;
|
|
129
|
+
*/
|
|
130
|
+
idempotencyKey?: string;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Required whenever idempotency_key is set
|
|
134
|
+
*
|
|
135
|
+
* @generated from field: optional uint64 idempotency_fencing_token = 11;
|
|
136
|
+
*/
|
|
137
|
+
idempotencyFencingToken?: bigint;
|
|
138
|
+
|
|
139
|
+
constructor(data?: PartialMessage<CommitStepRequest>) {
|
|
140
|
+
super();
|
|
141
|
+
proto3.util.initPartial(data, this);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
145
|
+
static readonly typeName = "cellaflow.v1.CommitStepRequest";
|
|
146
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
147
|
+
{ no: 1, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
148
|
+
{ no: 2, name: "step_result", kind: "message", T: StepResult },
|
|
149
|
+
{ no: 10, name: "idempotency_key", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
|
|
150
|
+
{ no: 11, name: "idempotency_fencing_token", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true },
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CommitStepRequest {
|
|
154
|
+
return new CommitStepRequest().fromBinary(bytes, options);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CommitStepRequest {
|
|
158
|
+
return new CommitStepRequest().fromJson(jsonValue, options);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CommitStepRequest {
|
|
162
|
+
return new CommitStepRequest().fromJsonString(jsonString, options);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static equals(a: CommitStepRequest | PlainMessage<CommitStepRequest> | undefined, b: CommitStepRequest | PlainMessage<CommitStepRequest> | undefined): boolean {
|
|
166
|
+
return proto3.util.equals(CommitStepRequest, a, b);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @generated from message cellaflow.v1.CommitStepResponse
|
|
172
|
+
*/
|
|
173
|
+
export class CommitStepResponse extends Message<CommitStepResponse> {
|
|
174
|
+
/**
|
|
175
|
+
* @generated from field: string session_id = 1;
|
|
176
|
+
*/
|
|
177
|
+
sessionId = "";
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @generated from field: uint64 next_sequence = 2;
|
|
181
|
+
*/
|
|
182
|
+
nextSequence = protoInt64.zero;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @generated from field: optional cellaflow.v1.IdempotencyCommitStatus idempotency_status = 5;
|
|
186
|
+
*/
|
|
187
|
+
idempotencyStatus?: IdempotencyCommitStatus;
|
|
188
|
+
|
|
189
|
+
constructor(data?: PartialMessage<CommitStepResponse>) {
|
|
190
|
+
super();
|
|
191
|
+
proto3.util.initPartial(data, this);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
195
|
+
static readonly typeName = "cellaflow.v1.CommitStepResponse";
|
|
196
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
197
|
+
{ no: 1, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
198
|
+
{ no: 2, name: "next_sequence", kind: "scalar", T: 4 /* ScalarType.UINT64 */ },
|
|
199
|
+
{ no: 5, name: "idempotency_status", kind: "enum", T: proto3.getEnumType(IdempotencyCommitStatus), opt: true },
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CommitStepResponse {
|
|
203
|
+
return new CommitStepResponse().fromBinary(bytes, options);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CommitStepResponse {
|
|
207
|
+
return new CommitStepResponse().fromJson(jsonValue, options);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CommitStepResponse {
|
|
211
|
+
return new CommitStepResponse().fromJsonString(jsonString, options);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static equals(a: CommitStepResponse | PlainMessage<CommitStepResponse> | undefined, b: CommitStepResponse | PlainMessage<CommitStepResponse> | undefined): boolean {
|
|
215
|
+
return proto3.util.equals(CommitStepResponse, a, b);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @generated from message cellaflow.v1.GetGraphRequest
|
|
221
|
+
*/
|
|
222
|
+
export class GetGraphRequest extends Message<GetGraphRequest> {
|
|
223
|
+
/**
|
|
224
|
+
* @generated from field: string session_id = 1;
|
|
225
|
+
*/
|
|
226
|
+
sessionId = "";
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Maximum number of items to retrieve in a single page.
|
|
230
|
+
* Enforced limits: Default = 100, Max = 1000.
|
|
231
|
+
*
|
|
232
|
+
* @generated from field: optional uint32 limit = 2;
|
|
233
|
+
*/
|
|
234
|
+
limit?: number;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Cursor for pagination token.
|
|
238
|
+
*
|
|
239
|
+
* @generated from field: optional string cursor = 3;
|
|
240
|
+
*/
|
|
241
|
+
cursor?: string;
|
|
242
|
+
|
|
243
|
+
constructor(data?: PartialMessage<GetGraphRequest>) {
|
|
244
|
+
super();
|
|
245
|
+
proto3.util.initPartial(data, this);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
249
|
+
static readonly typeName = "cellaflow.v1.GetGraphRequest";
|
|
250
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
251
|
+
{ no: 1, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
252
|
+
{ no: 2, name: "limit", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true },
|
|
253
|
+
{ no: 3, name: "cursor", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
|
|
254
|
+
]);
|
|
255
|
+
|
|
256
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetGraphRequest {
|
|
257
|
+
return new GetGraphRequest().fromBinary(bytes, options);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetGraphRequest {
|
|
261
|
+
return new GetGraphRequest().fromJson(jsonValue, options);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetGraphRequest {
|
|
265
|
+
return new GetGraphRequest().fromJsonString(jsonString, options);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
static equals(a: GetGraphRequest | PlainMessage<GetGraphRequest> | undefined, b: GetGraphRequest | PlainMessage<GetGraphRequest> | undefined): boolean {
|
|
269
|
+
return proto3.util.equals(GetGraphRequest, a, b);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* @generated from message cellaflow.v1.GetGraphResponse
|
|
275
|
+
*/
|
|
276
|
+
export class GetGraphResponse extends Message<GetGraphResponse> {
|
|
277
|
+
/**
|
|
278
|
+
* @generated from field: string session_id = 1;
|
|
279
|
+
*/
|
|
280
|
+
sessionId = "";
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @generated from field: repeated cellaflow.v1.StepResult steps = 2;
|
|
284
|
+
*/
|
|
285
|
+
steps: StepResult[] = [];
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Token for fetching the next page, or empty if there are no more pages.
|
|
289
|
+
*
|
|
290
|
+
* @generated from field: optional string next_cursor = 3;
|
|
291
|
+
*/
|
|
292
|
+
nextCursor?: string;
|
|
293
|
+
|
|
294
|
+
constructor(data?: PartialMessage<GetGraphResponse>) {
|
|
295
|
+
super();
|
|
296
|
+
proto3.util.initPartial(data, this);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
300
|
+
static readonly typeName = "cellaflow.v1.GetGraphResponse";
|
|
301
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
302
|
+
{ no: 1, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
303
|
+
{ no: 2, name: "steps", kind: "message", T: StepResult, repeated: true },
|
|
304
|
+
{ no: 3, name: "next_cursor", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
|
|
305
|
+
]);
|
|
306
|
+
|
|
307
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetGraphResponse {
|
|
308
|
+
return new GetGraphResponse().fromBinary(bytes, options);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetGraphResponse {
|
|
312
|
+
return new GetGraphResponse().fromJson(jsonValue, options);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetGraphResponse {
|
|
316
|
+
return new GetGraphResponse().fromJsonString(jsonString, options);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
static equals(a: GetGraphResponse | PlainMessage<GetGraphResponse> | undefined, b: GetGraphResponse | PlainMessage<GetGraphResponse> | undefined): boolean {
|
|
320
|
+
return proto3.util.equals(GetGraphResponse, a, b);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPromiseClient,
|
|
3
|
+
PromiseClient,
|
|
4
|
+
Transport,
|
|
5
|
+
} from "@connectrpc/connect";
|
|
6
|
+
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
7
|
+
import type { PartialMessage } from "@bufbuild/protobuf";
|
|
8
|
+
import { WorkflowEngineService } from "./cellaflow/v1/service_connect.js";
|
|
9
|
+
import type {
|
|
10
|
+
StartSessionResponse,
|
|
11
|
+
CommitStepResponse,
|
|
12
|
+
} from "./cellaflow/v1/service_pb.js";
|
|
13
|
+
import {
|
|
14
|
+
StartSessionRequest,
|
|
15
|
+
CommitStepRequest,
|
|
16
|
+
GetGraphRequest,
|
|
17
|
+
} from "./cellaflow/v1/service_pb.js";
|
|
18
|
+
import { StepStatus } from "./cellaflow/v1/common_pb.js";
|
|
19
|
+
import type {
|
|
20
|
+
CheckCacheResponse,
|
|
21
|
+
RenewLeaseResponse,
|
|
22
|
+
ReleaseLeaseResponse,
|
|
23
|
+
} from "./cellaflow/v1/idempotency_pb.js";
|
|
24
|
+
import {
|
|
25
|
+
CheckCacheRequest,
|
|
26
|
+
RenewLeaseRequest,
|
|
27
|
+
ReleaseLeaseRequest,
|
|
28
|
+
} from "./cellaflow/v1/idempotency_pb.js";
|
|
29
|
+
import { serialize, deserialize } from "./serialization.js";
|
|
30
|
+
|
|
31
|
+
export interface CellaflowClientOptions {
|
|
32
|
+
target?: string;
|
|
33
|
+
secure?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class CellaflowClient {
|
|
37
|
+
/**
|
|
38
|
+
* gRPC Client for the Cellaflow Engine (Connect-ES transport).
|
|
39
|
+
* Handles communication with the engine and strictly uses MessagePack
|
|
40
|
+
* for state payloads.
|
|
41
|
+
*/
|
|
42
|
+
private client: PromiseClient<typeof WorkflowEngineService>;
|
|
43
|
+
|
|
44
|
+
constructor(options: CellaflowClientOptions = {}) {
|
|
45
|
+
const { target = "localhost:50051", secure = false } = options;
|
|
46
|
+
|
|
47
|
+
// Use http/https based on the secure flag
|
|
48
|
+
const baseUrl = secure ? `https://${target}` : `http://${target}`;
|
|
49
|
+
|
|
50
|
+
const transport: Transport = createGrpcTransport({
|
|
51
|
+
baseUrl,
|
|
52
|
+
httpVersion: "2",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
this.client = createPromiseClient(WorkflowEngineService, transport);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Starts a new workflow execution session.
|
|
60
|
+
*
|
|
61
|
+
* @param workflowId - The workflow definition ID.
|
|
62
|
+
* @param version - The workflow version string.
|
|
63
|
+
* @param sessionId - Optional client-proposed session ID. When provided, the
|
|
64
|
+
* engine performs a transactional check-and-insert to prevent concurrent
|
|
65
|
+
* race conditions. Omit to let the engine assign one.
|
|
66
|
+
*/
|
|
67
|
+
async startSession(
|
|
68
|
+
workflowId: string,
|
|
69
|
+
version: string,
|
|
70
|
+
sessionId?: string
|
|
71
|
+
): Promise<StartSessionResponse> {
|
|
72
|
+
const req: PartialMessage<StartSessionRequest> = { workflowId, version };
|
|
73
|
+
// Only set sessionId when truthy — matches Python's `if session_id:` guard.
|
|
74
|
+
// Sending an empty string may trigger the engine's custom-ID validation path.
|
|
75
|
+
if (sessionId) {
|
|
76
|
+
req.sessionId = sessionId;
|
|
77
|
+
}
|
|
78
|
+
return await this.client.startSession(req);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Commits a completed step result to the session graph.
|
|
83
|
+
*
|
|
84
|
+
* @param sessionId - The session to commit to.
|
|
85
|
+
* @param sequence - The step sequence number (1-based).
|
|
86
|
+
* @param name - Human-readable step name.
|
|
87
|
+
* @param status - The step outcome status.
|
|
88
|
+
* @param outputPayload - Arbitrary step output. Serialized as MessagePack.
|
|
89
|
+
* @param idempotencyKey - Optional idempotency lease key.
|
|
90
|
+
* @param idempotencyFencingToken - Required when `idempotencyKey` is set.
|
|
91
|
+
*/
|
|
92
|
+
async commitStep(
|
|
93
|
+
sessionId: string,
|
|
94
|
+
sequence: number,
|
|
95
|
+
name: string,
|
|
96
|
+
status: StepStatus,
|
|
97
|
+
outputPayload: Record<string, any>,
|
|
98
|
+
idempotencyKey?: string,
|
|
99
|
+
idempotencyFencingToken?: number
|
|
100
|
+
): Promise<CommitStepResponse> {
|
|
101
|
+
// Strictly serialize object to MessagePack
|
|
102
|
+
const serializedState = serialize(outputPayload);
|
|
103
|
+
|
|
104
|
+
const req: PartialMessage<CommitStepRequest> = {
|
|
105
|
+
sessionId,
|
|
106
|
+
stepResult: {
|
|
107
|
+
sequence: BigInt(sequence),
|
|
108
|
+
name,
|
|
109
|
+
status,
|
|
110
|
+
outputPayload: Buffer.from(serializedState) as unknown as Uint8Array<ArrayBuffer>,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
if (idempotencyKey !== undefined) {
|
|
115
|
+
req.idempotencyKey = idempotencyKey;
|
|
116
|
+
if (idempotencyFencingToken === undefined) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
"idempotencyFencingToken required if idempotencyKey is set"
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
req.idempotencyFencingToken = BigInt(idempotencyFencingToken);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return await this.client.commitStep(req);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Returns a paginated list of committed step results for a session.
|
|
129
|
+
*
|
|
130
|
+
* @returns A tuple of (step results, next_cursor). `next_cursor` is
|
|
131
|
+
* `undefined` when there are no more pages. Each step result's
|
|
132
|
+
* `outputPayload` is fully deserialized from MessagePack.
|
|
133
|
+
*/
|
|
134
|
+
async getGraph(
|
|
135
|
+
sessionId: string,
|
|
136
|
+
limit?: number,
|
|
137
|
+
cursor?: string
|
|
138
|
+
): Promise<[Record<string, any>[], string | undefined]> {
|
|
139
|
+
const req: PartialMessage<GetGraphRequest> = { sessionId };
|
|
140
|
+
if (limit !== undefined) {
|
|
141
|
+
req.limit = limit;
|
|
142
|
+
}
|
|
143
|
+
if (cursor !== undefined) {
|
|
144
|
+
req.cursor = cursor;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const resp = await this.client.getGraph(req);
|
|
148
|
+
|
|
149
|
+
const results = resp.steps.map((step) => ({
|
|
150
|
+
sequence: step.sequence,
|
|
151
|
+
name: step.name,
|
|
152
|
+
status: step.status,
|
|
153
|
+
// Guard against empty payload (default Uint8Array(0)) to prevent
|
|
154
|
+
// msgpack from throwing on an empty buffer.
|
|
155
|
+
outputPayload:
|
|
156
|
+
step.outputPayload.length > 0 ? deserialize(step.outputPayload) : {},
|
|
157
|
+
idempotencyKey: step.idempotencyKey,
|
|
158
|
+
}));
|
|
159
|
+
|
|
160
|
+
const nextCursor = resp.nextCursor ? resp.nextCursor : undefined;
|
|
161
|
+
return [results, nextCursor];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Arbitrates the idempotency lease for `idempotencyKey`.
|
|
166
|
+
*
|
|
167
|
+
* Supplying `sessionId` also asks the engine for the session's committed
|
|
168
|
+
* position, returned as `currentSequence` on every status. The idempotency
|
|
169
|
+
* key is opaque to the engine, so the session cannot be inferred from it —
|
|
170
|
+
* without this the engine has nothing to answer from.
|
|
171
|
+
*
|
|
172
|
+
* Supplying `sequence` — the position this caller intends to write to —
|
|
173
|
+
* additionally lets the engine refuse a lease that would authorise a side
|
|
174
|
+
* effect at an already-committed position, instead of rejecting the commit
|
|
175
|
+
* afterwards once the side effect has happened. The engine raises
|
|
176
|
+
* `FAILED_PRECONDITION` when refused. Both fields are optional on the wire;
|
|
177
|
+
* omitting `sequence` keeps the position unguarded.
|
|
178
|
+
*/
|
|
179
|
+
async checkIdempotencyCache(
|
|
180
|
+
agentId: string,
|
|
181
|
+
idempotencyKey: string,
|
|
182
|
+
waitTimeoutMs?: number,
|
|
183
|
+
leaseTtlMs?: number,
|
|
184
|
+
sessionId?: string,
|
|
185
|
+
sequence?: number
|
|
186
|
+
): Promise<CheckCacheResponse> {
|
|
187
|
+
const req: PartialMessage<CheckCacheRequest> = { agentId, idempotencyKey };
|
|
188
|
+
// These proto fields are uint64 → bigint; convert from the JS number API.
|
|
189
|
+
if (waitTimeoutMs !== undefined) {
|
|
190
|
+
req.waitTimeoutMs = BigInt(waitTimeoutMs);
|
|
191
|
+
}
|
|
192
|
+
if (leaseTtlMs !== undefined) {
|
|
193
|
+
req.leaseTtlMs = BigInt(leaseTtlMs);
|
|
194
|
+
}
|
|
195
|
+
if (sessionId !== undefined) {
|
|
196
|
+
req.sessionId = sessionId;
|
|
197
|
+
}
|
|
198
|
+
if (sequence !== undefined) {
|
|
199
|
+
req.sequence = BigInt(sequence);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return await this.client.checkIdempotencyCache(req);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Renews a held idempotency lease.
|
|
207
|
+
*
|
|
208
|
+
* @param timeoutSecs - Bounds the RPC in **seconds**. Heartbeat callers
|
|
209
|
+
* MUST supply a positive value: without a deadline a black-holed
|
|
210
|
+
* connection parks the calling thread indefinitely, and the shutdown
|
|
211
|
+
* path that joins that thread parks with it.
|
|
212
|
+
*/
|
|
213
|
+
async renewLease(
|
|
214
|
+
agentId: string,
|
|
215
|
+
idempotencyKey: string,
|
|
216
|
+
fencingToken: number,
|
|
217
|
+
extendMs: number,
|
|
218
|
+
timeoutSecs?: number
|
|
219
|
+
): Promise<RenewLeaseResponse> {
|
|
220
|
+
const req: PartialMessage<RenewLeaseRequest> = {
|
|
221
|
+
agentId,
|
|
222
|
+
idempotencyKey,
|
|
223
|
+
fencingToken: BigInt(fencingToken),
|
|
224
|
+
extendMs: BigInt(extendMs),
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return await this.client.renewLease(req, {
|
|
228
|
+
// Guard against timeout=0 which would cause an instant timeout.
|
|
229
|
+
timeoutMs:
|
|
230
|
+
timeoutSecs !== undefined && timeoutSecs > 0
|
|
231
|
+
? timeoutSecs * 1000
|
|
232
|
+
: undefined,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Releases a held idempotency lease.
|
|
238
|
+
*
|
|
239
|
+
* @param timeoutSecs - Bounds the RPC in **seconds**.
|
|
240
|
+
*/
|
|
241
|
+
async releaseLease(
|
|
242
|
+
agentId: string,
|
|
243
|
+
idempotencyKey: string,
|
|
244
|
+
fencingToken: number,
|
|
245
|
+
reason?: string,
|
|
246
|
+
timeoutSecs?: number
|
|
247
|
+
): Promise<ReleaseLeaseResponse> {
|
|
248
|
+
const req: PartialMessage<ReleaseLeaseRequest> = {
|
|
249
|
+
agentId,
|
|
250
|
+
idempotencyKey,
|
|
251
|
+
fencingToken: BigInt(fencingToken),
|
|
252
|
+
};
|
|
253
|
+
if (reason !== undefined) {
|
|
254
|
+
req.reason = reason;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return await this.client.releaseLease(req, {
|
|
258
|
+
timeoutMs:
|
|
259
|
+
timeoutSecs !== undefined && timeoutSecs > 0
|
|
260
|
+
? timeoutSecs * 1000
|
|
261
|
+
: undefined,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Provided for API compatibility with the Python client.
|
|
267
|
+
*
|
|
268
|
+
* Connect-ES v1 with `createGrpcTransport` does not expose an explicit
|
|
269
|
+
* close/shutdown method — HTTP/2 sessions are managed by Node.js and are
|
|
270
|
+
* cleaned up on process exit or when the client is garbage-collected.
|
|
271
|
+
* Long-lived server processes with many short-lived clients should let the
|
|
272
|
+
* garbage collector handle cleanup.
|
|
273
|
+
*/
|
|
274
|
+
close(): void {
|
|
275
|
+
// No-op: Connect-ES v1 does not provide a transport.close() API.
|
|
276
|
+
}
|
|
277
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./client.js";
|
|
2
|
+
export * from "./serialization.js";
|
|
3
|
+
export * from "./cellaflow/v1/common_pb.js";
|
|
4
|
+
export * from "./cellaflow/v1/idempotency_pb.js";
|
|
5
|
+
// Note: internal_pb is intentionally NOT re-exported here. It contains
|
|
6
|
+
// engine-internal types (CacheRecord, LeaseRecord, etc.) that are not part
|
|
7
|
+
// of the public SDK surface.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { encode, decode } from "@msgpack/msgpack";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Serializes a JavaScript object to a MessagePack byte array.
|
|
5
|
+
* This ensures we never use JSON for state payloads, mitigating RCE risks.
|
|
6
|
+
*
|
|
7
|
+
* @throws {TypeError} If `data` is not a plain, non-null object.
|
|
8
|
+
*/
|
|
9
|
+
export function serialize(data: Record<string, any>): Uint8Array {
|
|
10
|
+
// Explicit null check first — `typeof null === "object"` would otherwise
|
|
11
|
+
// produce a misleading error message reporting "got object" instead of "got null".
|
|
12
|
+
if (data === null) {
|
|
13
|
+
throw new TypeError("Expected an object for serialization, got null");
|
|
14
|
+
}
|
|
15
|
+
if (typeof data !== "object" || Array.isArray(data)) {
|
|
16
|
+
throw new TypeError(
|
|
17
|
+
`Expected an object for serialization, got ${Array.isArray(data) ? "array" : typeof data}`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return encode(data);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Deserializes a MessagePack byte array back into a JavaScript object.
|
|
25
|
+
*
|
|
26
|
+
* Uses `ArrayBuffer.isView()` instead of `instanceof Uint8Array` to work
|
|
27
|
+
* correctly across JS realms (worker threads, vm contexts, etc.).
|
|
28
|
+
*
|
|
29
|
+
* @throws {TypeError} If `data` is not a Uint8Array / ArrayBufferView.
|
|
30
|
+
* @throws {TypeError} If the deserialized value is not a plain object.
|
|
31
|
+
*/
|
|
32
|
+
export function deserialize(data: Uint8Array): Record<string, any> {
|
|
33
|
+
// ArrayBuffer.isView is cross-realm safe; instanceof Uint8Array is not.
|
|
34
|
+
if (!ArrayBuffer.isView(data)) {
|
|
35
|
+
throw new TypeError(
|
|
36
|
+
`Expected Uint8Array for deserialization, got ${data === null ? "null" : typeof data}`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const unpacked = decode(data);
|
|
41
|
+
|
|
42
|
+
if (
|
|
43
|
+
typeof unpacked !== "object" ||
|
|
44
|
+
unpacked === null ||
|
|
45
|
+
Array.isArray(unpacked)
|
|
46
|
+
) {
|
|
47
|
+
throw new TypeError(
|
|
48
|
+
`Deserialized data is not an object, got ${unpacked === null ? "null" : typeof unpacked}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return unpacked as Record<string, any>;
|
|
53
|
+
}
|