From ed1e597895340aa7f1ab4cab92f7d80aeceb8b22 Mon Sep 17 00:00:00 2001 From: GenaRazmakhnin Date: Fri, 2 Feb 2024 15:33:41 +0100 Subject: [PATCH] fix(sub-subscription): remove prefix slash in url --- resources/index.ts | 1004 ++++++++++++++++++++++++---------------- vendor/r4/index.js | 2 +- vendor/r4/package.json | 2 +- 3 files changed, 609 insertions(+), 399 deletions(-) diff --git a/resources/index.ts b/resources/index.ts index f7ad6d1..ad28588 100644 --- a/resources/index.ts +++ b/resources/index.ts @@ -1,34 +1,40 @@ -import base64 from '@juanelas/base64' +import base64 from '@juanelas/base64'; import { HttpClientInstance, httpClient as http, HTTPError, Input, - Options, NormalizedOptions, ResponsePromise -} from './http-client' + Options, + NormalizedOptions, + ResponsePromise, +} from './http-client'; import { TaskDefinitionsMap, WorkflowDefinitionsMap, ResourceTypeMap, SearchParams, - SubsSubscription -} from './types' + SubsSubscription, +} from './types'; -export { HTTPError } +export { HTTPError }; -export function decode (str: string): string { - return base64.decode(str, true).toString() +export function decode(str: string): string { + return base64.decode(str, true).toString(); } -export function encode (str: string): string { - return base64.encode(str) +export function encode(str: string): string { + return base64.encode(str); } -export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) -export const buildResourceUrl = (resource: string, id?: string) => ['fhir', resource, id && id].filter(Boolean).join('/') +export const sleep = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); +export const buildResourceUrl = (resource: string, id?: string) => + ['fhir', resource, id && id].filter(Boolean).join('/'); -type PartialResourceBody = Partial>; +type PartialResourceBody = Partial< + Omit +>; type SetOptional = Pick, K> & Omit; @@ -47,7 +53,16 @@ type Dir = 'asc' | 'desc'; export type PrefixWithArray = 'eq' | 'ne'; -export type Prefix = 'eq' | 'ne' | 'gt' | 'lt' | 'ge' | 'le' | 'sa' | 'eb' | 'ap'; +export type Prefix = + | 'eq' + | 'ne' + | 'gt' + | 'lt' + | 'ge' + | 'le' + | 'sa' + | 'eb' + | 'ap'; export type ExecuteQueryResponseWrapper = { data: T; @@ -82,16 +97,31 @@ export type BaseResponseResources = { 'query-sql': (string | number)[]; }; -export type BaseResponseResource = ResourceTypeMap[T]; +export type BaseResponseResource = + ResourceTypeMap[T]; -export type ResourceKeys = Omit; +export type ResourceKeys< + T extends keyof ResourceTypeMap, + I extends ResourceTypeMap[T], +> = Omit; -type SortKey = keyof SearchParams[T] | `.${string}`; +type SortKey = + | keyof SearchParams[T] + | `.${string}`; -type ElementsParams = Array>; +type ElementsParams< + T extends keyof ResourceTypeMap, + R extends ResourceTypeMap[T], +> = Array>; type ChangeFields = Omit & R; -type SubscriptionParams = Omit }>, 'resourceType'> & { id: string }; +type SubscriptionParams = Omit< + ChangeFields< + SubsSubscription, + { channel: Omit } + >, + 'resourceType' +> & { id: string }; export type LogData = { message: Record; @@ -100,121 +130,153 @@ export type LogData = { fx?: string; }; -interface JsonObject { [key: string]: JsonValue; } -type JsonPrimitive = string | number | boolean | null -type JsonValue = JsonPrimitive | JsonArray | JsonObject -type JsonArray = JsonValue[] +interface JsonObject { + [key: string]: JsonValue; +} +type JsonPrimitive = string | number | boolean | null; +type JsonValue = JsonPrimitive | JsonArray | JsonObject; +type JsonArray = JsonValue[]; export interface R { // request: {}, - response: { headers: Headers, url: string, status: number, data: T }, + response: { headers: Headers; url: string; status: number; data: T }; } export class E extends Error { - public response: R['response'] - public request: Request - public options: NormalizedOptions - - constructor (data: T, response: Response, request: Request, options: NormalizedOptions) { - const code = (response.status || response.status === 0) ? response.status : '' - const title = response.statusText || '' - const status = `${code} ${title}`.trim() - const reason = status ? `status code ${status}` : 'an unknown error' - - super(`Request failed with ${reason}`) - - this.name = 'HTTPError' - this.response = { status: response.status, headers: response.headers, url: response.url, data } - this.request = request - this.options = options + public response: R['response']; + public request: Request; + public options: NormalizedOptions; + + constructor( + data: T, + response: Response, + request: Request, + options: NormalizedOptions, + ) { + const code = + response.status || response.status === 0 ? response.status : ''; + const title = response.statusText || ''; + const status = `${code} ${title}`.trim(); + const reason = status ? `status code ${status}` : 'an unknown error'; + + super(`Request failed with ${reason}`); + + this.name = 'HTTPError'; + this.response = { + status: response.status, + headers: response.headers, + url: response.url, + data, + }; + this.request = request; + this.options = options; } } -const request = (fn: (url: Input, options?: Options) => ResponsePromise) => async (url: Input, options?: Options): Promise> => { - try { - const response = await fn(url, options) - return { response: { url: response.url, headers: response.headers, status: response.status, data: await response.json() } } - } catch (error: unknown) { - if (error instanceof HTTPError) { - const data = await error.response.json() - throw new E(data, error.response, error.request, error.options) - } +const request = + (fn: (url: Input, options?: Options) => ResponsePromise) => + async (url: Input, options?: Options): Promise> => { + try { + const response = await fn(url, options); + return { + response: { + url: response.url, + headers: response.headers, + status: response.status, + data: await response.json(), + }, + }; + } catch (error: unknown) { + if (error instanceof HTTPError) { + const data = await error.response.json(); + throw new E(data, error.response, error.request, error.options); + } - throw error - } -} + throw error; + } + }; class Task { - private readonly workers: Array + private readonly workers: Array; - private client: HttpClientInstance - constructor (client: HttpClientInstance) { - this.client = client - this.workers = [] + private client: HttpClientInstance; + constructor(client: HttpClientInstance) { + this.client = client; + this.workers = []; } - async cancel (id: string) { - const response = await this.client.post('rpc', { - json: { - method: 'awf.task/cancel', - params: { id } - } - }).json() + async cancel(id: string) { + const response = await this.client + .post('rpc', { + json: { + method: 'awf.task/cancel', + params: { id }, + }, + }) + .json(); - return response.result.resource + return response.result.resource; } - async start (id: string, executionId: string) { + async start(id: string, executionId: string) { try { - return this.client.post('rpc', { - json: { - method: 'awf.task/start', - params: { id, execId: executionId } - } - }).json() + return this.client + .post('rpc', { + json: { + method: 'awf.task/start', + params: { id, execId: executionId }, + }, + }) + .json(); } catch (error: any) { if (error.name === 'HTTPError') { - const errorJson = await error.response.json() - console.dir(errorJson, { depth: 5 }) + const errorJson = await error.response.json(); + console.dir(errorJson, { depth: 5 }); } } } - async complete (id: string, executionId: string, payload: unknown) { - return this.client.post('rpc', { - json: { - method: 'awf.task/success', - params: { id, execId: executionId, result: payload } - } - }).json() + async complete(id: string, executionId: string, payload: unknown) { + return this.client + .post('rpc', { + json: { + method: 'awf.task/success', + params: { id, execId: executionId, result: payload }, + }, + }) + .json(); } - async fail (id: string, executionId: string, payload: unknown) { + async fail(id: string, executionId: string, payload: unknown) { try { - return this.client.post('rpc', { - json: { - method: 'awf.task/fail', - params: { id, execId: executionId, result: payload } - } - }).json() + return this.client + .post('rpc', { + json: { + method: 'awf.task/fail', + params: { id, execId: executionId, result: payload }, + }, + }) + .json(); } catch (error: any) { if (error.name === 'HTTPError') { - const errorJson = await error.response.json() - console.dir(errorJson, { depth: 5 }) + const errorJson = await error.response.json(); + console.dir(errorJson, { depth: 5 }); } } } - private execute ( + private execute( definition: K, - params: TaskDefinitionsMap[K]['params'] + params: TaskDefinitionsMap[K]['params'], ): Promise { - return this.client.post('rpc', { - json: { - method: 'awf.task/create-and-execute', - params: { definition, params } - } - }).json() + return this.client + .post('rpc', { + json: { + method: 'awf.task/create-and-execute', + params: { definition, params }, + }, + }) + .json(); } /** @@ -225,184 +287,235 @@ class Task { * */ - async pendingTasks (definition?: keyof TaskDefinitionsMap): Promise { - const params = new URLSearchParams({ '_count': '0', '.status': 'ready', 'definition-not': 'awf.workflow/decision-task' }) + async pendingTasks(definition?: keyof TaskDefinitionsMap): Promise { + const params = new URLSearchParams({ + _count: '0', + '.status': 'ready', + 'definition-not': 'awf.workflow/decision-task', + }); if (definition) { - params.append('definition', definition) - params.delete('definition-not') + params.append('definition', definition); + params.delete('definition-not'); } - return this.client.get('AidboxTask', { - searchParams: params - }).json<{ total: number }>().then(r => r.total) + return this.client + .get('AidboxTask', { + searchParams: params, + }) + .json<{ total: number }>() + .then((r) => r.total); } - async pendingDecisions () { - return this.client.get('AidboxTask', { - searchParams: new URLSearchParams({ '_count': '0', '.status': 'ready', 'definition': 'awf.workflow/decision-task' }) - }).json<{ total: number }>().then(r => r.total) + async pendingDecisions() { + return this.client + .get('AidboxTask', { + searchParams: new URLSearchParams({ + _count: '0', + '.status': 'ready', + definition: 'awf.workflow/decision-task', + }), + }) + .json<{ total: number }>() + .then((r) => r.total); } - async history (id: string) { - return this.client.post('rpc', { - json: { - method: 'awf.task/status', - params: { id, 'include-log?': true } - } - }).json<{ result: { resource: TaskMeta, log: Record[] } }>().then(r => r.result) + async history(id: string) { + return this.client + .post('rpc', { + json: { + method: 'awf.task/status', + params: { id, 'include-log?': true }, + }, + }) + .json<{ + result: { resource: TaskMeta; log: Record[] }; + }>() + .then((r) => r.result); } - async inProgress () { - return this.client.get('AidboxTask', { - searchParams: new URLSearchParams({ '_count': '0', '.status': 'in-progress' }) - }).json<{ total: number }>().then(r => r.total) + async inProgress() { + return this.client + .get('AidboxTask', { + searchParams: new URLSearchParams({ + _count: '0', + '.status': 'in-progress', + }), + }) + .json<{ total: number }>() + .then((r) => r.total); } - createHandler (handler: (task: TaskMeta) => void) { + createHandler( + handler: (task: TaskMeta) => void, + ) { return async (task: TaskMeta) => { - await this.start(task.id, task.execId) + await this.start(task.id, task.execId); try { - const result = await handler(task) - await this.complete(task.id, task.execId, result) + const result = await handler(task); + await this.complete(task.id, task.execId, result); } catch (error: any) { if (error.name === 'HTTPError') { - const errorJson = await error.response.json() - console.dir(errorJson, { depth: 5 }) - await this.fail(task.id, task.execId, errorJson) + const errorJson = await error.response.json(); + console.dir(errorJson, { depth: 5 }); + await this.fail(task.id, task.execId, errorJson); } else { - console.dir(error, { depth: 5 }) + console.dir(error, { depth: 5 }); // for some reason does not fail the task - await this.fail(task.id, task.execId, error) + await this.fail(task.id, task.execId, error); } } - } + }; } - async poll (params: { workflowDefinitions?: [string]; taskDefinitions?: [string] }, options: WorkerOptions) { - const tasksBatch = await this.client.post('rpc', { - json: { - method: 'awf.task/poll', - params: { ...params, maxBatchSize: options.batchSize } - } - }).json() + async poll( + params: { workflowDefinitions?: [string]; taskDefinitions?: [string] }, + options: WorkerOptions, + ) { + const tasksBatch = await this.client + .post('rpc', { + json: { + method: 'awf.task/poll', + params: { ...params, maxBatchSize: options.batchSize }, + }, + }) + .json(); - return tasksBatch.result.resources + return tasksBatch.result.resources; } - private async runDaemon ( + private async runDaemon( poll: () => Promise>>, handler: (input: any) => any, - options: WorkerOptions + options: WorkerOptions, ) { while (true) { - const tasks = await poll() - await Promise.allSettled(tasks.map(async (task) => handler(task))) - await sleep(options.pollInterval || 1000) + const tasks = await poll(); + await Promise.allSettled(tasks.map(async (task) => handler(task))); + await sleep(options.pollInterval || 1000); } } - implement> ( + implement>( name: K, handler: TaskHandler, - options: WorkerOptions = {} + options: WorkerOptions = {}, ): void { const worker = this.runDaemon( () => this.poll({ taskDefinitions: [name] }, options), this.createHandler(handler), - options - ) - this.workers.push(worker) + options, + ); + this.workers.push(worker); } } class Workflow { - private readonly workers: Array - - private client: HttpClientInstance - private task: Task - constructor (client: HttpClientInstance, task: Task) { - this.client = client - this.task = task - this.workers = [] + private readonly workers: Array; + + private client: HttpClientInstance; + private task: Task; + constructor(client: HttpClientInstance, task: Task) { + this.client = client; + this.task = task; + this.workers = []; } - private async runDaemon ( + private async runDaemon( poll: () => Promise>>, handler: (input: any) => any, - options: WorkerOptions + options: WorkerOptions, ) { while (true) { - const tasks = await poll() - await Promise.allSettled(tasks.map(async (task) => handler(task))) - await sleep(options.pollInterval || 1000) + const tasks = await poll(); + await Promise.allSettled(tasks.map(async (task) => handler(task))); + await sleep(options.pollInterval || 1000); } } - implement ( + implement( name: W, handler: WorkflowHandler, - options: WorkerOptions = {} + options: WorkerOptions = {}, ): void { const worker = this.runDaemon( () => this.task.poll({ workflowDefinitions: [name] }, options), this.task.createHandler(this.wrapHandler(handler)), - options - ) - this.workers.push(worker) + options, + ); + this.workers.push(worker); } - private wrapHandler (handler: WorkflowHandler) { + private wrapHandler( + handler: WorkflowHandler, + ) { return (params: TaskMeta) => handler(params, { complete: (result: WorkflowDefinitionsMap[W]['result']) => ({ action: 'awf.workflow.action/complete-workflow', - result + result, }), execute: (params: { definition: T; params: TaskDefinitionsMap[T]['params']; }) => ({ - 'action': 'awf.workflow.action/schedule-task', - 'task-request': { definition: params.definition, params: params.params } + action: 'awf.workflow.action/schedule-task', + 'task-request': { + definition: params.definition, + params: params.params, + }, }), - fail: (error: any) => ({ action: 'awf.workflow.action/fail', error }) - }) + fail: (error: any) => ({ action: 'awf.workflow.action/fail', error }), + }); } - execute ( + execute( definition: K, - params: WorkflowDefinitionsMap[K]['params'] + params: WorkflowDefinitionsMap[K]['params'], ): Promise { - return this.client.post('rpc', { - json: { - method: 'awf.workflow/create-and-execute', - params: { definition, params } - } - }).json() + return this.client + .post('rpc', { + json: { + method: 'awf.workflow/create-and-execute', + params: { definition, params }, + }, + }) + .json(); } - async terminate (id: string) { - return this.client.post('rpc', { - json: { - method: 'awf.workflow/cancel', - params: { id } - } - }).json().then(r => r.result.resource) + async terminate(id: string) { + return this.client + .post('rpc', { + json: { + method: 'awf.workflow/cancel', + params: { id }, + }, + }) + .json() + .then((r) => r.result.resource); } - async inProgress () { - return this.client.get('AidboxWorkflow', { - searchParams: new URLSearchParams({ '_count': '0', '.status': 'in-progress' }) - }).json<{ total: number }>().then(r => r.total) + async inProgress() { + return this.client + .get('AidboxWorkflow', { + searchParams: new URLSearchParams({ + _count: '0', + '.status': 'in-progress', + }), + }) + .json<{ total: number }>() + .then((r) => r.total); } - async history (id: string) { - return this.client.post('rpc', { - json: { - method: 'awf.workflow/status', - params: { id, 'include-activities?': true } - } - }).json().then(r => r.result) + async history(id: string) { + return this.client + .post('rpc', { + json: { + method: 'awf.workflow/status', + params: { id, 'include-activities?': true }, + }, + }) + .json() + .then((r) => r.result); } } @@ -411,46 +524,71 @@ export interface TokenStorage { set: (token: string | undefined) => Promise | void; } -const resourceOwnerAuthorization = (httpclient: HttpClientInstance, auth: ResourceOwnerAuthorization) => async ({ username, password }: { username: string, password: string }) => { - if (typeof auth.storage.set === 'function') { await auth.storage.set('') } - - const response = await httpclient.post('auth/token', { - json: { - username, - password, - client_id: auth.client.id, - client_secret: auth.client.secret, - grant_type: 'password' +const resourceOwnerAuthorization = + (httpclient: HttpClientInstance, auth: ResourceOwnerAuthorization) => + async ({ username, password }: { username: string; password: string }) => { + if (typeof auth.storage.set === 'function') { + await auth.storage.set(''); } - }).json<{ access_token: string, token_type: 'Bearer', userinfo: { email: string, id: string } }>() - if (typeof auth.storage.set === 'function') { await auth.storage.set(response.access_token) } + const response = await httpclient + .post('auth/token', { + json: { + username, + password, + client_id: auth.client.id, + client_secret: auth.client.secret, + grant_type: 'password', + }, + }) + .json<{ + access_token: string; + token_type: 'Bearer'; + userinfo: { email: string; id: string }; + }>(); + + if (typeof auth.storage.set === 'function') { + await auth.storage.set(response.access_token); + } - return response -} + return response; + }; -const resourceOwnerLogout = (httpclient: HttpClientInstance, auth: ResourceOwnerAuthorization) => async () => { - auth.storage.set(undefined) -} +const resourceOwnerLogout = + (httpclient: HttpClientInstance, auth: ResourceOwnerAuthorization) => + async () => { + auth.storage.set(undefined); + }; -type BasicAuthorization = { method: 'basic', credentials: { username: string, password: string } } -type ResourceOwnerAuthorization = { method: 'resource-owner', client: { id: string, secret: string }, storage: TokenStorage } +type BasicAuthorization = { + method: 'basic'; + credentials: { username: string; password: string }; +}; +type ResourceOwnerAuthorization = { + method: 'resource-owner'; + client: { id: string; secret: string }; + storage: TokenStorage; +}; -function isBasic (params: BasicAuthorization | ResourceOwnerAuthorization): params is BasicAuthorization { - return params.method === 'basic' +function isBasic( + params: BasicAuthorization | ResourceOwnerAuthorization, +): params is BasicAuthorization { + return params.method === 'basic'; } -function isResourceOwner (params: BasicAuthorization | ResourceOwnerAuthorization): params is ResourceOwnerAuthorization { - return params.method === 'resource-owner' +function isResourceOwner( + params: BasicAuthorization | ResourceOwnerAuthorization, +): params is ResourceOwnerAuthorization { + return params.method === 'resource-owner'; } export class Client { - private client: HttpClientInstance - private config: { auth: T } - task: Task - workflow: Workflow - constructor (baseURL: string, config: { auth: T }) { - this.config = config + private client: HttpClientInstance; + private config: { auth: T }; + task: Task; + workflow: Workflow; + constructor(baseURL: string, config: { auth: T }) { + this.config = config; const client = http.create({ prefixUrl: baseURL, throwHttpErrors: true, @@ -458,37 +596,45 @@ export class Client { beforeRequest: [ async (request) => { if (isBasic(config.auth)) { - const { username, password } = config.auth.credentials - request.headers.set('Authorization', `Basic ${encode(`${username}:${password}`)}`) + const { username, password } = config.auth.credentials; + request.headers.set( + 'Authorization', + `Basic ${encode(`${username}:${password}`)}`, + ); } if (isResourceOwner(config.auth)) { - const token = config.auth.storage.get() - if (token) request.headers.set('Authorization', `Bearer ${token}`) + const token = config.auth.storage.get(); + if (token) + request.headers.set('Authorization', `Bearer ${token}`); } - } - ] - } - }) - const taskClient = new Task(client) - this.task = taskClient - this.workflow = new Workflow(client, taskClient) - this.client = client + }, + ], + }, + }); + const taskClient = new Task(client); + this.task = taskClient; + this.workflow = new Workflow(client, taskClient); + this.client = client; } - public get auth () { - if (isBasic(this.config.auth)) return this.config.auth + public get auth() { + if (isBasic(this.config.auth)) return this.config.auth; if (isResourceOwner(this.config.auth)) { return { ...this.config.auth, signIn: resourceOwnerAuthorization(this.client, this.config.auth), - signUp: () => { console.log('TBD') }, - signOut: () => { console.log('TBD') } - } + signUp: () => { + console.log('TBD'); + }, + signOut: () => { + console.log('TBD'); + }, + }; } - throw new Error('') + throw new Error(''); } // переделать на reduce и добавить полей @@ -498,209 +644,261 @@ export class Client { patch: request(this.client.patch), put: request(this.client.put), delete: request(this.client.delete), - head: request(this.client.head) - }) + head: request(this.client.head), + }); resource = { list: (resourceName: T) => { - return new GetResources(this.client, resourceName) + return new GetResources(this.client, resourceName); }, - get: async (resourceName: T, id: string): Promise> => { - return this.client.get(buildResourceUrl(resourceName, id)).json>() + get: async ( + resourceName: T, + id: string, + ): Promise> => { + return this.client + .get(buildResourceUrl(resourceName, id)) + .json>(); }, - delete: async (resourceName: T, id: string): Promise> => { - return this.client.delete(buildResourceUrl(resourceName, id)).json>() + delete: async ( + resourceName: T, + id: string, + ): Promise> => { + return this.client + .delete(buildResourceUrl(resourceName, id)) + .json>(); }, - update: async( + update: async ( resourceName: T, id: string, - input: PartialResourceBody + input: PartialResourceBody, ): Promise> => { - return this.client.patch(buildResourceUrl(resourceName, id), { json: input }).json>() + return this.client + .patch(buildResourceUrl(resourceName, id), { json: input }) + .json>(); }, - create: async( + create: async ( resourceName: T, - input: SetOptional + input: SetOptional< + ResourceTypeMap[T] & { resourceType: string }, + 'resourceType' + >, ): Promise> => { - return this.client.post(buildResourceUrl(resourceName), { json: input }).json>() + return this.client + .post(buildResourceUrl(resourceName), { json: input }) + .json>(); }, - override: async( + override: async ( resourceName: T, id: string, - input: PartialResourceBody + input: PartialResourceBody, ): Promise> => { - return this.client.put(buildResourceUrl(resourceName, id), { json: input }).json>() - } - } + return this.client + .put(buildResourceUrl(resourceName, id), { json: input }) + .json>(); + }, + }; - async rpc (method: string, params: unknown): Promise { + async rpc(method: string, params: unknown): Promise { const response = await this.client.post('rpc', { method: 'POST', - json: { method, params } - }) + json: { method, params }, + }); - return response.json() + return response.json(); } aidboxQuery = { create: async (name: string, json: CreateQueryBody) => { - const response = await this.client.put(`AidboxQuery/${name}`, { json }) - return response.json() + const response = await this.client.put(`AidboxQuery/${name}`, { json }); + return response.json(); }, - execute: async (name: string, - params?: Record) => { - const queryParams = new URLSearchParams() + execute: async (name: string, params?: Record) => { + const queryParams = new URLSearchParams(); if (params) { for (const key of Object.keys(params)) { - const value = params[key] + const value = params[key]; if (value) { - queryParams.set(key, (value as any).toString()) + queryParams.set(key, (value as any).toString()); } } } - return this.client.get(`/$query/${name}`, { - searchParams: queryParams - }).json>() - } - } + return this.client + .get(`/$query/${name}`, { + searchParams: queryParams, + }) + .json>(); + }, + }; subsSubscription = { - create: async ({ id, status, trigger, channel }: SubscriptionParams): Promise => { - const response = await this.client.put(`/SubsSubscription/${id}`, { + create: async ({ + id, + status, + trigger, + channel, + }: SubscriptionParams): Promise => { + const response = await this.client.put(`SubsSubscription/${id}`, { json: { status, trigger, - channel: { ...channel, type: 'rest-hook' } - } - }) - return response.json() - } - } + channel: { ...channel, type: 'rest-hook' }, + }, + }); + return response.json(); + }, + }; - async rawSQL (sql: string, params?: string[]): Promise { - const body = [sql, ...(params?.map((value: unknown) => value?.toString()) ?? [])] + async rawSQL(sql: string, params?: string[]): Promise { + const body = [ + sql, + ...(params?.map((value: unknown) => value?.toString()) ?? []), + ]; - const response = await this.client.post('$sql', { json: body }) - return response.json() + const response = await this.client.post('$sql', { json: body }); + return response.json(); } - async sendLog (data: LogData): Promise { - await this.client.post('$loggy', { json: data }) + async sendLog(data: LogData): Promise { + await this.client.post('$loggy', { json: data }); } } -export class GetResources - implements PromiseLike> { - private searchParamsObject: URLSearchParams - resourceName: T - client: HttpClientInstance - - constructor (client: HttpClientInstance, resourceName: T) { - this.searchParamsObject = new URLSearchParams() - this.resourceName = resourceName - this.client = client - } - - where( - key: K | string, - value: SP | SP[], - prefix?: PR, - ): this; - - where>( - key: K | string, - value: SP, - prefix?: PR, - ): this; - - where ( - key: K | string, - value: SP | SP[], - prefix?: Prefix | never - ): this { +export class GetResources< + T extends keyof ResourceTypeMap, + R extends ResourceTypeMap[T], +> implements PromiseLike> +{ + private searchParamsObject: URLSearchParams; + resourceName: T; + client: HttpClientInstance; + + constructor(client: HttpClientInstance, resourceName: T) { + this.searchParamsObject = new URLSearchParams(); + this.resourceName = resourceName; + this.client = client; + } + + where< + K extends keyof SearchParams[T], + SP extends SearchParams[T][K], + PR extends PrefixWithArray, + >(key: K | string, value: SP | SP[], prefix?: PR): this; + + where< + K extends keyof SearchParams[T], + SP extends SearchParams[T][K], + PR extends Exclude, + >(key: K | string, value: SP, prefix?: PR): this; + + where< + K extends keyof SearchParams[T], + SP extends SearchParams[T][K], + PR extends SP extends number ? Prefix : never, + >(key: K | string, value: SP | SP[], prefix?: Prefix | never): this { if (Array.isArray(value)) { - const val = value as SP[] + const val = value as SP[]; if (prefix) { if (prefix === 'eq') { - this.searchParamsObject.append(key.toString(), val.join(',')) - return this + this.searchParamsObject.append(key.toString(), val.join(',')); + return this; } val.forEach((item) => { - this.searchParamsObject.append(key.toString(), `${prefix}${item}`) - }) + this.searchParamsObject.append(key.toString(), `${prefix}${item}`); + }); - return this + return this; } - const queryValues = val.join(',') - this.searchParamsObject.append(key.toString(), queryValues) + const queryValues = val.join(','); + this.searchParamsObject.append(key.toString(), queryValues); - return this + return this; } - const queryValue = `${prefix ?? ''}${value}` + const queryValue = `${prefix ?? ''}${value}`; - this.searchParamsObject.append(key.toString(), queryValue) - return this + this.searchParamsObject.append(key.toString(), queryValue); + return this; } - contained (contained: boolean | 'both', containedType?: 'container' | 'contained') { - this.searchParamsObject.set('_contained', contained.toString()) + contained( + contained: boolean | 'both', + containedType?: 'container' | 'contained', + ) { + this.searchParamsObject.set('_contained', contained.toString()); if (containedType) { - this.searchParamsObject.set('_containedType', containedType) + this.searchParamsObject.set('_containedType', containedType); } - return this + return this; } - count (value: number) { - this.searchParamsObject.set('_count', value.toString()) + count(value: number) { + this.searchParamsObject.set('_count', value.toString()); - return this + return this; } - elements (args: ElementsParams) { - const queryValue = args.join(',') + elements(args: ElementsParams) { + const queryValue = args.join(','); - this.searchParamsObject.set('_elements', queryValue) + this.searchParamsObject.set('_elements', queryValue); - return this + return this; } - summary (type: boolean | 'text' | 'data' | 'count') { - this.searchParamsObject.set('_summary', type.toString()) + summary(type: boolean | 'text' | 'data' | 'count') { + this.searchParamsObject.set('_summary', type.toString()); - return this + return this; } - sort (key: SortKey, dir: Dir) { - const existedSortParams = this.searchParamsObject.get('_sort') + sort(key: SortKey, dir: Dir) { + const existedSortParams = this.searchParamsObject.get('_sort'); if (existedSortParams) { - const newSortParams = `${existedSortParams},${dir === 'asc' ? '-' : ''}${key.toString()}` + const newSortParams = `${existedSortParams},${ + dir === 'asc' ? '-' : '' + }${key.toString()}`; - this.searchParamsObject.set('_sort', newSortParams) - return this + this.searchParamsObject.set('_sort', newSortParams); + return this; } - this.searchParamsObject.set('_sort', dir === 'asc' ? `-${key.toString()}` : key.toString()) + this.searchParamsObject.set( + '_sort', + dir === 'asc' ? `-${key.toString()}` : key.toString(), + ); - return this + return this; } - then, TResult2 = never> ( - onfulfilled?: ((value: BaseResponseResources) => PromiseLike | TResult1) | undefined | null, - _onrejected?: ((reason: unknown) => PromiseLike | TResult2) | undefined | null + then, TResult2 = never>( + onfulfilled?: + | ((value: BaseResponseResources) => PromiseLike | TResult1) + | undefined + | null, + _onrejected?: + | ((reason: unknown) => PromiseLike | TResult2) + | undefined + | null, ): PromiseLike { - return this.client.get(buildResourceUrl(this.resourceName), { searchParams: this.searchParamsObject }) - .then((response: any) => { - return onfulfilled ? onfulfilled(response.json()) : (response.json() as TResult1) + return this.client + .get(buildResourceUrl(this.resourceName), { + searchParams: this.searchParamsObject, }) + .then((response: any) => { + return onfulfilled + ? onfulfilled(response.json()) + : (response.json() as TResult1); + }); } } -type EventType = 'awf.workflow.event/workflow-init' | 'awf.workflow.event/task-completed'; +type EventType = + | 'awf.workflow.event/workflow-init' + | 'awf.workflow.event/task-completed'; type TaskStatus = 'requested' | 'in-progress'; type RequesterType = 'AidboxWorkflow'; @@ -729,35 +927,38 @@ interface TasksBatch { } interface TaskRpcResult { - result: { resource: TaskMeta } + result: { resource: TaskMeta }; } interface AidboxWorkflow { - requester: { id: string, resourceType: string } - retryCount: number - execId: string - status: 'created' | 'in-progress' | 'done' - outcome?: 'succeeded' | 'failed' | 'canceled' + requester: { id: string; resourceType: string }; + retryCount: number; + execId: string; + status: 'created' | 'in-progress' | 'done'; + outcome?: 'succeeded' | 'failed' | 'canceled'; outcomeReason?: { - type: 'awf.task/failed-due-to-in-progress-timeout' | 'awf.workflow/failed-by-executor' | 'awf.executor/unknown-error', - message: string, - data?: any - } - result: any - error: any + type: + | 'awf.task/failed-due-to-in-progress-timeout' + | 'awf.workflow/failed-by-executor' + | 'awf.executor/unknown-error'; + message: string; + data?: any; + }; + result: any; + error: any; } interface WorkflowTerminateRpc { result: { - resource: AidboxWorkflow - } + resource: AidboxWorkflow; + }; } interface WorkflowHistoryRpc { result: { - resource: AidboxWorkflow, - activities: TaskMeta - } + resource: AidboxWorkflow; + activities: TaskMeta; + }; } interface WorkflowActions { @@ -772,7 +973,10 @@ interface WorkflowActions { action: 'awf.workflow.action/schedule-task'; 'task-request': { definition: T; params: TaskDefinitionsMap[T]['params'] }; }; - fail: (params: unknown) => { action: 'awf.workflow.action/fail'; error: unknown }; + fail: (params: unknown) => { + action: 'awf.workflow.action/fail'; + error: unknown; + }; } type TaskHandler> = ( @@ -789,41 +993,47 @@ type BundleRequestEntry = { resource?: T; }; -export type HTTPMethod = 'POST' | 'PATCH' | 'PUT' | 'GET' +export type HTTPMethod = 'POST' | 'PATCH' | 'PUT' | 'GET'; export class Bundle { - entry: BundleRequestEntry[] - type: 'batch' | 'transaction' + entry: BundleRequestEntry[]; + type: 'batch' | 'transaction'; - constructor (type: 'batch' | 'transaction' = 'transaction') { - this.type = type - this.entry = [] + constructor(type: 'batch' | 'transaction' = 'transaction') { + this.type = type; + this.entry = []; } - addEntry (resource: ResourceTypeMap[T], - { method, resourceName, id }: { method: HTTPMethod, resourceName: T, id?: string }) { + addEntry( + resource: ResourceTypeMap[T], + { + method, + resourceName, + id, + }: { method: HTTPMethod; resourceName: T; id?: string }, + ) { this.entry.push({ request: { method, - url: buildResourceUrl(resourceName, id) + url: buildResourceUrl(resourceName, id), }, -resource: { ...resource, resourceType: resourceName } - }) + resource: { ...resource, resourceType: resourceName }, + }); } - toJSON (): ResourceTypeMap['Bundle'] { + toJSON(): ResourceTypeMap['Bundle'] { return { resourceType: 'Bundle', type: this.type, - entry: this.entry - } + entry: this.entry, + }; } - toString () { + toString() { return JSON.stringify({ resourceType: 'Bundle', type: this.type, - entry: this.entry - }) + entry: this.entry, + }); } } diff --git a/vendor/r4/index.js b/vendor/r4/index.js index a55076b..d50be21 100644 --- a/vendor/r4/index.js +++ b/vendor/r4/index.js @@ -323,7 +323,7 @@ class Client { }; this.subsSubscription = { create: async ({ id, status, trigger, channel }) => { - const response = await this.client.put(`/SubsSubscription/${id}`, { + const response = await this.client.put(`SubsSubscription/${id}`, { json: { status, trigger, diff --git a/vendor/r4/package.json b/vendor/r4/package.json index ee7e31e..b0d1fe3 100644 --- a/vendor/r4/package.json +++ b/vendor/r4/package.json @@ -1,6 +1,6 @@ { "name": "@aidbox/sdk-r4", - "version": "1.0.8", + "version": "1.0.9", "description": "Default Aidbox SDK with HL7-R4 package", "main": "index.js", "scripts": {