UNPKG

@commercelayer/sdk-utils

Version:
1 lines 13.1 kB
{"version":3,"sources":["../src/batch.ts"],"names":["batch","init_default","invalidToken","sleep","headerRateLimits","computeRateLimits"],"mappings":"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","file":"chunk-IIOABVXI.cjs","sourcesContent":["import type { ListResponse, Resource, ResourceCreate, ResourceId, ResourceUpdate, ResourcesConfig, CreatableResourceType, DeletableResourceType, ListableResourceType, ResourceTypeLock, RetrievableResourceType, UpdatableResourceType, ApiError, SdkError, QueryParamsList, QueryParams } from \"@commercelayer/sdk\"\nimport CommerceLayerUtils from './init'\nimport { computeRateLimits, headerRateLimits, type RateLimitInfo } from \"./rate_limit\"\nimport { invalidToken, sleep } from \"./common\"\n\n/*\ncreateAll: \t\tKO, can be done with imports\ndeleteAll: \t\tKO, can be done with cleanups\nupdateAll:\t\tOK, update of known resources can be done with imports, but would be useful a feature to update resources using a filter\nretrieveAll:\tOK, list all resources with pagination, zero offset and token refresh (listAll)\n*/\n\nexport type TaskOperation = 'retrieve' | 'list' | 'create' | 'update' | 'delete'\n\nexport type TaskResourceParam = ResourceId | ResourceCreate | ResourceUpdate\nexport type TaskResourceResult = Resource | ListResponse<Resource>\nexport type TaskResult = TaskResourceResult | undefined\n\n\nexport class InvalidTokenError extends Error {\n\treadonly cause: ApiError\n\tconstructor(error: ApiError) {\n\t\tsuper(error.first().detail as string)\n\t\tthis.cause = error\n\t}\n}\n\n\nexport type SuccessCallback = (output: TaskResult, task: Task) => Promise<void> | void\nexport type FailureCallback = (error: SdkError, task: Task) => Promise<boolean> | boolean\nexport type TokenCallback = (error: InvalidTokenError, task: Task) => Promise<string> | string\n\nexport type PrepareResourceResult = TaskResourceParam | undefined\nexport type PrepareResourceCallback = (resource: TaskResourceParam, last: TaskResourceResult) => Promise<PrepareResourceResult> | PrepareResourceResult\n\nexport type TemplateTask = Partial<Task>\n\ntype CreateTask = CRUDTask & {\n\tresourceType: CreatableResourceType,\n\toperation: 'create',\n\tresource: ResourceCreate\n}\n\ntype UpdateTask = CRUDTask & {\n\tresourceType: UpdatableResourceType,\n\toperation: 'update',\n\tresource: ResourceUpdate\n}\n\ntype DeleteTask = CRUDTask & {\n\tresourceType: DeletableResourceType,\n\toperation: 'delete',\n\tresource: ResourceId\n}\n\ntype ListTask = {\n\tresourceType: ListableResourceType,\n\toperation: 'list',\n\tparams?: QueryParamsList\n}\n\ntype RetrieveTask = CRUDTask & {\n\tresourceType: RetrievableResourceType,\n\toperation: 'retrieve',\n\tresource: ResourceId\n}\n\ntype CRUDTask = {\n\tresourceType: ResourceTypeLock\n\toperation: 'create' | 'retrieve' | 'update' | 'delete'\n\tresource: Record<string, any>\n\tprepareResource?: PrepareResourceCallback\n}\n\n\nexport type Task = {\n\tlabel?: string\n\tresourceType: ResourceTypeLock\n\toperation: TaskOperation\n\tparams?: QueryParams\n\toptions?: ResourcesConfig\n\texecuted?: boolean\n\tonSuccess?: {\n\t\tcallback?: SuccessCallback\n\t\tresult?: TaskResult,\n\t},\n\tonFailure?: {\n\t\terror?: SdkError\n\t\thaltOnError?: boolean\n\t\terrorHandler?: FailureCallback\n\t}\n} & (CreateTask | UpdateTask | DeleteTask | ListTask | RetrieveTask)\n\n\nexport type BatchResult = {\n\tstartedAt: Date,\n\tfinishedAt?: Date\n}\n\n\nexport type BatchOptions = {\n\thaltOnError?: boolean,\n\trefreshToken?: TokenCallback\n}\n\n\nexport type Batch = {\n\ttasks: Task[]\n\trateLimits?: Partial<Record<ResourceTypeLock, Partial<Record<TaskOperation, RateLimitInfo>>>>\n\trunning?: boolean\n\trunningTask?: string,\n\toptions?: BatchOptions\n}\n\n\n\nconst isCRUDTask = (task: any): task is CRUDTask => {\n\treturn task.resource && ['create', 'retrieve', 'update', 'delete'].includes(task.operation as string)\n}\n\n\nconst taskRateLimit = (batch: Batch, task: Task, info?: RateLimitInfo): RateLimitInfo | undefined => {\n\n\tif (info) {\n\t\tif (!batch.rateLimits) batch.rateLimits = {}\n\t\tObject.assign(batch.rateLimits || {}, { [task.resourceType]: { [task.operation]: info } })\n\t}\n\n\tconst resLimits = batch.rateLimits?.[task.resourceType]\n\treturn resLimits ? resLimits[task.operation] : undefined\n\n}\n\n\n\nconst executeTask = async (task: Task, options: BatchOptions = {}): Promise<TaskResult> => {\n\n\t// const client = cl[task.resourceType as keyof CommerceLayerBundle]\n\tconst client = CommerceLayerUtils().api(task.resourceType)\n\tlet out: TaskResult\n\n\ttry {\n\n\t\ttask.executed = false\n\n\t\tconst op = client[task.operation as keyof typeof client] as any\n\t\tif (!op) throw new Error(`Unsupported operation [resource: ${task.resourceType}, operation: ${task.operation}]`)\n\n\t\tswitch (task.operation) {\n\t\t\tcase 'list': {\n\t\t\t\tout = await (client[task.operation as keyof typeof client] as any)(task.params, task.options) as ListResponse<Resource>\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'delete': {\n\t\t\t\tawait (client[task.operation as keyof typeof client] as any)(task.resource, task.options)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'create':\n\t\t\tcase 'retrieve':\n\t\t\tcase 'update': {\n\t\t\t\tout = await (client[task.operation as keyof typeof client] as any)(task.resource, task.params, task.options) as Resource\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (!task.onSuccess) task.onSuccess = {}\n\t\tconst success = task.onSuccess\n\t\tsuccess.result = out\n\t\tif (success.callback) try { await success.callback(success.result, task) } catch (err) { }\n\n\t\treturn out\n\n\t} catch (error: unknown) {\n\n\t\tif (invalidToken(error)) throw new InvalidTokenError(error)\n\n\t\tif (!task.onFailure) task.onFailure = {}\n\t\tconst failure = task.onFailure\n\t\tfailure.error = error as SdkError\n\t\tlet halt = options.haltOnError || failure.haltOnError\n\t\tif (failure.errorHandler) try { halt = halt || await failure.errorHandler(failure.error, task) } catch (err) { }\n\t\tif (halt) throw error\n\n\t} finally {\n\t\ttask.executed = true\n\t}\n\n}\n\n\nconst resolvePlaceholders: PrepareResourceCallback = (resource: TaskResourceParam, last: TaskResourceResult): undefined => {\n\t/*\n\tif (!last) return\n\tlet lastResult: Resource\n\tif (Array.isArray(last)) {\n\t\tif (last.length === 0) return\n\t\tlastResult = last[0]\n\t} else lastResult = last\n\n\tObject.entries(resource.).forEach(([k, v]) => {\n\t\tconst val = String(v)\n\t\tconst vars = val.match(/{{[\\w]{2,}\\([\\d]\\)?}}/g)\n\t\tif (vars?.length) for (const v of vars) {\n\t\t\tconst newVal = lastResult[v as keyof typeof lastResult]\n\n\t\t}\n\t})\n\t*/\n}\n\n\nexport const executeBatch = async (batch: Batch): Promise<BatchResult> => {\n\n\tconst cl = CommerceLayerUtils().sdk\n\tconst rrr = cl.addRawResponseReader({ headers: true })\n\tbatch.running = false\n\n\tconst result: BatchResult = {\n\t\tstartedAt: new Date()\n\t}\n\n\tlet runningIndex = -1\n\tlet lastResult: TaskResult\n\tfor (const task of batch.tasks) {\n\n\t\trunningIndex++\n\t\tbatch.running = true\n\t\tbatch.runningTask = task.label || String(runningIndex)\n\n\t\tlet rateLimit = taskRateLimit(batch, task)\n\t\tif (rateLimit) await sleep(rateLimit.delay)\n\n\t\ttry {\n\t\t\tif (lastResult && isCRUDTask(task)) {\n\t\t\t\tlet modRes: PrepareResourceResult\n\t\t\t\ttry {\n\t\t\t\t\tif (task.resource && task.prepareResource) modRes = await task.prepareResource(task.resource, lastResult)\n\t\t\t\t\telse modRes = await resolvePlaceholders(task.resource, lastResult)\n\t\t\t\t} catch (e: any) { modRes = undefined }\n\t\t\t\tif (modRes) task.resource = modRes\n\t\t\t}\n\t\t\tlastResult = undefined\n\t\t\tlastResult = await executeTask(task, batch.options)\n\t\t} catch (err: unknown) {\n\t\t\t// Refresh access token if needed and re-execute the task\n\t\t\tif ((err instanceof InvalidTokenError) && batch.options?.refreshToken) {\n\t\t\t\tconst newAccessToken = await batch.options.refreshToken(err, task)\n\t\t\t\tcl.config({ accessToken: newAccessToken })\n\t\t\t\tawait executeTask(task, batch.options)\n\t\t\t} else throw err\n\t\t} finally {\n\t\t\tbatch.running = false\n\t\t\tbatch.runningTask = undefined\n\t\t}\n\n\t\tif (!rateLimit) try {\n\t\t\t// Compute and store rate limit for this kind of resource/operation\n\t\t\tconst rateLimits = headerRateLimits(rrr.headers)\n\t\t\trateLimit = computeRateLimits(rateLimits, task, batch.tasks)\n\t\t\ttaskRateLimit(batch, task, rateLimit)\n\t\t} catch (error: any) { }\n\n\t}\n\n\tif (cl && rrr) cl.removeRawResponseReader()\n\n\tresult.finishedAt = new Date()\n\n\n\treturn result\n\n}\n\n\nexport const batch = {\n\texecute: executeBatch\n}\n"]}