@temporalio/common 1.1.0 → 1.4.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/lib/activity-options.d.ts +138 -0
- package/lib/activity-options.js +15 -0
- package/lib/activity-options.js.map +1 -0
- package/lib/converter/data-converter.d.ts +20 -1
- package/lib/converter/data-converter.js +14 -3
- package/lib/converter/data-converter.js.map +1 -1
- package/lib/converter/failure-converter.d.ts +75 -0
- package/lib/converter/failure-converter.js +239 -0
- package/lib/converter/failure-converter.js.map +1 -0
- package/lib/converter/payload-codec.d.ts +1 -1
- package/lib/converter/payload-converter.d.ts +85 -1
- package/lib/converter/payload-converter.js +210 -1
- package/lib/converter/payload-converter.js.map +1 -1
- package/lib/converter/protobuf-payload-converters.d.ts +3 -3
- package/lib/converter/protobuf-payload-converters.js +20 -19
- package/lib/converter/protobuf-payload-converters.js.map +1 -1
- package/lib/converter/types.d.ts +0 -6
- package/lib/converter/types.js +7 -18
- package/lib/converter/types.js.map +1 -1
- package/lib/deprecated-time.d.ts +52 -0
- package/lib/deprecated-time.js +106 -0
- package/lib/deprecated-time.js.map +1 -0
- package/lib/{converter/encoding.d.ts → encoding.d.ts} +8 -0
- package/lib/{converter/encoding.js → encoding.js} +15 -1
- package/lib/encoding.js.map +1 -0
- package/lib/errors.d.ts +47 -0
- package/lib/errors.js +68 -0
- package/lib/errors.js.map +1 -0
- package/lib/failure.d.ts +0 -27
- package/lib/failure.js +9 -203
- package/lib/failure.js.map +1 -1
- package/lib/index.d.ts +25 -8
- package/lib/index.js +43 -7
- package/lib/index.js.map +1 -1
- package/lib/interceptors.d.ts +18 -0
- package/lib/interceptors.js +24 -0
- package/lib/interceptors.js.map +1 -0
- package/lib/interfaces.d.ts +52 -0
- package/lib/interfaces.js +3 -0
- package/lib/interfaces.js.map +1 -0
- package/lib/internal-non-workflow/codec-helpers.d.ts +82 -0
- package/lib/internal-non-workflow/codec-helpers.js +295 -0
- package/lib/internal-non-workflow/codec-helpers.js.map +1 -0
- package/lib/internal-non-workflow/codec-types.d.ts +22 -0
- package/lib/internal-non-workflow/codec-types.js +3 -0
- package/lib/internal-non-workflow/codec-types.js.map +1 -0
- package/lib/internal-non-workflow/data-converter-helpers.d.ts +11 -0
- package/lib/internal-non-workflow/data-converter-helpers.js +66 -0
- package/lib/internal-non-workflow/data-converter-helpers.js.map +1 -0
- package/lib/internal-non-workflow/index.d.ts +10 -0
- package/lib/internal-non-workflow/index.js +27 -0
- package/lib/internal-non-workflow/index.js.map +1 -0
- package/lib/internal-non-workflow/tls-config.d.ts +32 -0
- package/lib/internal-non-workflow/tls-config.js +11 -0
- package/lib/internal-non-workflow/tls-config.js.map +1 -0
- package/lib/internal-non-workflow/utils.d.ts +4 -0
- package/lib/internal-non-workflow/utils.js +11 -0
- package/lib/internal-non-workflow/utils.js.map +1 -0
- package/lib/otel.d.ts +1 -1
- package/lib/otel.js +2 -2
- package/lib/otel.js.map +1 -1
- package/lib/retry-policy.d.ts +48 -0
- package/lib/retry-policy.js +62 -0
- package/lib/retry-policy.js.map +1 -0
- package/lib/time.d.ts +18 -0
- package/lib/time.js +79 -0
- package/lib/time.js.map +1 -0
- package/lib/type-helpers.d.ts +21 -0
- package/lib/type-helpers.js +46 -0
- package/lib/type-helpers.js.map +1 -0
- package/lib/workflow-handle.d.ts +27 -0
- package/lib/workflow-handle.js +3 -0
- package/lib/workflow-handle.js.map +1 -0
- package/lib/workflow-options.d.ts +118 -0
- package/lib/workflow-options.js +53 -0
- package/lib/workflow-options.js.map +1 -0
- package/package.json +5 -4
- package/src/activity-options.ts +159 -0
- package/src/converter/data-converter.ts +24 -3
- package/src/converter/failure-converter.ts +355 -0
- package/src/converter/payload-codec.ts +1 -1
- package/src/converter/payload-converter.ts +246 -1
- package/src/converter/protobuf-payload-converters.ts +14 -25
- package/src/converter/types.ts +6 -19
- package/src/deprecated-time.ts +80 -0
- package/src/{converter/encoding.ts → encoding.ts} +14 -0
- package/src/errors.ts +55 -0
- package/src/failure.ts +3 -251
- package/src/index.ts +34 -8
- package/src/interceptors.ts +32 -0
- package/src/interfaces.ts +64 -0
- package/src/internal-non-workflow/codec-helpers.ts +348 -0
- package/src/internal-non-workflow/codec-types.ts +34 -0
- package/src/internal-non-workflow/data-converter-helpers.ts +81 -0
- package/src/internal-non-workflow/index.ts +10 -0
- package/src/internal-non-workflow/tls-config.ts +35 -0
- package/src/internal-non-workflow/utils.ts +6 -0
- package/src/otel.ts +2 -2
- package/src/retry-policy.ts +101 -0
- package/src/time.ts +79 -0
- package/src/type-helpers.ts +64 -0
- package/src/workflow-handle.ts +30 -0
- package/src/workflow-options.ts +156 -0
- package/lib/converter/encoding.js.map +0 -1
- package/lib/converter/json-payload-converter.d.ts +0 -10
- package/lib/converter/json-payload-converter.js +0 -39
- package/lib/converter/json-payload-converter.js.map +0 -1
- package/lib/converter/payload-converters.d.ts +0 -67
- package/lib/converter/payload-converters.js +0 -124
- package/lib/converter/payload-converters.js.map +0 -1
- package/lib/converter/search-attribute-payload-converter.d.ts +0 -12
- package/lib/converter/search-attribute-payload-converter.js +0 -64
- package/lib/converter/search-attribute-payload-converter.js.map +0 -1
- package/src/converter/json-payload-converter.ts +0 -37
- package/src/converter/payload-converters.ts +0 -148
- package/src/converter/search-attribute-payload-converter.ts +0 -71
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { Payload } from '../interfaces';
|
|
2
|
+
import { arrayFromPayloads, fromPayloadsAtIndex, toPayloads } from '../converter/payload-converter';
|
|
3
|
+
import { PayloadConverterError } from '../errors';
|
|
4
|
+
import { PayloadCodec } from '../converter/payload-codec';
|
|
5
|
+
import { ProtoFailure, TemporalFailure } from '../failure';
|
|
6
|
+
import { LoadedDataConverter } from '../converter/data-converter';
|
|
7
|
+
import { DecodedPayload, DecodedProtoFailure, EncodedPayload, EncodedProtoFailure } from './codec-types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Decode through each codec, starting with the last codec.
|
|
11
|
+
*/
|
|
12
|
+
export async function decode(codecs: PayloadCodec[], payloads: Payload[]): Promise<DecodedPayload[]> {
|
|
13
|
+
for (let i = codecs.length - 1; i >= 0; i--) {
|
|
14
|
+
payloads = await codecs[i].decode(payloads);
|
|
15
|
+
}
|
|
16
|
+
return payloads as DecodedPayload[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Encode through each codec, starting with the first codec.
|
|
21
|
+
*/
|
|
22
|
+
export async function encode(codecs: PayloadCodec[], payloads: Payload[]): Promise<EncodedPayload[]> {
|
|
23
|
+
for (let i = 0; i < codecs.length; i++) {
|
|
24
|
+
payloads = await codecs[i].encode(payloads);
|
|
25
|
+
}
|
|
26
|
+
return payloads as EncodedPayload[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Run {@link PayloadCodec.encode} on `payloads` */
|
|
30
|
+
export async function encodeOptional(
|
|
31
|
+
codecs: PayloadCodec[],
|
|
32
|
+
payloads: Payload[] | null | undefined
|
|
33
|
+
): Promise<EncodedPayload[] | null | undefined> {
|
|
34
|
+
if (payloads == null) return payloads;
|
|
35
|
+
return await encode(codecs, payloads);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Run {@link PayloadCodec.decode} on `payloads` */
|
|
39
|
+
export async function decodeOptional(
|
|
40
|
+
codecs: PayloadCodec[],
|
|
41
|
+
payloads: Payload[] | null | undefined
|
|
42
|
+
): Promise<DecodedPayload[] | null | undefined> {
|
|
43
|
+
if (payloads == null) return payloads;
|
|
44
|
+
return await decode(codecs, payloads);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function encodeSingle(codecs: PayloadCodec[], payload: Payload): Promise<EncodedPayload> {
|
|
48
|
+
const encodedPayloads = await encode(codecs, [payload]);
|
|
49
|
+
return encodedPayloads[0] as EncodedPayload;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function decodeSingle(codecs: PayloadCodec[], payload: Payload): Promise<DecodedPayload> {
|
|
53
|
+
const [decodedPayload] = await decode(codecs, [payload]);
|
|
54
|
+
return decodedPayload;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Run {@link PayloadCodec.encode} on a single Payload */
|
|
58
|
+
export async function encodeOptionalSingle(
|
|
59
|
+
codecs: PayloadCodec[],
|
|
60
|
+
payload: Payload | null | undefined
|
|
61
|
+
): Promise<EncodedPayload | null | undefined> {
|
|
62
|
+
if (payload == null) return payload;
|
|
63
|
+
return await encodeSingle(codecs, payload);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Run {@link PayloadCodec.decode} on a single Payload */
|
|
67
|
+
export async function decodeOptionalSingle(
|
|
68
|
+
codecs: PayloadCodec[],
|
|
69
|
+
payload: Payload | null | undefined
|
|
70
|
+
): Promise<DecodedPayload | null | undefined> {
|
|
71
|
+
if (payload == null) return payload;
|
|
72
|
+
return await decodeSingle(codecs, payload);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Run {@link PayloadConverter.toPayload} on value, and then encode it.
|
|
77
|
+
*/
|
|
78
|
+
export async function encodeToPayload(converter: LoadedDataConverter, value: unknown): Promise<Payload> {
|
|
79
|
+
const { payloadConverter, payloadCodecs } = converter;
|
|
80
|
+
return await encodeSingle(payloadCodecs, payloadConverter.toPayload(value));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Decode `payloads` and then return {@link arrayFromPayloads}`.
|
|
85
|
+
*/
|
|
86
|
+
export async function decodeArrayFromPayloads(
|
|
87
|
+
converter: LoadedDataConverter,
|
|
88
|
+
payloads?: Payload[] | null
|
|
89
|
+
): Promise<unknown[]> {
|
|
90
|
+
const { payloadConverter, payloadCodecs } = converter;
|
|
91
|
+
return arrayFromPayloads(payloadConverter, await decodeOptional(payloadCodecs, payloads));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Decode `payloads` and then return {@link fromPayloadsAtIndex}.
|
|
96
|
+
*/
|
|
97
|
+
export async function decodeFromPayloadsAtIndex<T>(
|
|
98
|
+
converter: LoadedDataConverter,
|
|
99
|
+
index: number,
|
|
100
|
+
payloads?: Payload[] | null
|
|
101
|
+
): Promise<T> {
|
|
102
|
+
const { payloadConverter, payloadCodecs } = converter;
|
|
103
|
+
return await fromPayloadsAtIndex(payloadConverter, index, await decodeOptional(payloadCodecs, payloads));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run {@link decodeFailure} and then return {@link failureToError}.
|
|
108
|
+
*/
|
|
109
|
+
export async function decodeOptionalFailureToOptionalError(
|
|
110
|
+
converter: LoadedDataConverter,
|
|
111
|
+
failure: ProtoFailure | undefined | null
|
|
112
|
+
): Promise<TemporalFailure | undefined> {
|
|
113
|
+
const { failureConverter, payloadCodecs } = converter;
|
|
114
|
+
return failure ? failureConverter.failureToError(await decodeFailure(payloadCodecs, failure)) : undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function decodeOptionalMap(
|
|
118
|
+
codecs: PayloadCodec[],
|
|
119
|
+
payloads: Record<string, Payload> | null | undefined
|
|
120
|
+
): Promise<Record<string, DecodedPayload> | null | undefined> {
|
|
121
|
+
if (payloads == null) return payloads;
|
|
122
|
+
return Object.fromEntries(
|
|
123
|
+
await Promise.all(Object.entries(payloads).map(async ([k, v]) => [k, await decode(codecs, [v])]))
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Run {@link PayloadConverter.toPayload} on values, and then encode them.
|
|
129
|
+
*/
|
|
130
|
+
export async function encodeToPayloads(
|
|
131
|
+
converter: LoadedDataConverter,
|
|
132
|
+
...values: unknown[]
|
|
133
|
+
): Promise<Payload[] | undefined> {
|
|
134
|
+
const { payloadConverter, payloadCodecs } = converter;
|
|
135
|
+
if (values.length === 0) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
const payloads = toPayloads(payloadConverter, ...values);
|
|
139
|
+
return payloads ? await encode(payloadCodecs, payloads) : undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Run {@link PayloadCodec.decode} and then {@link PayloadConverter.fromPayload} on values in `map`.
|
|
144
|
+
*/
|
|
145
|
+
export async function decodeMapFromPayloads<K extends string>(
|
|
146
|
+
converter: LoadedDataConverter,
|
|
147
|
+
map: Record<K, Payload> | null | undefined
|
|
148
|
+
): Promise<Record<K, unknown> | undefined> {
|
|
149
|
+
if (!map) return undefined;
|
|
150
|
+
const { payloadConverter, payloadCodecs } = converter;
|
|
151
|
+
return Object.fromEntries(
|
|
152
|
+
await Promise.all(
|
|
153
|
+
Object.entries(map).map(async ([k, payload]): Promise<[K, unknown]> => {
|
|
154
|
+
const [decodedPayload] = await decode(payloadCodecs, [payload as Payload]);
|
|
155
|
+
const value = payloadConverter.fromPayload(decodedPayload);
|
|
156
|
+
return [k as K, value];
|
|
157
|
+
})
|
|
158
|
+
)
|
|
159
|
+
) as Record<K, unknown>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Run {@link PayloadCodec.encode} on all values in `map` */
|
|
163
|
+
export async function encodeMap<K extends string>(
|
|
164
|
+
codecs: PayloadCodec[],
|
|
165
|
+
map: Record<K, Payload> | null | undefined
|
|
166
|
+
): Promise<Record<K, EncodedPayload> | null | undefined> {
|
|
167
|
+
if (map === null) return null;
|
|
168
|
+
if (map === undefined) return undefined;
|
|
169
|
+
return Object.fromEntries(
|
|
170
|
+
await Promise.all(
|
|
171
|
+
Object.entries(map).map(async ([k, payload]): Promise<[K, EncodedPayload]> => {
|
|
172
|
+
return [k as K, await encodeSingle(codecs, payload as Payload)];
|
|
173
|
+
})
|
|
174
|
+
)
|
|
175
|
+
) as Record<K, EncodedPayload>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Run {@link PayloadConverter.toPayload} and then {@link PayloadCodec.encode} on values in `map`.
|
|
180
|
+
*/
|
|
181
|
+
export async function encodeMapToPayloads<K extends string>(
|
|
182
|
+
converter: LoadedDataConverter,
|
|
183
|
+
map: Record<K, unknown>
|
|
184
|
+
): Promise<Record<K, Payload>> {
|
|
185
|
+
const { payloadConverter, payloadCodecs } = converter;
|
|
186
|
+
return Object.fromEntries(
|
|
187
|
+
await Promise.all(
|
|
188
|
+
Object.entries(map).map(async ([k, v]): Promise<[K, Payload]> => {
|
|
189
|
+
const payload = payloadConverter.toPayload(v);
|
|
190
|
+
if (payload === undefined) throw new PayloadConverterError(`Failed to encode entry: ${k}: ${v}`);
|
|
191
|
+
const [encodedPayload] = await encode(payloadCodecs, [payload]);
|
|
192
|
+
return [k as K, encodedPayload];
|
|
193
|
+
})
|
|
194
|
+
)
|
|
195
|
+
) as Record<K, Payload>;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Run {@link errorToFailure} on `error`, and then {@link encodeFailure}.
|
|
200
|
+
*/
|
|
201
|
+
export async function encodeErrorToFailure(dataConverter: LoadedDataConverter, error: unknown): Promise<ProtoFailure> {
|
|
202
|
+
const { failureConverter, payloadCodecs } = dataConverter;
|
|
203
|
+
return await encodeFailure(payloadCodecs, failureConverter.errorToFailure(error));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Return a new {@link ProtoFailure} with `codec.encode()` run on all the {@link Payload}s.
|
|
208
|
+
*/
|
|
209
|
+
export async function encodeFailure(codecs: PayloadCodec[], failure: ProtoFailure): Promise<EncodedProtoFailure> {
|
|
210
|
+
return {
|
|
211
|
+
...failure,
|
|
212
|
+
encodedAttributes: failure.encodedAttributes ? (await encode(codecs, [failure.encodedAttributes]))[0] : undefined,
|
|
213
|
+
cause: failure.cause ? await encodeFailure(codecs, failure.cause) : null,
|
|
214
|
+
applicationFailureInfo: failure.applicationFailureInfo
|
|
215
|
+
? {
|
|
216
|
+
...failure.applicationFailureInfo,
|
|
217
|
+
details: failure.applicationFailureInfo.details
|
|
218
|
+
? {
|
|
219
|
+
payloads: await encode(codecs, failure.applicationFailureInfo.details.payloads ?? []),
|
|
220
|
+
}
|
|
221
|
+
: undefined,
|
|
222
|
+
}
|
|
223
|
+
: undefined,
|
|
224
|
+
timeoutFailureInfo: failure.timeoutFailureInfo
|
|
225
|
+
? {
|
|
226
|
+
...failure.timeoutFailureInfo,
|
|
227
|
+
lastHeartbeatDetails: failure.timeoutFailureInfo.lastHeartbeatDetails
|
|
228
|
+
? {
|
|
229
|
+
payloads: await encode(codecs, failure.timeoutFailureInfo.lastHeartbeatDetails.payloads ?? []),
|
|
230
|
+
}
|
|
231
|
+
: undefined,
|
|
232
|
+
}
|
|
233
|
+
: undefined,
|
|
234
|
+
canceledFailureInfo: failure.canceledFailureInfo
|
|
235
|
+
? {
|
|
236
|
+
...failure.canceledFailureInfo,
|
|
237
|
+
details: failure.canceledFailureInfo.details
|
|
238
|
+
? {
|
|
239
|
+
payloads: await encode(codecs, failure.canceledFailureInfo.details.payloads ?? []),
|
|
240
|
+
}
|
|
241
|
+
: undefined,
|
|
242
|
+
}
|
|
243
|
+
: undefined,
|
|
244
|
+
resetWorkflowFailureInfo: failure.resetWorkflowFailureInfo
|
|
245
|
+
? {
|
|
246
|
+
...failure.resetWorkflowFailureInfo,
|
|
247
|
+
lastHeartbeatDetails: failure.resetWorkflowFailureInfo.lastHeartbeatDetails
|
|
248
|
+
? {
|
|
249
|
+
payloads: await encode(codecs, failure.resetWorkflowFailureInfo.lastHeartbeatDetails.payloads ?? []),
|
|
250
|
+
}
|
|
251
|
+
: undefined,
|
|
252
|
+
}
|
|
253
|
+
: undefined,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Return a new {@link ProtoFailure} with `codec.decode()` run on all the {@link Payload}s.
|
|
259
|
+
*/
|
|
260
|
+
export async function decodeFailure(codecs: PayloadCodec[], failure: ProtoFailure): Promise<DecodedProtoFailure> {
|
|
261
|
+
return {
|
|
262
|
+
...failure,
|
|
263
|
+
encodedAttributes: failure.encodedAttributes ? (await decode(codecs, [failure.encodedAttributes]))[0] : undefined,
|
|
264
|
+
cause: failure.cause ? await decodeFailure(codecs, failure.cause) : null,
|
|
265
|
+
applicationFailureInfo: failure.applicationFailureInfo
|
|
266
|
+
? {
|
|
267
|
+
...failure.applicationFailureInfo,
|
|
268
|
+
details: failure.applicationFailureInfo.details
|
|
269
|
+
? {
|
|
270
|
+
payloads: await decode(codecs, failure.applicationFailureInfo.details.payloads ?? []),
|
|
271
|
+
}
|
|
272
|
+
: undefined,
|
|
273
|
+
}
|
|
274
|
+
: undefined,
|
|
275
|
+
timeoutFailureInfo: failure.timeoutFailureInfo
|
|
276
|
+
? {
|
|
277
|
+
...failure.timeoutFailureInfo,
|
|
278
|
+
lastHeartbeatDetails: failure.timeoutFailureInfo.lastHeartbeatDetails
|
|
279
|
+
? {
|
|
280
|
+
payloads: await decode(codecs, failure.timeoutFailureInfo.lastHeartbeatDetails.payloads ?? []),
|
|
281
|
+
}
|
|
282
|
+
: undefined,
|
|
283
|
+
}
|
|
284
|
+
: undefined,
|
|
285
|
+
canceledFailureInfo: failure.canceledFailureInfo
|
|
286
|
+
? {
|
|
287
|
+
...failure.canceledFailureInfo,
|
|
288
|
+
details: failure.canceledFailureInfo.details
|
|
289
|
+
? {
|
|
290
|
+
payloads: await decode(codecs, failure.canceledFailureInfo.details.payloads ?? []),
|
|
291
|
+
}
|
|
292
|
+
: undefined,
|
|
293
|
+
}
|
|
294
|
+
: undefined,
|
|
295
|
+
resetWorkflowFailureInfo: failure.resetWorkflowFailureInfo
|
|
296
|
+
? {
|
|
297
|
+
...failure.resetWorkflowFailureInfo,
|
|
298
|
+
lastHeartbeatDetails: failure.resetWorkflowFailureInfo.lastHeartbeatDetails
|
|
299
|
+
? {
|
|
300
|
+
payloads: await decode(codecs, failure.resetWorkflowFailureInfo.lastHeartbeatDetails.payloads ?? []),
|
|
301
|
+
}
|
|
302
|
+
: undefined,
|
|
303
|
+
}
|
|
304
|
+
: undefined,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Return a new {@link ProtoFailure} with `codec.encode()` run on all the {@link Payload}s.
|
|
310
|
+
*/
|
|
311
|
+
export async function encodeOptionalFailure(
|
|
312
|
+
codecs: PayloadCodec[],
|
|
313
|
+
failure: ProtoFailure | null | undefined
|
|
314
|
+
): Promise<EncodedProtoFailure | null | undefined> {
|
|
315
|
+
if (failure == null) return failure;
|
|
316
|
+
return await encodeFailure(codecs, failure);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Return a new {@link ProtoFailure} with `codec.encode()` run on all the {@link Payload}s.
|
|
321
|
+
*/
|
|
322
|
+
export async function decodeOptionalFailure(
|
|
323
|
+
codecs: PayloadCodec[],
|
|
324
|
+
failure: ProtoFailure | null | undefined
|
|
325
|
+
): Promise<DecodedProtoFailure | null | undefined> {
|
|
326
|
+
if (failure == null) return failure;
|
|
327
|
+
return await decodeFailure(codecs, failure);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Mark all values in the map as encoded.
|
|
332
|
+
* Use this for headers, which we don't encode.
|
|
333
|
+
*/
|
|
334
|
+
export function noopEncodeMap<K extends string>(
|
|
335
|
+
map: Record<K, Payload> | null | undefined
|
|
336
|
+
): Record<K, EncodedPayload> | null | undefined {
|
|
337
|
+
return map as Record<K, EncodedPayload> | null | undefined;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Mark all values in the map as decoded.
|
|
342
|
+
* Use this for headers, which we don't encode.
|
|
343
|
+
*/
|
|
344
|
+
export function noopDecodeMap<K extends string>(
|
|
345
|
+
map: Record<K, Payload> | null | undefined
|
|
346
|
+
): Record<K, DecodedPayload> | null | undefined {
|
|
347
|
+
return map as Record<K, DecodedPayload> | null | undefined;
|
|
348
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Payload } from '../interfaces';
|
|
2
|
+
import type { ProtoFailure } from '../failure';
|
|
3
|
+
|
|
4
|
+
export interface EncodedPayload extends Payload {
|
|
5
|
+
encoded: true;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface DecodedPayload extends Payload {
|
|
9
|
+
decoded: true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Replace `Payload`s with `EncodedPayload`s */
|
|
13
|
+
export type Encoded<T> = ReplaceNested<T, Payload, EncodedPayload>;
|
|
14
|
+
|
|
15
|
+
/** Replace `Payload`s with `DecodedPayload`s */
|
|
16
|
+
export type Decoded<T> = ReplaceNested<T, Payload, DecodedPayload>;
|
|
17
|
+
|
|
18
|
+
export type EncodedProtoFailure = Encoded<ProtoFailure>;
|
|
19
|
+
export type DecodedProtoFailure = Decoded<ProtoFailure>;
|
|
20
|
+
|
|
21
|
+
/** An object T with any nested values of type ToReplace replaced with ReplaceWith */
|
|
22
|
+
export type ReplaceNested<T, ToReplace, ReplaceWith> = T extends (...args: any[]) => any
|
|
23
|
+
? T
|
|
24
|
+
: [keyof T] extends [never]
|
|
25
|
+
? T
|
|
26
|
+
: T extends { [k: string]: ToReplace }
|
|
27
|
+
? {
|
|
28
|
+
[P in keyof T]: ReplaceNested<T[P], ToReplace, ReplaceWith>;
|
|
29
|
+
}
|
|
30
|
+
: T extends ToReplace
|
|
31
|
+
? ReplaceWith | Exclude<T, ToReplace>
|
|
32
|
+
: {
|
|
33
|
+
[P in keyof T]: ReplaceNested<T[P], ToReplace, ReplaceWith>;
|
|
34
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { PayloadConverter } from '../converter/payload-converter';
|
|
2
|
+
import { DataConverter, defaultFailureConverter, LoadedDataConverter } from '../converter/data-converter';
|
|
3
|
+
import { FailureConverter } from '../converter/failure-converter';
|
|
4
|
+
import { defaultPayloadConverter } from '../converter/payload-converter';
|
|
5
|
+
import { errorCode, hasOwnProperty, isRecord } from '../type-helpers';
|
|
6
|
+
import { ValueError } from '../errors';
|
|
7
|
+
|
|
8
|
+
const isValidPayloadConverter = (converter: unknown): converter is PayloadConverter =>
|
|
9
|
+
typeof converter === 'object' &&
|
|
10
|
+
converter !== null &&
|
|
11
|
+
['toPayload', 'fromPayload'].every((method) => typeof (converter as Record<string, unknown>)[method] === 'function');
|
|
12
|
+
|
|
13
|
+
const isValidFailureConverter = (converter: unknown): converter is FailureConverter =>
|
|
14
|
+
typeof converter === 'object' &&
|
|
15
|
+
converter !== null &&
|
|
16
|
+
['errorToFailure', 'failureToError'].every(
|
|
17
|
+
(method) => typeof (converter as Record<string, unknown>)[method] === 'function'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
function requireConverter<T>(path: string, type: string, validator: (converter: unknown) => converter is T): T {
|
|
21
|
+
let module;
|
|
22
|
+
try {
|
|
23
|
+
module = require(path); // eslint-disable-line @typescript-eslint/no-var-requires
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (errorCode(error) === 'MODULE_NOT_FOUND') {
|
|
26
|
+
throw new ValueError(`Could not find a file at the specified ${type}Path: '${path}'.`);
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isRecord(module) && hasOwnProperty(module, type)) {
|
|
32
|
+
const converter = module[type];
|
|
33
|
+
if (validator(converter)) {
|
|
34
|
+
return converter;
|
|
35
|
+
} else {
|
|
36
|
+
throw new ValueError(
|
|
37
|
+
`payloadConverter export at ${path} must be an object with toPayload and fromPayload methods`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
throw new ValueError(`Module ${path} does not have a \`payloadConverter\` named export`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* If {@link DataConverter.payloadConverterPath} is specified, `require()` it and validate that the module has a `payloadConverter` named export.
|
|
47
|
+
* If not, use {@link defaultPayloadConverter}.
|
|
48
|
+
* If {@link DataConverter.payloadCodecs} is unspecified, use an empty array.
|
|
49
|
+
*/
|
|
50
|
+
export function loadDataConverter(dataConverter?: DataConverter): LoadedDataConverter {
|
|
51
|
+
let payloadConverter: PayloadConverter = defaultPayloadConverter;
|
|
52
|
+
if (dataConverter?.payloadConverterPath) {
|
|
53
|
+
payloadConverter = requireConverter(
|
|
54
|
+
dataConverter.payloadConverterPath,
|
|
55
|
+
'payloadConverter',
|
|
56
|
+
isValidPayloadConverter
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
let failureConverter: FailureConverter = defaultFailureConverter;
|
|
60
|
+
if (dataConverter?.failureConverterPath) {
|
|
61
|
+
failureConverter = requireConverter(
|
|
62
|
+
dataConverter.failureConverterPath,
|
|
63
|
+
'failureConverter',
|
|
64
|
+
isValidFailureConverter
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
payloadConverter,
|
|
69
|
+
failureConverter,
|
|
70
|
+
payloadCodecs: dataConverter?.payloadCodecs ?? [],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns true if the converter is already "loaded"
|
|
76
|
+
*/
|
|
77
|
+
export function isLoadedDataConverter(
|
|
78
|
+
dataConverter?: DataConverter | LoadedDataConverter
|
|
79
|
+
): dataConverter is LoadedDataConverter {
|
|
80
|
+
return isRecord(dataConverter) && hasOwnProperty(dataConverter, 'payloadConverter');
|
|
81
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal SDK library: users should usually use other packages instead. Not included in Workflow bundle.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
export * from './codec-helpers';
|
|
7
|
+
export * from './codec-types';
|
|
8
|
+
export * from './data-converter-helpers';
|
|
9
|
+
export * from './tls-config';
|
|
10
|
+
export * from './utils';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** TLS configuration options. */
|
|
2
|
+
export interface TLSConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Overrides the target name used for SSL host name checking.
|
|
5
|
+
* If this attribute is not specified, the name used for SSL host name checking will be the host from {@link ServerOptions.url}.
|
|
6
|
+
* This _should_ be used for testing only.
|
|
7
|
+
*/
|
|
8
|
+
serverNameOverride?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Root CA certificate used by the server. If not set, and the server's
|
|
11
|
+
* cert is issued by someone the operating system trusts, verification will still work (ex: Cloud offering).
|
|
12
|
+
*/
|
|
13
|
+
serverRootCACertificate?: Buffer;
|
|
14
|
+
/** Sets the client certificate and key for connecting with mTLS */
|
|
15
|
+
clientCertPair?: {
|
|
16
|
+
/** The certificate for this client */
|
|
17
|
+
crt: Buffer;
|
|
18
|
+
/** The private key for this client */
|
|
19
|
+
key: Buffer;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* TLS configuration.
|
|
25
|
+
* Pass a falsy value to use a non-encrypted connection or `true` or `{}` to
|
|
26
|
+
* connect with TLS without any customization.
|
|
27
|
+
*/
|
|
28
|
+
export type TLSConfigOption = TLSConfig | boolean | null;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Normalize {@link TLSConfigOption} by turning false and null to undefined and true to and empty object
|
|
32
|
+
*/
|
|
33
|
+
export function normalizeTlsConfig(tls?: TLSConfigOption): TLSConfig | undefined {
|
|
34
|
+
return typeof tls === 'object' ? (tls === null ? undefined : tls) : tls ? {} : undefined;
|
|
35
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper to prevent undefined and null values overriding defaults when merging maps
|
|
3
|
+
*/
|
|
4
|
+
export function filterNullAndUndefined<T extends Record<string, any>>(obj: T): T {
|
|
5
|
+
return Object.fromEntries(Object.entries(obj).filter(([_k, v]) => v != null)) as any;
|
|
6
|
+
}
|
package/src/otel.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
|
-
import { Headers } from '
|
|
3
|
-
import { defaultPayloadConverter } from './converter/payload-
|
|
2
|
+
import { Headers } from './interceptors';
|
|
3
|
+
import { defaultPayloadConverter } from './converter/payload-converter';
|
|
4
4
|
|
|
5
5
|
/** Default trace header for opentelemetry interceptors */
|
|
6
6
|
export const TRACE_HEADER = '_tracer-data';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { temporal } from '@temporalio/proto';
|
|
2
|
+
import { ValueError } from './errors';
|
|
3
|
+
import { msOptionalToNumber, msOptionalToTs, msToNumber, msToTs, optionalTsToMs } from './time';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for retrying Workflows and Activities
|
|
7
|
+
*/
|
|
8
|
+
export interface RetryPolicy {
|
|
9
|
+
/**
|
|
10
|
+
* Coefficient used to calculate the next retry interval.
|
|
11
|
+
* The next retry interval is previous interval multiplied by this coefficient.
|
|
12
|
+
* @minimum 1
|
|
13
|
+
* @default 2
|
|
14
|
+
*/
|
|
15
|
+
backoffCoefficient?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Interval of the first retry.
|
|
18
|
+
* If coefficient is 1 then it is used for all retries
|
|
19
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
20
|
+
* @default 1 second
|
|
21
|
+
*/
|
|
22
|
+
initialInterval?: string | number;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum number of attempts. When exceeded, retries stop (even if {@link ActivityOptions.scheduleToCloseTimeout}
|
|
25
|
+
* hasn't been reached).
|
|
26
|
+
*
|
|
27
|
+
* @default Infinity
|
|
28
|
+
*/
|
|
29
|
+
maximumAttempts?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Maximum interval between retries.
|
|
32
|
+
* Exponential backoff leads to interval increase.
|
|
33
|
+
* This value is the cap of the increase.
|
|
34
|
+
*
|
|
35
|
+
* @default 100x of {@link initialInterval}
|
|
36
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
37
|
+
*/
|
|
38
|
+
maximumInterval?: string | number;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* List of application failures types to not retry.
|
|
42
|
+
*/
|
|
43
|
+
nonRetryableErrorTypes?: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Turn a TS RetryPolicy into a proto compatible RetryPolicy
|
|
48
|
+
*/
|
|
49
|
+
export function compileRetryPolicy(retryPolicy: RetryPolicy): temporal.api.common.v1.IRetryPolicy {
|
|
50
|
+
if (retryPolicy.backoffCoefficient != null && retryPolicy.backoffCoefficient <= 0) {
|
|
51
|
+
throw new ValueError('RetryPolicy.backoffCoefficient must be greater than 0');
|
|
52
|
+
}
|
|
53
|
+
if (retryPolicy.maximumAttempts != null) {
|
|
54
|
+
if (retryPolicy.maximumAttempts === Number.POSITIVE_INFINITY) {
|
|
55
|
+
// drop field (Infinity is the default)
|
|
56
|
+
const { maximumAttempts: _, ...without } = retryPolicy;
|
|
57
|
+
retryPolicy = without;
|
|
58
|
+
} else if (retryPolicy.maximumAttempts <= 0) {
|
|
59
|
+
throw new ValueError('RetryPolicy.maximumAttempts must be a positive integer');
|
|
60
|
+
} else if (!Number.isInteger(retryPolicy.maximumAttempts)) {
|
|
61
|
+
throw new ValueError('RetryPolicy.maximumAttempts must be an integer');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const maximumInterval = msOptionalToNumber(retryPolicy.maximumInterval);
|
|
65
|
+
const initialInterval = msToNumber(retryPolicy.initialInterval ?? 1000);
|
|
66
|
+
if (maximumInterval === 0) {
|
|
67
|
+
throw new ValueError('RetryPolicy.maximumInterval cannot be 0');
|
|
68
|
+
}
|
|
69
|
+
if (initialInterval === 0) {
|
|
70
|
+
throw new ValueError('RetryPolicy.initialInterval cannot be 0');
|
|
71
|
+
}
|
|
72
|
+
if (maximumInterval != null && maximumInterval < initialInterval) {
|
|
73
|
+
throw new ValueError('RetryPolicy.maximumInterval cannot be less than its initialInterval');
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
maximumAttempts: retryPolicy.maximumAttempts,
|
|
77
|
+
initialInterval: msToTs(initialInterval),
|
|
78
|
+
maximumInterval: msOptionalToTs(maximumInterval),
|
|
79
|
+
backoffCoefficient: retryPolicy.backoffCoefficient,
|
|
80
|
+
nonRetryableErrorTypes: retryPolicy.nonRetryableErrorTypes,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Turn a proto compatible RetryPolicy into a TS RetryPolicy
|
|
86
|
+
*/
|
|
87
|
+
export function decompileRetryPolicy(
|
|
88
|
+
retryPolicy?: temporal.api.common.v1.IRetryPolicy | null
|
|
89
|
+
): RetryPolicy | undefined {
|
|
90
|
+
if (!retryPolicy) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
backoffCoefficient: retryPolicy.backoffCoefficient ?? undefined,
|
|
96
|
+
maximumAttempts: retryPolicy.maximumAttempts ?? undefined,
|
|
97
|
+
maximumInterval: optionalTsToMs(retryPolicy.maximumInterval),
|
|
98
|
+
initialInterval: optionalTsToMs(retryPolicy.initialInterval),
|
|
99
|
+
nonRetryableErrorTypes: retryPolicy.nonRetryableErrorTypes ?? undefined,
|
|
100
|
+
};
|
|
101
|
+
}
|