Skip to content

Commit

Permalink
feat(repo): add stack traces to async REST errors (#131)
Browse files Browse the repository at this point in the history
* feat(repo): add stack traces to async REST errors

* test(operate): disable OAuth in unit test

* test(operate): disable OAuth for Operate client in test

* test(operate): rename integration test file

* chore(repo): run unit test in pre-commit hook

* test(operate): change process filename casing
  • Loading branch information
jwulf authored Apr 9, 2024
1 parent f0e6ab0 commit ef8d9c6
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 61 deletions.
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
npm run test
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

This is the official Camunda 8 JavaScript SDK. It is written in TypeScript and runs on Node.js. See why [this does not run in a web browser](https://github.com/camunda/camunda-8-js-sdk/issues/79).

Full API Docs are [here](https://camunda.github.io/camunda-8-js-sdk/). See the QUICKSTART.md file in [the repository](https://github.com/camunda/camunda-8-js-sdk) for a quick start.

## What does "supported" mean?

This is the official supported-by-Camunda Nodejs SDK for Camunda Platform 8.
Expand Down Expand Up @@ -34,7 +36,7 @@ In this release, the functionality of Camunda 8 is exposed via dedicated clients
import { Camunda8 } from '@camunda8/sdk'

const c8 = new Camunda8()
const zeebe = c8.getZeebeGrpcClient()
const zeebe = c8.getZeebeGrpcApiClient()
const operate = c8.getOperateApiClient()
const optimize = c8.getOptimizeApiClient()
const tasklist = c8.getTasklistApiClient()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { LosslessNumber } from 'lossless-json'

import { OperateApiClient } from '../../operate'
import { ProcessDefinition, Query } from '../../operate/lib/OperateDto'
import { ZeebeGrpcClient } from '../../zeebe'

jest.setTimeout(15000)
describe('Operate Integration', () => {
Expand Down Expand Up @@ -33,3 +34,20 @@ describe('Operate Integration', () => {
expect(defs.total).toBeGreaterThanOrEqual(0)
})
})

test('getJSONVariablesforProcess works', async () => {
const c = new OperateApiClient()
const zeebe = new ZeebeGrpcClient()
await zeebe.deployResource({
processFilename: 'src/__tests__/testdata/Operate-StraightThrough.bpmn',
})
const p = await zeebe.createProcessInstanceWithResult({
bpmnProcessId: 'operate-straightthrough',
variables: {
foo: 'bar',
},
})
await new Promise((res) => setTimeout(() => res(null), 5000))
const res = await c.getJSONVariablesforProcess(p.processInstanceKey)
expect(res.foo).toBe('bar')
})
32 changes: 32 additions & 0 deletions src/__tests__/testdata/Operate-StraightThrough.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1kv929v" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.21.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
<bpmn:process id="operate-straightthrough" name="Operate Straight Through" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Start Operate Test">
<bpmn:outgoing>Flow_0wppa4s</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_0wppa4s" sourceRef="StartEvent_1" targetRef="Event_1h6ie86" />
<bpmn:endEvent id="Event_1h6ie86" name="End Operate Test">
<bpmn:incoming>Flow_0wppa4s</bpmn:incoming>
</bpmn:endEvent>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="operate-straightthrough">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="79" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="152" y="122" width="90" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1h6ie86_di" bpmnElement="Event_1h6ie86">
<dc:Bounds x="432" y="79" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="407" y="122" width="86" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0wppa4s_di" bpmnElement="Flow_0wppa4s">
<di:waypoint x="215" y="97" />
<di:waypoint x="432" y="97" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
24 changes: 13 additions & 11 deletions src/admin/lib/AdminApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,22 @@ export class AdminApiClient {
https: {
certificateAuthority,
},
handlers: [
(options, next) => {
if (Object.isFrozen(options.context)) {
options.context = { ...options.context }
}
Error.captureStackTrace(options.context)
return next(options)
},
],
hooks: {
beforeError: [
(error) => {
const { request } = error
if (request) {
debug(`Error in request to ${request.options.url.href}`)
debug(
`Request headers: ${JSON.stringify(request.options.headers)}`
)
debug(`Error: ${error.code} - ${error.message}`)

// Attach more contextual information to the error object
error.message += ` (request to ${request.options.url.href})`
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(error as any).source = (error as any).options.context.stack.split(
'\n'
)
return error
},
],
Expand Down
23 changes: 13 additions & 10 deletions src/modeler/lib/ModelerAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,22 @@ export class ModelerApiClient {
certificateAuthority,
},
responseType: 'json',
handlers: [
(options, next) => {
if (Object.isFrozen(options.context)) {
options.context = { ...options.context }
}
Error.captureStackTrace(options.context)
return next(options)
},
],
hooks: {
beforeError: [
(error) => {
const { request } = error
if (request) {
debug(`Error in request to ${request.options.url.href}`)
debug(
`Request headers: ${JSON.stringify(request.options.headers)}`
)
debug(`Error: ${error.code} - ${error.message}`)
// Attach more contextual information to the error object
error.message += ` (request to ${request.options.url.href})`
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(error as any).source = (error as any).options.context.stack.split(
'\n'
)
return error
},
],
Expand Down
28 changes: 14 additions & 14 deletions src/operate/lib/OperateApiClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { debug as d } from 'debug'
import got from 'got'

import {
Expand Down Expand Up @@ -32,8 +31,6 @@ import { parseSearchResults } from './parseSearchResults'

const OPERATE_API_VERSION = 'v1'

const debug = d('camunda:operate')

type JSONDoc = { [key: string]: string | boolean | number | JSONDoc }
type EnhanceWithTenantIdIfMissing<T> = T extends {
filter: { tenantId: string | undefined }
Expand Down Expand Up @@ -95,20 +92,23 @@ export class OperateApiClient {
https: {
certificateAuthority,
},
handlers: [
(options, next) => {
if (Object.isFrozen(options.context)) {
options.context = { ...options.context }
}
Error.captureStackTrace(options.context)

return next(options)
},
],
hooks: {
beforeError: [
(error) => {
const { request } = error
if (request) {
debug(`Error in request to ${request.options.url.href}`)
debug(
`Request headers: ${JSON.stringify(request.options.headers)}`
)
debug(`Error: ${error.code} - ${error.message}`)

// Attach more contextual information to the error object
error.message += ` (request to ${request.options.url.href})`
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(error as any).source = (error as any).options.context.stack.split(
'\n'
)
return error
},
],
Expand Down
27 changes: 13 additions & 14 deletions src/optimize/lib/OptimizeApiClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { debug as d } from 'debug'
import got from 'got'

import {
Expand All @@ -24,8 +23,6 @@ import {
} from './APIObjects'
import { ReportResults } from './ReportResults'

const debug = d('camunda:optimize')

/**
* @description The high-level API client for Optimize.
* @example
Expand Down Expand Up @@ -76,20 +73,22 @@ export class OptimizeApiClient {
https: {
certificateAuthority,
},
handlers: [
(options, next) => {
if (Object.isFrozen(options.context)) {
options.context = { ...options.context }
}
Error.captureStackTrace(options.context)
return next(options)
},
],
hooks: {
beforeError: [
(error) => {
const { request } = error
if (request) {
debug(`Error in request to ${request.options.url.href}`)
debug(
`Request headers: ${JSON.stringify(request.options.headers)}`
)
debug(`Error: ${error.code} - ${error.message}`)

// Attach more contextual information to the error object
error.message += ` (request to ${request.options.url.href})`
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(error as any).source = (error as any).options.context.stack.split(
'\n'
)
return error
},
],
Expand Down
24 changes: 13 additions & 11 deletions src/tasklist/lib/TasklistApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,22 @@ export class TasklistApiClient {
https: {
certificateAuthority,
},
handlers: [
(options, next) => {
if (Object.isFrozen(options.context)) {
options.context = { ...options.context }
}
Error.captureStackTrace(options.context)
return next(options)
},
],
hooks: {
beforeError: [
(error) => {
const { request } = error
if (request) {
debug(`Error in request to ${request.options.url.href}`)
debug(
`Request headers: ${JSON.stringify(request.options.headers)}`
)
debug(`Error: ${error.code} - ${error.message}`)

// Attach more contextual information to the error object
error.message += ` (request to ${request.options.url.href})`
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(error as any).source = (error as any).options.context.stack.split(
'\n'
)
return error
},
],
Expand Down

0 comments on commit ef8d9c6

Please sign in to comment.