@temporalio/common 1.8.0 → 1.8.2
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 +8 -0
- package/lib/activity-options.js.map +1 -1
- package/lib/converter/failure-converter.js +10 -10
- package/lib/converter/failure-converter.js.map +1 -1
- package/lib/converter/payload-converter.js +2 -2
- package/lib/converter/payload-converter.js.map +1 -1
- package/lib/converter/protobuf-payload-converters.js +58 -7
- package/lib/converter/protobuf-payload-converters.js.map +1 -1
- package/lib/errors.d.ts +0 -16
- package/lib/errors.js +37 -38
- package/lib/errors.js.map +1 -1
- package/lib/failure.d.ts +0 -81
- package/lib/failure.js +50 -131
- package/lib/failure.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/type-helpers.d.ts +33 -0
- package/lib/type-helpers.js +70 -9
- package/lib/type-helpers.js.map +1 -1
- package/lib/versioning-intent.d.ts +18 -0
- package/lib/versioning-intent.js +3 -0
- package/lib/versioning-intent.js.map +1 -0
- package/package.json +3 -3
- package/src/activity-options.ts +9 -0
- package/src/converter/failure-converter.ts +12 -12
- package/src/converter/payload-converter.ts +2 -2
- package/src/converter/protobuf-payload-converters.ts +62 -8
- package/src/errors.ts +9 -31
- package/src/failure.ts +13 -138
- package/src/index.ts +1 -0
- package/src/type-helpers.ts +78 -11
- package/src/versioning-intent.ts +18 -0
package/lib/type-helpers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertNever = exports.errorCode = exports.errorMessage = exports.hasOwnProperties = exports.hasOwnProperty = exports.isRecord = exports.checkExtends = void 0;
|
|
3
|
+
exports.SymbolBasedInstanceOfError = exports.assertNever = exports.errorCode = exports.errorMessage = exports.isAbortError = exports.isError = exports.hasOwnProperties = exports.hasOwnProperty = exports.isRecord = exports.checkExtends = void 0;
|
|
4
4
|
/** Verify that an type _Copy extends _Orig */
|
|
5
5
|
function checkExtends() {
|
|
6
6
|
// noop, just type check
|
|
@@ -10,7 +10,6 @@ function isRecord(value) {
|
|
|
10
10
|
return typeof value === 'object' && value !== null;
|
|
11
11
|
}
|
|
12
12
|
exports.isRecord = isRecord;
|
|
13
|
-
// ts-prune-ignore-next
|
|
14
13
|
function hasOwnProperty(record, prop) {
|
|
15
14
|
return prop in record;
|
|
16
15
|
}
|
|
@@ -19,26 +18,38 @@ function hasOwnProperties(record, props) {
|
|
|
19
18
|
return props.every((prop) => prop in record);
|
|
20
19
|
}
|
|
21
20
|
exports.hasOwnProperties = hasOwnProperties;
|
|
21
|
+
function isError(error) {
|
|
22
|
+
return (isRecord(error) &&
|
|
23
|
+
typeof error.name === 'string' &&
|
|
24
|
+
typeof error.message === 'string' &&
|
|
25
|
+
(error.stack == null || typeof error.stack === 'string'));
|
|
26
|
+
}
|
|
27
|
+
exports.isError = isError;
|
|
28
|
+
function isAbortError(error) {
|
|
29
|
+
return isError(error) && error.name === 'AbortError';
|
|
30
|
+
}
|
|
31
|
+
exports.isAbortError = isAbortError;
|
|
22
32
|
/**
|
|
23
33
|
* Get `error.message` (or `undefined` if not present)
|
|
24
34
|
*/
|
|
25
35
|
function errorMessage(error) {
|
|
26
|
-
if (
|
|
27
|
-
return error;
|
|
28
|
-
}
|
|
29
|
-
if (error instanceof Error) {
|
|
36
|
+
if (isError(error)) {
|
|
30
37
|
return error.message;
|
|
31
38
|
}
|
|
39
|
+
else if (typeof error === 'string') {
|
|
40
|
+
return error;
|
|
41
|
+
}
|
|
32
42
|
return undefined;
|
|
33
43
|
}
|
|
34
44
|
exports.errorMessage = errorMessage;
|
|
45
|
+
function isErrorWithCode(error) {
|
|
46
|
+
return isRecord(error) && typeof error.code === 'string';
|
|
47
|
+
}
|
|
35
48
|
/**
|
|
36
49
|
* Get `error.code` (or `undefined` if not present)
|
|
37
50
|
*/
|
|
38
51
|
function errorCode(error) {
|
|
39
|
-
if (
|
|
40
|
-
error.code !== undefined &&
|
|
41
|
-
typeof error.code === 'string') {
|
|
52
|
+
if (isErrorWithCode(error)) {
|
|
42
53
|
return error.code;
|
|
43
54
|
}
|
|
44
55
|
return undefined;
|
|
@@ -51,4 +62,54 @@ function assertNever(msg, x) {
|
|
|
51
62
|
throw new TypeError(msg + ': ' + x);
|
|
52
63
|
}
|
|
53
64
|
exports.assertNever = assertNever;
|
|
65
|
+
/**
|
|
66
|
+
* A decorator to be used on error classes. It adds the 'name' property AND provides a custom
|
|
67
|
+
* 'instanceof' handler that works correctly across execution contexts.
|
|
68
|
+
*
|
|
69
|
+
* ### Details ###
|
|
70
|
+
*
|
|
71
|
+
* According to the EcmaScript's spec, the default behavior of JavaScript's `x instanceof Y` operator is to walk up the
|
|
72
|
+
* prototype chain of object 'x', checking if any constructor in that hierarchy is _exactly the same object_ as the
|
|
73
|
+
* constructor function 'Y'.
|
|
74
|
+
*
|
|
75
|
+
* Unfortunately, it happens in various situations that different constructor function objects get created for what
|
|
76
|
+
* appears to be the very same class. This leads to surprising behavior where `instanceof` returns false though it is
|
|
77
|
+
* known that the object is indeed an instance of that class. One particular case where this happens is when constructor
|
|
78
|
+
* 'Y' belongs to a different realm than the constuctor with which 'x' was instantiated. Another case is when two copies
|
|
79
|
+
* of the same library gets loaded in the same realm.
|
|
80
|
+
*
|
|
81
|
+
* In practice, this tends to cause issues when crossing the workflow-sandboxing boundary (since Node's vm module
|
|
82
|
+
* really creates new execution realms), as well as when running tests using Jest (see https://github.com/jestjs/jest/issues/2549
|
|
83
|
+
* for some details on that one).
|
|
84
|
+
*
|
|
85
|
+
* This function injects a custom 'instanceof' handler into the prototype of 'clazz', which is both cross-realm safe and
|
|
86
|
+
* cross-copies-of-the-same-lib safe. It works by adding a special symbol property to the prototype of 'clazz', and then
|
|
87
|
+
* checking for the presence of that symbol.
|
|
88
|
+
*/
|
|
89
|
+
function SymbolBasedInstanceOfError(markerName) {
|
|
90
|
+
return (clazz) => {
|
|
91
|
+
const marker = Symbol.for(`__temporal_is${markerName}`);
|
|
92
|
+
Object.defineProperty(clazz.prototype, 'name', { value: markerName, enumerable: true });
|
|
93
|
+
Object.defineProperty(clazz.prototype, marker, { value: true, enumerable: false });
|
|
94
|
+
Object.defineProperty(clazz, Symbol.hasInstance, {
|
|
95
|
+
// eslint-disable-next-line object-shorthand
|
|
96
|
+
value: function (error) {
|
|
97
|
+
if (this === clazz) {
|
|
98
|
+
return isRecord(error) && error[marker] === true;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// 'this' must be a _subclass_ of clazz that doesn't redefined [Symbol.hasInstance], so that it inherited
|
|
102
|
+
// from clazz's [Symbol.hasInstance]. If we don't handle this particular situation, then
|
|
103
|
+
// `x instanceof SubclassOfParent` would return true for any instance of 'Parent', which is clearly wrong.
|
|
104
|
+
//
|
|
105
|
+
// Ideally, it'd be preferable to avoid this case entirely, by making sure that all subclasses of 'clazz'
|
|
106
|
+
// redefine [Symbol.hasInstance], but we can't enforce that. We therefore fallback to the default instanceof
|
|
107
|
+
// behavior (which is NOT cross-realm safe).
|
|
108
|
+
return this.prototype.isPrototypeOf(error); // eslint-disable-line no-prototype-builtins
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
exports.SymbolBasedInstanceOfError = SymbolBasedInstanceOfError;
|
|
54
115
|
//# sourceMappingURL=type-helpers.js.map
|
package/lib/type-helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-helpers.js","sourceRoot":"","sources":["../src/type-helpers.ts"],"names":[],"mappings":";;;AAYA,8CAA8C;AAC9C,SAAgB,YAAY;IAC1B,wBAAwB;AAC1B,CAAC;AAFD,oCAEC;AAID,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAFD,4BAEC;AAED,
|
|
1
|
+
{"version":3,"file":"type-helpers.js","sourceRoot":"","sources":["../src/type-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indicates whether the user intends certain commands to be run on a compatible worker Build Id
|
|
3
|
+
* version or not.
|
|
4
|
+
*
|
|
5
|
+
* `COMPATIBLE` indicates that the command should run on a worker with compatible version if
|
|
6
|
+
* possible. It may not be possible if the target task queue does not also have knowledge of the
|
|
7
|
+
* current worker's Build Id.
|
|
8
|
+
*
|
|
9
|
+
* `DEFAULT` indicates that the command should run on the target task queue's current
|
|
10
|
+
* overall-default Build Id.
|
|
11
|
+
*
|
|
12
|
+
* Where this type is accepted optionally, an unset value indicates that the SDK should choose the
|
|
13
|
+
* most sensible default behavior for the type of command, accounting for whether the command will
|
|
14
|
+
* be run on the same task queue as the current worker.
|
|
15
|
+
*
|
|
16
|
+
* @experimental
|
|
17
|
+
*/
|
|
18
|
+
export type VersioningIntent = 'COMPATIBLE' | 'DEFAULT';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versioning-intent.js","sourceRoot":"","sources":["../src/versioning-intent.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temporalio/common",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "Common library for code that's used across the Client, Worker, and/or Workflow",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@opentelemetry/api": "^1.4.1",
|
|
16
|
-
"@temporalio/proto": "1.8.
|
|
16
|
+
"@temporalio/proto": "1.8.2",
|
|
17
17
|
"long": "^5.2.0",
|
|
18
18
|
"ms": "^3.0.0-canary.1",
|
|
19
19
|
"proto3-json-serializer": "^1.0.3",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"src",
|
|
36
36
|
"lib"
|
|
37
37
|
],
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "d85bf54da757741b438f8d39a0e7265b80d4f0d6"
|
|
39
39
|
}
|
package/src/activity-options.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { coresdk } from '@temporalio/proto';
|
|
|
2
2
|
import { RetryPolicy } from './retry-policy';
|
|
3
3
|
import { checkExtends } from './type-helpers';
|
|
4
4
|
import { Duration } from './time';
|
|
5
|
+
import { VersioningIntent } from './versioning-intent';
|
|
5
6
|
|
|
6
7
|
// Avoid importing the proto implementation to reduce workflow bundle size
|
|
7
8
|
// Copied from coresdk.workflow_commands.ActivityCancellationType
|
|
@@ -100,6 +101,14 @@ export interface ActivityOptions {
|
|
|
100
101
|
* @default true
|
|
101
102
|
*/
|
|
102
103
|
allowEagerDispatch?: boolean;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* When using the Worker Versioning feature, specifies whether this Activity should run on a
|
|
107
|
+
* worker with a compatible Build Id or not. See {@link VersioningIntent}.
|
|
108
|
+
*
|
|
109
|
+
* @experimental
|
|
110
|
+
*/
|
|
111
|
+
versioningIntent?: VersioningIntent;
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
/**
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
TimeoutFailure,
|
|
13
13
|
TimeoutType,
|
|
14
14
|
} from '../failure';
|
|
15
|
-
import {
|
|
15
|
+
import { isError } from '../type-helpers';
|
|
16
16
|
import { arrayFromPayloads, fromPayloadsAtIndex, PayloadConverter, toPayloads } from './payload-converter';
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -219,7 +219,7 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
errorToFailureInner(err: unknown, payloadConverter: PayloadConverter): ProtoFailure {
|
|
222
|
-
if (TemporalFailure
|
|
222
|
+
if (err instanceof TemporalFailure) {
|
|
223
223
|
if (err.failure) return err.failure;
|
|
224
224
|
const base = {
|
|
225
225
|
message: err.message,
|
|
@@ -228,7 +228,7 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
228
228
|
source: FAILURE_SOURCE,
|
|
229
229
|
};
|
|
230
230
|
|
|
231
|
-
if (ActivityFailure
|
|
231
|
+
if (err instanceof ActivityFailure) {
|
|
232
232
|
return {
|
|
233
233
|
...base,
|
|
234
234
|
activityFailureInfo: {
|
|
@@ -237,7 +237,7 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
237
237
|
},
|
|
238
238
|
};
|
|
239
239
|
}
|
|
240
|
-
if (ChildWorkflowFailure
|
|
240
|
+
if (err instanceof ChildWorkflowFailure) {
|
|
241
241
|
return {
|
|
242
242
|
...base,
|
|
243
243
|
childWorkflowExecutionFailureInfo: {
|
|
@@ -247,7 +247,7 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
247
247
|
},
|
|
248
248
|
};
|
|
249
249
|
}
|
|
250
|
-
if (ApplicationFailure
|
|
250
|
+
if (err instanceof ApplicationFailure) {
|
|
251
251
|
return {
|
|
252
252
|
...base,
|
|
253
253
|
applicationFailureInfo: {
|
|
@@ -260,7 +260,7 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
260
260
|
},
|
|
261
261
|
};
|
|
262
262
|
}
|
|
263
|
-
if (CancelledFailure
|
|
263
|
+
if (err instanceof CancelledFailure) {
|
|
264
264
|
return {
|
|
265
265
|
...base,
|
|
266
266
|
canceledFailureInfo: {
|
|
@@ -271,7 +271,7 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
271
271
|
},
|
|
272
272
|
};
|
|
273
273
|
}
|
|
274
|
-
if (TimeoutFailure
|
|
274
|
+
if (err instanceof TimeoutFailure) {
|
|
275
275
|
return {
|
|
276
276
|
...base,
|
|
277
277
|
timeoutFailureInfo: {
|
|
@@ -282,13 +282,13 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
282
282
|
},
|
|
283
283
|
};
|
|
284
284
|
}
|
|
285
|
-
if (ServerFailure
|
|
285
|
+
if (err instanceof ServerFailure) {
|
|
286
286
|
return {
|
|
287
287
|
...base,
|
|
288
288
|
serverFailureInfo: { nonRetryable: err.nonRetryable },
|
|
289
289
|
};
|
|
290
290
|
}
|
|
291
|
-
if (TerminatedFailure
|
|
291
|
+
if (err instanceof TerminatedFailure) {
|
|
292
292
|
return {
|
|
293
293
|
...base,
|
|
294
294
|
terminatedFailureInfo: {},
|
|
@@ -302,12 +302,12 @@ export class DefaultFailureConverter implements FailureConverter {
|
|
|
302
302
|
source: FAILURE_SOURCE,
|
|
303
303
|
};
|
|
304
304
|
|
|
305
|
-
if (
|
|
305
|
+
if (isError(err)) {
|
|
306
306
|
return {
|
|
307
307
|
...base,
|
|
308
308
|
message: String(err.message) ?? '',
|
|
309
|
-
stackTrace: cutoffStackTrace(
|
|
310
|
-
cause: this.optionalErrorToOptionalFailure(err.cause, payloadConverter),
|
|
309
|
+
stackTrace: cutoffStackTrace(err.stack),
|
|
310
|
+
cause: this.optionalErrorToOptionalFailure((err as any).cause, payloadConverter),
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
313
|
|
|
@@ -260,7 +260,7 @@ export class SearchAttributePayloadConverter implements PayloadConverter {
|
|
|
260
260
|
validNonDateTypes = ['string', 'number', 'boolean'];
|
|
261
261
|
|
|
262
262
|
public toPayload(values: unknown): Payload {
|
|
263
|
-
if (!(values
|
|
263
|
+
if (!Array.isArray(values)) {
|
|
264
264
|
throw new ValueError(`SearchAttribute value must be an array`);
|
|
265
265
|
}
|
|
266
266
|
|
|
@@ -309,7 +309,7 @@ export class SearchAttributePayloadConverter implements PayloadConverter {
|
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
const value = this.jsonConverter.fromPayload(payload);
|
|
312
|
-
let arrayWrappedValue = value
|
|
312
|
+
let arrayWrappedValue = Array.isArray(value) ? value : [value];
|
|
313
313
|
|
|
314
314
|
const searchAttributeType = decode(payload.metadata.type);
|
|
315
315
|
if (searchAttributeType === 'Datetime') {
|
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
|
|
15
15
|
import { encodingTypes, METADATA_ENCODING_KEY, METADATA_MESSAGE_TYPE_KEY } from './types';
|
|
16
16
|
|
|
17
|
+
const GLOBAL_BUFFER = globalThis.constructor.constructor('return globalThis.Buffer')();
|
|
18
|
+
|
|
17
19
|
abstract class ProtobufPayloadConverter implements PayloadConverterWithEncoding {
|
|
18
20
|
protected readonly root: Root | undefined;
|
|
19
21
|
public abstract encodingType: string;
|
|
@@ -121,17 +123,69 @@ export class ProtobufJsonPayloadConverter extends ProtobufPayloadConverter {
|
|
|
121
123
|
return undefined;
|
|
122
124
|
}
|
|
123
125
|
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
const hasBufferChanged = setBufferInGlobal();
|
|
127
|
+
try {
|
|
128
|
+
const jsonValue = protoJsonSerializer.toProto3JSON(value);
|
|
129
|
+
|
|
130
|
+
return this.constructPayload({
|
|
131
|
+
messageTypeName: getNamespacedTypeName(value.$type),
|
|
132
|
+
message: encode(JSON.stringify(jsonValue)),
|
|
133
|
+
});
|
|
134
|
+
} finally {
|
|
135
|
+
resetBufferInGlobal(hasBufferChanged);
|
|
136
|
+
}
|
|
130
137
|
}
|
|
131
138
|
|
|
132
139
|
public fromPayload<T>(content: Payload): T {
|
|
133
|
-
const
|
|
134
|
-
|
|
140
|
+
const hasBufferChanged = setBufferInGlobal();
|
|
141
|
+
try {
|
|
142
|
+
const { messageType, data } = this.validatePayload(content);
|
|
143
|
+
const res = protoJsonSerializer.fromProto3JSON(messageType, JSON.parse(decode(data))) as unknown as T;
|
|
144
|
+
if (Buffer.isBuffer(res)) {
|
|
145
|
+
return new Uint8Array(res) as any;
|
|
146
|
+
}
|
|
147
|
+
replaceBuffers(res);
|
|
148
|
+
return res;
|
|
149
|
+
} finally {
|
|
150
|
+
resetBufferInGlobal(hasBufferChanged);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function replaceBuffers<X>(obj: X) {
|
|
156
|
+
const replaceBuffersImpl = <Y>(value: any, key: string | number, target: Y) => {
|
|
157
|
+
if (Buffer.isBuffer(value)) {
|
|
158
|
+
// Need to copy. `Buffer` manages a pool slab, internally reused when Buffer objects are GC.
|
|
159
|
+
type T = keyof typeof target;
|
|
160
|
+
target[key as T] = new Uint8Array(value) as any;
|
|
161
|
+
} else {
|
|
162
|
+
replaceBuffers(value);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
if (obj != null && typeof obj === 'object') {
|
|
167
|
+
// Performance optimization for large arrays
|
|
168
|
+
if (Array.isArray(obj)) {
|
|
169
|
+
obj.forEach(replaceBuffersImpl);
|
|
170
|
+
} else {
|
|
171
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
172
|
+
replaceBuffersImpl(value, key, obj);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function setBufferInGlobal(): boolean {
|
|
179
|
+
if (typeof globalThis.Buffer === 'undefined') {
|
|
180
|
+
globalThis.Buffer = GLOBAL_BUFFER;
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function resetBufferInGlobal(hasChanged: boolean): void {
|
|
187
|
+
if (hasChanged) {
|
|
188
|
+
delete (globalThis as any).Buffer;
|
|
135
189
|
}
|
|
136
190
|
}
|
|
137
191
|
|
package/src/errors.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { TemporalFailure } from './failure';
|
|
2
|
+
import { SymbolBasedInstanceOfError } from './type-helpers';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Thrown from code that receives a value that is unexpected or that it's unable to handle.
|
|
5
6
|
*/
|
|
7
|
+
@SymbolBasedInstanceOfError('ValueError')
|
|
6
8
|
export class ValueError extends Error {
|
|
7
|
-
public readonly name: string = 'ValueError';
|
|
8
|
-
|
|
9
9
|
constructor(message: string | undefined, public readonly cause?: unknown) {
|
|
10
10
|
super(message ?? undefined);
|
|
11
11
|
}
|
|
@@ -14,18 +14,14 @@ export class ValueError extends Error {
|
|
|
14
14
|
/**
|
|
15
15
|
* Thrown when a Payload Converter is misconfigured.
|
|
16
16
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
17
|
+
@SymbolBasedInstanceOfError('PayloadConverterError')
|
|
18
|
+
export class PayloadConverterError extends ValueError {}
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* Used in different parts of the SDK to note that something unexpected has happened.
|
|
23
22
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const isWorkflowExecutionAlreadyStartedError = Symbol.for('__temporal_isWorkflowExecutionAlreadyStartedError');
|
|
23
|
+
@SymbolBasedInstanceOfError('IllegalStateError')
|
|
24
|
+
export class IllegalStateError extends Error {}
|
|
29
25
|
|
|
30
26
|
/**
|
|
31
27
|
* This exception is thrown in the following cases:
|
|
@@ -35,27 +31,11 @@ const isWorkflowExecutionAlreadyStartedError = Symbol.for('__temporal_isWorkflow
|
|
|
35
31
|
* - There is closed Workflow in the `Completed` state with the same Workflow Id and the {@link WorkflowOptions.workflowIdReusePolicy}
|
|
36
32
|
* is `WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY`
|
|
37
33
|
*/
|
|
34
|
+
@SymbolBasedInstanceOfError('WorkflowExecutionAlreadyStartedError')
|
|
38
35
|
export class WorkflowExecutionAlreadyStartedError extends TemporalFailure {
|
|
39
|
-
public readonly name: string = 'WorkflowExecutionAlreadyStartedError';
|
|
40
|
-
|
|
41
36
|
constructor(message: string, public readonly workflowId: string, public readonly workflowType: string) {
|
|
42
37
|
super(message);
|
|
43
38
|
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Marker to determine whether an error is an instance of WorkflowExecutionAlreadyStartedError.
|
|
47
|
-
*/
|
|
48
|
-
protected readonly [isWorkflowExecutionAlreadyStartedError] = true;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Instanceof check that works when multiple versions of @temporalio/common are installed.
|
|
52
|
-
*/
|
|
53
|
-
static is(error: unknown): error is WorkflowExecutionAlreadyStartedError {
|
|
54
|
-
return (
|
|
55
|
-
error instanceof WorkflowExecutionAlreadyStartedError ||
|
|
56
|
-
(error instanceof Error && (error as any)[isWorkflowExecutionAlreadyStartedError])
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
39
|
}
|
|
60
40
|
|
|
61
41
|
/**
|
|
@@ -65,9 +45,8 @@ export class WorkflowExecutionAlreadyStartedError extends TemporalFailure {
|
|
|
65
45
|
* - Workflow is closed (for some calls, e.g. `terminate`)
|
|
66
46
|
* - Workflow was deleted from the Server after reaching its retention limit
|
|
67
47
|
*/
|
|
48
|
+
@SymbolBasedInstanceOfError('WorkflowNotFoundError')
|
|
68
49
|
export class WorkflowNotFoundError extends Error {
|
|
69
|
-
public readonly name: string = 'WorkflowNotFoundError';
|
|
70
|
-
|
|
71
50
|
constructor(message: string, public readonly workflowId: string, public readonly runId: string | undefined) {
|
|
72
51
|
super(message);
|
|
73
52
|
}
|
|
@@ -76,9 +55,8 @@ export class WorkflowNotFoundError extends Error {
|
|
|
76
55
|
/**
|
|
77
56
|
* Thrown when the specified namespace is not known to Temporal Server.
|
|
78
57
|
*/
|
|
58
|
+
@SymbolBasedInstanceOfError('NamespaceNotFoundError')
|
|
79
59
|
export class NamespaceNotFoundError extends Error {
|
|
80
|
-
public readonly name: string = 'NamespaceNotFoundError';
|
|
81
|
-
|
|
82
60
|
constructor(public readonly namespace: string) {
|
|
83
61
|
super(`Namespace not found: '${namespace}'`);
|
|
84
62
|
}
|