@milaboratories/pl-errors 1.0.2 → 1.0.4
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 +33 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +117 -98
- package/dist/index.mjs.map +1 -1
- package/dist/parsed_error.d.ts +18 -15
- package/dist/parsed_error.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/parsed_error.test.ts +41 -1
- package/src/parsed_error.ts +89 -57
package/dist/index.js
CHANGED
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var z=Object.defineProperty;var v=(t,e,r)=>e in t?z(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var l=(t,e,r)=>v(t,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("zod"),p=require("@milaboratories/pl-client"),m=require("@milaboratories/ts-helpers");class I extends Error{constructor(r,o){super(`PlQuickJSError: ${o.message}`,{cause:o});l(this,"stack");l(this,"fullMessage");this.name="PlQuickJSError";let s=m.notEmpty(r.stack);s=s.replace(r.message,""),s=s.replace(m.notEmpty(o.message),""),this.stack=s;const n="fullMessage"in o&&typeof o.fullMessage=="string"?o.fullMessage:o.message;this.fullMessage=`PlQuickJSError: ${n}
|
|
2
|
+
QuickJS stacktrace:
|
|
3
|
+
${this.stack}
|
|
4
|
+
`}}class E extends Error{constructor(r,o,s,n,a,i,c){const w=n.map(u=>u.message).join(`
|
|
2
5
|
|
|
3
|
-
`)
|
|
4
|
-
|
|
5
|
-
${
|
|
6
|
-
|
|
6
|
+
`),y=n.map(u=>u.fullMessage).join(`
|
|
7
|
+
|
|
8
|
+
`);super(`PlErrorReport: ${w}`);l(this,"fullMessage");this.rawBackendMessage=r,this.plErrorType=o,this.plMessage=s,this.errors=n,this.fieldName=a,this.resource=i,this.resourceType=c,this.name="PlErrorReport";const T=this.resourceType?`${p.resourceTypeToString(this.resourceType)},`:"",S=this.resource?p.resourceIdToString(this.resource):"",x=this.fieldName?`/${this.fieldName}`:"",R=this.plErrorType?`error type: ${this.plErrorType}`:"";this.fullMessage=`PlErrorReport: resource: ${T} ${S}${x}
|
|
9
|
+
${R}
|
|
10
|
+
${y}
|
|
11
|
+
`}}class M extends Error{constructor(r){super(r);l(this,"fullMessage");this.message=r,this.name="PlInternalError",this.fullMessage=`PlInternalError: ${r}`}}class $ extends Error{constructor(r,o,s,n){const a=`PlTengoError:
|
|
7
12
|
message:
|
|
8
|
-
${
|
|
13
|
+
${s}
|
|
14
|
+
template: ${o}
|
|
9
15
|
tengo stacktrace:
|
|
10
|
-
${
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
${this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
${n}
|
|
17
|
+
`;super(a);l(this,"fullMessage");this.rawBackendMessage=r,this.templateName=o,this.tengoMessage=s,this.tengoStacktrace=n,this.name="PlTengoError",this.fullMessage=`${a}
|
|
18
|
+
raw message:
|
|
19
|
+
${this.rawBackendMessage}
|
|
20
|
+
`}}class h extends Error{constructor(r,o,s,n,a){const i=`PlRunnerError:
|
|
21
|
+
command: ${o}
|
|
22
|
+
exit code: ${s}
|
|
23
|
+
working directory: ${a}
|
|
17
24
|
stdout:
|
|
25
|
+
${n}`;super(i);l(this,"fullMessage");this.rawBackendMessage=r,this.commandName=o,this.exitCode=s,this.stdout=n,this.workingDirectory=a,this.name="PlRunnerError",this.fullMessage=`
|
|
26
|
+
${i}
|
|
27
|
+
raw message:
|
|
28
|
+
${this.rawBackendMessage}
|
|
29
|
+
`}}class P extends h{constructor(r,o,s,n,a){super(r,o,s,n,a);l(this,"fullMessage");const i=`Monetizaiton error:
|
|
18
30
|
${this.stdout}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
${this.fullMessage}`}}class S extends h{constructor(t,o,s,n,i){super(t,o,s,n,i);c(this,"message");this.name="PlMonetizationError",this.message=this.toString()}toString(){return`PlMonetizationError:
|
|
31
|
+
`;this.message=i,this.name="PlMonetizationError",this.fullMessage=`
|
|
32
|
+
${i}
|
|
22
33
|
command: ${this.commandName}
|
|
23
34
|
exit code: ${this.exitCode}
|
|
24
35
|
working directory: ${this.workingDirectory}
|
|
25
|
-
stdout:
|
|
26
|
-
${this.stdout}
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
${this.
|
|
30
|
-
`
|
|
31
|
-
`)
|
|
32
|
-
`);
|
|
37
|
+
raw message:
|
|
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.parse(JSON.parse(t)),n=k(s.message);return new E(t,s.errorType,s.message,n,o,e,r)}function k(t){const e={stage:"initial",value:[],result:[]};for(const o of t.split(`
|
|
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
|
+
`);e.result.push(f(s)),e.value=[]}e.value.push(o)}const r=e.value.join(`
|
|
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;
|
|
33
43
|
//# sourceMappingURL=index.js.map
|
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 { ResourceId, resourceIdToString, ResourceType, resourceTypeToString } from \"@milaboratories/pl-client\";\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 message: string;\n\n constructor(\n /** Full message from the Pl backend. */\n public readonly fullMessage: 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 super(fullMessage);\n this.name = 'PlErrorReport';\n this.message = this.toString();\n }\n\n toString() {\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 const subErrors = this.errors.map(e => e.message).join('\\n\\n');\n\n return `PlErrorReport: resource: ${rt} ${r}${f}\n${errType}\n${subErrors}`;\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 constructor(\n public readonly message: string,\n ) {\n super(message);\n this.name = 'PlInternalError';\n }\n}\n\n/**\n * Happens when workflow template panics.\n */\nexport class PlTengoError extends Error {\n message: string;\n\n constructor(\n public readonly fullMessage: string,\n public readonly templateName: string,\n public readonly tengoMessage: string,\n public readonly tengoStacktrace: string,\n ) {\n super(fullMessage);\n this.name = 'PlWorkflowError';\n this.message = this.toString();\n }\n\n toString() {\n return `PlWorkflowError:\ntemplate: ${this.templateName}\nmessage:\n${this.tengoMessage}\ntengo stacktrace:\n${this.tengoStacktrace}\n\nfull message:\n${this.fullMessage}`;\n }\n}\n\n/**\n * Happens when a command fails to run.\n */\nexport class PlRunnerError extends Error {\n message: string;\n\n constructor(\n public readonly fullMessage: string,\n public readonly commandName: string,\n public readonly exitCode: number,\n public readonly stdout: string,\n public readonly workingDirectory: string,\n ) {\n super(fullMessage);\n this.name = 'PlRunnerError';\n this.message = this.toString();\n }\n\n toString() {\n return `PlRunnerError:\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\nstdout:\n${this.stdout}\n\nfull message:\n${this.fullMessage}`;\n }\n}\n\n/**\n * Happens when a monetization command fails to run.\n */\nexport class PlMonetizationError extends PlRunnerError {\n message: string;\n\n constructor(\n fullMessage: string,\n commandName: string,\n exitCode: number,\n stdout: string,\n workingDirectory: string,\n ) {\n super(fullMessage, commandName, exitCode, stdout, workingDirectory);\n this.name = 'PlMonetizationError';\n this.message = this.toString();\n }\n\n toString() {\n return `PlMonetizationError:\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\nstdout:\n${this.stdout}\n\nfull message:\n${this.fullMessage}`;\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\n resource?: ResourceId,\n resourceType?: ResourceType,\n field?: string,\n): PlErrorReport {\n const parsed = backendErrorSchema.parse(JSON.parse(error));\n const subErrors = parseSubErrors(parsed.message);\n\n return new PlErrorReport(\n error,\n parsed.errorType,\n parsed.message,\n subErrors,\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\n } else if (state.stage == 'path' && !isPath(line)) {\n state.stage = 'message';\n\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":["PlErrorReport","fullMessage","plErrorType","plMessage","errors","fieldName","resource","resourceType","__publicField","rt","resourceTypeToString","r","resourceIdToString","f","errType","subErrors","e","PlInternalError","message","PlTengoError","templateName","tengoMessage","tengoStacktrace","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(),\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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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,148 +1,167 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var c = (
|
|
4
|
-
import { z as
|
|
5
|
-
import { resourceTypeToString as
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this
|
|
1
|
+
var P = Object.defineProperty;
|
|
2
|
+
var y = (t, e, r) => e in t ? P(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r;
|
|
3
|
+
var c = (t, e, r) => y(t, typeof e != "symbol" ? e + "" : e, r);
|
|
4
|
+
import { z as h } from "zod";
|
|
5
|
+
import { resourceTypeToString as T, resourceIdToString as x } from "@milaboratories/pl-client";
|
|
6
|
+
import { notEmpty as g } from "@milaboratories/ts-helpers";
|
|
7
|
+
class W extends Error {
|
|
8
|
+
constructor(r, o) {
|
|
9
|
+
super(`PlQuickJSError: ${o.message}`, { cause: o });
|
|
10
|
+
c(this, "stack");
|
|
11
|
+
c(this, "fullMessage");
|
|
12
|
+
this.name = "PlQuickJSError";
|
|
13
|
+
let s = g(r.stack);
|
|
14
|
+
s = s.replace(r.message, ""), s = s.replace(g(o.message), ""), this.stack = s;
|
|
15
|
+
const n = "fullMessage" in o && typeof o.fullMessage == "string" ? o.fullMessage : o.message;
|
|
16
|
+
this.fullMessage = `PlQuickJSError: ${n}
|
|
17
|
+
QuickJS stacktrace:
|
|
18
|
+
${this.stack}
|
|
19
|
+
`;
|
|
11
20
|
}
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
}
|
|
22
|
+
class S extends Error {
|
|
23
|
+
constructor(r, o, s, n, a, i, l) {
|
|
24
|
+
const d = n.map((u) => u.message).join(`
|
|
25
|
+
|
|
26
|
+
`), E = n.map((u) => u.fullMessage).join(`
|
|
14
27
|
|
|
15
28
|
`);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
super(`PlErrorReport: ${d}`);
|
|
30
|
+
c(this, "fullMessage");
|
|
31
|
+
this.rawBackendMessage = r, this.plErrorType = o, this.plMessage = s, this.errors = n, this.fieldName = a, this.resource = i, this.resourceType = l, this.name = "PlErrorReport";
|
|
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
|
+
this.fullMessage = `PlErrorReport: resource: ${M} ${$}${k}
|
|
34
|
+
${w}
|
|
35
|
+
${E}
|
|
36
|
+
`;
|
|
19
37
|
}
|
|
20
38
|
}
|
|
21
|
-
class
|
|
22
|
-
constructor(
|
|
23
|
-
super(
|
|
39
|
+
class R extends Error {
|
|
40
|
+
constructor(r) {
|
|
41
|
+
super(r);
|
|
42
|
+
c(this, "fullMessage");
|
|
43
|
+
this.message = r, this.name = "PlInternalError", this.fullMessage = `PlInternalError: ${r}`;
|
|
24
44
|
}
|
|
25
45
|
}
|
|
26
|
-
class
|
|
46
|
+
class v extends Error {
|
|
27
47
|
constructor(r, o, s, n) {
|
|
28
|
-
|
|
29
|
-
c(this, "message");
|
|
30
|
-
this.fullMessage = r, this.templateName = o, this.tengoMessage = s, this.tengoStacktrace = n, this.name = "PlWorkflowError", this.message = this.toString();
|
|
31
|
-
}
|
|
32
|
-
toString() {
|
|
33
|
-
return `PlWorkflowError:
|
|
34
|
-
template: ${this.templateName}
|
|
48
|
+
const a = `PlTengoError:
|
|
35
49
|
message:
|
|
36
|
-
${
|
|
50
|
+
${s}
|
|
51
|
+
template: ${o}
|
|
37
52
|
tengo stacktrace:
|
|
38
|
-
${
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
${n}
|
|
54
|
+
`;
|
|
55
|
+
super(a);
|
|
56
|
+
c(this, "fullMessage");
|
|
57
|
+
this.rawBackendMessage = r, this.templateName = o, this.tengoMessage = s, this.tengoStacktrace = n, this.name = "PlTengoError", this.fullMessage = `${a}
|
|
58
|
+
raw message:
|
|
59
|
+
${this.rawBackendMessage}
|
|
60
|
+
`;
|
|
42
61
|
}
|
|
43
62
|
}
|
|
44
|
-
class
|
|
45
|
-
constructor(r, o, s, n,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
toString() {
|
|
51
|
-
return `PlRunnerError:
|
|
52
|
-
command: ${this.commandName}
|
|
53
|
-
exit code: ${this.exitCode}
|
|
54
|
-
working directory: ${this.workingDirectory}
|
|
63
|
+
class f extends Error {
|
|
64
|
+
constructor(r, o, s, n, a) {
|
|
65
|
+
const i = `PlRunnerError:
|
|
66
|
+
command: ${o}
|
|
67
|
+
exit code: ${s}
|
|
68
|
+
working directory: ${a}
|
|
55
69
|
stdout:
|
|
56
|
-
${
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
${n}`;
|
|
71
|
+
super(i);
|
|
72
|
+
c(this, "fullMessage");
|
|
73
|
+
this.rawBackendMessage = r, this.commandName = o, this.exitCode = s, this.stdout = n, this.workingDirectory = a, this.name = "PlRunnerError", this.fullMessage = `
|
|
74
|
+
${i}
|
|
75
|
+
raw message:
|
|
76
|
+
${this.rawBackendMessage}
|
|
77
|
+
`;
|
|
60
78
|
}
|
|
61
79
|
}
|
|
62
|
-
class
|
|
63
|
-
constructor(r, o, s, n,
|
|
64
|
-
super(r, o, s, n,
|
|
65
|
-
c(this, "
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
80
|
+
class B extends f {
|
|
81
|
+
constructor(r, o, s, n, a) {
|
|
82
|
+
super(r, o, s, n, a);
|
|
83
|
+
c(this, "fullMessage");
|
|
84
|
+
const i = `Monetizaiton error:
|
|
85
|
+
${this.stdout}
|
|
86
|
+
`;
|
|
87
|
+
this.message = i, this.name = "PlMonetizationError", this.fullMessage = `
|
|
88
|
+
${i}
|
|
70
89
|
command: ${this.commandName}
|
|
71
90
|
exit code: ${this.exitCode}
|
|
72
91
|
working directory: ${this.workingDirectory}
|
|
73
|
-
stdout:
|
|
74
|
-
${this.stdout}
|
|
75
92
|
|
|
76
|
-
|
|
77
|
-
${this.
|
|
93
|
+
raw message:
|
|
94
|
+
${this.rawBackendMessage}
|
|
95
|
+
`;
|
|
78
96
|
}
|
|
79
97
|
}
|
|
80
|
-
const
|
|
81
|
-
errorType:
|
|
82
|
-
message:
|
|
98
|
+
const I = h.object({
|
|
99
|
+
errorType: h.string(),
|
|
100
|
+
message: h.string()
|
|
83
101
|
});
|
|
84
|
-
function
|
|
85
|
-
const s =
|
|
86
|
-
return new
|
|
87
|
-
|
|
102
|
+
function b(t, e, r, o) {
|
|
103
|
+
const s = I.parse(JSON.parse(t)), n = N(s.message);
|
|
104
|
+
return new S(
|
|
105
|
+
t,
|
|
88
106
|
s.errorType,
|
|
89
107
|
s.message,
|
|
90
108
|
n,
|
|
91
109
|
o,
|
|
92
|
-
|
|
110
|
+
e,
|
|
93
111
|
r
|
|
94
112
|
);
|
|
95
113
|
}
|
|
96
|
-
function
|
|
97
|
-
const
|
|
114
|
+
function N(t) {
|
|
115
|
+
const e = {
|
|
98
116
|
stage: "initial",
|
|
99
117
|
value: [],
|
|
100
118
|
result: []
|
|
101
119
|
};
|
|
102
|
-
for (const o of
|
|
120
|
+
for (const o of t.split(`
|
|
103
121
|
`)) {
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
else if (
|
|
107
|
-
|
|
108
|
-
else if (
|
|
109
|
-
|
|
110
|
-
const s =
|
|
122
|
+
if (e.stage == "initial")
|
|
123
|
+
e.stage = "path";
|
|
124
|
+
else if (e.stage == "path" && !p(o))
|
|
125
|
+
e.stage = "message";
|
|
126
|
+
else if (e.stage == "message" && p(o)) {
|
|
127
|
+
e.stage = "path";
|
|
128
|
+
const s = e.value.join(`
|
|
111
129
|
`);
|
|
112
|
-
|
|
130
|
+
e.result.push(m(s)), e.value = [];
|
|
113
131
|
}
|
|
114
|
-
|
|
132
|
+
e.value.push(o);
|
|
115
133
|
}
|
|
116
|
-
const r =
|
|
134
|
+
const r = e.value.join(`
|
|
117
135
|
`);
|
|
118
|
-
return
|
|
136
|
+
return e.result.push(m(r)), e.result;
|
|
119
137
|
}
|
|
120
|
-
function
|
|
121
|
-
for (const
|
|
122
|
-
if (
|
|
138
|
+
function p(t) {
|
|
139
|
+
for (const e of ["U", "I", "O", "S", "OTW", "D", "MTW"])
|
|
140
|
+
if (t.startsWith(`[${e}]`))
|
|
123
141
|
return !0;
|
|
124
142
|
return !1;
|
|
125
143
|
}
|
|
126
|
-
function m(
|
|
127
|
-
const
|
|
144
|
+
function m(t) {
|
|
145
|
+
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);
|
|
128
146
|
if (r) {
|
|
129
|
-
const n = r[1],
|
|
130
|
-
return
|
|
147
|
+
const n = r[1], a = r[2], i = parseInt(r[3], 10), l = r[4].trim();
|
|
148
|
+
return a.endsWith("mnz-client") && i == 1 ? new B(t, a, i, l, n) : new f(t, a, i, l, n);
|
|
131
149
|
}
|
|
132
|
-
const o = /cannot eval code: cannot eval template: template: (.+)\n\t(.*?)\n\t(at [\s\S]*)/, s =
|
|
150
|
+
const o = /cannot eval code: cannot eval template: template: (.+)\n\t(.*?)\n\t(at [\s\S]*)/, s = t.match(o);
|
|
133
151
|
if (s) {
|
|
134
|
-
const n = s[1],
|
|
135
|
-
return new
|
|
152
|
+
const n = s[1], a = s[2], i = s[3];
|
|
153
|
+
return new v(t, n, a, i);
|
|
136
154
|
}
|
|
137
|
-
return new
|
|
155
|
+
return new R(t);
|
|
138
156
|
}
|
|
139
157
|
export {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
158
|
+
S as PlErrorReport,
|
|
159
|
+
R as PlInternalError,
|
|
160
|
+
B as PlMonetizationError,
|
|
161
|
+
W as PlQuickJSError,
|
|
162
|
+
f as PlRunnerError,
|
|
163
|
+
v as PlTengoError,
|
|
164
|
+
b as parsePlError,
|
|
165
|
+
N as parseSubErrors
|
|
147
166
|
};
|
|
148
167
|
//# sourceMappingURL=index.mjs.map
|
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 { ResourceId, resourceIdToString, ResourceType, resourceTypeToString } from \"@milaboratories/pl-client\";\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 message: string;\n\n constructor(\n /** Full message from the Pl backend. */\n public readonly fullMessage: 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 super(fullMessage);\n this.name = 'PlErrorReport';\n this.message = this.toString();\n }\n\n toString() {\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 const subErrors = this.errors.map(e => e.message).join('\\n\\n');\n\n return `PlErrorReport: resource: ${rt} ${r}${f}\n${errType}\n${subErrors}`;\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 constructor(\n public readonly message: string,\n ) {\n super(message);\n this.name = 'PlInternalError';\n }\n}\n\n/**\n * Happens when workflow template panics.\n */\nexport class PlTengoError extends Error {\n message: string;\n\n constructor(\n public readonly fullMessage: string,\n public readonly templateName: string,\n public readonly tengoMessage: string,\n public readonly tengoStacktrace: string,\n ) {\n super(fullMessage);\n this.name = 'PlWorkflowError';\n this.message = this.toString();\n }\n\n toString() {\n return `PlWorkflowError:\ntemplate: ${this.templateName}\nmessage:\n${this.tengoMessage}\ntengo stacktrace:\n${this.tengoStacktrace}\n\nfull message:\n${this.fullMessage}`;\n }\n}\n\n/**\n * Happens when a command fails to run.\n */\nexport class PlRunnerError extends Error {\n message: string;\n\n constructor(\n public readonly fullMessage: string,\n public readonly commandName: string,\n public readonly exitCode: number,\n public readonly stdout: string,\n public readonly workingDirectory: string,\n ) {\n super(fullMessage);\n this.name = 'PlRunnerError';\n this.message = this.toString();\n }\n\n toString() {\n return `PlRunnerError:\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\nstdout:\n${this.stdout}\n\nfull message:\n${this.fullMessage}`;\n }\n}\n\n/**\n * Happens when a monetization command fails to run.\n */\nexport class PlMonetizationError extends PlRunnerError {\n message: string;\n\n constructor(\n fullMessage: string,\n commandName: string,\n exitCode: number,\n stdout: string,\n workingDirectory: string,\n ) {\n super(fullMessage, commandName, exitCode, stdout, workingDirectory);\n this.name = 'PlMonetizationError';\n this.message = this.toString();\n }\n\n toString() {\n return `PlMonetizationError:\ncommand: ${this.commandName}\nexit code: ${this.exitCode}\nworking directory: ${this.workingDirectory}\nstdout:\n${this.stdout}\n\nfull message:\n${this.fullMessage}`;\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\n resource?: ResourceId,\n resourceType?: ResourceType,\n field?: string,\n): PlErrorReport {\n const parsed = backendErrorSchema.parse(JSON.parse(error));\n const subErrors = parseSubErrors(parsed.message);\n\n return new PlErrorReport(\n error,\n parsed.errorType,\n parsed.message,\n subErrors,\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\n } else if (state.stage == 'path' && !isPath(line)) {\n state.stage = 'message';\n\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":["PlErrorReport","fullMessage","plErrorType","plMessage","errors","fieldName","resource","resourceType","__publicField","rt","resourceTypeToString","r","resourceIdToString","f","errType","subErrors","e","PlInternalError","message","PlTengoError","templateName","tengoMessage","tengoStacktrace","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(),\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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"}
|
package/dist/parsed_error.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { ResourceId, ResourceType } from '@milaboratories/pl-client';
|
|
2
|
+
/** The error that comes from QuickJS. */
|
|
3
|
+
export declare class PlQuickJSError extends Error {
|
|
4
|
+
stack: string;
|
|
5
|
+
fullMessage: string;
|
|
6
|
+
constructor(quickJSError: Error, cause: Error);
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* A parsed error from the Pl backend.
|
|
4
10
|
* It contains several suberrors, which could be one or different causes of the error.
|
|
5
11
|
*/
|
|
6
12
|
export declare class PlErrorReport extends Error {
|
|
7
13
|
/** Full message from the Pl backend. */
|
|
8
|
-
readonly
|
|
14
|
+
readonly rawBackendMessage: string;
|
|
9
15
|
/** Either CID conflict or a error from controller. */
|
|
10
16
|
readonly plErrorType: string;
|
|
11
17
|
/** Parsed pl backend message that will be futher parsed into suberrors. */
|
|
@@ -16,10 +22,10 @@ export declare class PlErrorReport extends Error {
|
|
|
16
22
|
readonly fieldName?: string | undefined;
|
|
17
23
|
readonly resource?: ResourceId | undefined;
|
|
18
24
|
readonly resourceType?: ResourceType | undefined;
|
|
19
|
-
|
|
25
|
+
readonly fullMessage: string;
|
|
20
26
|
constructor(
|
|
21
27
|
/** Full message from the Pl backend. */
|
|
22
|
-
|
|
28
|
+
rawBackendMessage: string,
|
|
23
29
|
/** Either CID conflict or a error from controller. */
|
|
24
30
|
plErrorType: string,
|
|
25
31
|
/** Parsed pl backend message that will be futher parsed into suberrors. */
|
|
@@ -28,7 +34,6 @@ export declare class PlErrorReport extends Error {
|
|
|
28
34
|
errors: PlCoreError[],
|
|
29
35
|
/** Optional info about a resource where the error happened. */
|
|
30
36
|
fieldName?: string | undefined, resource?: ResourceId | undefined, resourceType?: ResourceType | undefined);
|
|
31
|
-
toString(): string;
|
|
32
37
|
}
|
|
33
38
|
/**
|
|
34
39
|
* A suberror of a parsed error.
|
|
@@ -39,40 +44,38 @@ export type PlCoreError = PlInternalError | PlTengoError | PlRunnerError | PlMon
|
|
|
39
44
|
*/
|
|
40
45
|
export declare class PlInternalError extends Error {
|
|
41
46
|
readonly message: string;
|
|
47
|
+
readonly fullMessage: string;
|
|
42
48
|
constructor(message: string);
|
|
43
49
|
}
|
|
44
50
|
/**
|
|
45
51
|
* Happens when workflow template panics.
|
|
46
52
|
*/
|
|
47
53
|
export declare class PlTengoError extends Error {
|
|
48
|
-
readonly
|
|
54
|
+
readonly rawBackendMessage: string;
|
|
49
55
|
readonly templateName: string;
|
|
50
56
|
readonly tengoMessage: string;
|
|
51
57
|
readonly tengoStacktrace: string;
|
|
52
|
-
|
|
53
|
-
constructor(
|
|
54
|
-
toString(): string;
|
|
58
|
+
readonly fullMessage: string;
|
|
59
|
+
constructor(rawBackendMessage: string, templateName: string, tengoMessage: string, tengoStacktrace: string);
|
|
55
60
|
}
|
|
56
61
|
/**
|
|
57
62
|
* Happens when a command fails to run.
|
|
58
63
|
*/
|
|
59
64
|
export declare class PlRunnerError extends Error {
|
|
60
|
-
readonly
|
|
65
|
+
readonly rawBackendMessage: string;
|
|
61
66
|
readonly commandName: string;
|
|
62
67
|
readonly exitCode: number;
|
|
63
68
|
readonly stdout: string;
|
|
64
69
|
readonly workingDirectory: string;
|
|
65
|
-
|
|
66
|
-
constructor(
|
|
67
|
-
toString(): string;
|
|
70
|
+
readonly fullMessage: string;
|
|
71
|
+
constructor(rawBackendMessage: string, commandName: string, exitCode: number, stdout: string, workingDirectory: string);
|
|
68
72
|
}
|
|
69
73
|
/**
|
|
70
74
|
* Happens when a monetization command fails to run.
|
|
71
75
|
*/
|
|
72
76
|
export declare class PlMonetizationError extends PlRunnerError {
|
|
73
|
-
|
|
74
|
-
constructor(
|
|
75
|
-
toString(): string;
|
|
77
|
+
readonly fullMessage: string;
|
|
78
|
+
constructor(rawBackendMessage: string, commandName: string, exitCode: number, stdout: string, workingDirectory: string);
|
|
76
79
|
}
|
|
77
80
|
/**
|
|
78
81
|
* Parses a Pl error and suberrors from the Pl backend.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsed_error.d.ts","sourceRoot":"","sources":["../src/parsed_error.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAG/E,OAAO,EAAE,UAAU,
|
|
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,CAcf;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.4",
|
|
4
4
|
"description": "Parsing errors from Pl backend",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,18 +18,21 @@
|
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"zod": "~3.23.8",
|
|
21
|
-
"@milaboratories/pl-client": "2.7.
|
|
21
|
+
"@milaboratories/pl-client": "2.7.14",
|
|
22
|
+
"@milaboratories/ts-helpers": "1.1.5"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"typescript": "~5.5.4",
|
|
25
26
|
"vite": "^5.4.11",
|
|
26
27
|
"vitest": "^2.1.8",
|
|
28
|
+
"@milaboratories/pl-error-like": "1.12.0",
|
|
27
29
|
"@milaboratories/platforma-build-configs": "1.0.3",
|
|
28
|
-
"@milaboratories/eslint-config": "^1.0.
|
|
30
|
+
"@milaboratories/eslint-config": "^1.0.4"
|
|
29
31
|
},
|
|
30
32
|
"scripts": {
|
|
31
33
|
"type-check": "tsc --noEmit --composite false",
|
|
32
34
|
"build": "vite build",
|
|
35
|
+
"lint": "eslint .",
|
|
33
36
|
"test": "vitest",
|
|
34
37
|
"do-pack": "rm -f *.tgz && pnpm pack && mv *.tgz package.tgz"
|
|
35
38
|
}
|
package/src/parsed_error.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ResourceId, resourceIdFromString, stringifyWithResourceId } from "@milaboratories/pl-client";
|
|
2
2
|
import { parsePlError, parseSubErrors, PlMonetizationError, PlErrorReport, PlRunnerError, PlTengoError } from './parsed_error';
|
|
3
|
-
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { describe, test, it, expect } from 'vitest';
|
|
4
|
+
import { ensureErrorLike } from "@milaboratories/pl-error-like";
|
|
4
5
|
|
|
5
6
|
const runnerError = '{"errorType":"","message":"\\"NG:0x2331A5\\" has 1 input errors:\\n[I] \\"NG:0x2331A5/blob\\": \\"NG:0x2331A4\\" has 1 input errors:\\n[I] \\"NG:0x2331A4/resource\\": \\"NG:0x2331CD\\" has 1 input errors:\\n[I] \\"NG:0x2331CD/resource\\": \\"NG:0x2331CA\\" has 1 input errors:\\n[I] \\"NG:0x2331CA/inputs\\": \\"NG:0x2331CB\\" has 1 input errors:\\n[I] \\"NG:0x2331CB/workdir\\": working directory: \\"workdirs/0x2331E0\\"\\nfailed to run command: \\"java\\" exited with code 22.\\nHere is the latest command output:\\n\\tLicense manager thread died.\\n\\t=== No License ===\\n\\t\\n\\tTo use MiXCR, please, provide a valid license.\\n\\t\\n\\tIf you already have a license, activate it by calling:\\n\\t mixcr activate-license\\n\\t\\n\\t\\n"}'
|
|
6
7
|
|
|
@@ -47,6 +48,19 @@ describe('parsePlError', () => {
|
|
|
47
48
|
expect((result.errors[0] as PlRunnerError).exitCode).toBe(22);
|
|
48
49
|
expect((result.errors[0] as PlRunnerError).stdout).toBeDefined();
|
|
49
50
|
expect((result.errors[0] as PlRunnerError).workingDirectory).toBe('workdirs/0x2331E0');
|
|
51
|
+
|
|
52
|
+
expect((result.errors[0]).message).toBe(`PlRunnerError:
|
|
53
|
+
command: java
|
|
54
|
+
exit code: 22
|
|
55
|
+
working directory: workdirs/0x2331E0
|
|
56
|
+
stdout:
|
|
57
|
+
License manager thread died.
|
|
58
|
+
=== No License ===
|
|
59
|
+
|
|
60
|
+
To use MiXCR, please, provide a valid license.
|
|
61
|
+
|
|
62
|
+
If you already have a license, activate it by calling:
|
|
63
|
+
mixcr activate-license`);
|
|
50
64
|
});
|
|
51
65
|
|
|
52
66
|
it('should parse workflow error correctly', () => {
|
|
@@ -62,6 +76,20 @@ describe('parsePlError', () => {
|
|
|
62
76
|
expect(result.errors[0]).toBeInstanceOf(PlTengoError);
|
|
63
77
|
expect((result.errors[0] as PlTengoError).templateName).toBe('@platforma-open/milaboratories.samples-and-data.workflow:main@1.10.0');
|
|
64
78
|
expect((result.errors[0] as PlTengoError).tengoMessage).toBe('Runtime Error: File handle not set for "R1" in sample "S63UG7K2IRZSSMAI4UVB5CNJ"');
|
|
79
|
+
|
|
80
|
+
expect((result.errors[0]).message).toBe(`PlTengoError:
|
|
81
|
+
message:
|
|
82
|
+
Runtime Error: File handle not set for "R1" in sample "S63UG7K2IRZSSMAI4UVB5CNJ"
|
|
83
|
+
template: @platforma-open/milaboratories.samples-and-data.workflow:main@1.10.0
|
|
84
|
+
tengo stacktrace:
|
|
85
|
+
at @platforma-sdk/workflow-tengo:ll:25:1
|
|
86
|
+
at @platforma-open/milaboratories.samples-and-data.workflow:main:205:7
|
|
87
|
+
at @platforma-sdk/workflow-tengo:workflow:264:11
|
|
88
|
+
at @platforma-sdk/workflow-tengo:tpl:470:11
|
|
89
|
+
at @platforma-sdk/workflow-tengo:tpl:373:1
|
|
90
|
+
at @platforma-sdk/workflow-tengo:workflow:261:1
|
|
91
|
+
at @platforma-open/milaboratories.samples-and-data.workflow:main:35:1
|
|
92
|
+
`);
|
|
65
93
|
});
|
|
66
94
|
|
|
67
95
|
it('should parse monetization sub errors correctly', () => {
|
|
@@ -80,5 +108,17 @@ describe('parsePlError', () => {
|
|
|
80
108
|
expect((result[1] as PlMonetizationError).exitCode).toBe(1);
|
|
81
109
|
expect((result[1] as PlMonetizationError).stdout).toBeDefined();
|
|
82
110
|
expect((result[1] as PlMonetizationError).workingDirectory).toBe('workdirs/0x1F9514');
|
|
111
|
+
|
|
112
|
+
expect((result[1]).message).toBe(`Monetizaiton error:
|
|
113
|
+
2025/03/13 17:25:18 get API error: VALIDATION_ERR Invalid /mnz/run-spec body: field productKey -> Invalid product key
|
|
114
|
+
`);
|
|
83
115
|
});
|
|
84
116
|
});
|
|
117
|
+
|
|
118
|
+
test('pl error report has error like shape', () => {
|
|
119
|
+
const plErrorReport = new PlErrorReport('test error report', '', '', []);
|
|
120
|
+
|
|
121
|
+
const got = ensureErrorLike(plErrorReport);
|
|
122
|
+
|
|
123
|
+
expect(got).toBeDefined();
|
|
124
|
+
});
|
package/src/parsed_error.ts
CHANGED
|
@@ -1,18 +1,51 @@
|
|
|
1
1
|
/** Pl Backend throws arbitrary errors, and we're trying to parse them here. */
|
|
2
2
|
|
|
3
|
-
import { z } from
|
|
4
|
-
import { ResourceId,
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import type { ResourceId, ResourceType } from '@milaboratories/pl-client';
|
|
5
|
+
import { resourceIdToString, resourceTypeToString } from '@milaboratories/pl-client';
|
|
6
|
+
import { notEmpty } from '@milaboratories/ts-helpers';
|
|
7
|
+
|
|
8
|
+
/** The error that comes from QuickJS. */
|
|
9
|
+
export class PlQuickJSError extends Error {
|
|
10
|
+
public stack: string;
|
|
11
|
+
public fullMessage: string;
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
quickJSError: Error,
|
|
15
|
+
cause: Error,
|
|
16
|
+
) {
|
|
17
|
+
super(`PlQuickJSError: ${cause.message}`, { cause });
|
|
18
|
+
this.name = 'PlQuickJSError';
|
|
19
|
+
|
|
20
|
+
// QuickJS wraps the error with the name and the message,
|
|
21
|
+
// but we need another format.
|
|
22
|
+
let stack = notEmpty(quickJSError.stack);
|
|
23
|
+
stack = stack.replace(quickJSError.message, '');
|
|
24
|
+
stack = stack.replace(notEmpty(cause.message), '');
|
|
25
|
+
|
|
26
|
+
this.stack = stack;
|
|
27
|
+
|
|
28
|
+
const causeMsg = 'fullMessage' in cause && typeof cause.fullMessage === 'string'
|
|
29
|
+
? cause.fullMessage
|
|
30
|
+
: cause.message;
|
|
31
|
+
|
|
32
|
+
this.fullMessage = `PlQuickJSError: ${causeMsg}
|
|
33
|
+
QuickJS stacktrace:
|
|
34
|
+
${this.stack}
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
5
38
|
|
|
6
39
|
/**
|
|
7
40
|
* A parsed error from the Pl backend.
|
|
8
41
|
* It contains several suberrors, which could be one or different causes of the error.
|
|
9
42
|
*/
|
|
10
43
|
export class PlErrorReport extends Error {
|
|
11
|
-
|
|
44
|
+
public readonly fullMessage: string;
|
|
12
45
|
|
|
13
46
|
constructor(
|
|
14
47
|
/** Full message from the Pl backend. */
|
|
15
|
-
public readonly
|
|
48
|
+
public readonly rawBackendMessage: string,
|
|
16
49
|
|
|
17
50
|
/** Either CID conflict or a error from controller. */
|
|
18
51
|
public readonly plErrorType: string,
|
|
@@ -28,21 +61,21 @@ export class PlErrorReport extends Error {
|
|
|
28
61
|
public readonly resource?: ResourceId,
|
|
29
62
|
public readonly resourceType?: ResourceType,
|
|
30
63
|
) {
|
|
31
|
-
|
|
64
|
+
const errorMessages = errors.map((e) => e.message).join('\n\n');
|
|
65
|
+
const errorFullMessages = errors.map((e) => e.fullMessage).join('\n\n');
|
|
66
|
+
|
|
67
|
+
super(`PlErrorReport: ${errorMessages}`);
|
|
32
68
|
this.name = 'PlErrorReport';
|
|
33
|
-
this.message = this.toString();
|
|
34
|
-
}
|
|
35
69
|
|
|
36
|
-
toString() {
|
|
37
70
|
const rt = this.resourceType ? `${resourceTypeToString(this.resourceType)},` : '';
|
|
38
71
|
const r = this.resource ? resourceIdToString(this.resource) : '';
|
|
39
72
|
const f = this.fieldName ? `/${this.fieldName}` : '';
|
|
40
73
|
const errType = this.plErrorType ? `error type: ${this.plErrorType}` : '';
|
|
41
|
-
const subErrors = this.errors.map(e => e.message).join('\n\n');
|
|
42
74
|
|
|
43
|
-
|
|
75
|
+
this.fullMessage = `PlErrorReport: resource: ${rt} ${r}${f}
|
|
44
76
|
${errType}
|
|
45
|
-
${
|
|
77
|
+
${errorFullMessages}
|
|
78
|
+
`;
|
|
46
79
|
}
|
|
47
80
|
}
|
|
48
81
|
|
|
@@ -59,11 +92,13 @@ export type PlCoreError =
|
|
|
59
92
|
* An general error when we couldn't parse the cause.
|
|
60
93
|
*/
|
|
61
94
|
export class PlInternalError extends Error {
|
|
95
|
+
public readonly fullMessage: string;
|
|
62
96
|
constructor(
|
|
63
97
|
public readonly message: string,
|
|
64
98
|
) {
|
|
65
99
|
super(message);
|
|
66
100
|
this.name = 'PlInternalError';
|
|
101
|
+
this.fullMessage = `PlInternalError: ${message}`;
|
|
67
102
|
}
|
|
68
103
|
}
|
|
69
104
|
|
|
@@ -71,29 +106,29 @@ export class PlInternalError extends Error {
|
|
|
71
106
|
* Happens when workflow template panics.
|
|
72
107
|
*/
|
|
73
108
|
export class PlTengoError extends Error {
|
|
74
|
-
|
|
109
|
+
public readonly fullMessage: string;
|
|
75
110
|
|
|
76
111
|
constructor(
|
|
77
|
-
public readonly
|
|
112
|
+
public readonly rawBackendMessage: string,
|
|
78
113
|
public readonly templateName: string,
|
|
79
114
|
public readonly tengoMessage: string,
|
|
80
115
|
public readonly tengoStacktrace: string,
|
|
81
116
|
) {
|
|
82
|
-
|
|
83
|
-
this.name = 'PlWorkflowError';
|
|
84
|
-
this.message = this.toString();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
toString() {
|
|
88
|
-
return `PlWorkflowError:
|
|
89
|
-
template: ${this.templateName}
|
|
117
|
+
const msg = `PlTengoError:
|
|
90
118
|
message:
|
|
91
|
-
${
|
|
119
|
+
${tengoMessage}
|
|
120
|
+
template: ${templateName}
|
|
92
121
|
tengo stacktrace:
|
|
93
|
-
${
|
|
122
|
+
${tengoStacktrace}
|
|
123
|
+
`;
|
|
94
124
|
|
|
95
|
-
|
|
96
|
-
|
|
125
|
+
super(msg);
|
|
126
|
+
this.name = 'PlTengoError';
|
|
127
|
+
|
|
128
|
+
this.fullMessage = `${msg}
|
|
129
|
+
raw message:
|
|
130
|
+
${this.rawBackendMessage}
|
|
131
|
+
`;
|
|
97
132
|
}
|
|
98
133
|
}
|
|
99
134
|
|
|
@@ -101,30 +136,29 @@ ${this.fullMessage}`;
|
|
|
101
136
|
* Happens when a command fails to run.
|
|
102
137
|
*/
|
|
103
138
|
export class PlRunnerError extends Error {
|
|
104
|
-
|
|
139
|
+
public readonly fullMessage: string;
|
|
105
140
|
|
|
106
141
|
constructor(
|
|
107
|
-
public readonly
|
|
142
|
+
public readonly rawBackendMessage: string,
|
|
108
143
|
public readonly commandName: string,
|
|
109
144
|
public readonly exitCode: number,
|
|
110
145
|
public readonly stdout: string,
|
|
111
146
|
public readonly workingDirectory: string,
|
|
112
147
|
) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
toString() {
|
|
119
|
-
return `PlRunnerError:
|
|
120
|
-
command: ${this.commandName}
|
|
121
|
-
exit code: ${this.exitCode}
|
|
122
|
-
working directory: ${this.workingDirectory}
|
|
148
|
+
const msg = `PlRunnerError:
|
|
149
|
+
command: ${commandName}
|
|
150
|
+
exit code: ${exitCode}
|
|
151
|
+
working directory: ${workingDirectory}
|
|
123
152
|
stdout:
|
|
124
|
-
${
|
|
153
|
+
${stdout}`;
|
|
125
154
|
|
|
126
|
-
|
|
127
|
-
|
|
155
|
+
super(msg);
|
|
156
|
+
this.name = 'PlRunnerError';
|
|
157
|
+
this.fullMessage = `
|
|
158
|
+
${msg}
|
|
159
|
+
raw message:
|
|
160
|
+
${this.rawBackendMessage}
|
|
161
|
+
`;
|
|
128
162
|
}
|
|
129
163
|
}
|
|
130
164
|
|
|
@@ -132,30 +166,31 @@ ${this.fullMessage}`;
|
|
|
132
166
|
* Happens when a monetization command fails to run.
|
|
133
167
|
*/
|
|
134
168
|
export class PlMonetizationError extends PlRunnerError {
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
public readonly fullMessage: string;
|
|
137
170
|
constructor(
|
|
138
|
-
|
|
171
|
+
rawBackendMessage: string,
|
|
139
172
|
commandName: string,
|
|
140
173
|
exitCode: number,
|
|
141
174
|
stdout: string,
|
|
142
175
|
workingDirectory: string,
|
|
143
176
|
) {
|
|
144
|
-
super(
|
|
177
|
+
super(rawBackendMessage, commandName, exitCode, stdout, workingDirectory);
|
|
178
|
+
const msg = `Monetizaiton error:
|
|
179
|
+
${this.stdout}
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
this.message = msg;
|
|
145
183
|
this.name = 'PlMonetizationError';
|
|
146
|
-
this.message = this.toString();
|
|
147
|
-
}
|
|
148
184
|
|
|
149
|
-
|
|
150
|
-
|
|
185
|
+
this.fullMessage = `
|
|
186
|
+
${msg}
|
|
151
187
|
command: ${this.commandName}
|
|
152
188
|
exit code: ${this.exitCode}
|
|
153
189
|
working directory: ${this.workingDirectory}
|
|
154
|
-
stdout:
|
|
155
|
-
${this.stdout}
|
|
156
190
|
|
|
157
|
-
|
|
158
|
-
${this.
|
|
191
|
+
raw message:
|
|
192
|
+
${this.rawBackendMessage}
|
|
193
|
+
`;
|
|
159
194
|
}
|
|
160
195
|
}
|
|
161
196
|
|
|
@@ -172,19 +207,18 @@ const backendErrorSchema = z.object({
|
|
|
172
207
|
*/
|
|
173
208
|
export function parsePlError(
|
|
174
209
|
error: string,
|
|
175
|
-
|
|
176
210
|
resource?: ResourceId,
|
|
177
211
|
resourceType?: ResourceType,
|
|
178
212
|
field?: string,
|
|
179
213
|
): PlErrorReport {
|
|
180
214
|
const parsed = backendErrorSchema.parse(JSON.parse(error));
|
|
181
|
-
const
|
|
215
|
+
const errors = parseSubErrors(parsed.message);
|
|
182
216
|
|
|
183
217
|
return new PlErrorReport(
|
|
184
218
|
error,
|
|
185
219
|
parsed.errorType,
|
|
186
220
|
parsed.message,
|
|
187
|
-
|
|
221
|
+
errors,
|
|
188
222
|
|
|
189
223
|
field,
|
|
190
224
|
resource,
|
|
@@ -209,10 +243,8 @@ export function parseSubErrors(message: string): PlCoreError[] {
|
|
|
209
243
|
// we need initial stage because apparently the first line
|
|
210
244
|
// of the error doesn't have [I], but is a path line.
|
|
211
245
|
state.stage = 'path';
|
|
212
|
-
|
|
213
246
|
} else if (state.stage == 'path' && !isPath(line)) {
|
|
214
247
|
state.stage = 'message';
|
|
215
|
-
|
|
216
248
|
} else if (state.stage == 'message' && isPath(line)) {
|
|
217
249
|
state.stage = 'path';
|
|
218
250
|
const text = state.value.join('\n');
|