@milaboratories/pl-model-common 1.15.3 → 1.15.5
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/drivers/pframe/spec/spec.d.ts.map +1 -1
- package/dist/errors.d.ts +40 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +284 -188
- package/dist/index.mjs.map +1 -1
- package/dist/pool/query.d.ts.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/drivers/pframe/spec/spec.ts +5 -1
- package/src/errors.test.ts +48 -0
- package/src/errors.ts +141 -0
- package/src/index.ts +1 -0
- package/src/pool/query.ts +0 -1
- package/src/util.ts +0 -1
package/dist/pool/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/pool/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,MAAM,MAAM,cAAc,GACtB;IACA,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B,GACC;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,cAAc,CAAC;CACzB,GACC;IACA,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,GACC;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,GACC;IACA,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,GACC;IACA,IAAI,EAAE,oBAAoB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GACC;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;CACzB,CAAC;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/pool/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,MAAM,MAAM,cAAc,GACtB;IACA,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B,GACC;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,cAAc,CAAC;CACzB,GACC;IACA,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,GACC;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,GACC;IACA,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,GACC;IACA,IAAI,EAAE,oBAAoB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GACC;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;CACzB,CAAC;AAMJ,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,cAAc,EACzB,IAAI,EAAE,WAAW,GAChB,OAAO,CAkDT"}
|
package/dist/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAE3C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-model-common",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.5",
|
|
4
4
|
"description": "Platforma SDK Model",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"typescript": "~5.5.4",
|
|
27
27
|
"vite": "^6.3.5",
|
|
28
28
|
"vitest": "^2.1.9",
|
|
29
|
-
"@
|
|
30
|
-
"@platforma-
|
|
29
|
+
"@platforma-sdk/eslint-config": "1.0.3",
|
|
30
|
+
"@milaboratories/platforma-build-configs": "1.0.3"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"type-check": "tsc --noEmit --composite false",
|
|
@@ -186,7 +186,11 @@ export type AxesId = AxisId[];
|
|
|
186
186
|
/** Extracts axis ids from axis spec */
|
|
187
187
|
export function getAxisId(spec: AxisSpec): AxisId {
|
|
188
188
|
const { type, name, domain } = spec;
|
|
189
|
-
|
|
189
|
+
const result = { type, name };
|
|
190
|
+
if (domain && Object.entries(domain).length > 0) {
|
|
191
|
+
Object.assign(result, { domain });
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
190
194
|
}
|
|
191
195
|
|
|
192
196
|
/** Extracts axes ids from axes spec array from column spec */
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
deserializeResult,
|
|
4
|
+
unwrapResult,
|
|
5
|
+
AbortError,
|
|
6
|
+
hasAbortError,
|
|
7
|
+
wrapAndSerializeAsync,
|
|
8
|
+
} from './errors';
|
|
9
|
+
|
|
10
|
+
describe('Full error handling cycle example', () => {
|
|
11
|
+
test('should handle complete workflow: async callback -> serialize -> deserialize with nested AbortError', async () => {
|
|
12
|
+
const abortError = new AbortError('Operation was aborted');
|
|
13
|
+
const middleError = new Error('Middle layer failed', { cause: abortError });
|
|
14
|
+
const topError = new Error('Top level operation failed', { cause: middleError });
|
|
15
|
+
|
|
16
|
+
const serialized = await wrapAndSerializeAsync(async () => {
|
|
17
|
+
throw topError;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
expect(serialized.error).toBeDefined();
|
|
21
|
+
expect(serialized.error?.message).toBe('Top level operation failed');
|
|
22
|
+
expect(serialized.error?.cause?.message).toBe('Middle layer failed');
|
|
23
|
+
expect(serialized.error?.cause?.cause?.message).toBe('Operation was aborted');
|
|
24
|
+
expect(serialized.error?.cause?.cause?.name).toBe('AbortError');
|
|
25
|
+
|
|
26
|
+
const deserialized = deserializeResult(serialized);
|
|
27
|
+
expect(deserialized.error).toBeInstanceOf(Error);
|
|
28
|
+
expect(deserialized.error?.message).toBe('Top level operation failed');
|
|
29
|
+
|
|
30
|
+
if (!deserialized.error) {
|
|
31
|
+
throw new Error('Deserialized error is undefined');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const deserializedError = deserialized.error;
|
|
35
|
+
const middleCause = deserializedError.cause as Error;
|
|
36
|
+
const abortCause = middleCause.cause as Error;
|
|
37
|
+
|
|
38
|
+
expect(middleCause).toBeInstanceOf(Error);
|
|
39
|
+
expect(middleCause.message).toBe('Middle layer failed');
|
|
40
|
+
|
|
41
|
+
expect(abortCause).toBeInstanceOf(Error);
|
|
42
|
+
expect(abortCause.message).toBe('Operation was aborted');
|
|
43
|
+
expect(abortCause.name).toBe('AbortError');
|
|
44
|
+
|
|
45
|
+
expect(() => unwrapResult(deserialized)).toThrow('Top level operation failed');
|
|
46
|
+
expect(hasAbortError(deserialized.error)).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
});
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Just for convenience, usually it is an Error with name 'AbortError'
|
|
3
|
+
*/
|
|
4
|
+
export class AbortError extends Error {
|
|
5
|
+
name = 'AbortError';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Throw this to show a message without stack trace in UI
|
|
10
|
+
*/
|
|
11
|
+
export class UiError extends Error {
|
|
12
|
+
name = 'UiError';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isAbortError(error: unknown): error is Error & { name: 'AbortError' } {
|
|
16
|
+
return error instanceof Error && error.name === 'AbortError';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function hasAbortError(error: unknown): boolean {
|
|
20
|
+
if (!(error instanceof Error)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return error.name === 'AbortError' || hasAbortError(error.cause);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isAggregateError(error: unknown): error is AggregateError {
|
|
28
|
+
return error instanceof Error && error.name === 'AggregateError';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function stringifyValue(value: unknown): string {
|
|
32
|
+
if (typeof value === 'string') {
|
|
33
|
+
return `String value was thrown: ${value}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (value && typeof value === 'object') {
|
|
37
|
+
try {
|
|
38
|
+
return `Plain object was thrown: ${JSON.stringify(value)}`;
|
|
39
|
+
} catch (jsonError) {
|
|
40
|
+
const errorMessage = jsonError instanceof Error ? jsonError.message : String(jsonError);
|
|
41
|
+
return `Non-serializable object was thrown (JSON.stringify failed: ${errorMessage}): ${String(value)}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return String(`Non-Error value (${typeof value}) was thrown: ${value}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function ensureError(value: unknown): Error {
|
|
49
|
+
if (value instanceof Error) {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return new Error(stringifyValue(value));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Error serialization for IPC/network transmission (Error objects can't be JSON serialized)
|
|
57
|
+
|
|
58
|
+
export type SerializedError = {
|
|
59
|
+
name: string;
|
|
60
|
+
message: string;
|
|
61
|
+
stack: string | undefined;
|
|
62
|
+
cause?: SerializedError;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export function deserializeError(obj: SerializedError): Error {
|
|
66
|
+
const cause = obj.cause ? deserializeError(obj.cause) : undefined;
|
|
67
|
+
|
|
68
|
+
const error = new Error(obj.message, cause !== undefined ? { cause } : undefined);
|
|
69
|
+
error.name = obj.name || 'Error';
|
|
70
|
+
error.stack = obj.stack;
|
|
71
|
+
|
|
72
|
+
return error;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function serializeError(e: unknown): SerializedError {
|
|
76
|
+
const error = ensureError(e);
|
|
77
|
+
const cause = error.cause ? serializeError(error.cause) : undefined;
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
name: error.name,
|
|
81
|
+
message: error.message,
|
|
82
|
+
stack: error.stack,
|
|
83
|
+
...(error.cause !== undefined && { cause }),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type ResultOrError<S, F = Error> = {
|
|
88
|
+
value: S;
|
|
89
|
+
error?: undefined;
|
|
90
|
+
} | {
|
|
91
|
+
error: F;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export function unwrapResult<T>(result: ResultOrError<T>): T {
|
|
95
|
+
if (result.error) {
|
|
96
|
+
throw result.error;
|
|
97
|
+
}
|
|
98
|
+
return result.value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function serializeResult<T>(result: ResultOrError<T>): ResultOrError<T, SerializedError> {
|
|
102
|
+
if (result.error) {
|
|
103
|
+
return { error: serializeError(result.error) };
|
|
104
|
+
}
|
|
105
|
+
return { value: result.value };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function deserializeResult<T>(result: ResultOrError<T, SerializedError>): ResultOrError<T> {
|
|
109
|
+
if (result.error) {
|
|
110
|
+
return { error: deserializeError(result.error) };
|
|
111
|
+
}
|
|
112
|
+
return { value: result.value };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function wrapCallback<T>(callback: () => T): ResultOrError<T> {
|
|
116
|
+
try {
|
|
117
|
+
const value = callback();
|
|
118
|
+
return { value };
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return { error: ensureError(error) };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function wrapAsyncCallback<T>(callback: () => Promise<T>): Promise<ResultOrError<T>> {
|
|
125
|
+
try {
|
|
126
|
+
const value = await callback();
|
|
127
|
+
return { value };
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return { error: ensureError(error) };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function wrapAndSerialize<T>(callback: () => T): ResultOrError<T, SerializedError> {
|
|
134
|
+
const result = wrapCallback(callback);
|
|
135
|
+
return serializeResult(result);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function wrapAndSerializeAsync<T>(callback: () => Promise<T>): Promise<ResultOrError<T, SerializedError>> {
|
|
139
|
+
const result = await wrapAsyncCallback(callback);
|
|
140
|
+
return serializeResult(result);
|
|
141
|
+
}
|
package/src/index.ts
CHANGED
package/src/pool/query.ts
CHANGED
|
@@ -35,7 +35,6 @@ export type PSpecPredicate =
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
function assertNever(x: never): never {
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
39
38
|
throw new Error('Unexpected object: ' + x); // This is ok, because this is a possible runtime error
|
|
40
39
|
}
|
|
41
40
|
|
package/src/util.ts
CHANGED