@temporalio/common 1.8.1 → 1.8.3
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/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 -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-enum.d.ts +12 -0
- package/lib/versioning-intent-enum.js +33 -0
- package/lib/versioning-intent-enum.js.map +1 -0
- package/lib/workflow-options.d.ts +1 -1
- package/package.json +3 -3
- 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 -1
- package/src/type-helpers.ts +78 -11
- package/src/versioning-intent-enum.ts +32 -0
- package/src/workflow-options.ts +1 -1
package/src/type-helpers.ts
CHANGED
|
@@ -21,7 +21,6 @@ export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
21
21
|
return typeof value === 'object' && value !== null;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
// ts-prune-ignore-next
|
|
25
24
|
export function hasOwnProperty<X extends Record<string, unknown>, Y extends PropertyKey>(
|
|
26
25
|
record: X,
|
|
27
26
|
prop: Y
|
|
@@ -36,15 +35,27 @@ export function hasOwnProperties<X extends Record<string, unknown>, Y extends Pr
|
|
|
36
35
|
return props.every((prop) => prop in record);
|
|
37
36
|
}
|
|
38
37
|
|
|
38
|
+
export function isError(error: unknown): error is Error {
|
|
39
|
+
return (
|
|
40
|
+
isRecord(error) &&
|
|
41
|
+
typeof error.name === 'string' &&
|
|
42
|
+
typeof error.message === 'string' &&
|
|
43
|
+
(error.stack == null || typeof error.stack === 'string')
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function isAbortError(error: unknown): error is Error & { name: 'AbortError' } {
|
|
48
|
+
return isError(error) && error.name === 'AbortError';
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
/**
|
|
40
52
|
* Get `error.message` (or `undefined` if not present)
|
|
41
53
|
*/
|
|
42
54
|
export function errorMessage(error: unknown): string | undefined {
|
|
43
|
-
if (
|
|
44
|
-
return error;
|
|
45
|
-
}
|
|
46
|
-
if (error instanceof Error) {
|
|
55
|
+
if (isError(error)) {
|
|
47
56
|
return error.message;
|
|
57
|
+
} else if (typeof error === 'string') {
|
|
58
|
+
return error;
|
|
48
59
|
}
|
|
49
60
|
return undefined;
|
|
50
61
|
}
|
|
@@ -52,16 +63,17 @@ export function errorMessage(error: unknown): string | undefined {
|
|
|
52
63
|
interface ErrorWithCode {
|
|
53
64
|
code: string;
|
|
54
65
|
}
|
|
66
|
+
|
|
67
|
+
function isErrorWithCode(error: unknown): error is ErrorWithCode {
|
|
68
|
+
return isRecord(error) && typeof error.code === 'string';
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
/**
|
|
56
72
|
* Get `error.code` (or `undefined` if not present)
|
|
57
73
|
*/
|
|
58
74
|
export function errorCode(error: unknown): string | undefined {
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
(error as ErrorWithCode).code !== undefined &&
|
|
62
|
-
typeof (error as ErrorWithCode).code === 'string'
|
|
63
|
-
) {
|
|
64
|
-
return (error as ErrorWithCode).code;
|
|
75
|
+
if (isErrorWithCode(error)) {
|
|
76
|
+
return error.code;
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
return undefined;
|
|
@@ -73,3 +85,58 @@ export function errorCode(error: unknown): string | undefined {
|
|
|
73
85
|
export function assertNever(msg: string, x: never): never {
|
|
74
86
|
throw new TypeError(msg + ': ' + x);
|
|
75
87
|
}
|
|
88
|
+
|
|
89
|
+
export type Class<E extends Error> = {
|
|
90
|
+
new (...args: any[]): E;
|
|
91
|
+
prototype: E;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A decorator to be used on error classes. It adds the 'name' property AND provides a custom
|
|
96
|
+
* 'instanceof' handler that works correctly across execution contexts.
|
|
97
|
+
*
|
|
98
|
+
* ### Details ###
|
|
99
|
+
*
|
|
100
|
+
* According to the EcmaScript's spec, the default behavior of JavaScript's `x instanceof Y` operator is to walk up the
|
|
101
|
+
* prototype chain of object 'x', checking if any constructor in that hierarchy is _exactly the same object_ as the
|
|
102
|
+
* constructor function 'Y'.
|
|
103
|
+
*
|
|
104
|
+
* Unfortunately, it happens in various situations that different constructor function objects get created for what
|
|
105
|
+
* appears to be the very same class. This leads to surprising behavior where `instanceof` returns false though it is
|
|
106
|
+
* known that the object is indeed an instance of that class. One particular case where this happens is when constructor
|
|
107
|
+
* 'Y' belongs to a different realm than the constuctor with which 'x' was instantiated. Another case is when two copies
|
|
108
|
+
* of the same library gets loaded in the same realm.
|
|
109
|
+
*
|
|
110
|
+
* In practice, this tends to cause issues when crossing the workflow-sandboxing boundary (since Node's vm module
|
|
111
|
+
* really creates new execution realms), as well as when running tests using Jest (see https://github.com/jestjs/jest/issues/2549
|
|
112
|
+
* for some details on that one).
|
|
113
|
+
*
|
|
114
|
+
* This function injects a custom 'instanceof' handler into the prototype of 'clazz', which is both cross-realm safe and
|
|
115
|
+
* cross-copies-of-the-same-lib safe. It works by adding a special symbol property to the prototype of 'clazz', and then
|
|
116
|
+
* checking for the presence of that symbol.
|
|
117
|
+
*/
|
|
118
|
+
export function SymbolBasedInstanceOfError<E extends Error>(markerName: string): (clazz: Class<E>) => void {
|
|
119
|
+
return (clazz: Class<E>): void => {
|
|
120
|
+
const marker = Symbol.for(`__temporal_is${markerName}`);
|
|
121
|
+
|
|
122
|
+
Object.defineProperty(clazz.prototype, 'name', { value: markerName, enumerable: true });
|
|
123
|
+
Object.defineProperty(clazz.prototype, marker, { value: true, enumerable: false });
|
|
124
|
+
Object.defineProperty(clazz, Symbol.hasInstance, {
|
|
125
|
+
// eslint-disable-next-line object-shorthand
|
|
126
|
+
value: function (this: any, error: object): boolean {
|
|
127
|
+
if (this === clazz) {
|
|
128
|
+
return isRecord(error) && (error as any)[marker] === true;
|
|
129
|
+
} else {
|
|
130
|
+
// 'this' must be a _subclass_ of clazz that doesn't redefined [Symbol.hasInstance], so that it inherited
|
|
131
|
+
// from clazz's [Symbol.hasInstance]. If we don't handle this particular situation, then
|
|
132
|
+
// `x instanceof SubclassOfParent` would return true for any instance of 'Parent', which is clearly wrong.
|
|
133
|
+
//
|
|
134
|
+
// Ideally, it'd be preferable to avoid this case entirely, by making sure that all subclasses of 'clazz'
|
|
135
|
+
// redefine [Symbol.hasInstance], but we can't enforce that. We therefore fallback to the default instanceof
|
|
136
|
+
// behavior (which is NOT cross-realm safe).
|
|
137
|
+
return this.prototype.isPrototypeOf(error); // eslint-disable-line no-prototype-builtins
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { coresdk } from '@temporalio/proto';
|
|
2
|
+
import type { VersioningIntent as VersioningIntentString } from './versioning-intent';
|
|
3
|
+
import { assertNever, checkExtends } from './type-helpers';
|
|
4
|
+
|
|
5
|
+
// Avoid importing the proto implementation to reduce workflow bundle size
|
|
6
|
+
// Copied from coresdk.common.VersioningIntent
|
|
7
|
+
/**
|
|
8
|
+
* Protobuf enum representation of {@link VersioningIntentString}.
|
|
9
|
+
*
|
|
10
|
+
* @experimental
|
|
11
|
+
*/
|
|
12
|
+
export enum VersioningIntent {
|
|
13
|
+
UNSPECIFIED = 0,
|
|
14
|
+
COMPATIBLE = 1,
|
|
15
|
+
DEFAULT = 2,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
checkExtends<coresdk.common.VersioningIntent, VersioningIntent>();
|
|
19
|
+
checkExtends<VersioningIntent, coresdk.common.VersioningIntent>();
|
|
20
|
+
|
|
21
|
+
export function versioningIntentToProto(intent: VersioningIntentString | undefined): VersioningIntent {
|
|
22
|
+
switch (intent) {
|
|
23
|
+
case 'DEFAULT':
|
|
24
|
+
return VersioningIntent.DEFAULT;
|
|
25
|
+
case 'COMPATIBLE':
|
|
26
|
+
return VersioningIntent.COMPATIBLE;
|
|
27
|
+
case undefined:
|
|
28
|
+
return VersioningIntent.UNSPECIFIED;
|
|
29
|
+
default:
|
|
30
|
+
assertNever('Unexpected VersioningIntent', intent);
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/workflow-options.ts
CHANGED
|
@@ -52,7 +52,7 @@ export interface BaseWorkflowOptions {
|
|
|
52
52
|
*
|
|
53
53
|
* *Note: A Workflow can never be started with a Workflow Id of a Running Workflow.*
|
|
54
54
|
*
|
|
55
|
-
* @default {@link WorkflowIdReusePolicy.
|
|
55
|
+
* @default {@link WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE}
|
|
56
56
|
*/
|
|
57
57
|
workflowIdReusePolicy?: WorkflowIdReusePolicy;
|
|
58
58
|
|