@lowdefy/errors 0.0.0-experimental-20260219135421 → 0.0.0-experimental-20260220095000
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/ActionError.js +22 -0
- package/dist/BlockError.js +22 -0
- package/dist/BuildError.js +34 -0
- package/dist/ConfigError.js +35 -63
- package/dist/ConfigWarning.js +13 -25
- package/dist/{LowdefyError.js → LowdefyInternalError.js} +6 -34
- package/dist/OperatorError.js +22 -0
- package/dist/PluginError.js +24 -77
- package/dist/RequestError.js +22 -0
- package/dist/ServiceError.js +25 -58
- package/dist/UserError.js +2 -5
- package/dist/{formatErrorMessage.js → errorToDisplayString.js} +9 -11
- package/dist/index.js +30 -8
- package/dist/loadAndResolveErrorLocation.js +63 -0
- package/dist/{build/resolveConfigLocation.js → resolveConfigLocation.js} +2 -4
- package/dist/resolveErrorLocation.js +58 -0
- package/dist/shouldSuppressBuildCheck.js +58 -0
- package/package.json +2 -5
- package/dist/build/ConfigError.js +0 -119
- package/dist/build/ConfigMessage.js +0 -123
- package/dist/build/ConfigWarning.js +0 -111
- package/dist/build/index.js +0 -37
- package/dist/build/resolveErrorConfigLocation.js +0 -45
- package/dist/client/ConfigError.js +0 -79
- package/dist/client/LowdefyError.js +0 -55
- package/dist/client/index.js +0 -31
- package/dist/deserializeError.js +0 -36
- package/dist/server/index.js +0 -30
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import PluginError from './PluginError.js';
|
|
16
|
+
let ActionError = class ActionError extends PluginError {
|
|
17
|
+
constructor(message, options = {}){
|
|
18
|
+
super(message, options);
|
|
19
|
+
this.name = 'ActionError';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export default ActionError;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import PluginError from './PluginError.js';
|
|
16
|
+
let BlockError = class BlockError extends PluginError {
|
|
17
|
+
constructor(message, options = {}){
|
|
18
|
+
super(message, options);
|
|
19
|
+
this.name = 'BlockError';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export default BlockError;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ /**
|
|
16
|
+
* Summary error thrown after build errors have already been logged.
|
|
17
|
+
*
|
|
18
|
+
* Used to stop the build process with a summary message like
|
|
19
|
+
* "Build failed with 5 error(s). See above for details."
|
|
20
|
+
* The real errors are logged individually before this is thrown.
|
|
21
|
+
*
|
|
22
|
+
* Stack traces are suppressed by the CLI logger via isLowdefyError marker.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* context.handleError(configError); // log the real error
|
|
26
|
+
* throw new BuildError('Build failed with 1 error(s). See above for details.');
|
|
27
|
+
*/ let BuildError = class BuildError extends Error {
|
|
28
|
+
constructor(message){
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'BuildError';
|
|
31
|
+
this.isLowdefyError = true;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export default BuildError;
|
package/dist/ConfigError.js
CHANGED
|
@@ -15,10 +15,7 @@
|
|
|
15
15
|
*/ /**
|
|
16
16
|
* Base error class for configuration errors (invalid YAML, schema violations, validation errors).
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
* - Build-time: Use @lowdefy/errors/build (sync resolution via keyMap/refMap)
|
|
20
|
-
* - Server-side: Use @lowdefy/errors/server (re-exports base)
|
|
21
|
-
* - Client-side: Use @lowdefy/errors/client (async resolution via API)
|
|
18
|
+
* Import from @lowdefy/errors for general use.
|
|
22
19
|
*
|
|
23
20
|
* @example
|
|
24
21
|
* // Simple string (for plugins - configKey added by interface layer)
|
|
@@ -26,71 +23,46 @@
|
|
|
26
23
|
*
|
|
27
24
|
* @example
|
|
28
25
|
* // With options
|
|
29
|
-
* throw new ConfigError({
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
26
|
+
* throw new ConfigError('Invalid block type', { configKey: block['~k'] });
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // With raw file location (YAML parse errors, pre-addKeys)
|
|
30
|
+
* throw new ConfigError('Error parsing file', {
|
|
31
|
+
* filePath: 'pages/home.yaml',
|
|
32
|
+
* lineNumber: 6,
|
|
33
33
|
* });
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Serializes the error for transport (e.g., client to server).
|
|
41
|
-
* @returns {Object} Serialized error data with type marker
|
|
42
|
-
*/ serialize() {
|
|
43
|
-
return {
|
|
44
|
-
'~err': 'ConfigError',
|
|
45
|
-
message: this.message,
|
|
46
|
-
configKey: this.configKey
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Deserializes error data back into a ConfigError.
|
|
51
|
-
* @param {Object} data - Serialized error data
|
|
52
|
-
* @returns {ConfigError}
|
|
53
|
-
*/ static deserialize(data) {
|
|
54
|
-
return new ConfigError({
|
|
55
|
-
message: data.message,
|
|
56
|
-
configKey: data.configKey
|
|
57
|
-
});
|
|
58
|
-
}
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // Wrapping an error
|
|
37
|
+
* throw new ConfigError(error.message, { cause: error, filePath });
|
|
38
|
+
*/ let ConfigError = class ConfigError extends Error {
|
|
59
39
|
/**
|
|
60
40
|
* Creates a ConfigError instance with formatted message.
|
|
61
|
-
* @param {string
|
|
62
|
-
* @param {
|
|
63
|
-
* @param {Error} [
|
|
64
|
-
* @param {string} [
|
|
65
|
-
* @param {
|
|
66
|
-
* @param {string} [
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const checkSlug = isString ? undefined : messageOrParams.checkSlug;
|
|
75
|
-
const received = isString ? undefined : messageOrParams.received !== undefined ? messageOrParams.received : error?.received;
|
|
76
|
-
const operatorLocation = isString ? null : messageOrParams.operatorLocation;
|
|
77
|
-
// Message without prefix - logger uses error.name for display
|
|
78
|
-
super(message);
|
|
41
|
+
* @param {string} [message] - Error message (falls back to cause.message)
|
|
42
|
+
* @param {Object} [options]
|
|
43
|
+
* @param {Error} [options.cause] - Original error to wrap
|
|
44
|
+
* @param {string} [options.configKey] - Config key (~k) for location resolution
|
|
45
|
+
* @param {string} [options.filePath] - Raw file path for pre-addKeys errors
|
|
46
|
+
* @param {string|number} [options.lineNumber] - Line number for pre-addKeys errors
|
|
47
|
+
* @param {string} [options.checkSlug] - The build check that triggered this error
|
|
48
|
+
* @param {*} [options.received] - The input that caused the error
|
|
49
|
+
*/ constructor(message, { cause, configKey, filePath, lineNumber, checkSlug, received } = {}){
|
|
50
|
+
const resolvedMessage = message ?? cause?.message;
|
|
51
|
+
super(resolvedMessage, {
|
|
52
|
+
cause
|
|
53
|
+
});
|
|
79
54
|
this.name = 'ConfigError';
|
|
80
|
-
this.
|
|
55
|
+
this.isLowdefyError = true;
|
|
56
|
+
this.configKey = configKey ?? cause?.configKey ?? null;
|
|
81
57
|
this.checkSlug = checkSlug;
|
|
82
58
|
// For logger formatting
|
|
83
|
-
this.received = received;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.
|
|
87
|
-
|
|
88
|
-
this.
|
|
89
|
-
this.
|
|
90
|
-
// Preserve original error's stack if wrapping
|
|
91
|
-
if (error?.stack) {
|
|
92
|
-
this.stack = error.stack;
|
|
93
|
-
}
|
|
59
|
+
this.received = received !== undefined ? received : cause?.received;
|
|
60
|
+
// Raw file location for pre-addKeys errors (resolved by handleError/handleWarning)
|
|
61
|
+
this.filePath = filePath ?? null;
|
|
62
|
+
this.lineNumber = lineNumber ?? null;
|
|
63
|
+
// Location outputs (set by handlers via resolveErrorLocation, not at construction)
|
|
64
|
+
this.source = null;
|
|
65
|
+
this.config = null;
|
|
94
66
|
}
|
|
95
67
|
};
|
|
96
68
|
export default ConfigError;
|
package/dist/ConfigWarning.js
CHANGED
|
@@ -12,31 +12,19 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
print() {
|
|
29
|
-
return formatErrorMessage(this);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* @param {Object} params
|
|
33
|
-
* @param {string} params.message - The warning message
|
|
34
|
-
* @param {string} [params.source] - Source file:line
|
|
35
|
-
*/ constructor({ message, source }){
|
|
36
|
-
this.name = 'Config Warning';
|
|
37
|
-
// Message without prefix - logger uses class name for display
|
|
38
|
-
this.message = message;
|
|
39
|
-
this.source = source ?? null;
|
|
15
|
+
*/ import ConfigError from './ConfigError.js';
|
|
16
|
+
let ConfigWarning = class ConfigWarning extends ConfigError {
|
|
17
|
+
constructor(message, { cause, configKey, checkSlug, filePath, lineNumber, received, prodError } = {}){
|
|
18
|
+
super(message, {
|
|
19
|
+
cause,
|
|
20
|
+
configKey,
|
|
21
|
+
checkSlug,
|
|
22
|
+
filePath,
|
|
23
|
+
lineNumber,
|
|
24
|
+
received
|
|
25
|
+
});
|
|
26
|
+
this.name = 'ConfigWarning';
|
|
27
|
+
this.prodError = prodError ?? false;
|
|
40
28
|
}
|
|
41
29
|
};
|
|
42
30
|
export default ConfigWarning;
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* // Create a new error
|
|
23
|
-
* throw new
|
|
23
|
+
* throw new LowdefyInternalError('Unexpected condition');
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
26
|
* // At top-level catch, log the error with stack
|
|
@@ -28,46 +28,18 @@
|
|
|
28
28
|
* console.error(err.message);
|
|
29
29
|
* console.error(err.stack);
|
|
30
30
|
* }
|
|
31
|
-
*/
|
|
32
|
-
let LowdefyError = class LowdefyError extends Error {
|
|
33
|
-
print() {
|
|
34
|
-
const message = formatErrorMessage(this);
|
|
35
|
-
if (this.stack) {
|
|
36
|
-
return `${message}\n${this.stack}`;
|
|
37
|
-
}
|
|
38
|
-
return message;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Serializes the error for transport (e.g., client to server).
|
|
42
|
-
* @returns {Object} Serialized error data with type marker
|
|
43
|
-
*/ serialize() {
|
|
44
|
-
return {
|
|
45
|
-
'~err': 'LowdefyError',
|
|
46
|
-
message: this.message,
|
|
47
|
-
stack: this.stack
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Deserializes error data back into a LowdefyError.
|
|
52
|
-
* @param {Object} data - Serialized error data
|
|
53
|
-
* @returns {LowdefyError}
|
|
54
|
-
*/ static deserialize(data) {
|
|
55
|
-
const error = new LowdefyError(data.message);
|
|
56
|
-
if (data.stack) {
|
|
57
|
-
error.stack = data.stack;
|
|
58
|
-
}
|
|
59
|
-
return error;
|
|
60
|
-
}
|
|
31
|
+
*/ let LowdefyInternalError = class LowdefyInternalError extends Error {
|
|
61
32
|
/**
|
|
62
|
-
* Creates a
|
|
33
|
+
* Creates a LowdefyInternalError instance.
|
|
63
34
|
* @param {string} message - The error message
|
|
64
35
|
* @param {Object} [options]
|
|
65
36
|
* @param {Error} [options.cause] - The original error that caused this
|
|
66
37
|
*/ constructor(message, options = {}){
|
|
67
38
|
// Message without prefix - logger uses error.name for display
|
|
68
39
|
super(message, options);
|
|
69
|
-
this.name = '
|
|
40
|
+
this.name = 'LowdefyInternalError';
|
|
41
|
+
this.isLowdefyError = true;
|
|
70
42
|
this.configKey = null;
|
|
71
43
|
}
|
|
72
44
|
};
|
|
73
|
-
export default
|
|
45
|
+
export default LowdefyInternalError;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import PluginError from './PluginError.js';
|
|
16
|
+
let OperatorError = class OperatorError extends PluginError {
|
|
17
|
+
constructor(message, options = {}){
|
|
18
|
+
super(message, options);
|
|
19
|
+
this.name = 'OperatorError';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export default OperatorError;
|
package/dist/PluginError.js
CHANGED
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ /**
|
|
16
|
-
*
|
|
16
|
+
* Base error class for plugin failures (operators, actions, blocks, requests).
|
|
17
17
|
*
|
|
18
18
|
* Plugins throw plain Error objects with simple messages.
|
|
19
|
-
* The plugin interface layer catches these and wraps them in
|
|
20
|
-
*
|
|
19
|
+
* The plugin interface layer catches these and wraps them in a typed subclass
|
|
20
|
+
* (OperatorError, ActionError, BlockError, RequestError) with additional context.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* // In operator parser (plugin interface layer):
|
|
@@ -25,96 +25,43 @@
|
|
|
25
25
|
* return operator({ params });
|
|
26
26
|
* } catch (error) {
|
|
27
27
|
* if (error instanceof ConfigError) throw error;
|
|
28
|
-
* throw new
|
|
29
|
-
* error,
|
|
30
|
-
*
|
|
31
|
-
* pluginName: '_if',
|
|
28
|
+
* throw new OperatorError(error.message, {
|
|
29
|
+
* cause: error,
|
|
30
|
+
* typeName: '_if',
|
|
32
31
|
* received: params,
|
|
33
32
|
* location: 'blocks.0.properties.visible',
|
|
34
33
|
* configKey: block['~k'],
|
|
35
34
|
* });
|
|
36
35
|
* }
|
|
37
|
-
|
|
38
|
-
*/ import formatErrorMessage from './formatErrorMessage.js';
|
|
39
|
-
let PluginError = class PluginError extends Error {
|
|
40
|
-
print() {
|
|
41
|
-
return formatErrorMessage(this);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Serializes the error for transport (e.g., client to server).
|
|
45
|
-
* @returns {Object} Serialized error data with type marker
|
|
46
|
-
*/ serialize() {
|
|
47
|
-
return {
|
|
48
|
-
'~err': 'PluginError',
|
|
49
|
-
message: this.message,
|
|
50
|
-
rawMessage: this.rawMessage,
|
|
51
|
-
pluginType: this.pluginType,
|
|
52
|
-
pluginName: this.pluginName,
|
|
53
|
-
location: this.location,
|
|
54
|
-
configKey: this.configKey,
|
|
55
|
-
stack: this.stack
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Deserializes error data back into a PluginError.
|
|
60
|
-
* Note: message already contains location/received, so we don't pass them
|
|
61
|
-
* to avoid double-formatting.
|
|
62
|
-
* @param {Object} data - Serialized error data
|
|
63
|
-
* @returns {PluginError}
|
|
64
|
-
*/ static deserialize(data) {
|
|
65
|
-
// Use rawMessage if available, fallback to message
|
|
66
|
-
const messageToUse = data.rawMessage || data.message;
|
|
67
|
-
const error = new PluginError({
|
|
68
|
-
message: messageToUse,
|
|
69
|
-
pluginType: data.pluginType,
|
|
70
|
-
pluginName: data.pluginName,
|
|
71
|
-
configKey: data.configKey
|
|
72
|
-
});
|
|
73
|
-
// Set location separately to preserve it without re-formatting message
|
|
74
|
-
error.location = data.location;
|
|
75
|
-
// Preserve the formatted message if different from rawMessage
|
|
76
|
-
if (data.message && data.message !== messageToUse) {
|
|
77
|
-
error.message = data.message;
|
|
78
|
-
}
|
|
79
|
-
if (data.stack) {
|
|
80
|
-
error.stack = data.stack;
|
|
81
|
-
}
|
|
82
|
-
return error;
|
|
83
|
-
}
|
|
36
|
+
*/ let PluginError = class PluginError extends Error {
|
|
84
37
|
/**
|
|
85
38
|
* Creates a PluginError instance with formatted message.
|
|
86
|
-
* @param {
|
|
87
|
-
* @param {
|
|
88
|
-
* @param {
|
|
89
|
-
* @param {string} [
|
|
90
|
-
* @param {*} [
|
|
91
|
-
* @param {string} [
|
|
92
|
-
* @param {string} [
|
|
93
|
-
*/ constructor(
|
|
94
|
-
|
|
95
|
-
// Accept either error object or direct message string
|
|
96
|
-
const rawMessage = message ?? error?.message;
|
|
39
|
+
* @param {string} [message] - Error message (falls back to cause.message)
|
|
40
|
+
* @param {Object} [options]
|
|
41
|
+
* @param {Error} [options.cause] - The original error thrown by the plugin
|
|
42
|
+
* @param {string} [options.typeName] - The config type name (e.g., '_if', 'SetState', 'MongoDBFind')
|
|
43
|
+
* @param {*} [options.received] - The input that caused the error
|
|
44
|
+
* @param {string} [options.location] - Where in the config the error occurred
|
|
45
|
+
* @param {string} [options.configKey] - Config key (~k) for location resolution
|
|
46
|
+
*/ constructor(message, { cause, typeName, received, location, configKey } = {}){
|
|
47
|
+
const rawMessage = message ?? cause?.message;
|
|
97
48
|
let formattedMessage = rawMessage;
|
|
98
49
|
if (location) {
|
|
99
|
-
formattedMessage = rawMessage
|
|
50
|
+
formattedMessage = rawMessage ? `${rawMessage} at ${location}.` : `at ${location}.`;
|
|
100
51
|
}
|
|
101
52
|
super(formattedMessage, {
|
|
102
|
-
cause
|
|
53
|
+
cause
|
|
103
54
|
});
|
|
104
55
|
this.name = 'PluginError';
|
|
105
|
-
this.
|
|
106
|
-
this.
|
|
107
|
-
this.
|
|
108
|
-
this.received = received !== undefined ? received :
|
|
56
|
+
this.isLowdefyError = true;
|
|
57
|
+
this.typeName = typeName;
|
|
58
|
+
this._message = rawMessage;
|
|
59
|
+
this.received = received !== undefined ? received : cause?.received;
|
|
109
60
|
this.location = location;
|
|
110
|
-
this.configKey =
|
|
111
|
-
// Location
|
|
61
|
+
this.configKey = configKey ?? cause?.configKey ?? null;
|
|
62
|
+
// Location outputs (set by server-side resolution)
|
|
112
63
|
this.source = null;
|
|
113
64
|
this.config = null;
|
|
114
|
-
this.link = null;
|
|
115
|
-
if (error?.stack) {
|
|
116
|
-
this.stack = error.stack;
|
|
117
|
-
}
|
|
118
65
|
}
|
|
119
66
|
};
|
|
120
67
|
export default PluginError;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import PluginError from './PluginError.js';
|
|
16
|
+
let RequestError = class RequestError extends PluginError {
|
|
17
|
+
constructor(message, options = {}){
|
|
18
|
+
super(message, options);
|
|
19
|
+
this.name = 'RequestError';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export default RequestError;
|
package/dist/ServiceError.js
CHANGED
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
* Error class for external service failures (network, timeout, database, 5xx).
|
|
33
33
|
*
|
|
34
34
|
* ServiceError represents infrastructure/service issues that are NOT caused by
|
|
35
|
-
* invalid configuration.
|
|
36
|
-
*
|
|
35
|
+
* invalid configuration. The config location is still resolved to help developers
|
|
36
|
+
* identify which request/connection triggered the service failure.
|
|
37
37
|
*
|
|
38
38
|
* The message is formatted in the constructor - no format() method needed.
|
|
39
39
|
*
|
|
@@ -43,13 +43,12 @@
|
|
|
43
43
|
* return await fetch(url);
|
|
44
44
|
* } catch (error) {
|
|
45
45
|
* if (ServiceError.isServiceError(error)) {
|
|
46
|
-
* throw ServiceError
|
|
46
|
+
* throw new ServiceError(undefined, { cause: error, service: 'MongoDB' });
|
|
47
47
|
* }
|
|
48
|
-
* throw new PluginError({ error, ... });
|
|
48
|
+
* throw new PluginError(error.message, { cause: error, ... });
|
|
49
49
|
* }
|
|
50
|
-
* // error.message = "
|
|
51
|
-
*/
|
|
52
|
-
let ServiceError = class ServiceError extends Error {
|
|
50
|
+
* // error.message = "MongoDB: Connection refused. The service may be down..."
|
|
51
|
+
*/ let ServiceError = class ServiceError extends Error {
|
|
53
52
|
/**
|
|
54
53
|
* Checks if an error is a service error (network issues, timeouts, 5xx).
|
|
55
54
|
* @param {Error} error - The error to check
|
|
@@ -80,82 +79,50 @@ let ServiceError = class ServiceError extends Error {
|
|
|
80
79
|
const code = error.code;
|
|
81
80
|
const statusCode = error.statusCode ?? error.status ?? error.response?.status;
|
|
82
81
|
if (code === 'ECONNREFUSED') {
|
|
83
|
-
return `Connection refused. The service may be down or the address may be incorrect. ${error.message}`;
|
|
82
|
+
return `Connection refused. The service may be down or the address may be incorrect. ${error.message ?? ''}`;
|
|
84
83
|
}
|
|
85
84
|
if (code === 'ENOTFOUND') {
|
|
86
|
-
return `DNS lookup failed. The hostname could not be resolved. ${error.message}`;
|
|
85
|
+
return `DNS lookup failed. The hostname could not be resolved. ${error.message ?? ''}`;
|
|
87
86
|
}
|
|
88
87
|
if (code === 'ETIMEDOUT') {
|
|
89
|
-
return `Connection timed out. The service may be slow or unreachable. ${error.message}`;
|
|
88
|
+
return `Connection timed out. The service may be slow or unreachable. ${error.message ?? ''}`;
|
|
90
89
|
}
|
|
91
90
|
if (code === 'ECONNRESET') {
|
|
92
|
-
return `Connection reset by the server. ${error.message}`;
|
|
91
|
+
return `Connection reset by the server. ${error.message ?? ''}`;
|
|
93
92
|
}
|
|
94
93
|
if (statusCode && statusCode >= 500) {
|
|
95
|
-
return `Server returned error ${statusCode}. ${error.message}`;
|
|
94
|
+
return `Server returned error ${statusCode}. ${error.message ?? ''}`;
|
|
96
95
|
}
|
|
97
96
|
return error.message;
|
|
98
97
|
}
|
|
99
|
-
print() {
|
|
100
|
-
return formatErrorMessage(this);
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Serializes the error for transport (e.g., client to server).
|
|
104
|
-
* @returns {Object} Serialized error data with type marker
|
|
105
|
-
*/ serialize() {
|
|
106
|
-
return {
|
|
107
|
-
'~err': 'ServiceError',
|
|
108
|
-
message: this.message,
|
|
109
|
-
service: this.service,
|
|
110
|
-
code: this.code,
|
|
111
|
-
statusCode: this.statusCode
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Deserializes error data back into a ServiceError.
|
|
116
|
-
* Note: message already contains service prefix, so we don't pass service
|
|
117
|
-
* to avoid double-prefixing.
|
|
118
|
-
* @param {Object} data - Serialized error data
|
|
119
|
-
* @returns {ServiceError}
|
|
120
|
-
*/ static deserialize(data) {
|
|
121
|
-
const error = new ServiceError({
|
|
122
|
-
message: data.message,
|
|
123
|
-
code: data.code,
|
|
124
|
-
statusCode: data.statusCode
|
|
125
|
-
});
|
|
126
|
-
// Set service separately to preserve it without re-prefixing the message
|
|
127
|
-
error.service = data.service;
|
|
128
|
-
return error;
|
|
129
|
-
}
|
|
130
98
|
/**
|
|
131
99
|
* Creates a ServiceError instance with formatted message.
|
|
132
|
-
* @param {
|
|
133
|
-
* @param {
|
|
134
|
-
* @param {Error} [
|
|
135
|
-
* @param {string} [
|
|
136
|
-
* @param {string} [
|
|
137
|
-
* @param {number} [
|
|
138
|
-
* @param {string} [
|
|
139
|
-
*/ constructor(
|
|
100
|
+
* @param {string} [message] - Error message (falls back to enhanced cause message)
|
|
101
|
+
* @param {Object} [options]
|
|
102
|
+
* @param {Error} [options.cause] - Original error to wrap (auto-enhances message)
|
|
103
|
+
* @param {string} [options.service] - Name of the service that failed
|
|
104
|
+
* @param {string} [options.code] - Error code (e.g., 'ECONNREFUSED')
|
|
105
|
+
* @param {number} [options.statusCode] - HTTP status code if applicable
|
|
106
|
+
* @param {string} [options.configKey] - Config key for location resolution
|
|
107
|
+
*/ constructor(message, { cause, service, code, statusCode, configKey } = {}){
|
|
140
108
|
// Extract info from wrapped error if provided
|
|
141
|
-
const errorCode = code ??
|
|
142
|
-
const errorStatusCode = statusCode ??
|
|
109
|
+
const errorCode = code ?? cause?.code;
|
|
110
|
+
const errorStatusCode = statusCode ?? cause?.statusCode ?? cause?.status ?? cause?.response?.status;
|
|
143
111
|
// Use provided message, or enhance wrapped error's message
|
|
144
|
-
const baseMessage = message ?? (
|
|
112
|
+
const baseMessage = message ?? (cause ? ServiceError.enhanceMessage(cause) : 'Service error');
|
|
145
113
|
// Message without prefix - logger uses error.name for display
|
|
146
114
|
// Include service in message if provided
|
|
147
115
|
const formattedMessage = service ? `${service}: ${baseMessage}` : baseMessage;
|
|
148
116
|
super(formattedMessage, {
|
|
149
|
-
cause
|
|
117
|
+
cause
|
|
150
118
|
});
|
|
151
119
|
this.name = 'ServiceError';
|
|
120
|
+
this.isLowdefyError = true;
|
|
121
|
+
this._message = baseMessage;
|
|
152
122
|
this.service = service;
|
|
153
123
|
this.code = errorCode;
|
|
154
124
|
this.statusCode = errorStatusCode;
|
|
155
125
|
this.configKey = configKey ?? null;
|
|
156
|
-
if (error?.stack) {
|
|
157
|
-
this.stack = error.stack;
|
|
158
|
-
}
|
|
159
126
|
}
|
|
160
127
|
};
|
|
161
128
|
export default ServiceError;
|
package/dist/UserError.js
CHANGED
|
@@ -12,14 +12,11 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
let UserError = class UserError extends Error {
|
|
17
|
-
print() {
|
|
18
|
-
return formatErrorMessage(this);
|
|
19
|
-
}
|
|
15
|
+
*/ let UserError = class UserError extends Error {
|
|
20
16
|
constructor(message, { blockId, metaData, pageId } = {}){
|
|
21
17
|
super(message);
|
|
22
18
|
this.name = 'UserError';
|
|
19
|
+
this.isLowdefyError = true;
|
|
23
20
|
this.blockId = blockId;
|
|
24
21
|
this.metaData = metaData;
|
|
25
22
|
this.pageId = pageId;
|