@milaboratories/pl-errors 1.0.5 → 1.0.6
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/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -26
- package/dist/index.mjs.map +1 -1
- package/dist/parsed_error.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/parsed_error.test.ts +13 -0
- package/src/parsed_error.ts +9 -5
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ working directory: ${this.workingDirectory}
|
|
|
36
36
|
|
|
37
37
|
raw message:
|
|
38
38
|
${this.rawBackendMessage}
|
|
39
|
-
`}}const b=g.z.object({errorType:g.z.string(),message:g.z.string()});function j(t,e,r,o){const s=b.
|
|
39
|
+
`}}const b=g.z.object({errorType:g.z.string().default(""),message:g.z.string()});function j(t,e,r,o){const s=b.safeParse(JSON.parse(t));if(!s.success)throw new Error(`parsePlError: failed to parse the message, got ${t}`);const n=k(s.data.message);return new E(t,s.data.errorType,s.data.message,n,o,e,r)}function k(t){const e={stage:"initial",value:[],result:[]};for(const o of t.split(`
|
|
40
40
|
`)){if(e.stage=="initial")e.stage="path";else if(e.stage=="path"&&!d(o))e.stage="message";else if(e.stage=="message"&&d(o)){e.stage="path";const s=e.value.join(`
|
|
41
41
|
`);e.result.push(f(s)),e.value=[]}e.value.push(o)}const r=e.value.join(`
|
|
42
42
|
`);return e.result.push(f(r)),e.result}function d(t){for(const e of["U","I","O","S","OTW","D","MTW"])if(t.startsWith(`[${e}]`))return!0;return!1}function f(t){const e=/working directory: "(.*)"[\s\S]failed to run command: "([^"]+)" exited with code (\d+)\.[\s\S]*?Here is the latest command output:[\s\S]*?\t([\s\S]*)/,r=t.match(e);if(r){const n=r[1],a=r[2],i=parseInt(r[3],10),c=r[4].trim();return a.endsWith("mnz-client")&&i==1?new P(t,a,i,c,n):new h(t,a,i,c,n)}const o=/cannot eval code: cannot eval template: template: (.+)\n\t(.*?)\n\t(at [\s\S]*)/,s=t.match(o);if(s){const n=s[1],a=s[2],i=s[3];return new $(t,n,a,i)}return new M(t)}exports.PlErrorReport=E;exports.PlInternalError=M;exports.PlMonetizationError=P;exports.PlQuickJSError=I;exports.PlRunnerError=h;exports.PlTengoError=$;exports.parsePlError=j;exports.parseSubErrors=k;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/parsed_error.ts"],"sourcesContent":["/** Pl Backend throws arbitrary errors, and we're trying to parse them here. */\n\nimport { z } from 'zod';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { resourceIdToString, resourceTypeToString } from '@milaboratories/pl-client';\nimport { notEmpty } from '@milaboratories/ts-helpers';\n\n/** The error that comes from QuickJS. */\nexport class PlQuickJSError extends Error {\n public stack: string;\n public fullMessage: string;\n\n constructor(\n quickJSError: Error,\n cause: Error,\n ) {\n super(`PlQuickJSError: ${cause.message}`, { cause });\n this.name = 'PlQuickJSError';\n\n // QuickJS wraps the error with the name and the message,\n // but we need another format.\n let stack = notEmpty(quickJSError.stack);\n stack = stack.replace(quickJSError.message, '');\n stack = stack.replace(notEmpty(cause.message), '');\n\n this.stack = stack;\n\n const causeMsg = 'fullMessage' in cause && typeof cause.fullMessage === 'string'\n ? cause.fullMessage\n : cause.message;\n\n this.fullMessage = `PlQuickJSError: ${causeMsg}\nQuickJS stacktrace:\n${this.stack}\n`;\n }\n}\n\n/**\n * A parsed error from the Pl backend.\n * It contains several suberrors, which could be one or different causes of the error.\n */\nexport class PlErrorReport extends Error {\n public readonly fullMessage: string;\n\n constructor(\n /** Full message from the Pl backend. */\n public readonly rawBackendMessage: string,\n\n /** Either CID conflict or a error from controller. */\n public readonly plErrorType: string,\n\n /** Parsed pl backend message that will be futher parsed into suberrors. */\n public readonly plMessage: string,\n\n /** Could be several different errors, the name is from AggregateError. */\n public readonly errors: PlCoreError[],\n\n /** Optional info about a resource where the error happened. */\n public readonly fieldName?: string,\n public readonly resource?: ResourceId,\n public readonly resourceType?: ResourceType,\n ) {\n const errorMessages = errors.map((e) => e.message).join('\\n\\n');\n const errorFullMessages = errors.map((e) => e.fullMessage).join('\\n\\n');\n\n super(`PlErrorReport: ${errorMessages}`);\n this.name = 'PlErrorReport';\n\n const rt = this.resourceType ? `${resourceTypeToString(this.resourceType)},` : '';\n const r = this.resource ? resourceIdToString(this.resource) : '';\n const f = this.fieldName ? `/${this.fieldName}` : '';\n const errType = this.plErrorType ? `error type: ${this.plErrorType}` : '';\n\n this.fullMessage = `PlErrorReport: resource: ${rt} ${r}${f}\n${errType}\n${errorFullMessages}\n`;\n }\n}\n\n/**\n * A suberror of a parsed error.\n */\nexport type PlCoreError =\n | PlInternalError\n | PlTengoError\n | PlRunnerError\n | PlMonetizationError;\n\n/**\n * An general error when we couldn't parse the cause.\n */\nexport class PlInternalError extends Error {\n public readonly fullMessage: string;\n constructor(\n public readonly message: string,\n ) {\n super(message);\n this.name = 'PlInternalError';\n this.fullMessage = `PlInternalError: ${message}`;\n }\n}\n\n/**\n * Happens when workflow template panics.\n */\nexport class PlTengoError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly templateName: string,\n public readonly tengoMessage: string,\n public readonly tengoStacktrace: string,\n ) {\n const msg = `PlTengoError:\nmessage:\n${tengoMessage}\ntemplate: ${templateName}\ntengo stacktrace:\n${tengoStacktrace}\n`;\n\n super(msg);\n this.name = 'PlTengoError';\n\n this.fullMessage = `${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a command fails to run.\n */\nexport class PlRunnerError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly commandName: string,\n public readonly exitCode: number,\n public readonly stdout: string,\n public readonly workingDirectory: string,\n ) {\n const msg = `PlRunnerError:\ncommand: ${commandName}\nexit code: ${exitCode}\nworking directory: ${workingDirectory}\nstdout:\n${stdout}`;\n\n super(msg);\n this.name = 'PlRunnerError';\n this.fullMessage = `\n${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a monetization command fails to run.\n */\nexport class PlMonetizationError extends PlRunnerError {\n public readonly fullMessage: string;\n constructor(\n rawBackendMessage: string,\n commandName: string,\n exitCode: number,\n stdout: string,\n workingDirectory: string,\n ) {\n super(rawBackendMessage, commandName, exitCode, stdout, workingDirectory);\n const msg = `Monetizaiton error:\n${this.stdout}\n`;\n\n this.message = msg;\n this.name = 'PlMonetizationError';\n\n this.fullMessage = `\n${msg}\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\n\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * How the Pl backend represents an error.\n */\nconst backendErrorSchema = z.object({\n errorType: z.string(),\n message: z.string(),\n});\n\n/**\n * Parses a Pl error and suberrors from the Pl backend.\n */\nexport function parsePlError(\n error: string,\n resource?: ResourceId,\n resourceType?: ResourceType,\n field?: string,\n): PlErrorReport {\n const parsed = backendErrorSchema.parse(JSON.parse(error));\n const errors = parseSubErrors(parsed.message);\n\n return new PlErrorReport(\n error,\n parsed.errorType,\n parsed.message,\n errors,\n\n field,\n resource,\n resourceType,\n );\n}\n\n/**\n * Reduces over the lines of the pl error message\n * to extract messages, and categorizes them.\n */\nexport function parseSubErrors(message: string): PlCoreError[] {\n // the state of this reducing function\n const state = {\n stage: 'initial' as 'initial' | 'path' | 'message',\n value: [] as string[],\n result: [] as PlCoreError[],\n };\n\n for (const line of message.split('\\n')) {\n if (state.stage == 'initial') {\n // we need initial stage because apparently the first line\n // of the error doesn't have [I], but is a path line.\n state.stage = 'path';\n } else if (state.stage == 'path' && !isPath(line)) {\n state.stage = 'message';\n } else if (state.stage == 'message' && isPath(line)) {\n state.stage = 'path';\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n state.value = [];\n }\n\n state.value.push(line);\n }\n\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n\n return state.result;\n}\n\nfunction isPath(line: string): boolean {\n for (const fieldType of ['U', 'I', 'O', 'S', 'OTW', 'D', 'MTW']) {\n if (line.startsWith(`[${fieldType}]`))\n return true;\n }\n\n return false;\n}\n\n/**\n * Parses a suberror from the Pl backend.\n */\nfunction parseCoreError(message: string): PlCoreError {\n // trying to parse a runner or monetization error.\n // https://regex101.com/r/tmKLj7/1\n const runnerErrorRegex = /working directory: \"(.*)\"[\\s\\S]failed to run command: \"([^\"]+)\" exited with code (\\d+)\\.[\\s\\S]*?Here is the latest command output:[\\s\\S]*?\\t([\\s\\S]*)/;\n const match = message.match(runnerErrorRegex);\n if (match) {\n const workingDirectory = match[1];\n const command = match[2];\n const exitCode = parseInt(match[3], 10);\n const stdout = match[4].trim();\n\n if (command.endsWith(`mnz-client`) && exitCode == 1) {\n return new PlMonetizationError(message, command, exitCode, stdout, workingDirectory);\n }\n\n return new PlRunnerError(message, command, exitCode, stdout, workingDirectory);\n }\n\n // trying to parse a Tengo error.\n // https://regex101.com/r/1a7RpO/1\n const workflowErrorRegex = /cannot eval code: cannot eval template: template: (.+)\\n\\t(.*?)\\n\\t(at [\\s\\S]*)/;\n const workflowMatch = message.match(workflowErrorRegex);\n if (workflowMatch) {\n const templateName = workflowMatch[1];\n const errorMessage = workflowMatch[2];\n const stackTrace = workflowMatch[3];\n\n return new PlTengoError(message, templateName, errorMessage, stackTrace);\n }\n\n // if we couldn't parse the error, return a general error.\n return new PlInternalError(message);\n}\n"],"names":["PlQuickJSError","quickJSError","cause","__publicField","stack","notEmpty","causeMsg","PlErrorReport","rawBackendMessage","plErrorType","plMessage","errors","fieldName","resource","resourceType","errorMessages","e","errorFullMessages","rt","resourceTypeToString","r","resourceIdToString","f","errType","PlInternalError","message","PlTengoError","templateName","tengoMessage","tengoStacktrace","msg","PlRunnerError","commandName","exitCode","stdout","workingDirectory","PlMonetizationError","backendErrorSchema","z","parsePlError","error","field","parsed","parseSubErrors","state","line","isPath","text","parseCoreError","fieldType","runnerErrorRegex","match","command","workflowErrorRegex","workflowMatch","errorMessage","stackTrace"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/parsed_error.ts"],"sourcesContent":["/** Pl Backend throws arbitrary errors, and we're trying to parse them here. */\n\nimport { z } from 'zod';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { resourceIdToString, resourceTypeToString } from '@milaboratories/pl-client';\nimport { notEmpty } from '@milaboratories/ts-helpers';\n\n/** The error that comes from QuickJS. */\nexport class PlQuickJSError extends Error {\n public stack: string;\n public fullMessage: string;\n\n constructor(\n quickJSError: Error,\n cause: Error,\n ) {\n super(`PlQuickJSError: ${cause.message}`, { cause });\n this.name = 'PlQuickJSError';\n\n // QuickJS wraps the error with the name and the message,\n // but we need another format.\n let stack = notEmpty(quickJSError.stack);\n stack = stack.replace(quickJSError.message, '');\n stack = stack.replace(notEmpty(cause.message), '');\n\n this.stack = stack;\n\n const causeMsg = 'fullMessage' in cause && typeof cause.fullMessage === 'string'\n ? cause.fullMessage\n : cause.message;\n\n this.fullMessage = `PlQuickJSError: ${causeMsg}\nQuickJS stacktrace:\n${this.stack}\n`;\n }\n}\n\n/**\n * A parsed error from the Pl backend.\n * It contains several suberrors, which could be one or different causes of the error.\n */\nexport class PlErrorReport extends Error {\n public readonly fullMessage: string;\n\n constructor(\n /** Full message from the Pl backend. */\n public readonly rawBackendMessage: string,\n\n /** Either CID conflict or a error from controller. */\n public readonly plErrorType: string,\n\n /** Parsed pl backend message that will be futher parsed into suberrors. */\n public readonly plMessage: string,\n\n /** Could be several different errors, the name is from AggregateError. */\n public readonly errors: PlCoreError[],\n\n /** Optional info about a resource where the error happened. */\n public readonly fieldName?: string,\n public readonly resource?: ResourceId,\n public readonly resourceType?: ResourceType,\n ) {\n const errorMessages = errors.map((e) => e.message).join('\\n\\n');\n const errorFullMessages = errors.map((e) => e.fullMessage).join('\\n\\n');\n\n super(`PlErrorReport: ${errorMessages}`);\n this.name = 'PlErrorReport';\n\n const rt = this.resourceType ? `${resourceTypeToString(this.resourceType)},` : '';\n const r = this.resource ? resourceIdToString(this.resource) : '';\n const f = this.fieldName ? `/${this.fieldName}` : '';\n const errType = this.plErrorType ? `error type: ${this.plErrorType}` : '';\n\n this.fullMessage = `PlErrorReport: resource: ${rt} ${r}${f}\n${errType}\n${errorFullMessages}\n`;\n }\n}\n\n/**\n * A suberror of a parsed error.\n */\nexport type PlCoreError =\n | PlInternalError\n | PlTengoError\n | PlRunnerError\n | PlMonetizationError;\n\n/**\n * An general error when we couldn't parse the cause.\n */\nexport class PlInternalError extends Error {\n public readonly fullMessage: string;\n constructor(\n public readonly message: string,\n ) {\n super(message);\n this.name = 'PlInternalError';\n this.fullMessage = `PlInternalError: ${message}`;\n }\n}\n\n/**\n * Happens when workflow template panics.\n */\nexport class PlTengoError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly templateName: string,\n public readonly tengoMessage: string,\n public readonly tengoStacktrace: string,\n ) {\n const msg = `PlTengoError:\nmessage:\n${tengoMessage}\ntemplate: ${templateName}\ntengo stacktrace:\n${tengoStacktrace}\n`;\n\n super(msg);\n this.name = 'PlTengoError';\n\n this.fullMessage = `${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a command fails to run.\n */\nexport class PlRunnerError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly commandName: string,\n public readonly exitCode: number,\n public readonly stdout: string,\n public readonly workingDirectory: string,\n ) {\n const msg = `PlRunnerError:\ncommand: ${commandName}\nexit code: ${exitCode}\nworking directory: ${workingDirectory}\nstdout:\n${stdout}`;\n\n super(msg);\n this.name = 'PlRunnerError';\n this.fullMessage = `\n${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a monetization command fails to run.\n */\nexport class PlMonetizationError extends PlRunnerError {\n public readonly fullMessage: string;\n constructor(\n rawBackendMessage: string,\n commandName: string,\n exitCode: number,\n stdout: string,\n workingDirectory: string,\n ) {\n super(rawBackendMessage, commandName, exitCode, stdout, workingDirectory);\n const msg = `Monetizaiton error:\n${this.stdout}\n`;\n\n this.message = msg;\n this.name = 'PlMonetizationError';\n\n this.fullMessage = `\n${msg}\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\n\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * How the Pl backend represents an error.\n */\nconst backendErrorSchema = z.object({\n errorType: z.string().default(''),\n message: z.string(),\n});\n\n/**\n * Parses a Pl error and suberrors from the Pl backend.\n */\nexport function parsePlError(\n error: string,\n resource?: ResourceId,\n resourceType?: ResourceType,\n field?: string,\n): PlErrorReport {\n const parsed = backendErrorSchema.safeParse(JSON.parse(error));\n if (!parsed.success) {\n throw new Error(`parsePlError: failed to parse the message, got ${error}`);\n }\n\n const errors = parseSubErrors(parsed.data.message);\n\n return new PlErrorReport(\n error,\n parsed.data.errorType,\n parsed.data.message,\n errors,\n\n field,\n resource,\n resourceType,\n );\n}\n\n/**\n * Reduces over the lines of the pl error message\n * to extract messages, and categorizes them.\n */\nexport function parseSubErrors(message: string): PlCoreError[] {\n // the state of this reducing function\n const state = {\n stage: 'initial' as 'initial' | 'path' | 'message',\n value: [] as string[],\n result: [] as PlCoreError[],\n };\n\n for (const line of message.split('\\n')) {\n if (state.stage == 'initial') {\n // we need initial stage because apparently the first line\n // of the error doesn't have [I], but is a path line.\n state.stage = 'path';\n } else if (state.stage == 'path' && !isPath(line)) {\n state.stage = 'message';\n } else if (state.stage == 'message' && isPath(line)) {\n state.stage = 'path';\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n state.value = [];\n }\n\n state.value.push(line);\n }\n\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n\n return state.result;\n}\n\nfunction isPath(line: string): boolean {\n for (const fieldType of ['U', 'I', 'O', 'S', 'OTW', 'D', 'MTW']) {\n if (line.startsWith(`[${fieldType}]`))\n return true;\n }\n\n return false;\n}\n\n/**\n * Parses a suberror from the Pl backend.\n */\nfunction parseCoreError(message: string): PlCoreError {\n // trying to parse a runner or monetization error.\n // https://regex101.com/r/tmKLj7/1\n const runnerErrorRegex = /working directory: \"(.*)\"[\\s\\S]failed to run command: \"([^\"]+)\" exited with code (\\d+)\\.[\\s\\S]*?Here is the latest command output:[\\s\\S]*?\\t([\\s\\S]*)/;\n const match = message.match(runnerErrorRegex);\n if (match) {\n const workingDirectory = match[1];\n const command = match[2];\n const exitCode = parseInt(match[3], 10);\n const stdout = match[4].trim();\n\n if (command.endsWith(`mnz-client`) && exitCode == 1) {\n return new PlMonetizationError(message, command, exitCode, stdout, workingDirectory);\n }\n\n return new PlRunnerError(message, command, exitCode, stdout, workingDirectory);\n }\n\n // trying to parse a Tengo error.\n // https://regex101.com/r/1a7RpO/1\n const workflowErrorRegex = /cannot eval code: cannot eval template: template: (.+)\\n\\t(.*?)\\n\\t(at [\\s\\S]*)/;\n const workflowMatch = message.match(workflowErrorRegex);\n if (workflowMatch) {\n const templateName = workflowMatch[1];\n const errorMessage = workflowMatch[2];\n const stackTrace = workflowMatch[3];\n\n return new PlTengoError(message, templateName, errorMessage, stackTrace);\n }\n\n // if we couldn't parse the error, return a general error.\n return new PlInternalError(message);\n}\n"],"names":["PlQuickJSError","quickJSError","cause","__publicField","stack","notEmpty","causeMsg","PlErrorReport","rawBackendMessage","plErrorType","plMessage","errors","fieldName","resource","resourceType","errorMessages","e","errorFullMessages","rt","resourceTypeToString","r","resourceIdToString","f","errType","PlInternalError","message","PlTengoError","templateName","tengoMessage","tengoStacktrace","msg","PlRunnerError","commandName","exitCode","stdout","workingDirectory","PlMonetizationError","backendErrorSchema","z","parsePlError","error","field","parsed","parseSubErrors","state","line","isPath","text","parseCoreError","fieldType","runnerErrorRegex","match","command","workflowErrorRegex","workflowMatch","errorMessage","stackTrace"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -12,23 +12,23 @@ class W extends Error {
|
|
|
12
12
|
this.name = "PlQuickJSError";
|
|
13
13
|
let s = g(r.stack);
|
|
14
14
|
s = s.replace(r.message, ""), s = s.replace(g(o.message), ""), this.stack = s;
|
|
15
|
-
const
|
|
16
|
-
this.fullMessage = `PlQuickJSError: ${
|
|
15
|
+
const a = "fullMessage" in o && typeof o.fullMessage == "string" ? o.fullMessage : o.message;
|
|
16
|
+
this.fullMessage = `PlQuickJSError: ${a}
|
|
17
17
|
QuickJS stacktrace:
|
|
18
18
|
${this.stack}
|
|
19
19
|
`;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
class S extends Error {
|
|
23
|
-
constructor(r, o, s,
|
|
24
|
-
const d =
|
|
23
|
+
constructor(r, o, s, a, n, i, l) {
|
|
24
|
+
const d = a.map((u) => u.message).join(`
|
|
25
25
|
|
|
26
|
-
`), E =
|
|
26
|
+
`), E = a.map((u) => u.fullMessage).join(`
|
|
27
27
|
|
|
28
28
|
`);
|
|
29
29
|
super(`PlErrorReport: ${d}`);
|
|
30
30
|
c(this, "fullMessage");
|
|
31
|
-
this.rawBackendMessage = r, this.plErrorType = o, this.plMessage = s, this.errors =
|
|
31
|
+
this.rawBackendMessage = r, this.plErrorType = o, this.plMessage = s, this.errors = a, this.fieldName = n, this.resource = i, this.resourceType = l, this.name = "PlErrorReport";
|
|
32
32
|
const M = this.resourceType ? `${T(this.resourceType)},` : "", $ = this.resource ? x(this.resource) : "", k = this.fieldName ? `/${this.fieldName}` : "", w = this.plErrorType ? `error type: ${this.plErrorType}` : "";
|
|
33
33
|
this.fullMessage = `PlErrorReport: resource: ${M} ${$}${k}
|
|
34
34
|
${w}
|
|
@@ -44,33 +44,33 @@ class R extends Error {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
class v extends Error {
|
|
47
|
-
constructor(r, o, s,
|
|
48
|
-
const
|
|
47
|
+
constructor(r, o, s, a) {
|
|
48
|
+
const n = `PlTengoError:
|
|
49
49
|
message:
|
|
50
50
|
${s}
|
|
51
51
|
template: ${o}
|
|
52
52
|
tengo stacktrace:
|
|
53
|
-
${
|
|
53
|
+
${a}
|
|
54
54
|
`;
|
|
55
|
-
super(
|
|
55
|
+
super(n);
|
|
56
56
|
c(this, "fullMessage");
|
|
57
|
-
this.rawBackendMessage = r, this.templateName = o, this.tengoMessage = s, this.tengoStacktrace =
|
|
57
|
+
this.rawBackendMessage = r, this.templateName = o, this.tengoMessage = s, this.tengoStacktrace = a, this.name = "PlTengoError", this.fullMessage = `${n}
|
|
58
58
|
raw message:
|
|
59
59
|
${this.rawBackendMessage}
|
|
60
60
|
`;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
class f extends Error {
|
|
64
|
-
constructor(r, o, s,
|
|
64
|
+
constructor(r, o, s, a, n) {
|
|
65
65
|
const i = `PlRunnerError:
|
|
66
66
|
command: ${o}
|
|
67
67
|
exit code: ${s}
|
|
68
|
-
working directory: ${
|
|
68
|
+
working directory: ${n}
|
|
69
69
|
stdout:
|
|
70
|
-
${
|
|
70
|
+
${a}`;
|
|
71
71
|
super(i);
|
|
72
72
|
c(this, "fullMessage");
|
|
73
|
-
this.rawBackendMessage = r, this.commandName = o, this.exitCode = s, this.stdout =
|
|
73
|
+
this.rawBackendMessage = r, this.commandName = o, this.exitCode = s, this.stdout = a, this.workingDirectory = n, this.name = "PlRunnerError", this.fullMessage = `
|
|
74
74
|
${i}
|
|
75
75
|
raw message:
|
|
76
76
|
${this.rawBackendMessage}
|
|
@@ -78,8 +78,8 @@ ${this.rawBackendMessage}
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
class B extends f {
|
|
81
|
-
constructor(r, o, s,
|
|
82
|
-
super(r, o, s,
|
|
81
|
+
constructor(r, o, s, a, n) {
|
|
82
|
+
super(r, o, s, a, n);
|
|
83
83
|
c(this, "fullMessage");
|
|
84
84
|
const i = `Monetizaiton error:
|
|
85
85
|
${this.stdout}
|
|
@@ -96,16 +96,19 @@ ${this.rawBackendMessage}
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
const I = h.object({
|
|
99
|
-
errorType: h.string(),
|
|
99
|
+
errorType: h.string().default(""),
|
|
100
100
|
message: h.string()
|
|
101
101
|
});
|
|
102
102
|
function b(t, e, r, o) {
|
|
103
|
-
const s = I.
|
|
103
|
+
const s = I.safeParse(JSON.parse(t));
|
|
104
|
+
if (!s.success)
|
|
105
|
+
throw new Error(`parsePlError: failed to parse the message, got ${t}`);
|
|
106
|
+
const a = N(s.data.message);
|
|
104
107
|
return new S(
|
|
105
108
|
t,
|
|
106
|
-
s.errorType,
|
|
107
|
-
s.message,
|
|
108
|
-
|
|
109
|
+
s.data.errorType,
|
|
110
|
+
s.data.message,
|
|
111
|
+
a,
|
|
109
112
|
o,
|
|
110
113
|
e,
|
|
111
114
|
r
|
|
@@ -144,13 +147,13 @@ function p(t) {
|
|
|
144
147
|
function m(t) {
|
|
145
148
|
const e = /working directory: "(.*)"[\s\S]failed to run command: "([^"]+)" exited with code (\d+)\.[\s\S]*?Here is the latest command output:[\s\S]*?\t([\s\S]*)/, r = t.match(e);
|
|
146
149
|
if (r) {
|
|
147
|
-
const
|
|
148
|
-
return
|
|
150
|
+
const a = r[1], n = r[2], i = parseInt(r[3], 10), l = r[4].trim();
|
|
151
|
+
return n.endsWith("mnz-client") && i == 1 ? new B(t, n, i, l, a) : new f(t, n, i, l, a);
|
|
149
152
|
}
|
|
150
153
|
const o = /cannot eval code: cannot eval template: template: (.+)\n\t(.*?)\n\t(at [\s\S]*)/, s = t.match(o);
|
|
151
154
|
if (s) {
|
|
152
|
-
const
|
|
153
|
-
return new v(t,
|
|
155
|
+
const a = s[1], n = s[2], i = s[3];
|
|
156
|
+
return new v(t, a, n, i);
|
|
154
157
|
}
|
|
155
158
|
return new R(t);
|
|
156
159
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/parsed_error.ts"],"sourcesContent":["/** Pl Backend throws arbitrary errors, and we're trying to parse them here. */\n\nimport { z } from 'zod';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { resourceIdToString, resourceTypeToString } from '@milaboratories/pl-client';\nimport { notEmpty } from '@milaboratories/ts-helpers';\n\n/** The error that comes from QuickJS. */\nexport class PlQuickJSError extends Error {\n public stack: string;\n public fullMessage: string;\n\n constructor(\n quickJSError: Error,\n cause: Error,\n ) {\n super(`PlQuickJSError: ${cause.message}`, { cause });\n this.name = 'PlQuickJSError';\n\n // QuickJS wraps the error with the name and the message,\n // but we need another format.\n let stack = notEmpty(quickJSError.stack);\n stack = stack.replace(quickJSError.message, '');\n stack = stack.replace(notEmpty(cause.message), '');\n\n this.stack = stack;\n\n const causeMsg = 'fullMessage' in cause && typeof cause.fullMessage === 'string'\n ? cause.fullMessage\n : cause.message;\n\n this.fullMessage = `PlQuickJSError: ${causeMsg}\nQuickJS stacktrace:\n${this.stack}\n`;\n }\n}\n\n/**\n * A parsed error from the Pl backend.\n * It contains several suberrors, which could be one or different causes of the error.\n */\nexport class PlErrorReport extends Error {\n public readonly fullMessage: string;\n\n constructor(\n /** Full message from the Pl backend. */\n public readonly rawBackendMessage: string,\n\n /** Either CID conflict or a error from controller. */\n public readonly plErrorType: string,\n\n /** Parsed pl backend message that will be futher parsed into suberrors. */\n public readonly plMessage: string,\n\n /** Could be several different errors, the name is from AggregateError. */\n public readonly errors: PlCoreError[],\n\n /** Optional info about a resource where the error happened. */\n public readonly fieldName?: string,\n public readonly resource?: ResourceId,\n public readonly resourceType?: ResourceType,\n ) {\n const errorMessages = errors.map((e) => e.message).join('\\n\\n');\n const errorFullMessages = errors.map((e) => e.fullMessage).join('\\n\\n');\n\n super(`PlErrorReport: ${errorMessages}`);\n this.name = 'PlErrorReport';\n\n const rt = this.resourceType ? `${resourceTypeToString(this.resourceType)},` : '';\n const r = this.resource ? resourceIdToString(this.resource) : '';\n const f = this.fieldName ? `/${this.fieldName}` : '';\n const errType = this.plErrorType ? `error type: ${this.plErrorType}` : '';\n\n this.fullMessage = `PlErrorReport: resource: ${rt} ${r}${f}\n${errType}\n${errorFullMessages}\n`;\n }\n}\n\n/**\n * A suberror of a parsed error.\n */\nexport type PlCoreError =\n | PlInternalError\n | PlTengoError\n | PlRunnerError\n | PlMonetizationError;\n\n/**\n * An general error when we couldn't parse the cause.\n */\nexport class PlInternalError extends Error {\n public readonly fullMessage: string;\n constructor(\n public readonly message: string,\n ) {\n super(message);\n this.name = 'PlInternalError';\n this.fullMessage = `PlInternalError: ${message}`;\n }\n}\n\n/**\n * Happens when workflow template panics.\n */\nexport class PlTengoError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly templateName: string,\n public readonly tengoMessage: string,\n public readonly tengoStacktrace: string,\n ) {\n const msg = `PlTengoError:\nmessage:\n${tengoMessage}\ntemplate: ${templateName}\ntengo stacktrace:\n${tengoStacktrace}\n`;\n\n super(msg);\n this.name = 'PlTengoError';\n\n this.fullMessage = `${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a command fails to run.\n */\nexport class PlRunnerError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly commandName: string,\n public readonly exitCode: number,\n public readonly stdout: string,\n public readonly workingDirectory: string,\n ) {\n const msg = `PlRunnerError:\ncommand: ${commandName}\nexit code: ${exitCode}\nworking directory: ${workingDirectory}\nstdout:\n${stdout}`;\n\n super(msg);\n this.name = 'PlRunnerError';\n this.fullMessage = `\n${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a monetization command fails to run.\n */\nexport class PlMonetizationError extends PlRunnerError {\n public readonly fullMessage: string;\n constructor(\n rawBackendMessage: string,\n commandName: string,\n exitCode: number,\n stdout: string,\n workingDirectory: string,\n ) {\n super(rawBackendMessage, commandName, exitCode, stdout, workingDirectory);\n const msg = `Monetizaiton error:\n${this.stdout}\n`;\n\n this.message = msg;\n this.name = 'PlMonetizationError';\n\n this.fullMessage = `\n${msg}\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\n\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * How the Pl backend represents an error.\n */\nconst backendErrorSchema = z.object({\n errorType: z.string(),\n message: z.string(),\n});\n\n/**\n * Parses a Pl error and suberrors from the Pl backend.\n */\nexport function parsePlError(\n error: string,\n resource?: ResourceId,\n resourceType?: ResourceType,\n field?: string,\n): PlErrorReport {\n const parsed = backendErrorSchema.parse(JSON.parse(error));\n const errors = parseSubErrors(parsed.message);\n\n return new PlErrorReport(\n error,\n parsed.errorType,\n parsed.message,\n errors,\n\n field,\n resource,\n resourceType,\n );\n}\n\n/**\n * Reduces over the lines of the pl error message\n * to extract messages, and categorizes them.\n */\nexport function parseSubErrors(message: string): PlCoreError[] {\n // the state of this reducing function\n const state = {\n stage: 'initial' as 'initial' | 'path' | 'message',\n value: [] as string[],\n result: [] as PlCoreError[],\n };\n\n for (const line of message.split('\\n')) {\n if (state.stage == 'initial') {\n // we need initial stage because apparently the first line\n // of the error doesn't have [I], but is a path line.\n state.stage = 'path';\n } else if (state.stage == 'path' && !isPath(line)) {\n state.stage = 'message';\n } else if (state.stage == 'message' && isPath(line)) {\n state.stage = 'path';\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n state.value = [];\n }\n\n state.value.push(line);\n }\n\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n\n return state.result;\n}\n\nfunction isPath(line: string): boolean {\n for (const fieldType of ['U', 'I', 'O', 'S', 'OTW', 'D', 'MTW']) {\n if (line.startsWith(`[${fieldType}]`))\n return true;\n }\n\n return false;\n}\n\n/**\n * Parses a suberror from the Pl backend.\n */\nfunction parseCoreError(message: string): PlCoreError {\n // trying to parse a runner or monetization error.\n // https://regex101.com/r/tmKLj7/1\n const runnerErrorRegex = /working directory: \"(.*)\"[\\s\\S]failed to run command: \"([^\"]+)\" exited with code (\\d+)\\.[\\s\\S]*?Here is the latest command output:[\\s\\S]*?\\t([\\s\\S]*)/;\n const match = message.match(runnerErrorRegex);\n if (match) {\n const workingDirectory = match[1];\n const command = match[2];\n const exitCode = parseInt(match[3], 10);\n const stdout = match[4].trim();\n\n if (command.endsWith(`mnz-client`) && exitCode == 1) {\n return new PlMonetizationError(message, command, exitCode, stdout, workingDirectory);\n }\n\n return new PlRunnerError(message, command, exitCode, stdout, workingDirectory);\n }\n\n // trying to parse a Tengo error.\n // https://regex101.com/r/1a7RpO/1\n const workflowErrorRegex = /cannot eval code: cannot eval template: template: (.+)\\n\\t(.*?)\\n\\t(at [\\s\\S]*)/;\n const workflowMatch = message.match(workflowErrorRegex);\n if (workflowMatch) {\n const templateName = workflowMatch[1];\n const errorMessage = workflowMatch[2];\n const stackTrace = workflowMatch[3];\n\n return new PlTengoError(message, templateName, errorMessage, stackTrace);\n }\n\n // if we couldn't parse the error, return a general error.\n return new PlInternalError(message);\n}\n"],"names":["PlQuickJSError","quickJSError","cause","__publicField","stack","notEmpty","causeMsg","PlErrorReport","rawBackendMessage","plErrorType","plMessage","errors","fieldName","resource","resourceType","errorMessages","e","errorFullMessages","rt","resourceTypeToString","r","resourceIdToString","f","errType","PlInternalError","message","PlTengoError","templateName","tengoMessage","tengoStacktrace","msg","PlRunnerError","commandName","exitCode","stdout","workingDirectory","PlMonetizationError","backendErrorSchema","z","parsePlError","error","field","parsed","parseSubErrors","state","line","isPath","text","parseCoreError","fieldType","runnerErrorRegex","match","command","workflowErrorRegex","workflowMatch","errorMessage","stackTrace"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/parsed_error.ts"],"sourcesContent":["/** Pl Backend throws arbitrary errors, and we're trying to parse them here. */\n\nimport { z } from 'zod';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { resourceIdToString, resourceTypeToString } from '@milaboratories/pl-client';\nimport { notEmpty } from '@milaboratories/ts-helpers';\n\n/** The error that comes from QuickJS. */\nexport class PlQuickJSError extends Error {\n public stack: string;\n public fullMessage: string;\n\n constructor(\n quickJSError: Error,\n cause: Error,\n ) {\n super(`PlQuickJSError: ${cause.message}`, { cause });\n this.name = 'PlQuickJSError';\n\n // QuickJS wraps the error with the name and the message,\n // but we need another format.\n let stack = notEmpty(quickJSError.stack);\n stack = stack.replace(quickJSError.message, '');\n stack = stack.replace(notEmpty(cause.message), '');\n\n this.stack = stack;\n\n const causeMsg = 'fullMessage' in cause && typeof cause.fullMessage === 'string'\n ? cause.fullMessage\n : cause.message;\n\n this.fullMessage = `PlQuickJSError: ${causeMsg}\nQuickJS stacktrace:\n${this.stack}\n`;\n }\n}\n\n/**\n * A parsed error from the Pl backend.\n * It contains several suberrors, which could be one or different causes of the error.\n */\nexport class PlErrorReport extends Error {\n public readonly fullMessage: string;\n\n constructor(\n /** Full message from the Pl backend. */\n public readonly rawBackendMessage: string,\n\n /** Either CID conflict or a error from controller. */\n public readonly plErrorType: string,\n\n /** Parsed pl backend message that will be futher parsed into suberrors. */\n public readonly plMessage: string,\n\n /** Could be several different errors, the name is from AggregateError. */\n public readonly errors: PlCoreError[],\n\n /** Optional info about a resource where the error happened. */\n public readonly fieldName?: string,\n public readonly resource?: ResourceId,\n public readonly resourceType?: ResourceType,\n ) {\n const errorMessages = errors.map((e) => e.message).join('\\n\\n');\n const errorFullMessages = errors.map((e) => e.fullMessage).join('\\n\\n');\n\n super(`PlErrorReport: ${errorMessages}`);\n this.name = 'PlErrorReport';\n\n const rt = this.resourceType ? `${resourceTypeToString(this.resourceType)},` : '';\n const r = this.resource ? resourceIdToString(this.resource) : '';\n const f = this.fieldName ? `/${this.fieldName}` : '';\n const errType = this.plErrorType ? `error type: ${this.plErrorType}` : '';\n\n this.fullMessage = `PlErrorReport: resource: ${rt} ${r}${f}\n${errType}\n${errorFullMessages}\n`;\n }\n}\n\n/**\n * A suberror of a parsed error.\n */\nexport type PlCoreError =\n | PlInternalError\n | PlTengoError\n | PlRunnerError\n | PlMonetizationError;\n\n/**\n * An general error when we couldn't parse the cause.\n */\nexport class PlInternalError extends Error {\n public readonly fullMessage: string;\n constructor(\n public readonly message: string,\n ) {\n super(message);\n this.name = 'PlInternalError';\n this.fullMessage = `PlInternalError: ${message}`;\n }\n}\n\n/**\n * Happens when workflow template panics.\n */\nexport class PlTengoError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly templateName: string,\n public readonly tengoMessage: string,\n public readonly tengoStacktrace: string,\n ) {\n const msg = `PlTengoError:\nmessage:\n${tengoMessage}\ntemplate: ${templateName}\ntengo stacktrace:\n${tengoStacktrace}\n`;\n\n super(msg);\n this.name = 'PlTengoError';\n\n this.fullMessage = `${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a command fails to run.\n */\nexport class PlRunnerError extends Error {\n public readonly fullMessage: string;\n\n constructor(\n public readonly rawBackendMessage: string,\n public readonly commandName: string,\n public readonly exitCode: number,\n public readonly stdout: string,\n public readonly workingDirectory: string,\n ) {\n const msg = `PlRunnerError:\ncommand: ${commandName}\nexit code: ${exitCode}\nworking directory: ${workingDirectory}\nstdout:\n${stdout}`;\n\n super(msg);\n this.name = 'PlRunnerError';\n this.fullMessage = `\n${msg}\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * Happens when a monetization command fails to run.\n */\nexport class PlMonetizationError extends PlRunnerError {\n public readonly fullMessage: string;\n constructor(\n rawBackendMessage: string,\n commandName: string,\n exitCode: number,\n stdout: string,\n workingDirectory: string,\n ) {\n super(rawBackendMessage, commandName, exitCode, stdout, workingDirectory);\n const msg = `Monetizaiton error:\n${this.stdout}\n`;\n\n this.message = msg;\n this.name = 'PlMonetizationError';\n\n this.fullMessage = `\n${msg}\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\n\nraw message:\n${this.rawBackendMessage}\n`;\n }\n}\n\n/**\n * How the Pl backend represents an error.\n */\nconst backendErrorSchema = z.object({\n errorType: z.string().default(''),\n message: z.string(),\n});\n\n/**\n * Parses a Pl error and suberrors from the Pl backend.\n */\nexport function parsePlError(\n error: string,\n resource?: ResourceId,\n resourceType?: ResourceType,\n field?: string,\n): PlErrorReport {\n const parsed = backendErrorSchema.safeParse(JSON.parse(error));\n if (!parsed.success) {\n throw new Error(`parsePlError: failed to parse the message, got ${error}`);\n }\n\n const errors = parseSubErrors(parsed.data.message);\n\n return new PlErrorReport(\n error,\n parsed.data.errorType,\n parsed.data.message,\n errors,\n\n field,\n resource,\n resourceType,\n );\n}\n\n/**\n * Reduces over the lines of the pl error message\n * to extract messages, and categorizes them.\n */\nexport function parseSubErrors(message: string): PlCoreError[] {\n // the state of this reducing function\n const state = {\n stage: 'initial' as 'initial' | 'path' | 'message',\n value: [] as string[],\n result: [] as PlCoreError[],\n };\n\n for (const line of message.split('\\n')) {\n if (state.stage == 'initial') {\n // we need initial stage because apparently the first line\n // of the error doesn't have [I], but is a path line.\n state.stage = 'path';\n } else if (state.stage == 'path' && !isPath(line)) {\n state.stage = 'message';\n } else if (state.stage == 'message' && isPath(line)) {\n state.stage = 'path';\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n state.value = [];\n }\n\n state.value.push(line);\n }\n\n const text = state.value.join('\\n');\n state.result.push(parseCoreError(text));\n\n return state.result;\n}\n\nfunction isPath(line: string): boolean {\n for (const fieldType of ['U', 'I', 'O', 'S', 'OTW', 'D', 'MTW']) {\n if (line.startsWith(`[${fieldType}]`))\n return true;\n }\n\n return false;\n}\n\n/**\n * Parses a suberror from the Pl backend.\n */\nfunction parseCoreError(message: string): PlCoreError {\n // trying to parse a runner or monetization error.\n // https://regex101.com/r/tmKLj7/1\n const runnerErrorRegex = /working directory: \"(.*)\"[\\s\\S]failed to run command: \"([^\"]+)\" exited with code (\\d+)\\.[\\s\\S]*?Here is the latest command output:[\\s\\S]*?\\t([\\s\\S]*)/;\n const match = message.match(runnerErrorRegex);\n if (match) {\n const workingDirectory = match[1];\n const command = match[2];\n const exitCode = parseInt(match[3], 10);\n const stdout = match[4].trim();\n\n if (command.endsWith(`mnz-client`) && exitCode == 1) {\n return new PlMonetizationError(message, command, exitCode, stdout, workingDirectory);\n }\n\n return new PlRunnerError(message, command, exitCode, stdout, workingDirectory);\n }\n\n // trying to parse a Tengo error.\n // https://regex101.com/r/1a7RpO/1\n const workflowErrorRegex = /cannot eval code: cannot eval template: template: (.+)\\n\\t(.*?)\\n\\t(at [\\s\\S]*)/;\n const workflowMatch = message.match(workflowErrorRegex);\n if (workflowMatch) {\n const templateName = workflowMatch[1];\n const errorMessage = workflowMatch[2];\n const stackTrace = workflowMatch[3];\n\n return new PlTengoError(message, templateName, errorMessage, stackTrace);\n }\n\n // if we couldn't parse the error, return a general error.\n return new PlInternalError(message);\n}\n"],"names":["PlQuickJSError","quickJSError","cause","__publicField","stack","notEmpty","causeMsg","PlErrorReport","rawBackendMessage","plErrorType","plMessage","errors","fieldName","resource","resourceType","errorMessages","e","errorFullMessages","rt","resourceTypeToString","r","resourceIdToString","f","errType","PlInternalError","message","PlTengoError","templateName","tengoMessage","tengoStacktrace","msg","PlRunnerError","commandName","exitCode","stdout","workingDirectory","PlMonetizationError","backendErrorSchema","z","parsePlError","error","field","parsed","parseSubErrors","state","line","isPath","text","parseCoreError","fieldType","runnerErrorRegex","match","command","workflowErrorRegex","workflowMatch","errorMessage","stackTrace"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsed_error.d.ts","sourceRoot":"","sources":["../src/parsed_error.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAG/E,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAI1E,yCAAyC;AACzC,qBAAa,cAAe,SAAQ,KAAK;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;gBAGzB,YAAY,EAAE,KAAK,EACnB,KAAK,EAAE,KAAK;CAsBf;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAIpC,wCAAwC;aACxB,iBAAiB,EAAE,MAAM;IAEzC,sDAAsD;aACtC,WAAW,EAAE,MAAM;IAEnC,2EAA2E;aAC3D,SAAS,EAAE,MAAM;IAEjC,0EAA0E;aAC1D,MAAM,EAAE,WAAW,EAAE;IAErC,+DAA+D;aAC/C,SAAS,CAAC,EAAE,MAAM;aAClB,QAAQ,CAAC,EAAE,UAAU;aACrB,YAAY,CAAC,EAAE,YAAY;IAlB7C,SAAgB,WAAW,EAAE,MAAM,CAAC;;IAGlC,wCAAwC;IACxB,iBAAiB,EAAE,MAAM;IAEzC,sDAAsD;IACtC,WAAW,EAAE,MAAM;IAEnC,2EAA2E;IAC3D,SAAS,EAAE,MAAM;IAEjC,0EAA0E;IAC1D,MAAM,EAAE,WAAW,EAAE;IAErC,+DAA+D;IAC/C,SAAS,CAAC,EAAE,MAAM,YAAA,EAClB,QAAQ,CAAC,EAAE,UAAU,YAAA,EACrB,YAAY,CAAC,EAAE,YAAY,YAAA;CAkB9C;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,eAAe,GACf,YAAY,GACZ,aAAa,GACb,mBAAmB,CAAC;AAExB;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,OAAO,EAAE,MAAM;IAFjC,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,MAAM;CAMlC;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;aAInB,iBAAiB,EAAE,MAAM;aACzB,YAAY,EAAE,MAAM;aACpB,YAAY,EAAE,MAAM;aACpB,eAAe,EAAE,MAAM;IANzC,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAGlB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM;CAkB1C;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;aAIpB,iBAAiB,EAAE,MAAM;aACzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,MAAM;aACd,gBAAgB,EAAE,MAAM;IAP1C,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAGlB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM;CAiB3C;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAElC,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM;CAoB3B;AAUD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,UAAU,EACrB,YAAY,CAAC,EAAE,YAAY,EAC3B,KAAK,CAAC,EAAE,MAAM,GACb,aAAa,
|
|
1
|
+
{"version":3,"file":"parsed_error.d.ts","sourceRoot":"","sources":["../src/parsed_error.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAG/E,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAI1E,yCAAyC;AACzC,qBAAa,cAAe,SAAQ,KAAK;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;gBAGzB,YAAY,EAAE,KAAK,EACnB,KAAK,EAAE,KAAK;CAsBf;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAIpC,wCAAwC;aACxB,iBAAiB,EAAE,MAAM;IAEzC,sDAAsD;aACtC,WAAW,EAAE,MAAM;IAEnC,2EAA2E;aAC3D,SAAS,EAAE,MAAM;IAEjC,0EAA0E;aAC1D,MAAM,EAAE,WAAW,EAAE;IAErC,+DAA+D;aAC/C,SAAS,CAAC,EAAE,MAAM;aAClB,QAAQ,CAAC,EAAE,UAAU;aACrB,YAAY,CAAC,EAAE,YAAY;IAlB7C,SAAgB,WAAW,EAAE,MAAM,CAAC;;IAGlC,wCAAwC;IACxB,iBAAiB,EAAE,MAAM;IAEzC,sDAAsD;IACtC,WAAW,EAAE,MAAM;IAEnC,2EAA2E;IAC3D,SAAS,EAAE,MAAM;IAEjC,0EAA0E;IAC1D,MAAM,EAAE,WAAW,EAAE;IAErC,+DAA+D;IAC/C,SAAS,CAAC,EAAE,MAAM,YAAA,EAClB,QAAQ,CAAC,EAAE,UAAU,YAAA,EACrB,YAAY,CAAC,EAAE,YAAY,YAAA;CAkB9C;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,eAAe,GACf,YAAY,GACZ,aAAa,GACb,mBAAmB,CAAC;AAExB;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,OAAO,EAAE,MAAM;IAFjC,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,MAAM;CAMlC;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;aAInB,iBAAiB,EAAE,MAAM;aACzB,YAAY,EAAE,MAAM;aACpB,YAAY,EAAE,MAAM;aACpB,eAAe,EAAE,MAAM;IANzC,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAGlB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM;CAkB1C;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;aAIpB,iBAAiB,EAAE,MAAM;aACzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,MAAM;aACd,gBAAgB,EAAE,MAAM;IAP1C,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAGlB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM;CAiB3C;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,SAAgB,WAAW,EAAE,MAAM,CAAC;gBAElC,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM;CAoB3B;AAUD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,UAAU,EACrB,YAAY,CAAC,EAAE,YAAY,EAC3B,KAAK,CAAC,EAAE,MAAM,GACb,aAAa,CAkBf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CA6B7D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-errors",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Parsing errors from Pl backend",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"zod": "~3.23.8",
|
|
21
|
-
"@milaboratories/
|
|
22
|
-
"@milaboratories/
|
|
21
|
+
"@milaboratories/pl-client": "2.8.0",
|
|
22
|
+
"@milaboratories/ts-helpers": "1.1.5"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"typescript": "~5.5.4",
|
|
26
26
|
"vite": "^5.4.11",
|
|
27
27
|
"vitest": "^2.1.8",
|
|
28
|
-
"@milaboratories/pl-error-like": "1.12.0",
|
|
29
28
|
"@milaboratories/platforma-build-configs": "1.0.3",
|
|
29
|
+
"@milaboratories/pl-error-like": "1.12.0",
|
|
30
30
|
"@milaboratories/eslint-config": "^1.0.4"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
package/src/parsed_error.test.ts
CHANGED
|
@@ -7,6 +7,8 @@ const runnerError = '{"errorType":"","message":"\\"NG:0x2331A5\\" has 1 input er
|
|
|
7
7
|
|
|
8
8
|
const tengoError = "{\"errorType\":\"\",\"message\":\"\\\"NG:0x16A\\\" has 1 input errors:\\n[I] \\\"NG:0x16A/resource\\\": cannot eval code: cannot eval template: template: @platforma-open/milaboratories.samples-and-data.workflow:main@1.10.0\\n\\tRuntime Error: File handle not set for \\\"R1\\\" in sample \\\"S63UG7K2IRZSSMAI4UVB5CNJ\\\"\\n\\tat @platforma-sdk/workflow-tengo:ll:25:1\\n\\tat @platforma-open/milaboratories.samples-and-data.workflow:main:205:7\\n\\tat @platforma-sdk/workflow-tengo:workflow:264:11\\n\\tat @platforma-sdk/workflow-tengo:tpl:470:11\\n\\tat @platforma-sdk/workflow-tengo:tpl:373:1\\n\\tat @platforma-sdk/workflow-tengo:workflow:261:1\\n\\tat @platforma-open/milaboratories.samples-and-data.workflow:main:35:1\"}"
|
|
9
9
|
|
|
10
|
+
const tengoErrorNoErrorType = "{\"message\":\"\\\"NG:0x16A\\\" has 1 input errors:\\n[I] \\\"NG:0x16A/resource\\\": cannot eval code: cannot eval template: template: @platforma-open/milaboratories.samples-and-data.workflow:main@1.10.0\\n\\tRuntime Error: File handle not set for \\\"R1\\\" in sample \\\"S63UG7K2IRZSSMAI4UVB5CNJ\\\"\\n\\tat @platforma-sdk/workflow-tengo:ll:25:1\\n\\tat @platforma-open/milaboratories.samples-and-data.workflow:main:205:7\\n\\tat @platforma-sdk/workflow-tengo:workflow:264:11\\n\\tat @platforma-sdk/workflow-tengo:tpl:470:11\\n\\tat @platforma-sdk/workflow-tengo:tpl:373:1\\n\\tat @platforma-sdk/workflow-tengo:workflow:261:1\\n\\tat @platforma-open/milaboratories.samples-and-data.workflow:main:35:1\"}"
|
|
11
|
+
|
|
10
12
|
const monetizationSubErrors = `"NG:0x1F94C0" has 1 input errors:
|
|
11
13
|
[I] "NG:0x1F94C0/resource": "NG:0x1F94FA" has 1 input errors:
|
|
12
14
|
[I] "NG:0x1F94FA/resource": "NG:0x1F94F5" has 1 input errors:
|
|
@@ -92,6 +94,17 @@ at @platforma-sdk/workflow-tengo:ll:25:1
|
|
|
92
94
|
`);
|
|
93
95
|
});
|
|
94
96
|
|
|
97
|
+
it('should parse workflow error correctly even without the error type', () => {
|
|
98
|
+
const result = parsePlError(tengoErrorNoErrorType, resourceIdFromString('NG:0x16A')! as ResourceId, { name: 'RunCommand', version: "1" }, 'fieldName');
|
|
99
|
+
|
|
100
|
+
expect(result).toBeInstanceOf(PlErrorReport);
|
|
101
|
+
expect(result.name).toBe('PlErrorReport');
|
|
102
|
+
expect(result.plErrorType).toBe('');
|
|
103
|
+
|
|
104
|
+
expect(result.errors.length).toBe(1);
|
|
105
|
+
expect(result.errors[0]).toBeInstanceOf(PlTengoError);
|
|
106
|
+
});
|
|
107
|
+
|
|
95
108
|
it('should parse monetization sub errors correctly', () => {
|
|
96
109
|
const result = parseSubErrors(monetizationSubErrors);
|
|
97
110
|
|
package/src/parsed_error.ts
CHANGED
|
@@ -198,7 +198,7 @@ ${this.rawBackendMessage}
|
|
|
198
198
|
* How the Pl backend represents an error.
|
|
199
199
|
*/
|
|
200
200
|
const backendErrorSchema = z.object({
|
|
201
|
-
errorType: z.string(),
|
|
201
|
+
errorType: z.string().default(''),
|
|
202
202
|
message: z.string(),
|
|
203
203
|
});
|
|
204
204
|
|
|
@@ -211,13 +211,17 @@ export function parsePlError(
|
|
|
211
211
|
resourceType?: ResourceType,
|
|
212
212
|
field?: string,
|
|
213
213
|
): PlErrorReport {
|
|
214
|
-
const parsed = backendErrorSchema.
|
|
215
|
-
|
|
214
|
+
const parsed = backendErrorSchema.safeParse(JSON.parse(error));
|
|
215
|
+
if (!parsed.success) {
|
|
216
|
+
throw new Error(`parsePlError: failed to parse the message, got ${error}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const errors = parseSubErrors(parsed.data.message);
|
|
216
220
|
|
|
217
221
|
return new PlErrorReport(
|
|
218
222
|
error,
|
|
219
|
-
parsed.errorType,
|
|
220
|
-
parsed.message,
|
|
223
|
+
parsed.data.errorType,
|
|
224
|
+
parsed.data.message,
|
|
221
225
|
errors,
|
|
222
226
|
|
|
223
227
|
field,
|