Skip to content

Commit

Permalink
Merge branch 'main' into display-grid
Browse files Browse the repository at this point in the history
  • Loading branch information
danphilibin authored Dec 22, 2022
2 parents 2a0cc17 + 612c7ae commit 5d1bc66
Show file tree
Hide file tree
Showing 18 changed files with 328 additions and 198 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"types": "dist/index.d.ts",
"scripts": {
"tar": "yarn pack",
"check": "tsc --noEmit",
"build:envoy": "yarn envoy $INIT_CWD/envoy.config.ts $INIT_CWD/.env $INIT_CWD/src/env.ts",
"build": "yarn build:envoy && tsc",
"demo:basic": "node ./dist/examples/basic/index.js",
Expand Down
145 changes: 83 additions & 62 deletions src/classes/IOClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,87 +152,108 @@ export class IOClient {
}

this.onResponseHandler = async result => {
if (result.inputGroupKey && result.inputGroupKey !== inputGroupKey) {
this.logger.debug('Received response for other input group')
return
}

if (this.isCanceled || isReturned) {
this.logger.debug('Received response after IO call complete')
return
}
try {
if (
result.inputGroupKey &&
result.inputGroupKey !== inputGroupKey
) {
this.logger.debug('Received response for other input group')
return
}

// Transaction canceled from Interval cloud UI
if (result.kind === 'CANCELED') {
this.isCanceled = true
reject(new IOError('CANCELED'))
return
}
if (this.isCanceled || isReturned) {
this.logger.debug('Received response after IO call complete')
return
}

if (result.values.length !== components.length) {
throw new Error('Mismatch in return array length')
}
// Transaction canceled from Interval cloud UI
if (result.kind === 'CANCELED') {
this.isCanceled = true
reject(new IOError('CANCELED'))
return
}

if (result.valuesMeta) {
result.values = superjson.deserialize({
json: result.values,
meta: result.valuesMeta,
})
}
if (result.values.length !== components.length) {
throw new Error('Mismatch in return array length')
}

if (result.kind === 'RETURN') {
const validities = await Promise.all(
result.values.map(async (v, index) => {
const component = components[index]
if (component.validator) {
const resp = await component.handleValidation(v)
if (resp !== undefined) {
return false
}
}
return true
if (result.valuesMeta) {
result.values = superjson.deserialize({
json: result.values,
meta: result.valuesMeta,
})
)

validationErrorMessage = undefined

if (validities.some(v => !v)) {
render()
return
}

if (groupValidator) {
validationErrorMessage = await groupValidator(
result.values as IOClientRenderReturnValues<typeof components>
if (result.kind === 'RETURN') {
const validities = await Promise.all(
result.values.map(async (v, index) => {
const component = components[index]
if (component.validator) {
const resp = await component.handleValidation(v)
if (resp !== undefined) {
return false
}
}
return true
})
)

if (validationErrorMessage) {
validationErrorMessage = undefined

if (validities.some(v => !v)) {
render()
return
}
}

isReturned = true

result.values.forEach((v, index) => {
// @ts-ignore
components[index].setReturnValue(v)
})
if (groupValidator) {
validationErrorMessage = await groupValidator(
result.values as IOClientRenderReturnValues<typeof components>
)

return
}
if (validationErrorMessage) {
render()
return
}
}

if (result.kind === 'SET_STATE') {
for (const [index, newState] of result.values.entries()) {
const prevState = components[index].getInstance().state
isReturned = true

if (JSON.stringify(newState) !== JSON.stringify(prevState)) {
this.logger.debug(`New state at ${index}`, newState)
result.values.forEach((v, index) => {
// @ts-ignore
await components[index].setState(newState)
components[index].setReturnValue(v)
})

return
}

if (result.kind === 'SET_STATE') {
for (const [index, newState] of result.values.entries()) {
const prevState = components[index].getInstance().state

if (JSON.stringify(newState) !== JSON.stringify(prevState)) {
this.logger.debug(`New state at ${index}`, newState)
// @ts-ignore
await components[index].setState(newState)
}
}
render()
}
} catch (err) {
if (err instanceof Error) {
const errorCause = err.cause
? err.cause instanceof Error
? err.cause.message
: err.cause
: undefined
if (errorCause) {
this.logger.error(`${err.message}:`, errorCause)
} else {
this.logger.error(err.message)
}
} else {
this.logger.error(err)
}
render()
reject(err)
}
}

Expand Down
23 changes: 20 additions & 3 deletions src/classes/IOComponent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from 'zod'
import { z, ZodError } from 'zod'
import {
ioSchema,
resolvesImmediately,
Expand All @@ -7,6 +7,7 @@ import {
T_IO_RETURNS,
} from '../ioSchema'
import { deserializeDates } from '../utils/deserialize'
import IOError from './IOError'
import { IOPromiseValidator } from './IOPromise'

type IoSchema = typeof ioSchema
Expand Down Expand Up @@ -155,7 +156,12 @@ export default class IOComponent<MethodName extends T_IO_METHOD_NAMES> {
this.resolver(parsed)
}
} catch (err) {
console.error('Received invalid return value:', err)
const ioError = new IOError(
'BAD_RESPONSE',
'Received invalid return value',
{ cause: err }
)
throw ioError
}
}

Expand All @@ -178,7 +184,18 @@ export default class IOComponent<MethodName extends T_IO_METHOD_NAMES> {
}
this.onStateChangeHandler && this.onStateChangeHandler()
} catch (err) {
console.error('Received invalid state:', err)
if (err instanceof ZodError) {
const ioError = new IOError('BAD_RESPONSE', 'Received invalid state')
ioError.cause = err
throw ioError
} else {
const ioError = new IOError(
'RESPONSE_HANDLER_ERROR',
'Error in state change handler'
)
ioError.cause = err
throw ioError
}
}

return this.instance
Expand Down
11 changes: 8 additions & 3 deletions src/classes/IOError.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
export type IOErrorKind = 'CANCELED' | 'TRANSACTION_CLOSED' | 'BAD_RESPONSE'
export type IOErrorKind =
| 'CANCELED'
| 'TRANSACTION_CLOSED'
| 'BAD_RESPONSE'
| 'RESPONSE_HANDLER_ERROR'

export default class IOError extends Error {
kind: IOErrorKind

constructor(kind: IOErrorKind, message?: string) {
super(message)
constructor(kind: IOErrorKind, message?: string, options?: { cause?: any }) {
super(message, options)
this.kind = kind
this.name = 'IOError'
}
}
Loading

0 comments on commit 5d1bc66

Please sign in to comment.