payload 3.42.0 → 3.43.0-internal.c5bbc84
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/admin/functions/index.d.ts +8 -0
- package/dist/admin/functions/index.d.ts.map +1 -1
- package/dist/admin/functions/index.js.map +1 -1
- package/dist/admin/types.d.ts +1 -1
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/admin/types.js.map +1 -1
- package/dist/admin/views/folderList.d.ts +14 -5
- package/dist/admin/views/folderList.d.ts.map +1 -1
- package/dist/admin/views/folderList.js.map +1 -1
- package/dist/auth/crypto.d.ts.map +1 -1
- package/dist/auth/crypto.js +6 -3
- package/dist/auth/crypto.js.map +1 -1
- package/dist/auth/operations/unlock.d.ts.map +1 -1
- package/dist/auth/operations/unlock.js +1 -2
- package/dist/auth/operations/unlock.js.map +1 -1
- package/dist/auth/strategies/local/authenticate.d.ts.map +1 -1
- package/dist/auth/strategies/local/authenticate.js +1 -0
- package/dist/auth/strategies/local/authenticate.js.map +1 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/bin/migrate.d.ts.map +1 -1
- package/dist/bin/migrate.js +2 -2
- package/dist/bin/migrate.js.map +1 -1
- package/dist/collections/config/client.d.ts.map +1 -1
- package/dist/collections/config/client.js +3 -1
- package/dist/collections/config/client.js.map +1 -1
- package/dist/collections/dataloader.d.ts.map +1 -1
- package/dist/collections/dataloader.js +0 -1
- package/dist/collections/dataloader.js.map +1 -1
- package/dist/collections/operations/delete.d.ts.map +1 -1
- package/dist/collections/operations/delete.js +1 -2
- package/dist/collections/operations/delete.js.map +1 -1
- package/dist/collections/operations/findVersions.js +0 -1
- package/dist/collections/operations/findVersions.js.map +1 -1
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +3 -2
- package/dist/collections/operations/update.js.map +1 -1
- package/dist/config/client.d.ts.map +1 -1
- package/dist/config/client.js +1 -1
- package/dist/config/client.js.map +1 -1
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/config/sanitize.js +1 -2
- package/dist/config/sanitize.js.map +1 -1
- package/dist/database/queryValidation/validateQueryPaths.d.ts.map +1 -1
- package/dist/database/queryValidation/validateQueryPaths.js +0 -1
- package/dist/database/queryValidation/validateQueryPaths.js.map +1 -1
- package/dist/database/queryValidation/validateSearchParams.d.ts.map +1 -1
- package/dist/database/queryValidation/validateSearchParams.js +0 -1
- package/dist/database/queryValidation/validateSearchParams.js.map +1 -1
- package/dist/database/sanitizeJoinQuery.d.ts.map +1 -1
- package/dist/database/sanitizeJoinQuery.js +3 -1
- package/dist/database/sanitizeJoinQuery.js.map +1 -1
- package/dist/fields/config/client.d.ts.map +1 -1
- package/dist/fields/config/client.js +6 -1
- package/dist/fields/config/client.js.map +1 -1
- package/dist/fields/config/sanitize.d.ts.map +1 -1
- package/dist/fields/config/sanitize.js +0 -1
- package/dist/fields/config/sanitize.js.map +1 -1
- package/dist/fields/hooks/afterRead/index.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/index.js +0 -1
- package/dist/fields/hooks/afterRead/index.js.map +1 -1
- package/dist/fields/hooks/afterRead/relationshipPopulationPromise.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/relationshipPopulationPromise.js +1 -2
- package/dist/fields/hooks/afterRead/relationshipPopulationPromise.js.map +1 -1
- package/dist/fields/hooks/beforeChange/promise.d.ts.map +1 -1
- package/dist/fields/hooks/beforeChange/promise.js +0 -1
- package/dist/fields/hooks/beforeChange/promise.js.map +1 -1
- package/dist/fields/setDefaultBeforeDuplicate.js.map +1 -1
- package/dist/fields/validations.d.ts.map +1 -1
- package/dist/fields/validations.js +1 -2
- package/dist/fields/validations.js.map +1 -1
- package/dist/folders/types.d.ts +2 -0
- package/dist/folders/types.d.ts.map +1 -1
- package/dist/folders/types.js.map +1 -1
- package/dist/globals/config/client.d.ts.map +1 -1
- package/dist/globals/config/client.js +2 -1
- package/dist/globals/config/client.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/index.js +0 -1
- package/dist/queues/operations/runJobs/index.js.map +1 -1
- package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJSONJob/index.js +2 -2
- package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +0 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/importHandlerPath.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/importHandlerPath.js +1 -2
- package/dist/queues/operations/runJobs/runJob/importHandlerPath.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/index.js +2 -2
- package/dist/queues/operations/runJobs/runJob/index.js.map +1 -1
- package/dist/uploads/cropImage.d.ts +0 -1
- package/dist/uploads/cropImage.d.ts.map +1 -1
- package/dist/uploads/cropImage.js +2 -3
- package/dist/uploads/cropImage.js.map +1 -1
- package/dist/uploads/endpoints/getFile.d.ts.map +1 -1
- package/dist/uploads/endpoints/getFile.js +0 -1
- package/dist/uploads/endpoints/getFile.js.map +1 -1
- package/dist/uploads/endpoints/getFileFromURL.d.ts.map +1 -1
- package/dist/uploads/endpoints/getFileFromURL.js +2 -3
- package/dist/uploads/endpoints/getFileFromURL.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/fileFactory.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/fileFactory.js +1 -0
- package/dist/uploads/fetchAPI-multipart/fileFactory.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts +6 -0
- package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.js +0 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processNested.d.ts +1 -1
- package/dist/uploads/fetchAPI-multipart/processNested.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processNested.js +0 -1
- package/dist/uploads/fetchAPI-multipart/processNested.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/utilities.d.ts +1 -1
- package/dist/uploads/fetchAPI-multipart/utilities.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/utilities.js +0 -1
- package/dist/uploads/fetchAPI-multipart/utilities.js.map +1 -1
- package/dist/uploads/fetchAPI-stream-file/index.d.ts +1 -1
- package/dist/uploads/fetchAPI-stream-file/index.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-stream-file/index.js +0 -1
- package/dist/uploads/fetchAPI-stream-file/index.js.map +1 -1
- package/dist/uploads/tempFile.d.ts +1 -1
- package/dist/uploads/tempFile.d.ts.map +1 -1
- package/dist/uploads/tempFile.js +0 -1
- package/dist/uploads/tempFile.js.map +1 -1
- package/dist/utilities/addLocalesToRequest.d.ts.map +1 -1
- package/dist/utilities/addLocalesToRequest.js +0 -1
- package/dist/utilities/addLocalesToRequest.js.map +1 -1
- package/dist/utilities/configToJSONSchema.d.ts.map +1 -1
- package/dist/utilities/configToJSONSchema.js +2 -1
- package/dist/utilities/configToJSONSchema.js.map +1 -1
- package/dist/utilities/deepCopyObject.js +1 -2
- package/dist/utilities/deepCopyObject.js.map +1 -1
- package/dist/utilities/fieldSchemaToJSON.d.ts.map +1 -1
- package/dist/utilities/fieldSchemaToJSON.js +0 -1
- package/dist/utilities/fieldSchemaToJSON.js.map +1 -1
- package/dist/utilities/flattenTopLevelFields.d.ts.map +1 -1
- package/dist/utilities/flattenTopLevelFields.js +0 -1
- package/dist/utilities/flattenTopLevelFields.js.map +1 -1
- package/dist/utilities/formatErrors.d.ts.map +1 -1
- package/dist/utilities/formatErrors.js +0 -1
- package/dist/utilities/formatErrors.js.map +1 -1
- package/dist/utilities/getCollectionIDFieldTypes.d.ts.map +1 -1
- package/dist/utilities/getCollectionIDFieldTypes.js +0 -1
- package/dist/utilities/getCollectionIDFieldTypes.js.map +1 -1
- package/dist/utilities/getDataByPath.d.ts.map +1 -1
- package/dist/utilities/getDataByPath.js +0 -1
- package/dist/utilities/getDataByPath.js.map +1 -1
- package/dist/utilities/getEntityPolicies.d.ts.map +1 -1
- package/dist/utilities/getEntityPolicies.js +3 -2
- package/dist/utilities/getEntityPolicies.js.map +1 -1
- package/dist/utilities/getFieldPermissions.d.ts.map +1 -1
- package/dist/utilities/getFieldPermissions.js +2 -3
- package/dist/utilities/getFieldPermissions.js.map +1 -1
- package/dist/utilities/getObjectDotNotation.d.ts.map +1 -1
- package/dist/utilities/getObjectDotNotation.js +0 -1
- package/dist/utilities/getObjectDotNotation.js.map +1 -1
- package/dist/utilities/getSiblingData.d.ts.map +1 -1
- package/dist/utilities/getSiblingData.js +0 -1
- package/dist/utilities/getSiblingData.js.map +1 -1
- package/dist/utilities/getUniqueListBy.d.ts.map +1 -1
- package/dist/utilities/getUniqueListBy.js +0 -1
- package/dist/utilities/getUniqueListBy.js.map +1 -1
- package/dist/utilities/handleEndpoints.d.ts.map +1 -1
- package/dist/utilities/handleEndpoints.js +2 -2
- package/dist/utilities/handleEndpoints.js.map +1 -1
- package/dist/utilities/logError.d.ts.map +1 -1
- package/dist/utilities/logError.js +0 -1
- package/dist/utilities/logError.js.map +1 -1
- package/dist/utilities/reduceFieldsToValues.d.ts.map +1 -1
- package/dist/utilities/reduceFieldsToValues.js +0 -1
- package/dist/utilities/reduceFieldsToValues.js.map +1 -1
- package/dist/utilities/sanitizeJoinParams.d.ts +1 -1
- package/dist/utilities/sanitizeJoinParams.d.ts.map +1 -1
- package/dist/utilities/sanitizeJoinParams.js +2 -2
- package/dist/utilities/sanitizeJoinParams.js.map +1 -1
- package/dist/utilities/sanitizePermissions.d.ts.map +1 -1
- package/dist/utilities/sanitizePermissions.js +2 -2
- package/dist/utilities/sanitizePermissions.js.map +1 -1
- package/dist/utilities/sanitizePopulateParam.d.ts.map +1 -1
- package/dist/utilities/sanitizePopulateParam.js +1 -1
- package/dist/utilities/sanitizePopulateParam.js.map +1 -1
- package/dist/utilities/sanitizeSelectParam.d.ts.map +1 -1
- package/dist/utilities/sanitizeSelectParam.js +4 -2
- package/dist/utilities/sanitizeSelectParam.js.map +1 -1
- package/dist/utilities/telemetry/conf/envPaths.d.ts +1 -1
- package/dist/utilities/telemetry/conf/envPaths.d.ts.map +1 -1
- package/dist/utilities/telemetry/conf/envPaths.js.map +1 -1
- package/dist/utilities/timestamp.d.ts +1 -1
- package/dist/utilities/timestamp.d.ts.map +1 -1
- package/dist/utilities/timestamp.js +0 -1
- package/dist/utilities/timestamp.js.map +1 -1
- package/dist/utilities/traverseFields.d.ts.map +1 -1
- package/dist/utilities/traverseFields.js +6 -1
- package/dist/utilities/traverseFields.js.map +1 -1
- package/dist/utilities/unflatten.d.ts.map +1 -1
- package/dist/utilities/unflatten.js +1 -2
- package/dist/utilities/unflatten.js.map +1 -1
- package/dist/utilities/wait.d.ts +1 -1
- package/dist/utilities/wait.d.ts.map +1 -1
- package/dist/utilities/wait.js +0 -1
- package/dist/utilities/wait.js.map +1 -1
- package/dist/versions/baseFields.d.ts +2 -7
- package/dist/versions/baseFields.d.ts.map +1 -1
- package/dist/versions/baseFields.js.map +1 -1
- package/dist/versions/drafts/replaceWithDraftIfAvailable.d.ts.map +1 -1
- package/dist/versions/drafts/replaceWithDraftIfAvailable.js +1 -0
- package/dist/versions/drafts/replaceWithDraftIfAvailable.js.map +1 -1
- package/dist/versions/getLatestGlobalVersion.d.ts.map +1 -1
- package/dist/versions/getLatestGlobalVersion.js +3 -1
- package/dist/versions/getLatestGlobalVersion.js.map +1 -1
- package/dist/versions/saveVersion.js +1 -1
- package/dist/versions/saveVersion.js.map +1 -1
- package/package.json +3 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/getRunTaskFunction.ts"],"sourcesContent":["// @ts-strict-ignore\nimport ObjectIdImport from 'bson-objectid'\n\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type {\n RetryConfig,\n RunInlineTaskFunction,\n RunTaskFunction,\n RunTaskFunctions,\n TaskConfig,\n TaskHandler,\n TaskHandlerResult,\n TaskType,\n} from '../../../config/types/taskTypes.js'\nimport type {\n BaseJob,\n RunningJob,\n SingleTaskStatus,\n WorkflowConfig,\n WorkflowTypes,\n} from '../../../config/types/workflowTypes.js'\nimport type { UpdateJobFunction } from './getUpdateJobFunction.js'\n\nimport { calculateBackoffWaitUntil } from './calculateBackoffWaitUntil.js'\nimport { importHandlerPath } from './importHandlerPath.js'\n\nconst ObjectId = (ObjectIdImport.default ||\n ObjectIdImport) as unknown as typeof ObjectIdImport.default\n\n// Helper object type to force being passed by reference\nexport type RunTaskFunctionState = {\n reachedMaxRetries: boolean\n}\n\nasync function getTaskHandlerFromConfig(taskConfig: TaskConfig<string>) {\n let handler: TaskHandler<TaskType>\n\n if (typeof taskConfig.handler === 'function') {\n handler = taskConfig.handler\n } else {\n handler = await importHandlerPath<TaskHandler<TaskType>>(taskConfig.handler)\n }\n return handler\n}\n\nexport async function handleTaskFailed({\n error,\n executedAt,\n input,\n job,\n maxRetries,\n output,\n parent,\n req,\n retriesConfig,\n state,\n taskConfig,\n taskHandlerResult,\n taskID,\n taskSlug,\n taskStatus,\n updateJob,\n}: {\n error?: Error\n executedAt: Date\n input: object\n job: BaseJob\n maxRetries: number\n output: object\n parent?: TaskParent\n req: PayloadRequest\n retriesConfig: number | RetryConfig\n state: RunTaskFunctionState\n taskConfig?: TaskConfig<string>\n taskHandlerResult?: TaskHandlerResult<string>\n taskID: string\n taskSlug: string\n taskStatus: null | SingleTaskStatus<string>\n updateJob: UpdateJobFunction\n}): Promise<never> {\n req.payload.logger.error({ err: error, job, msg: `Error running task ${taskID}`, taskSlug })\n\n if (taskConfig?.onFail) {\n await taskConfig.onFail()\n }\n\n if (!job.log) {\n job.log = []\n }\n const errorJSON = error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : {\n message:\n taskHandlerResult?.state === 'failed'\n ? (taskHandlerResult.errorMessage ?? taskHandlerResult.state)\n : 'failed',\n }\n\n job.log.push({\n id: new ObjectId().toHexString(),\n completedAt: new Date().toISOString(),\n error: errorJSON,\n executedAt: executedAt.toISOString(),\n input,\n output,\n parent: req?.payload?.config?.jobs?.addParentToTaskLog ? parent : undefined,\n state: 'failed',\n taskID,\n taskSlug,\n })\n\n if (job.waitUntil) {\n // Check if waitUntil is in the past\n const waitUntil = new Date(job.waitUntil)\n if (waitUntil < new Date()) {\n // Outdated waitUntil, remove it\n delete job.waitUntil\n }\n }\n\n if (!taskStatus?.complete && (taskStatus?.totalTried ?? 0) >= maxRetries) {\n state.reachedMaxRetries = true\n\n await updateJob({\n error,\n hasError: true,\n log: job.log,\n processing: false,\n waitUntil: job.waitUntil,\n })\n\n throw new Error(\n `Task ${taskSlug} has failed more than the allowed retries in workflow ${job.workflowSlug}${error ? `. Error: ${String(error)}` : ''}`,\n )\n } else {\n // Job will retry. Let's determine when!\n const waitUntil: Date = calculateBackoffWaitUntil({\n retriesConfig,\n totalTried: taskStatus?.totalTried ?? 0,\n })\n\n // Update job's waitUntil only if this waitUntil is later than the current one\n if (!job.waitUntil || waitUntil > new Date(job.waitUntil)) {\n job.waitUntil = waitUntil.toISOString()\n }\n\n await updateJob({\n log: job.log,\n processing: false,\n waitUntil: job.waitUntil,\n })\n throw error ?? new Error('Task failed')\n }\n}\n\nexport type TaskParent = {\n taskID: string\n taskSlug: string\n}\n\nexport const getRunTaskFunction = <TIsInline extends boolean>(\n state: RunTaskFunctionState,\n job: BaseJob,\n workflowConfig: WorkflowConfig<string>,\n req: PayloadRequest,\n isInline: TIsInline,\n updateJob: UpdateJobFunction,\n parent?: TaskParent,\n): TIsInline extends true ? RunInlineTaskFunction : RunTaskFunctions => {\n const runTask: <TTaskSlug extends string>(\n taskSlug: TTaskSlug,\n ) => TTaskSlug extends 'inline' ? RunInlineTaskFunction : RunTaskFunction<TTaskSlug> = (\n taskSlug,\n ) =>\n (async (\n taskID: Parameters<RunInlineTaskFunction>[0],\n {\n input,\n retries,\n task,\n }: Parameters<RunInlineTaskFunction>[1] & Parameters<RunTaskFunction<string>>[1],\n ) => {\n const executedAt = new Date()\n\n let inlineRunner: TaskHandler<TaskType> = null!\n if (isInline) {\n inlineRunner = task\n }\n\n let taskConfig!: TaskConfig<string>\n if (!isInline) {\n taskConfig = (req.payload.config.jobs.tasks?.length &&\n req.payload.config.jobs.tasks.find((t) => t.slug === taskSlug)) as TaskConfig<string>\n\n if (!taskConfig) {\n throw new Error(`Task ${taskSlug} not found in workflow ${job.workflowSlug}`)\n }\n }\n\n const retriesConfigFromPropsNormalized =\n retries == undefined || retries == null\n ? {}\n : typeof retries === 'number'\n ? { attempts: retries }\n : retries\n const retriesConfigFromTaskConfigNormalized = taskConfig\n ? typeof taskConfig.retries === 'number'\n ? { attempts: taskConfig.retries }\n : taskConfig.retries\n : {}\n\n const finalRetriesConfig: RetryConfig = {\n ...retriesConfigFromTaskConfigNormalized,\n ...retriesConfigFromPropsNormalized, // Retry config from props takes precedence\n }\n\n const taskStatus: null | SingleTaskStatus<string> = job?.taskStatus?.[taskSlug]\n ? job.taskStatus[taskSlug][taskID]!\n : null\n\n // Handle restoration of task if it succeeded in a previous run\n if (taskStatus && taskStatus.complete === true) {\n let shouldRestore = true\n if (finalRetriesConfig?.shouldRestore === false) {\n shouldRestore = false\n } else if (typeof finalRetriesConfig?.shouldRestore === 'function') {\n shouldRestore = await finalRetriesConfig.shouldRestore({\n input: input!,\n job,\n req,\n taskStatus,\n })\n }\n if (shouldRestore) {\n return taskStatus.output\n }\n }\n\n let runner: TaskHandler<TaskType>\n if (isInline) {\n runner = inlineRunner\n } else {\n if (!taskConfig) {\n throw new Error(`Task ${taskSlug} not found in workflow ${job.workflowSlug}`)\n }\n runner = await getTaskHandlerFromConfig(taskConfig)\n }\n\n if (!runner || typeof runner !== 'function') {\n const errorMessage = isInline\n ? `Can't find runner for inline task with ID ${taskID}`\n : `Can't find runner while importing with the path ${typeof workflowConfig.handler === 'string' ? workflowConfig.handler : 'unknown - no string path'} in job type ${job.workflowSlug} for task ${taskSlug}.`\n req.payload.logger.error(errorMessage)\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n log: [\n ...job.log,\n {\n id: new ObjectId().toHexString(),\n completedAt: new Date().toISOString(),\n error: errorMessage,\n executedAt: executedAt.toISOString(),\n parent: req?.payload?.config?.jobs?.addParentToTaskLog ? parent : undefined,\n state: 'failed',\n taskID,\n taskSlug,\n },\n ],\n processing: false,\n })\n\n throw new Error(errorMessage)\n }\n\n let maxRetries: number | undefined = finalRetriesConfig?.attempts\n\n if (maxRetries === undefined || maxRetries === null) {\n // Inherit retries from workflow config, if they are undefined and the workflow config has retries configured\n if (workflowConfig.retries !== undefined && workflowConfig.retries !== null) {\n maxRetries =\n typeof workflowConfig.retries === 'object'\n ? workflowConfig.retries.attempts\n : workflowConfig.retries\n } else {\n maxRetries = 0\n }\n }\n\n let taskHandlerResult: TaskHandlerResult<string>\n let output: object = {}\n\n try {\n taskHandlerResult = await runner({\n inlineTask: getRunTaskFunction(state, job, workflowConfig, req, true, updateJob, {\n taskID,\n taskSlug,\n }),\n input,\n job: job as unknown as RunningJob<WorkflowTypes>, // TODO: Type this better\n req,\n tasks: getRunTaskFunction(state, job, workflowConfig, req, false, updateJob, {\n taskID,\n taskSlug,\n }),\n })\n } catch (err) {\n await handleTaskFailed({\n error: err,\n executedAt,\n input: input!,\n job,\n maxRetries: maxRetries!,\n output,\n parent,\n req,\n retriesConfig: finalRetriesConfig,\n state,\n taskConfig,\n taskID,\n taskSlug,\n taskStatus,\n updateJob,\n })\n throw new Error('Task failed')\n }\n\n if (taskHandlerResult.state === 'failed') {\n await handleTaskFailed({\n executedAt,\n input: input!,\n job,\n maxRetries: maxRetries!,\n output,\n parent,\n req,\n retriesConfig: finalRetriesConfig,\n state,\n taskConfig,\n taskHandlerResult,\n taskID,\n taskSlug,\n taskStatus,\n updateJob,\n })\n throw new Error('Task failed')\n } else {\n output = taskHandlerResult.output!\n }\n\n if (taskConfig?.onSuccess) {\n await taskConfig.onSuccess()\n }\n\n if (!job.log) {\n job.log = []\n }\n job.log.push({\n id: new ObjectId().toHexString(),\n completedAt: new Date().toISOString(),\n executedAt: executedAt.toISOString(),\n input,\n output,\n parent: req?.payload?.config?.jobs?.addParentToTaskLog ? parent : undefined,\n state: 'succeeded',\n taskID,\n taskSlug,\n })\n\n await updateJob({\n log: job.log,\n })\n\n return output\n }) as any\n\n if (isInline) {\n return runTask('inline') as TIsInline extends true ? RunInlineTaskFunction : RunTaskFunctions\n } else {\n const tasks: RunTaskFunctions = {}\n for (const task of req?.payload?.config?.jobs?.tasks ?? []) {\n tasks[task.slug] = runTask(task.slug)\n }\n return tasks as TIsInline extends true ? RunInlineTaskFunction : RunTaskFunctions\n }\n}\n"],"names":["ObjectIdImport","calculateBackoffWaitUntil","importHandlerPath","ObjectId","default","getTaskHandlerFromConfig","taskConfig","handler","handleTaskFailed","error","executedAt","input","job","maxRetries","output","parent","req","retriesConfig","state","taskHandlerResult","taskID","taskSlug","taskStatus","updateJob","payload","logger","err","msg","onFail","log","errorJSON","name","message","stack","errorMessage","push","id","toHexString","completedAt","Date","toISOString","config","jobs","addParentToTaskLog","undefined","waitUntil","complete","totalTried","reachedMaxRetries","hasError","processing","Error","workflowSlug","String","getRunTaskFunction","workflowConfig","isInline","runTask","retries","task","inlineRunner","tasks","length","find","t","slug","retriesConfigFromPropsNormalized","attempts","retriesConfigFromTaskConfigNormalized","finalRetriesConfig","shouldRestore","runner","inlineTask","onSuccess"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/getRunTaskFunction.ts"],"sourcesContent":["import ObjectIdImport from 'bson-objectid'\n\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type {\n RetryConfig,\n RunInlineTaskFunction,\n RunTaskFunction,\n RunTaskFunctions,\n TaskConfig,\n TaskHandler,\n TaskHandlerResult,\n TaskType,\n} from '../../../config/types/taskTypes.js'\nimport type {\n BaseJob,\n RunningJob,\n SingleTaskStatus,\n WorkflowConfig,\n WorkflowTypes,\n} from '../../../config/types/workflowTypes.js'\nimport type { UpdateJobFunction } from './getUpdateJobFunction.js'\n\nimport { calculateBackoffWaitUntil } from './calculateBackoffWaitUntil.js'\nimport { importHandlerPath } from './importHandlerPath.js'\n\nconst ObjectId = (ObjectIdImport.default ||\n ObjectIdImport) as unknown as typeof ObjectIdImport.default\n\n// Helper object type to force being passed by reference\nexport type RunTaskFunctionState = {\n reachedMaxRetries: boolean\n}\n\nasync function getTaskHandlerFromConfig(taskConfig: TaskConfig<string>) {\n let handler: TaskHandler<TaskType>\n\n if (typeof taskConfig.handler === 'function') {\n handler = taskConfig.handler\n } else {\n handler = await importHandlerPath<TaskHandler<TaskType>>(taskConfig.handler)\n }\n return handler\n}\n\nexport async function handleTaskFailed({\n error,\n executedAt,\n input,\n job,\n maxRetries,\n output,\n parent,\n req,\n retriesConfig,\n state,\n taskConfig,\n taskHandlerResult,\n taskID,\n taskSlug,\n taskStatus,\n updateJob,\n}: {\n error?: Error\n executedAt: Date\n input: object\n job: BaseJob\n maxRetries: number\n output: object\n parent?: TaskParent\n req: PayloadRequest\n retriesConfig: number | RetryConfig\n state: RunTaskFunctionState\n taskConfig?: TaskConfig<string>\n taskHandlerResult?: TaskHandlerResult<string>\n taskID: string\n taskSlug: string\n taskStatus: null | SingleTaskStatus<string>\n updateJob: UpdateJobFunction\n}): Promise<never> {\n req.payload.logger.error({ err: error, job, msg: `Error running task ${taskID}`, taskSlug })\n\n if (taskConfig?.onFail) {\n await taskConfig.onFail()\n }\n\n if (!job.log) {\n job.log = []\n }\n const errorJSON = error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : {\n message:\n taskHandlerResult?.state === 'failed'\n ? (taskHandlerResult.errorMessage ?? taskHandlerResult.state)\n : 'failed',\n }\n\n job.log.push({\n id: new ObjectId().toHexString(),\n completedAt: new Date().toISOString(),\n error: errorJSON,\n executedAt: executedAt.toISOString(),\n input,\n output,\n parent: req?.payload?.config?.jobs?.addParentToTaskLog ? parent : undefined,\n state: 'failed',\n taskID,\n taskSlug,\n })\n\n if (job.waitUntil) {\n // Check if waitUntil is in the past\n const waitUntil = new Date(job.waitUntil)\n if (waitUntil < new Date()) {\n // Outdated waitUntil, remove it\n delete job.waitUntil\n }\n }\n\n if (!taskStatus?.complete && (taskStatus?.totalTried ?? 0) >= maxRetries) {\n state.reachedMaxRetries = true\n\n await updateJob({\n error,\n hasError: true,\n log: job.log,\n processing: false,\n waitUntil: job.waitUntil,\n })\n\n throw new Error(\n `Task ${taskSlug} has failed more than the allowed retries in workflow ${job.workflowSlug}${error ? `. Error: ${String(error)}` : ''}`,\n )\n } else {\n // Job will retry. Let's determine when!\n const waitUntil: Date = calculateBackoffWaitUntil({\n retriesConfig,\n totalTried: taskStatus?.totalTried ?? 0,\n })\n\n // Update job's waitUntil only if this waitUntil is later than the current one\n if (!job.waitUntil || waitUntil > new Date(job.waitUntil)) {\n job.waitUntil = waitUntil.toISOString()\n }\n\n await updateJob({\n log: job.log,\n processing: false,\n waitUntil: job.waitUntil,\n })\n throw error ?? new Error('Task failed')\n }\n}\n\nexport type TaskParent = {\n taskID: string\n taskSlug: string\n}\n\nexport const getRunTaskFunction = <TIsInline extends boolean>(\n state: RunTaskFunctionState,\n job: BaseJob,\n workflowConfig: WorkflowConfig<string>,\n req: PayloadRequest,\n isInline: TIsInline,\n updateJob: UpdateJobFunction,\n parent?: TaskParent,\n): TIsInline extends true ? RunInlineTaskFunction : RunTaskFunctions => {\n const runTask: <TTaskSlug extends string>(\n taskSlug: TTaskSlug,\n ) => TTaskSlug extends 'inline' ? RunInlineTaskFunction : RunTaskFunction<TTaskSlug> = (\n taskSlug,\n ) =>\n (async (\n taskID: Parameters<RunInlineTaskFunction>[0],\n {\n input,\n retries,\n task,\n }: Parameters<RunInlineTaskFunction>[1] & Parameters<RunTaskFunction<string>>[1],\n ) => {\n const executedAt = new Date()\n\n let inlineRunner: TaskHandler<TaskType> = null!\n if (isInline) {\n inlineRunner = task as TaskHandler<TaskType>\n }\n\n let taskConfig!: TaskConfig<string>\n if (!isInline) {\n taskConfig = (req.payload.config.jobs.tasks?.length &&\n req.payload.config.jobs.tasks.find((t) => t.slug === taskSlug)) as TaskConfig<string>\n\n if (!taskConfig) {\n throw new Error(`Task ${taskSlug} not found in workflow ${job.workflowSlug}`)\n }\n }\n\n const retriesConfigFromPropsNormalized =\n retries == undefined || retries == null\n ? {}\n : typeof retries === 'number'\n ? { attempts: retries }\n : retries\n const retriesConfigFromTaskConfigNormalized = taskConfig\n ? typeof taskConfig.retries === 'number'\n ? { attempts: taskConfig.retries }\n : taskConfig.retries\n : {}\n\n const finalRetriesConfig: RetryConfig = {\n ...retriesConfigFromTaskConfigNormalized,\n ...retriesConfigFromPropsNormalized, // Retry config from props takes precedence\n }\n\n const taskStatus: null | SingleTaskStatus<string> = job?.taskStatus?.[taskSlug]\n ? job.taskStatus[taskSlug][taskID]!\n : null\n\n // Handle restoration of task if it succeeded in a previous run\n if (taskStatus && taskStatus.complete === true) {\n let shouldRestore = true\n if (finalRetriesConfig?.shouldRestore === false) {\n shouldRestore = false\n } else if (typeof finalRetriesConfig?.shouldRestore === 'function') {\n shouldRestore = await finalRetriesConfig.shouldRestore({\n input: input!,\n job,\n req,\n taskStatus,\n })\n }\n if (shouldRestore) {\n return taskStatus.output\n }\n }\n\n let runner: TaskHandler<TaskType>\n if (isInline) {\n runner = inlineRunner\n } else {\n if (!taskConfig) {\n throw new Error(`Task ${taskSlug} not found in workflow ${job.workflowSlug}`)\n }\n runner = await getTaskHandlerFromConfig(taskConfig)\n }\n\n if (!runner || typeof runner !== 'function') {\n const errorMessage = isInline\n ? `Can't find runner for inline task with ID ${taskID}`\n : `Can't find runner while importing with the path ${typeof workflowConfig.handler === 'string' ? workflowConfig.handler : 'unknown - no string path'} in job type ${job.workflowSlug} for task ${taskSlug}.`\n req.payload.logger.error(errorMessage)\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n log: [\n ...job.log,\n {\n id: new ObjectId().toHexString(),\n completedAt: new Date().toISOString(),\n error: errorMessage,\n executedAt: executedAt.toISOString(),\n parent: req?.payload?.config?.jobs?.addParentToTaskLog ? parent : undefined,\n state: 'failed',\n taskID,\n taskSlug,\n },\n ],\n processing: false,\n })\n\n throw new Error(errorMessage)\n }\n\n let maxRetries: number | undefined = finalRetriesConfig?.attempts\n\n if (maxRetries === undefined || maxRetries === null) {\n // Inherit retries from workflow config, if they are undefined and the workflow config has retries configured\n if (workflowConfig.retries !== undefined && workflowConfig.retries !== null) {\n maxRetries =\n typeof workflowConfig.retries === 'object'\n ? workflowConfig.retries.attempts\n : workflowConfig.retries\n } else {\n maxRetries = 0\n }\n }\n\n let taskHandlerResult: TaskHandlerResult<string>\n let output: object = {}\n\n try {\n taskHandlerResult = await runner({\n inlineTask: getRunTaskFunction(state, job, workflowConfig, req, true, updateJob, {\n taskID,\n taskSlug,\n }),\n input,\n job: job as unknown as RunningJob<WorkflowTypes>, // TODO: Type this better\n req,\n tasks: getRunTaskFunction(state, job, workflowConfig, req, false, updateJob, {\n taskID,\n taskSlug,\n }),\n })\n } catch (err) {\n await handleTaskFailed({\n error: err as Error | undefined,\n executedAt,\n input: input!,\n job,\n maxRetries: maxRetries!,\n output,\n parent,\n req,\n retriesConfig: finalRetriesConfig,\n state,\n taskConfig,\n taskID,\n taskSlug,\n taskStatus,\n updateJob,\n })\n throw new Error('Task failed')\n }\n\n if (taskHandlerResult.state === 'failed') {\n await handleTaskFailed({\n executedAt,\n input: input!,\n job,\n maxRetries: maxRetries!,\n output,\n parent,\n req,\n retriesConfig: finalRetriesConfig,\n state,\n taskConfig,\n taskHandlerResult,\n taskID,\n taskSlug,\n taskStatus,\n updateJob,\n })\n throw new Error('Task failed')\n } else {\n output = taskHandlerResult.output!\n }\n\n if (taskConfig?.onSuccess) {\n await taskConfig.onSuccess()\n }\n\n if (!job.log) {\n job.log = []\n }\n job.log.push({\n id: new ObjectId().toHexString(),\n completedAt: new Date().toISOString(),\n executedAt: executedAt.toISOString(),\n input,\n output,\n parent: req?.payload?.config?.jobs?.addParentToTaskLog ? parent : undefined,\n state: 'succeeded',\n taskID,\n taskSlug,\n })\n\n await updateJob({\n log: job.log,\n })\n\n return output\n }) as any\n\n if (isInline) {\n return runTask('inline') as TIsInline extends true ? RunInlineTaskFunction : RunTaskFunctions\n } else {\n const tasks: RunTaskFunctions = {}\n for (const task of req?.payload?.config?.jobs?.tasks ?? []) {\n tasks[task.slug] = runTask(task.slug) as RunTaskFunction<string>\n }\n return tasks as TIsInline extends true ? RunInlineTaskFunction : RunTaskFunctions\n }\n}\n"],"names":["ObjectIdImport","calculateBackoffWaitUntil","importHandlerPath","ObjectId","default","getTaskHandlerFromConfig","taskConfig","handler","handleTaskFailed","error","executedAt","input","job","maxRetries","output","parent","req","retriesConfig","state","taskHandlerResult","taskID","taskSlug","taskStatus","updateJob","payload","logger","err","msg","onFail","log","errorJSON","name","message","stack","errorMessage","push","id","toHexString","completedAt","Date","toISOString","config","jobs","addParentToTaskLog","undefined","waitUntil","complete","totalTried","reachedMaxRetries","hasError","processing","Error","workflowSlug","String","getRunTaskFunction","workflowConfig","isInline","runTask","retries","task","inlineRunner","tasks","length","find","t","slug","retriesConfigFromPropsNormalized","attempts","retriesConfigFromTaskConfigNormalized","finalRetriesConfig","shouldRestore","runner","inlineTask","onSuccess"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUpdateJobFunction.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJob/getUpdateJobFunction.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getUpdateJobFunction.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJob/getUpdateJobFunction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAA;AAIrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,iBAAiB,CAoCzF"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-strict-ignore
|
|
2
1
|
import { updateJob } from '../../../utilities/updateJob.js';
|
|
3
2
|
export function getUpdateJobFunction(job, req) {
|
|
4
3
|
return async (jobData)=>{
|
|
@@ -23,6 +22,7 @@ export function getUpdateJobFunction(job, req) {
|
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
} else {
|
|
25
|
+
;
|
|
26
26
|
job[key] = updatedJob[key];
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/getUpdateJobFunction.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/getUpdateJobFunction.ts"],"sourcesContent":["import type { PayloadRequest } from '../../../../types/index.js'\nimport type { BaseJob } from '../../../config/types/workflowTypes.js'\n\nimport { updateJob } from '../../../utilities/updateJob.js'\n\nexport type UpdateJobFunction = (jobData: Partial<BaseJob>) => Promise<BaseJob>\n\nexport function getUpdateJobFunction(job: BaseJob, req: PayloadRequest): UpdateJobFunction {\n return async (jobData) => {\n const updatedJob = await updateJob({\n id: job.id,\n data: jobData,\n depth: req.payload.config.jobs.depth,\n disableTransaction: true,\n req,\n })\n\n // Update job object like this to modify the original object - that way, incoming changes (e.g. taskStatus field that will be re-generated through the hook) will be reflected in the calling function\n for (const key in updatedJob) {\n if (key === 'log') {\n if (!job.log) {\n job.log = []\n }\n // Add all new log entries to the original job.log object. Do not delete any existing log entries.\n // Do not update existing log entries, as existing log entries should be immutable.\n for (const logEntry of updatedJob.log) {\n if (!job.log.some((entry) => entry.id === logEntry.id)) {\n job.log.push(logEntry)\n }\n }\n } else {\n ;(job as any)[key] = updatedJob[key as keyof BaseJob]\n }\n }\n\n if ((updatedJob?.error as Record<string, unknown>)?.cancelled) {\n const cancelledError = new Error('Job cancelled') as { cancelled: boolean } & Error\n cancelledError.cancelled = true\n throw cancelledError\n }\n\n return updatedJob!\n }\n}\n"],"names":["updateJob","getUpdateJobFunction","job","req","jobData","updatedJob","id","data","depth","payload","config","jobs","disableTransaction","key","log","logEntry","some","entry","push","error","cancelled","cancelledError","Error"],"mappings":"AAGA,SAASA,SAAS,QAAQ,kCAAiC;AAI3D,OAAO,SAASC,qBAAqBC,GAAY,EAAEC,GAAmB;IACpE,OAAO,OAAOC;QACZ,MAAMC,aAAa,MAAML,UAAU;YACjCM,IAAIJ,IAAII,EAAE;YACVC,MAAMH;YACNI,OAAOL,IAAIM,OAAO,CAACC,MAAM,CAACC,IAAI,CAACH,KAAK;YACpCI,oBAAoB;YACpBT;QACF;QAEA,sMAAsM;QACtM,IAAK,MAAMU,OAAOR,WAAY;YAC5B,IAAIQ,QAAQ,OAAO;gBACjB,IAAI,CAACX,IAAIY,GAAG,EAAE;oBACZZ,IAAIY,GAAG,GAAG,EAAE;gBACd;gBACA,kGAAkG;gBAClG,mFAAmF;gBACnF,KAAK,MAAMC,YAAYV,WAAWS,GAAG,CAAE;oBACrC,IAAI,CAACZ,IAAIY,GAAG,CAACE,IAAI,CAAC,CAACC,QAAUA,MAAMX,EAAE,KAAKS,SAAST,EAAE,GAAG;wBACtDJ,IAAIY,GAAG,CAACI,IAAI,CAACH;oBACf;gBACF;YACF,OAAO;;gBACHb,GAAW,CAACW,IAAI,GAAGR,UAAU,CAACQ,IAAqB;YACvD;QACF;QAEA,IAAKR,YAAYc,OAAmCC,WAAW;YAC7D,MAAMC,iBAAiB,IAAIC,MAAM;YACjCD,eAAeD,SAAS,GAAG;YAC3B,MAAMC;QACR;QAEA,OAAOhB;IACT;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"importHandlerPath.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJob/importHandlerPath.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"importHandlerPath.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJob/importHandlerPath.ts"],"names":[],"mappings":"AAEA,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAkCnE"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-strict-ignore
|
|
2
1
|
import { pathToFileURL } from 'url';
|
|
3
2
|
export async function importHandlerPath(path) {
|
|
4
3
|
let runner;
|
|
@@ -9,7 +8,7 @@ export async function importHandlerPath(path) {
|
|
|
9
8
|
// properly support ESM, like Jest. This is not done to support projects without "type": "module" set
|
|
10
9
|
runnerModule = typeof require === 'function' ? await eval(`require('${runnerPath.replaceAll('\\', '/')}')`) : await eval(`import('${pathToFileURL(runnerPath).href}')`);
|
|
11
10
|
} catch (e) {
|
|
12
|
-
throw new Error(`Error importing job queue handler module for path ${path}. This is an advanced feature that may require a sophisticated build pipeline, especially when using it in production or within Next.js, e.g. by calling opening the /api/payload-jobs/run endpoint. You will have to transpile the handler files separately and ensure they are available in the same location when the job is run. If you're using an endpoint to execute your jobs, it's recommended to define your handlers as functions directly in your Payload Config, or use import paths handlers outside of Next.js. Import Error: \n${e.message}`);
|
|
11
|
+
throw new Error(`Error importing job queue handler module for path ${path}. This is an advanced feature that may require a sophisticated build pipeline, especially when using it in production or within Next.js, e.g. by calling opening the /api/payload-jobs/run endpoint. You will have to transpile the handler files separately and ensure they are available in the same location when the job is run. If you're using an endpoint to execute your jobs, it's recommended to define your handlers as functions directly in your Payload Config, or use import paths handlers outside of Next.js. Import Error: \n${e instanceof Error ? e.message : 'Unknown error'}`);
|
|
13
12
|
}
|
|
14
13
|
// If the path has indicated an #exportName, try to get it
|
|
15
14
|
if (runnerImportName && runnerModule[runnerImportName]) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/importHandlerPath.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/importHandlerPath.ts"],"sourcesContent":["import { pathToFileURL } from 'url'\n\nexport async function importHandlerPath<T>(path: string): Promise<T> {\n let runner!: T\n const [runnerPath, runnerImportName] = path.split('#')\n\n let runnerModule\n try {\n // We need to check for `require` for compatibility with outdated frameworks that do not\n // properly support ESM, like Jest. This is not done to support projects without \"type\": \"module\" set\n runnerModule =\n typeof require === 'function'\n ? await eval(`require('${runnerPath!.replaceAll('\\\\', '/')}')`)\n : await eval(`import('${pathToFileURL(runnerPath!).href}')`)\n } catch (e) {\n throw new Error(\n `Error importing job queue handler module for path ${path}. This is an advanced feature that may require a sophisticated build pipeline, especially when using it in production or within Next.js, e.g. by calling opening the /api/payload-jobs/run endpoint. You will have to transpile the handler files separately and ensure they are available in the same location when the job is run. If you're using an endpoint to execute your jobs, it's recommended to define your handlers as functions directly in your Payload Config, or use import paths handlers outside of Next.js. Import Error: \\n${e instanceof Error ? e.message : 'Unknown error'}`,\n )\n }\n\n // If the path has indicated an #exportName, try to get it\n if (runnerImportName && runnerModule[runnerImportName]) {\n runner = runnerModule[runnerImportName]\n }\n\n // If there is a default export, use it\n if (!runner && runnerModule.default) {\n runner = runnerModule.default\n }\n\n // Finally, use whatever was imported\n if (!runner) {\n runner = runnerModule\n }\n\n return runner\n}\n"],"names":["pathToFileURL","importHandlerPath","path","runner","runnerPath","runnerImportName","split","runnerModule","require","eval","replaceAll","href","e","Error","message","default"],"mappings":"AAAA,SAASA,aAAa,QAAQ,MAAK;AAEnC,OAAO,eAAeC,kBAAqBC,IAAY;IACrD,IAAIC;IACJ,MAAM,CAACC,YAAYC,iBAAiB,GAAGH,KAAKI,KAAK,CAAC;IAElD,IAAIC;IACJ,IAAI;QACF,wFAAwF;QACxF,qGAAqG;QACrGA,eACE,OAAOC,YAAY,aACf,MAAMC,KAAK,CAAC,SAAS,EAAEL,WAAYM,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC,IAC5D,MAAMD,KAAK,CAAC,QAAQ,EAAET,cAAcI,YAAaO,IAAI,CAAC,EAAE,CAAC;IACjE,EAAE,OAAOC,GAAG;QACV,MAAM,IAAIC,MACR,CAAC,kDAAkD,EAAEX,KAAK,+gBAA+gB,EAAEU,aAAaC,QAAQD,EAAEE,OAAO,GAAG,iBAAiB;IAEjoB;IAEA,0DAA0D;IAC1D,IAAIT,oBAAoBE,YAAY,CAACF,iBAAiB,EAAE;QACtDF,SAASI,YAAY,CAACF,iBAAiB;IACzC;IAEA,uCAAuC;IACvC,IAAI,CAACF,UAAUI,aAAaQ,OAAO,EAAE;QACnCZ,SAASI,aAAaQ,OAAO;IAC/B;IAEA,qCAAqC;IACrC,IAAI,CAACZ,QAAQ;QACXA,SAASI;IACX;IAEA,OAAOJ;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJob/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EACV,OAAO,EAEP,cAAc,EACd,eAAe,EACf,aAAa,EACd,MAAM,wCAAwC,CAAA;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAKlE,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,OAAO,CAAA;IACZ,GAAG,EAAE,cAAc,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,cAAc,EAAE,cAAc,CAAC,aAAa,CAAC,CAAA;IAC7C,eAAe,EAAE,eAAe,CAAC,aAAa,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,2BAA2B,GAAG,SAAS,CAAA;AAE5E,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,MAAM,8DAMhB,IAAI,KAAG,OAAO,CAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJob/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EACV,OAAO,EAEP,cAAc,EACd,eAAe,EACf,aAAa,EACd,MAAM,wCAAwC,CAAA;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAKlE,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,OAAO,CAAA;IACZ,GAAG,EAAE,cAAc,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,cAAc,EAAE,cAAc,CAAC,aAAa,CAAC,CAAA;IAC7C,eAAe,EAAE,eAAe,CAAC,aAAa,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,2BAA2B,GAAG,SAAS,CAAA;AAE5E,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,MAAM,8DAMhB,IAAI,KAAG,OAAO,CAAC,YAAY,CA2D7B,CAAA"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-strict-ignore
|
|
2
1
|
import { getRunTaskFunction } from './getRunTaskFunction.js';
|
|
3
2
|
import { handleWorkflowError } from './handleWorkflowError.js';
|
|
4
3
|
export const runJob = async ({ job, req, updateJob, workflowConfig, workflowHandler })=>{
|
|
@@ -15,7 +14,8 @@ export const runJob = async ({ job, req, updateJob, workflowConfig, workflowHand
|
|
|
15
14
|
req,
|
|
16
15
|
tasks: getRunTaskFunction(state, job, workflowConfig, req, false, updateJob)
|
|
17
16
|
});
|
|
18
|
-
} catch (
|
|
17
|
+
} catch (_err) {
|
|
18
|
+
const err = _err;
|
|
19
19
|
const { hasFinalError } = handleWorkflowError({
|
|
20
20
|
error: err,
|
|
21
21
|
job,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJob/index.ts"],"sourcesContent":["import type { APIError } from '../../../../errors/APIError.js'\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type {\n BaseJob,\n RunningJob,\n WorkflowConfig,\n WorkflowHandler,\n WorkflowTypes,\n} from '../../../config/types/workflowTypes.js'\nimport type { RunTaskFunctionState } from './getRunTaskFunction.js'\nimport type { UpdateJobFunction } from './getUpdateJobFunction.js'\n\nimport { getRunTaskFunction } from './getRunTaskFunction.js'\nimport { handleWorkflowError } from './handleWorkflowError.js'\n\ntype Args = {\n job: BaseJob\n req: PayloadRequest\n updateJob: UpdateJobFunction\n workflowConfig: WorkflowConfig<WorkflowTypes>\n workflowHandler: WorkflowHandler<WorkflowTypes>\n}\n\nexport type JobRunStatus = 'error' | 'error-reached-max-retries' | 'success'\n\nexport type RunJobResult = {\n status: JobRunStatus\n}\n\nexport const runJob = async ({\n job,\n req,\n updateJob,\n workflowConfig,\n workflowHandler,\n}: Args): Promise<RunJobResult> => {\n // Object so that we can pass contents by reference, not value.\n // We want any mutations to be reflected in here.\n const state: RunTaskFunctionState = {\n reachedMaxRetries: false,\n }\n\n // Run the job\n try {\n await workflowHandler({\n inlineTask: getRunTaskFunction(state, job, workflowConfig, req, true, updateJob),\n job: job as unknown as RunningJob<WorkflowTypes>, //TODO: Type this better\n req,\n tasks: getRunTaskFunction(state, job, workflowConfig, req, false, updateJob),\n })\n } catch (_err) {\n const err = _err as APIError\n const { hasFinalError } = handleWorkflowError({\n error: err,\n job,\n req,\n state,\n workflowConfig,\n })\n\n const errorJSON = hasFinalError\n ? {\n name: err.name,\n cancelled: Boolean('cancelled' in err && err.cancelled),\n message: err.message,\n stack: err.stack,\n }\n : undefined\n // Tasks update the job if they error - but in case there is an unhandled error (e.g. in the workflow itself, not in a task)\n // we need to ensure the job is updated to reflect the error\n await updateJob({\n error: errorJSON,\n hasError: hasFinalError, // If reached max retries => final error. If hasError is true this job will not be retried\n log: job.log,\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n status: hasFinalError ? 'error-reached-max-retries' : 'error',\n }\n }\n\n // Workflow has completed\n await updateJob({\n completedAt: new Date().toISOString(),\n log: job.log,\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n status: 'success',\n }\n}\n"],"names":["getRunTaskFunction","handleWorkflowError","runJob","job","req","updateJob","workflowConfig","workflowHandler","state","reachedMaxRetries","inlineTask","tasks","_err","err","hasFinalError","error","errorJSON","name","cancelled","Boolean","message","stack","undefined","hasError","log","processing","totalTried","status","completedAt","Date","toISOString"],"mappings":"AAYA,SAASA,kBAAkB,QAAQ,0BAAyB;AAC5D,SAASC,mBAAmB,QAAQ,2BAA0B;AAgB9D,OAAO,MAAMC,SAAS,OAAO,EAC3BC,GAAG,EACHC,GAAG,EACHC,SAAS,EACTC,cAAc,EACdC,eAAe,EACV;IACL,+DAA+D;IAC/D,iDAAiD;IACjD,MAAMC,QAA8B;QAClCC,mBAAmB;IACrB;IAEA,cAAc;IACd,IAAI;QACF,MAAMF,gBAAgB;YACpBG,YAAYV,mBAAmBQ,OAAOL,KAAKG,gBAAgBF,KAAK,MAAMC;YACtEF,KAAKA;YACLC;YACAO,OAAOX,mBAAmBQ,OAAOL,KAAKG,gBAAgBF,KAAK,OAAOC;QACpE;IACF,EAAE,OAAOO,MAAM;QACb,MAAMC,MAAMD;QACZ,MAAM,EAAEE,aAAa,EAAE,GAAGb,oBAAoB;YAC5Cc,OAAOF;YACPV;YACAC;YACAI;YACAF;QACF;QAEA,MAAMU,YAAYF,gBACd;YACEG,MAAMJ,IAAII,IAAI;YACdC,WAAWC,QAAQ,eAAeN,OAAOA,IAAIK,SAAS;YACtDE,SAASP,IAAIO,OAAO;YACpBC,OAAOR,IAAIQ,KAAK;QAClB,IACAC;QACJ,4HAA4H;QAC5H,4DAA4D;QAC5D,MAAMjB,UAAU;YACdU,OAAOC;YACPO,UAAUT;YACVU,KAAKrB,IAAIqB,GAAG;YACZC,YAAY;YACZC,YAAY,AAACvB,CAAAA,IAAIuB,UAAU,IAAI,CAAA,IAAK;QACtC;QAEA,OAAO;YACLC,QAAQb,gBAAgB,8BAA8B;QACxD;IACF;IAEA,yBAAyB;IACzB,MAAMT,UAAU;QACduB,aAAa,IAAIC,OAAOC,WAAW;QACnCN,KAAKrB,IAAIqB,GAAG;QACZC,YAAY;QACZC,YAAY,AAACvB,CAAAA,IAAIuB,UAAU,IAAI,CAAA,IAAK;IACtC;IAEA,OAAO;QACLC,QAAQ;IACV;AACF,EAAC"}
|
|
@@ -2,7 +2,6 @@ import type { SanitizedConfig } from '../config/types.js';
|
|
|
2
2
|
import type { PayloadRequest } from '../types/index.js';
|
|
3
3
|
import type { WithMetadata } from './optionallyAppendMetadata.js';
|
|
4
4
|
import type { UploadEdits } from './types.js';
|
|
5
|
-
export declare const percentToPixel: (value: any, dimension: any) => number;
|
|
6
5
|
type CropImageArgs = {
|
|
7
6
|
cropData: UploadEdits['crop'];
|
|
8
7
|
dimensions: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cropImage.d.ts","sourceRoot":"","sources":["../../src/uploads/cropImage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cropImage.d.ts","sourceRoot":"","sources":["../../src/uploads/cropImage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAQ7C,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC7B,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;IAC/B,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B,CAAA;AACD,wBAAsB,SAAS,CAAC,EAC9B,QAAQ,EACR,UAAU,EACV,IAAI,EAAE,OAAO,EACb,cAAc,EACd,GAAG,EACH,KAAK,EACL,aAAa,EACb,YAAY,GACb,EAAE,aAAa;;;;;;;;;;GA8Df"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// @ts-strict-ignore
|
|
2
1
|
import { optionallyAppendMetadata } from './optionallyAppendMetadata.js';
|
|
3
|
-
|
|
4
|
-
return Math.floor(
|
|
2
|
+
const percentToPixel = (value, dimension)=>{
|
|
3
|
+
return Math.floor(value / 100 * dimension);
|
|
5
4
|
};
|
|
6
5
|
export async function cropImage({ cropData, dimensions, file: fileArg, heightInPixels, req, sharp, widthInPixels, withMetadata }) {
|
|
7
6
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/cropImage.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/cropImage.ts"],"sourcesContent":["import type { SharpOptions } from 'sharp'\n\nimport type { SanitizedConfig } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { WithMetadata } from './optionallyAppendMetadata.js'\nimport type { UploadEdits } from './types.js'\n\nimport { optionallyAppendMetadata } from './optionallyAppendMetadata.js'\n\nconst percentToPixel = (value: number, dimension: number) => {\n return Math.floor((value / 100) * dimension)\n}\n\ntype CropImageArgs = {\n cropData: UploadEdits['crop']\n dimensions: { height: number; width: number }\n file: PayloadRequest['file']\n heightInPixels: number\n req?: PayloadRequest\n sharp: SanitizedConfig['sharp']\n widthInPixels: number\n withMetadata?: WithMetadata\n}\nexport async function cropImage({\n cropData,\n dimensions,\n file: fileArg,\n heightInPixels,\n req,\n sharp,\n widthInPixels,\n withMetadata,\n}: CropImageArgs) {\n try {\n const { x, y } = cropData!\n const file = fileArg!\n\n const fileIsAnimatedType = ['image/avif', 'image/gif', 'image/webp'].includes(file.mimetype)\n\n const sharpOptions: SharpOptions = {}\n\n if (fileIsAnimatedType) {\n sharpOptions.animated = true\n }\n\n const { height: originalHeight, width: originalWidth } = dimensions\n const newWidth = Number(widthInPixels)\n const newHeight = Number(heightInPixels)\n\n const dimensionsChanged = originalWidth !== newWidth || originalHeight !== newHeight\n\n if (!dimensionsChanged) {\n let adjustedHeight = originalHeight\n\n if (fileIsAnimatedType) {\n const animatedMetadata = await sharp(\n file.tempFilePath || file.data,\n sharpOptions,\n ).metadata()\n adjustedHeight = animatedMetadata.pages ? animatedMetadata.height! : originalHeight\n }\n\n return {\n data: file.data,\n info: {\n height: adjustedHeight,\n size: file.size,\n width: originalWidth,\n },\n }\n }\n\n const formattedCropData = {\n height: Number(heightInPixels),\n left: percentToPixel(x, dimensions.width),\n top: percentToPixel(y, dimensions.height),\n width: Number(widthInPixels),\n }\n\n let cropped = sharp(file.tempFilePath || file.data, sharpOptions).extract(formattedCropData)\n\n cropped = await optionallyAppendMetadata({\n req: req!,\n sharpFile: cropped,\n withMetadata: withMetadata!,\n })\n\n return await cropped.toBuffer({\n resolveWithObject: true,\n })\n } catch (error) {\n console.error(`Error cropping image:`, error)\n throw error\n }\n}\n"],"names":["optionallyAppendMetadata","percentToPixel","value","dimension","Math","floor","cropImage","cropData","dimensions","file","fileArg","heightInPixels","req","sharp","widthInPixels","withMetadata","x","y","fileIsAnimatedType","includes","mimetype","sharpOptions","animated","height","originalHeight","width","originalWidth","newWidth","Number","newHeight","dimensionsChanged","adjustedHeight","animatedMetadata","tempFilePath","data","metadata","pages","info","size","formattedCropData","left","top","cropped","extract","sharpFile","toBuffer","resolveWithObject","error","console"],"mappings":"AAOA,SAASA,wBAAwB,QAAQ,gCAA+B;AAExE,MAAMC,iBAAiB,CAACC,OAAeC;IACrC,OAAOC,KAAKC,KAAK,CAAC,AAACH,QAAQ,MAAOC;AACpC;AAYA,OAAO,eAAeG,UAAU,EAC9BC,QAAQ,EACRC,UAAU,EACVC,MAAMC,OAAO,EACbC,cAAc,EACdC,GAAG,EACHC,KAAK,EACLC,aAAa,EACbC,YAAY,EACE;IACd,IAAI;QACF,MAAM,EAAEC,CAAC,EAAEC,CAAC,EAAE,GAAGV;QACjB,MAAME,OAAOC;QAEb,MAAMQ,qBAAqB;YAAC;YAAc;YAAa;SAAa,CAACC,QAAQ,CAACV,KAAKW,QAAQ;QAE3F,MAAMC,eAA6B,CAAC;QAEpC,IAAIH,oBAAoB;YACtBG,aAAaC,QAAQ,GAAG;QAC1B;QAEA,MAAM,EAAEC,QAAQC,cAAc,EAAEC,OAAOC,aAAa,EAAE,GAAGlB;QACzD,MAAMmB,WAAWC,OAAOd;QACxB,MAAMe,YAAYD,OAAOjB;QAEzB,MAAMmB,oBAAoBJ,kBAAkBC,YAAYH,mBAAmBK;QAE3E,IAAI,CAACC,mBAAmB;YACtB,IAAIC,iBAAiBP;YAErB,IAAIN,oBAAoB;gBACtB,MAAMc,mBAAmB,MAAMnB,MAC7BJ,KAAKwB,YAAY,IAAIxB,KAAKyB,IAAI,EAC9Bb,cACAc,QAAQ;gBACVJ,iBAAiBC,iBAAiBI,KAAK,GAAGJ,iBAAiBT,MAAM,GAAIC;YACvE;YAEA,OAAO;gBACLU,MAAMzB,KAAKyB,IAAI;gBACfG,MAAM;oBACJd,QAAQQ;oBACRO,MAAM7B,KAAK6B,IAAI;oBACfb,OAAOC;gBACT;YACF;QACF;QAEA,MAAMa,oBAAoB;YACxBhB,QAAQK,OAAOjB;YACf6B,MAAMvC,eAAee,GAAGR,WAAWiB,KAAK;YACxCgB,KAAKxC,eAAegB,GAAGT,WAAWe,MAAM;YACxCE,OAAOG,OAAOd;QAChB;QAEA,IAAI4B,UAAU7B,MAAMJ,KAAKwB,YAAY,IAAIxB,KAAKyB,IAAI,EAAEb,cAAcsB,OAAO,CAACJ;QAE1EG,UAAU,MAAM1C,yBAAyB;YACvCY,KAAKA;YACLgC,WAAWF;YACX3B,cAAcA;QAChB;QAEA,OAAO,MAAM2B,QAAQG,QAAQ,CAAC;YAC5BC,mBAAmB;QACrB;IACF,EAAE,OAAOC,OAAO;QACdC,QAAQD,KAAK,CAAC,CAAC,qBAAqB,CAAC,EAAEA;QACvC,MAAMA;IACR;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../../../src/uploads/endpoints/getFile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../../../src/uploads/endpoints/getFile.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAS3D,eAAO,MAAM,cAAc,EAAE,cA2F5B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/endpoints/getFile.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/endpoints/getFile.ts"],"sourcesContent":["import type { Stats } from 'fs'\n\nimport { fileTypeFromFile } from 'file-type'\nimport fsPromises from 'fs/promises'\nimport { status as httpStatus } from 'http-status'\nimport path from 'path'\n\nimport type { PayloadHandler } from '../../config/types.js'\n\nimport { APIError } from '../../errors/APIError.js'\nimport { checkFileAccess } from '../../uploads/checkFileAccess.js'\nimport { streamFile } from '../../uploads/fetchAPI-stream-file/index.js'\nimport { getFileTypeFallback } from '../../uploads/getFileTypeFallback.js'\nimport { getRequestCollection } from '../../utilities/getRequestEntity.js'\nimport { headersWithCors } from '../../utilities/headersWithCors.js'\n\nexport const getFileHandler: PayloadHandler = async (req) => {\n const collection = getRequestCollection(req)\n\n const filename = req.routeParams?.filename as string\n\n if (!collection.config.upload) {\n throw new APIError(\n `This collection is not an upload collection: ${collection.config.slug}`,\n httpStatus.BAD_REQUEST,\n )\n }\n\n const accessResult = (await checkFileAccess({\n collection,\n filename,\n req,\n }))!\n\n if (accessResult instanceof Response) {\n return accessResult\n }\n\n if (collection.config.upload.handlers?.length) {\n let customResponse: null | Response | void = null\n for (const handler of collection.config.upload.handlers) {\n customResponse = await handler(req, {\n doc: accessResult,\n params: {\n collection: collection.config.slug,\n filename,\n },\n })\n }\n\n if (customResponse instanceof Response) {\n return customResponse\n }\n }\n\n const fileDir = collection.config.upload?.staticDir || collection.config.slug\n const filePath = path.resolve(`${fileDir}/${filename}`)\n let stats: Stats\n\n try {\n stats = await fsPromises.stat(filePath)\n } catch (err) {\n if ((err as { code?: string }).code === 'ENOENT') {\n req.payload.logger.error(\n `File ${filename} for collection ${collection.config.slug} is missing on the disk. Expected path: ${filePath}`,\n )\n\n // Omit going to the routeError handler by returning response instead of\n // throwing an error to cut down log noise. The response still matches what you get with APIError to not leak details to the user.\n return Response.json(\n {\n errors: [\n {\n message: 'Something went wrong.',\n },\n ],\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: 500,\n },\n )\n }\n\n throw err\n }\n\n const data = streamFile(filePath)\n const fileTypeResult = (await fileTypeFromFile(filePath)) || getFileTypeFallback(filePath)\n\n let headers = new Headers()\n headers.set('Content-Type', fileTypeResult.mime)\n headers.set('Content-Length', stats.size + '')\n headers = collection.config.upload?.modifyResponseHeaders\n ? collection.config.upload.modifyResponseHeaders({ headers })\n : headers\n\n return new Response(data, {\n headers: headersWithCors({\n headers,\n req,\n }),\n status: httpStatus.OK,\n })\n}\n"],"names":["fileTypeFromFile","fsPromises","status","httpStatus","path","APIError","checkFileAccess","streamFile","getFileTypeFallback","getRequestCollection","headersWithCors","getFileHandler","req","collection","filename","routeParams","config","upload","slug","BAD_REQUEST","accessResult","Response","handlers","length","customResponse","handler","doc","params","fileDir","staticDir","filePath","resolve","stats","stat","err","code","payload","logger","error","json","errors","message","headers","Headers","data","fileTypeResult","set","mime","size","modifyResponseHeaders","OK"],"mappings":"AAEA,SAASA,gBAAgB,QAAQ,YAAW;AAC5C,OAAOC,gBAAgB,cAAa;AACpC,SAASC,UAAUC,UAAU,QAAQ,cAAa;AAClD,OAAOC,UAAU,OAAM;AAIvB,SAASC,QAAQ,QAAQ,2BAA0B;AACnD,SAASC,eAAe,QAAQ,mCAAkC;AAClE,SAASC,UAAU,QAAQ,8CAA6C;AACxE,SAASC,mBAAmB,QAAQ,uCAAsC;AAC1E,SAASC,oBAAoB,QAAQ,sCAAqC;AAC1E,SAASC,eAAe,QAAQ,qCAAoC;AAEpE,OAAO,MAAMC,iBAAiC,OAAOC;IACnD,MAAMC,aAAaJ,qBAAqBG;IAExC,MAAME,WAAWF,IAAIG,WAAW,EAAED;IAElC,IAAI,CAACD,WAAWG,MAAM,CAACC,MAAM,EAAE;QAC7B,MAAM,IAAIZ,SACR,CAAC,6CAA6C,EAAEQ,WAAWG,MAAM,CAACE,IAAI,EAAE,EACxEf,WAAWgB,WAAW;IAE1B;IAEA,MAAMC,eAAgB,MAAMd,gBAAgB;QAC1CO;QACAC;QACAF;IACF;IAEA,IAAIQ,wBAAwBC,UAAU;QACpC,OAAOD;IACT;IAEA,IAAIP,WAAWG,MAAM,CAACC,MAAM,CAACK,QAAQ,EAAEC,QAAQ;QAC7C,IAAIC,iBAAyC;QAC7C,KAAK,MAAMC,WAAWZ,WAAWG,MAAM,CAACC,MAAM,CAACK,QAAQ,CAAE;YACvDE,iBAAiB,MAAMC,QAAQb,KAAK;gBAClCc,KAAKN;gBACLO,QAAQ;oBACNd,YAAYA,WAAWG,MAAM,CAACE,IAAI;oBAClCJ;gBACF;YACF;QACF;QAEA,IAAIU,0BAA0BH,UAAU;YACtC,OAAOG;QACT;IACF;IAEA,MAAMI,UAAUf,WAAWG,MAAM,CAACC,MAAM,EAAEY,aAAahB,WAAWG,MAAM,CAACE,IAAI;IAC7E,MAAMY,WAAW1B,KAAK2B,OAAO,CAAC,GAAGH,QAAQ,CAAC,EAAEd,UAAU;IACtD,IAAIkB;IAEJ,IAAI;QACFA,QAAQ,MAAM/B,WAAWgC,IAAI,CAACH;IAChC,EAAE,OAAOI,KAAK;QACZ,IAAI,AAACA,IAA0BC,IAAI,KAAK,UAAU;YAChDvB,IAAIwB,OAAO,CAACC,MAAM,CAACC,KAAK,CACtB,CAAC,KAAK,EAAExB,SAAS,gBAAgB,EAAED,WAAWG,MAAM,CAACE,IAAI,CAAC,wCAAwC,EAAEY,UAAU;YAGhH,wEAAwE;YACxE,kIAAkI;YAClI,OAAOT,SAASkB,IAAI,CAClB;gBACEC,QAAQ;oBACN;wBACEC,SAAS;oBACX;iBACD;YACH,GACA;gBACEC,SAAShC,gBAAgB;oBACvBgC,SAAS,IAAIC;oBACb/B;gBACF;gBACAV,QAAQ;YACV;QAEJ;QAEA,MAAMgC;IACR;IAEA,MAAMU,OAAOrC,WAAWuB;IACxB,MAAMe,iBAAiB,AAAC,MAAM7C,iBAAiB8B,aAActB,oBAAoBsB;IAEjF,IAAIY,UAAU,IAAIC;IAClBD,QAAQI,GAAG,CAAC,gBAAgBD,eAAeE,IAAI;IAC/CL,QAAQI,GAAG,CAAC,kBAAkBd,MAAMgB,IAAI,GAAG;IAC3CN,UAAU7B,WAAWG,MAAM,CAACC,MAAM,EAAEgC,wBAChCpC,WAAWG,MAAM,CAACC,MAAM,CAACgC,qBAAqB,CAAC;QAAEP;IAAQ,KACzDA;IAEJ,OAAO,IAAIrB,SAASuB,MAAM;QACxBF,SAAShC,gBAAgB;YACvBgC;YACA9B;QACF;QACAV,QAAQC,WAAW+C,EAAE;IACvB;AACF,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFileFromURL.d.ts","sourceRoot":"","sources":["../../../src/uploads/endpoints/getFileFromURL.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getFileFromURL.d.ts","sourceRoot":"","sources":["../../../src/uploads/endpoints/getFileFromURL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAc3D,eAAO,MAAM,qBAAqB,EAAE,cAqEnC,CAAA"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-strict-ignore
|
|
2
1
|
import executeAccess from '../../auth/executeAccess.js';
|
|
3
2
|
import { APIError } from '../../errors/APIError.js';
|
|
4
3
|
import { Forbidden } from '../../errors/Forbidden.js';
|
|
@@ -63,8 +62,8 @@ export const getFileFromURLHandler = async (req)=>{
|
|
|
63
62
|
'Content-Type': response.headers.get('content-type') || 'application/octet-stream'
|
|
64
63
|
}
|
|
65
64
|
});
|
|
66
|
-
} catch (
|
|
67
|
-
throw new APIError(`Error fetching file: ${
|
|
65
|
+
} catch (err) {
|
|
66
|
+
throw new APIError(`Error fetching file: ${err instanceof Error ? err.message : 'Unknown error'}`, 500);
|
|
68
67
|
}
|
|
69
68
|
};
|
|
70
69
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/endpoints/getFileFromURL.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/endpoints/getFileFromURL.ts"],"sourcesContent":["import type { PayloadHandler } from '../../config/types.js'\n\nimport executeAccess from '../../auth/executeAccess.js'\nimport { APIError } from '../../errors/APIError.js'\nimport { Forbidden } from '../../errors/Forbidden.js'\nimport { getRequestCollectionWithID } from '../../utilities/getRequestEntity.js'\nimport { isURLAllowed } from '../../utilities/isURLAllowed.js'\n\n// If doc id is provided, it means we are updating the doc\n// /:collectionSlug/paste-url/:doc-id?src=:fileUrl\n\n// If doc id is not provided, it means we are creating a new doc\n// /:collectionSlug/paste-url?src=:fileUrl\n\nexport const getFileFromURLHandler: PayloadHandler = async (req) => {\n const { id, collection } = getRequestCollectionWithID(req, { optionalID: true })\n\n if (!req.user) {\n throw new Forbidden(req.t)\n }\n\n const config = collection?.config\n\n if (id) {\n // updating doc\n const accessResult = await executeAccess({ req }, config.access.update)\n if (!accessResult) {\n throw new Forbidden(req.t)\n }\n } else {\n // creating doc\n const accessResult = await executeAccess({ req }, config.access?.create)\n if (!accessResult) {\n throw new Forbidden(req.t)\n }\n }\n try {\n if (!req.url) {\n throw new APIError('Request URL is missing.', 400)\n }\n\n const { searchParams } = new URL(req.url)\n const src = searchParams.get('src')\n\n if (!src || typeof src !== 'string') {\n throw new APIError('A valid URL string is required.', 400)\n }\n\n const validatedUrl = new URL(src)\n\n if (\n typeof config.upload?.pasteURL === 'object' &&\n !isURLAllowed(validatedUrl.href, config.upload.pasteURL.allowList)\n ) {\n throw new APIError(`The provided URL (${validatedUrl.href}) is not allowed.`, 400)\n }\n\n // Fetch the file with no compression\n const response = await fetch(validatedUrl.href, {\n headers: {\n 'Accept-Encoding': 'identity',\n },\n })\n\n if (!response.ok) {\n throw new APIError(`Failed to fetch file from ${validatedUrl.href}`, response.status)\n }\n\n const decodedFileName = decodeURIComponent(validatedUrl.pathname.split('/').pop() || '')\n\n return new Response(response.body, {\n headers: {\n 'Content-Disposition': `attachment; filename=\"${decodedFileName}\"`,\n 'Content-Length': response.headers.get('content-length') || '',\n 'Content-Type': response.headers.get('content-type') || 'application/octet-stream',\n },\n })\n } catch (err) {\n throw new APIError(\n `Error fetching file: ${err instanceof Error ? err.message : 'Unknown error'}`,\n 500,\n )\n }\n}\n"],"names":["executeAccess","APIError","Forbidden","getRequestCollectionWithID","isURLAllowed","getFileFromURLHandler","req","id","collection","optionalID","user","t","config","accessResult","access","update","create","url","searchParams","URL","src","get","validatedUrl","upload","pasteURL","href","allowList","response","fetch","headers","ok","status","decodedFileName","decodeURIComponent","pathname","split","pop","Response","body","err","Error","message"],"mappings":"AAEA,OAAOA,mBAAmB,8BAA6B;AACvD,SAASC,QAAQ,QAAQ,2BAA0B;AACnD,SAASC,SAAS,QAAQ,4BAA2B;AACrD,SAASC,0BAA0B,QAAQ,sCAAqC;AAChF,SAASC,YAAY,QAAQ,kCAAiC;AAE9D,0DAA0D;AAC1D,kDAAkD;AAElD,gEAAgE;AAChE,0CAA0C;AAE1C,OAAO,MAAMC,wBAAwC,OAAOC;IAC1D,MAAM,EAAEC,EAAE,EAAEC,UAAU,EAAE,GAAGL,2BAA2BG,KAAK;QAAEG,YAAY;IAAK;IAE9E,IAAI,CAACH,IAAII,IAAI,EAAE;QACb,MAAM,IAAIR,UAAUI,IAAIK,CAAC;IAC3B;IAEA,MAAMC,SAASJ,YAAYI;IAE3B,IAAIL,IAAI;QACN,eAAe;QACf,MAAMM,eAAe,MAAMb,cAAc;YAAEM;QAAI,GAAGM,OAAOE,MAAM,CAACC,MAAM;QACtE,IAAI,CAACF,cAAc;YACjB,MAAM,IAAIX,UAAUI,IAAIK,CAAC;QAC3B;IACF,OAAO;QACL,eAAe;QACf,MAAME,eAAe,MAAMb,cAAc;YAAEM;QAAI,GAAGM,OAAOE,MAAM,EAAEE;QACjE,IAAI,CAACH,cAAc;YACjB,MAAM,IAAIX,UAAUI,IAAIK,CAAC;QAC3B;IACF;IACA,IAAI;QACF,IAAI,CAACL,IAAIW,GAAG,EAAE;YACZ,MAAM,IAAIhB,SAAS,2BAA2B;QAChD;QAEA,MAAM,EAAEiB,YAAY,EAAE,GAAG,IAAIC,IAAIb,IAAIW,GAAG;QACxC,MAAMG,MAAMF,aAAaG,GAAG,CAAC;QAE7B,IAAI,CAACD,OAAO,OAAOA,QAAQ,UAAU;YACnC,MAAM,IAAInB,SAAS,mCAAmC;QACxD;QAEA,MAAMqB,eAAe,IAAIH,IAAIC;QAE7B,IACE,OAAOR,OAAOW,MAAM,EAAEC,aAAa,YACnC,CAACpB,aAAakB,aAAaG,IAAI,EAAEb,OAAOW,MAAM,CAACC,QAAQ,CAACE,SAAS,GACjE;YACA,MAAM,IAAIzB,SAAS,CAAC,kBAAkB,EAAEqB,aAAaG,IAAI,CAAC,iBAAiB,CAAC,EAAE;QAChF;QAEA,qCAAqC;QACrC,MAAME,WAAW,MAAMC,MAAMN,aAAaG,IAAI,EAAE;YAC9CI,SAAS;gBACP,mBAAmB;YACrB;QACF;QAEA,IAAI,CAACF,SAASG,EAAE,EAAE;YAChB,MAAM,IAAI7B,SAAS,CAAC,0BAA0B,EAAEqB,aAAaG,IAAI,EAAE,EAAEE,SAASI,MAAM;QACtF;QAEA,MAAMC,kBAAkBC,mBAAmBX,aAAaY,QAAQ,CAACC,KAAK,CAAC,KAAKC,GAAG,MAAM;QAErF,OAAO,IAAIC,SAASV,SAASW,IAAI,EAAE;YACjCT,SAAS;gBACP,uBAAuB,CAAC,sBAAsB,EAAEG,gBAAgB,CAAC,CAAC;gBAClE,kBAAkBL,SAASE,OAAO,CAACR,GAAG,CAAC,qBAAqB;gBAC5D,gBAAgBM,SAASE,OAAO,CAACR,GAAG,CAAC,mBAAmB;YAC1D;QACF;IACF,EAAE,OAAOkB,KAAK;QACZ,MAAM,IAAItC,SACR,CAAC,qBAAqB,EAAEsC,eAAeC,QAAQD,IAAIE,OAAO,GAAG,iBAAiB,EAC9E;IAEJ;AACF,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileFactory.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/fileFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"fileFactory.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/fileFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAoC3C,KAAK,kBAAkB,GAAG;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AACD,KAAK,WAAW,GAAG,CACjB,OAAO,EAAE,kBAAkB,EAC3B,iBAAiB,EAAE,yBAAyB,KACzC,SAAS,CAAA;AACd,eAAO,MAAM,WAAW,EAAE,WA4BzB,CAAA"}
|
|
@@ -11,6 +11,7 @@ import { checkAndMakeDir, debugLog, isFunc, moveFile, promiseCallback, saveBuffe
|
|
|
11
11
|
* which takes two function arguments to make it compatible w/ Promise or Callback APIs
|
|
12
12
|
*/ const moveFromBuffer = (filePath, options, fileUploadOptions)=>(resolve, reject)=>{
|
|
13
13
|
debugLog(fileUploadOptions, `Moving uploaded buffer to ${filePath}`);
|
|
14
|
+
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
|
14
15
|
saveBufferToFile(options.buffer, filePath, promiseCallback(resolve, reject));
|
|
15
16
|
};
|
|
16
17
|
export const fileFactory = (options, fileUploadOptions)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/fileFactory.ts"],"sourcesContent":["import type { FetchAPIFileUploadOptions } from '../../config/types.js'\nimport type { FileShape } from './index.js'\n\nimport {\n checkAndMakeDir,\n debugLog,\n isFunc,\n moveFile,\n promiseCallback,\n saveBufferToFile,\n} from './utilities.js'\n\ntype MoveFile = (\n filePath: string,\n options: FileFactoryOptions,\n fileUploadOptions: FetchAPIFileUploadOptions,\n) => (resolve: () => void, reject: () => void) => void\n\n/**\n * Returns Local function that moves the file to a different location on the filesystem\n * which takes two function arguments to make it compatible w/ Promise or Callback APIs\n */\nconst moveFromTemp: MoveFile = (filePath, options, fileUploadOptions) => (resolve, reject) => {\n debugLog(fileUploadOptions, `Moving temporary file ${options.tempFilePath} to ${filePath}`)\n moveFile(options.tempFilePath, filePath, promiseCallback(resolve, reject))\n}\n\n/**\n * Returns Local function that moves the file from buffer to a different location on the filesystem\n * which takes two function arguments to make it compatible w/ Promise or Callback APIs\n */\nconst moveFromBuffer: MoveFile = (filePath, options, fileUploadOptions) => (resolve, reject) => {\n debugLog(fileUploadOptions, `Moving uploaded buffer to ${filePath}`)\n saveBufferToFile(options.buffer, filePath, promiseCallback(resolve, reject))\n}\n\ntype FileFactoryOptions = {\n buffer: Buffer\n encoding: string\n hash: Buffer | string\n mimetype: string\n name: string\n size: number\n tempFilePath: string\n truncated: boolean\n}\ntype FileFactory = (\n options: FileFactoryOptions,\n fileUploadOptions: FetchAPIFileUploadOptions,\n) => FileShape\nexport const fileFactory: FileFactory = (options, fileUploadOptions) => {\n // see: https://github.com/richardgirges/express-fileupload/issues/14\n // firefox uploads empty file in case of cache miss when f5ing page.\n // resulting in unexpected behavior. if there is no file data, the file is invalid.\n // if (!fileUploadOptions.useTempFiles && !options.buffer.length) return;\n\n // Create and return file object.\n return {\n name: options.name,\n data: options.buffer,\n encoding: options.encoding,\n md5: options.hash,\n mimetype: options.mimetype,\n mv: (filePath: string, callback) => {\n // Define a proper move function.\n const moveFunc = fileUploadOptions.useTempFiles\n ? moveFromTemp(filePath, options, fileUploadOptions)\n : moveFromBuffer(filePath, options, fileUploadOptions)\n // Create a folder for a file.\n checkAndMakeDir(fileUploadOptions, filePath)\n // If callback is passed in, use the callback API, otherwise return a promise.\n const defaultReject = () => undefined\n return isFunc(callback) ? moveFunc(callback, defaultReject) : new Promise(moveFunc)\n },\n size: options.size,\n tempFilePath: options.tempFilePath,\n truncated: options.truncated,\n }\n}\n"],"names":["checkAndMakeDir","debugLog","isFunc","moveFile","promiseCallback","saveBufferToFile","moveFromTemp","filePath","options","fileUploadOptions","resolve","reject","tempFilePath","moveFromBuffer","buffer","fileFactory","name","data","encoding","md5","hash","mimetype","mv","callback","moveFunc","useTempFiles","defaultReject","undefined","Promise","size","truncated"],"mappings":"AAGA,SACEA,eAAe,EACfC,QAAQ,EACRC,MAAM,EACNC,QAAQ,EACRC,eAAe,EACfC,gBAAgB,QACX,iBAAgB;AAQvB;;;CAGC,GACD,MAAMC,eAAyB,CAACC,UAAUC,SAASC,oBAAsB,CAACC,SAASC;QACjFV,SAASQ,mBAAmB,CAAC,sBAAsB,EAAED,QAAQI,YAAY,CAAC,IAAI,EAAEL,UAAU;QAC1FJ,SAASK,QAAQI,YAAY,EAAEL,UAAUH,gBAAgBM,SAASC;IACpE;AAEA;;;CAGC,GACD,MAAME,iBAA2B,CAACN,UAAUC,SAASC,oBAAsB,CAACC,SAASC;QACnFV,SAASQ,mBAAmB,CAAC,0BAA0B,EAAEF,UAAU;
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/fileFactory.ts"],"sourcesContent":["import type { FetchAPIFileUploadOptions } from '../../config/types.js'\nimport type { FileShape } from './index.js'\n\nimport {\n checkAndMakeDir,\n debugLog,\n isFunc,\n moveFile,\n promiseCallback,\n saveBufferToFile,\n} from './utilities.js'\n\ntype MoveFile = (\n filePath: string,\n options: FileFactoryOptions,\n fileUploadOptions: FetchAPIFileUploadOptions,\n) => (resolve: () => void, reject: () => void) => void\n\n/**\n * Returns Local function that moves the file to a different location on the filesystem\n * which takes two function arguments to make it compatible w/ Promise or Callback APIs\n */\nconst moveFromTemp: MoveFile = (filePath, options, fileUploadOptions) => (resolve, reject) => {\n debugLog(fileUploadOptions, `Moving temporary file ${options.tempFilePath} to ${filePath}`)\n moveFile(options.tempFilePath, filePath, promiseCallback(resolve, reject))\n}\n\n/**\n * Returns Local function that moves the file from buffer to a different location on the filesystem\n * which takes two function arguments to make it compatible w/ Promise or Callback APIs\n */\nconst moveFromBuffer: MoveFile = (filePath, options, fileUploadOptions) => (resolve, reject) => {\n debugLog(fileUploadOptions, `Moving uploaded buffer to ${filePath}`)\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n saveBufferToFile(options.buffer, filePath, promiseCallback(resolve, reject))\n}\n\ntype FileFactoryOptions = {\n buffer: Buffer\n encoding: string\n hash: Buffer | string\n mimetype: string\n name: string\n size: number\n tempFilePath: string\n truncated: boolean\n}\ntype FileFactory = (\n options: FileFactoryOptions,\n fileUploadOptions: FetchAPIFileUploadOptions,\n) => FileShape\nexport const fileFactory: FileFactory = (options, fileUploadOptions) => {\n // see: https://github.com/richardgirges/express-fileupload/issues/14\n // firefox uploads empty file in case of cache miss when f5ing page.\n // resulting in unexpected behavior. if there is no file data, the file is invalid.\n // if (!fileUploadOptions.useTempFiles && !options.buffer.length) return;\n\n // Create and return file object.\n return {\n name: options.name,\n data: options.buffer,\n encoding: options.encoding,\n md5: options.hash,\n mimetype: options.mimetype,\n mv: (filePath: string, callback) => {\n // Define a proper move function.\n const moveFunc = fileUploadOptions.useTempFiles\n ? moveFromTemp(filePath, options, fileUploadOptions)\n : moveFromBuffer(filePath, options, fileUploadOptions)\n // Create a folder for a file.\n checkAndMakeDir(fileUploadOptions, filePath)\n // If callback is passed in, use the callback API, otherwise return a promise.\n const defaultReject = () => undefined\n return isFunc(callback) ? moveFunc(callback, defaultReject) : new Promise(moveFunc)\n },\n size: options.size,\n tempFilePath: options.tempFilePath,\n truncated: options.truncated,\n }\n}\n"],"names":["checkAndMakeDir","debugLog","isFunc","moveFile","promiseCallback","saveBufferToFile","moveFromTemp","filePath","options","fileUploadOptions","resolve","reject","tempFilePath","moveFromBuffer","buffer","fileFactory","name","data","encoding","md5","hash","mimetype","mv","callback","moveFunc","useTempFiles","defaultReject","undefined","Promise","size","truncated"],"mappings":"AAGA,SACEA,eAAe,EACfC,QAAQ,EACRC,MAAM,EACNC,QAAQ,EACRC,eAAe,EACfC,gBAAgB,QACX,iBAAgB;AAQvB;;;CAGC,GACD,MAAMC,eAAyB,CAACC,UAAUC,SAASC,oBAAsB,CAACC,SAASC;QACjFV,SAASQ,mBAAmB,CAAC,sBAAsB,EAAED,QAAQI,YAAY,CAAC,IAAI,EAAEL,UAAU;QAC1FJ,SAASK,QAAQI,YAAY,EAAEL,UAAUH,gBAAgBM,SAASC;IACpE;AAEA;;;CAGC,GACD,MAAME,iBAA2B,CAACN,UAAUC,SAASC,oBAAsB,CAACC,SAASC;QACnFV,SAASQ,mBAAmB,CAAC,0BAA0B,EAAEF,UAAU;QACnE,oFAAoF;QACpFF,iBAAiBG,QAAQM,MAAM,EAAEP,UAAUH,gBAAgBM,SAASC;IACtE;AAgBA,OAAO,MAAMI,cAA2B,CAACP,SAASC;IAChD,qEAAqE;IACrE,oEAAoE;IACpE,mFAAmF;IACnF,yEAAyE;IAEzE,iCAAiC;IACjC,OAAO;QACLO,MAAMR,QAAQQ,IAAI;QAClBC,MAAMT,QAAQM,MAAM;QACpBI,UAAUV,QAAQU,QAAQ;QAC1BC,KAAKX,QAAQY,IAAI;QACjBC,UAAUb,QAAQa,QAAQ;QAC1BC,IAAI,CAACf,UAAkBgB;YACrB,iCAAiC;YACjC,MAAMC,WAAWf,kBAAkBgB,YAAY,GAC3CnB,aAAaC,UAAUC,SAASC,qBAChCI,eAAeN,UAAUC,SAASC;YACtC,8BAA8B;YAC9BT,gBAAgBS,mBAAmBF;YACnC,8EAA8E;YAC9E,MAAMmB,gBAAgB,IAAMC;YAC5B,OAAOzB,OAAOqB,YAAYC,SAASD,UAAUG,iBAAiB,IAAIE,QAAQJ;QAC5E;QACAK,MAAMrB,QAAQqB,IAAI;QAClBjB,cAAcJ,QAAQI,YAAY;QAClCkB,WAAWtB,QAAQsB,SAAS;IAC9B;AACF,EAAC"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { FetchAPIFileUploadOptions } from '../../config/types.js';
|
|
2
2
|
import type { FetchAPIFileUploadResponse } from './index.js';
|
|
3
|
+
declare const waitFlushProperty: unique symbol;
|
|
4
|
+
declare global {
|
|
5
|
+
interface Request {
|
|
6
|
+
[waitFlushProperty]?: Promise<any>[];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
3
9
|
type ProcessMultipart = (args: {
|
|
4
10
|
options: FetchAPIFileUploadOptions;
|
|
5
11
|
request: Request;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processMultipart.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"processMultipart.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAS5D,QAAA,MAAM,iBAAiB,eAAuC,CAAA;AAE9D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO;QACf,CAAC,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;KACrC;CACF;AAED,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE;IAC7B,OAAO,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;AACzC,eAAO,MAAM,gBAAgB,EAAE,gBAwM9B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { Readable } from 'stream'\n\nimport Busboy from 'busboy'\nimport { status as httpStatus } from 'http-status'\n\nimport type { FetchAPIFileUploadOptions } from '../../config/types.js'\nimport type { FetchAPIFileUploadResponse } from './index.js'\n\nimport { APIError } from '../../errors/APIError.js'\nimport { fileFactory } from './fileFactory.js'\nimport { memHandler, tempFileHandler } from './handlers.js'\nimport { processNested } from './processNested.js'\nimport { createUploadTimer } from './uploadTimer.js'\nimport { buildFields, debugLog, isFunc, parseFileName } from './utilities.js'\n\nconst waitFlushProperty = Symbol('wait flush property symbol')\n\ntype ProcessMultipart = (args: {\n options: FetchAPIFileUploadOptions\n request: Request\n}) => Promise<FetchAPIFileUploadResponse>\nexport const processMultipart: ProcessMultipart = async ({ options, request }) => {\n let parsingRequest = true\n\n let shouldAbortProccessing = false\n let fileCount = 0\n let filesCompleted = 0\n let allFilesHaveResolved: (value?: unknown) => void\n let failedResolvingFiles: (err: Error) => void\n\n const allFilesComplete = new Promise((res, rej) => {\n allFilesHaveResolved = res\n failedResolvingFiles = rej\n })\n\n const result: FetchAPIFileUploadResponse = {\n fields: undefined!,\n files: undefined!,\n }\n\n const headersObject = {}\n request.headers.forEach((value, name) => {\n headersObject[name] = value\n })\n\n const reader = request.body?.getReader()\n\n const busboy = Busboy({ ...options, headers: headersObject })\n\n function abortAndDestroyFile(file: Readable, err: APIError) {\n file.destroy()\n shouldAbortProccessing = true\n failedResolvingFiles(err)\n }\n\n // Build multipart req.body fields\n busboy.on('field', (field, val) => {\n result.fields = buildFields(result.fields, field, val)\n })\n\n // Build req.files fields\n busboy.on('file', (field, file, info) => {\n fileCount += 1\n // Parse file name(cutting huge names, decoding, etc..).\n const { encoding, filename: name, mimeType: mime } = info\n const filename = parseFileName(options, name)\n\n const inferredMimeType =\n (filename && filename.endsWith('.glb') && 'model/gltf-binary') ||\n (filename && filename.endsWith('.gltf') && 'model/gltf+json') ||\n mime\n\n // Define methods and handlers for upload process.\n const { cleanup, complete, dataHandler, getFilePath, getFileSize, getHash, getWritePromise } =\n options.useTempFiles\n ? tempFileHandler(options, field, filename) // Upload into temporary file.\n : memHandler(options, field, filename) // Upload into RAM.\n\n const writePromise = options.useTempFiles\n ? getWritePromise().catch(() => {\n busboy.end()\n cleanup()\n })\n : getWritePromise()\n\n const uploadTimer = createUploadTimer(options.uploadTimeout, () => {\n return abortAndDestroyFile(\n file,\n new APIError(`Upload timeout for ${field}->${filename}, bytes:${getFileSize()}`),\n )\n })\n\n file.on('limit', () => {\n debugLog(options, `Size limit reached for ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.clear()\n\n if (isFunc(options.limitHandler)) {\n options.limitHandler({ request, size: getFileSize() })\n }\n\n // Return error and cleanup files if abortOnLimit set.\n if (options.abortOnLimit) {\n debugLog(options, `Upload file size limit reached ${field}->${filename}.`)\n cleanup()\n abortAndDestroyFile(\n file,\n new APIError(options.responseOnLimit!, httpStatus.REQUEST_ENTITY_TOO_LARGE, {\n size: getFileSize(),\n }),\n )\n }\n })\n\n file.on('data', (data) => {\n uploadTimer.set()\n dataHandler(data)\n })\n\n file.on('end', () => {\n const size = getFileSize()\n debugLog(options, `Upload finished ${field}->${filename}, bytes:${size}`)\n uploadTimer.clear()\n\n if (!name && size === 0) {\n fileCount -= 1\n if (options.useTempFiles) {\n cleanup()\n debugLog(options, `Removing the empty file ${field}->${filename}`)\n }\n return debugLog(options, `Don't add file instance if original name and size are empty`)\n }\n\n filesCompleted += 1\n\n result.files = buildFields(\n result.files,\n field,\n fileFactory(\n {\n name: filename,\n buffer: complete(),\n encoding,\n hash: getHash(),\n mimetype: inferredMimeType,\n size,\n tempFilePath: getFilePath(),\n truncated: Boolean('truncated' in file && file.truncated) || false,\n },\n options,\n ),\n )\n\n if (!request[waitFlushProperty]) {\n request[waitFlushProperty] = []\n }\n request[waitFlushProperty].push(writePromise)\n\n if (filesCompleted === fileCount) {\n allFilesHaveResolved()\n }\n })\n\n file.on('error', (err) => {\n uploadTimer.clear()\n debugLog(options, `File Error: ${err.message}`)\n cleanup()\n failedResolvingFiles(err)\n })\n\n // Start upload process.\n debugLog(options, `New upload started ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.set()\n })\n\n busboy.on('finish', async () => {\n debugLog(options, `Busboy finished parsing request.`)\n if (options.parseNested) {\n result.fields = processNested(result.fields)\n result.files = processNested(result.files)\n }\n\n if (request[waitFlushProperty]) {\n try {\n await Promise.all(request[waitFlushProperty]).then(() => {\n delete request[waitFlushProperty]\n })\n } catch (err) {\n debugLog(options, `Error waiting for file write promises: ${err}`)\n }\n }\n\n return result\n })\n\n busboy.on(\n 'error',\n (err = new APIError('Busboy error parsing multipart request', httpStatus.BAD_REQUEST)) => {\n debugLog(options, `Busboy error`)\n throw err\n },\n )\n\n while (parsingRequest) {\n const { done, value } = await reader!.read()\n\n if (done) {\n parsingRequest = false\n }\n\n if (value && !shouldAbortProccessing) {\n busboy.write(value)\n }\n }\n\n if (fileCount !== 0) {\n await allFilesComplete.catch((e) => {\n throw e\n })\n }\n\n return result\n}\n"],"names":["Busboy","status","httpStatus","APIError","fileFactory","memHandler","tempFileHandler","processNested","createUploadTimer","buildFields","debugLog","isFunc","parseFileName","waitFlushProperty","Symbol","processMultipart","options","request","parsingRequest","shouldAbortProccessing","fileCount","filesCompleted","allFilesHaveResolved","failedResolvingFiles","allFilesComplete","Promise","res","rej","result","fields","undefined","files","headersObject","headers","forEach","value","name","reader","body","getReader","busboy","abortAndDestroyFile","file","err","destroy","on","field","val","info","encoding","filename","mimeType","mime","inferredMimeType","endsWith","cleanup","complete","dataHandler","getFilePath","getFileSize","getHash","getWritePromise","useTempFiles","writePromise","catch","end","uploadTimer","uploadTimeout","clear","limitHandler","size","abortOnLimit","responseOnLimit","REQUEST_ENTITY_TOO_LARGE","data","set","buffer","hash","mimetype","tempFilePath","truncated","Boolean","push","message","parseNested","all","then","BAD_REQUEST","done","read","write","e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"sourcesContent":["import type { Readable } from 'stream'\n\nimport Busboy from 'busboy'\nimport { status as httpStatus } from 'http-status'\n\nimport type { FetchAPIFileUploadOptions } from '../../config/types.js'\nimport type { FetchAPIFileUploadResponse } from './index.js'\n\nimport { APIError } from '../../errors/APIError.js'\nimport { fileFactory } from './fileFactory.js'\nimport { memHandler, tempFileHandler } from './handlers.js'\nimport { processNested } from './processNested.js'\nimport { createUploadTimer } from './uploadTimer.js'\nimport { buildFields, debugLog, isFunc, parseFileName } from './utilities.js'\n\nconst waitFlushProperty = Symbol('wait flush property symbol')\n\ndeclare global {\n interface Request {\n [waitFlushProperty]?: Promise<any>[]\n }\n}\n\ntype ProcessMultipart = (args: {\n options: FetchAPIFileUploadOptions\n request: Request\n}) => Promise<FetchAPIFileUploadResponse>\nexport const processMultipart: ProcessMultipart = async ({ options, request }) => {\n let parsingRequest = true\n\n let shouldAbortProccessing = false\n let fileCount = 0\n let filesCompleted = 0\n let allFilesHaveResolved: (value?: unknown) => void\n let failedResolvingFiles: (err: Error) => void\n\n const allFilesComplete = new Promise((res, rej) => {\n allFilesHaveResolved = res\n failedResolvingFiles = rej\n })\n\n const result: FetchAPIFileUploadResponse = {\n fields: undefined!,\n files: undefined!,\n }\n\n const headersObject: Record<string, string> = {}\n request.headers.forEach((value, name) => {\n headersObject[name] = value\n })\n\n const reader = request.body?.getReader()\n\n const busboy = Busboy({ ...options, headers: headersObject })\n\n function abortAndDestroyFile(file: Readable, err: APIError) {\n file.destroy()\n shouldAbortProccessing = true\n failedResolvingFiles(err)\n }\n\n // Build multipart req.body fields\n busboy.on('field', (field, val) => {\n result.fields = buildFields(result.fields, field, val)\n })\n\n // Build req.files fields\n busboy.on('file', (field, file, info) => {\n fileCount += 1\n // Parse file name(cutting huge names, decoding, etc..).\n const { encoding, filename: name, mimeType: mime } = info\n const filename = parseFileName(options, name)\n\n const inferredMimeType =\n (filename && filename.endsWith('.glb') && 'model/gltf-binary') ||\n (filename && filename.endsWith('.gltf') && 'model/gltf+json') ||\n mime\n\n // Define methods and handlers for upload process.\n const { cleanup, complete, dataHandler, getFilePath, getFileSize, getHash, getWritePromise } =\n options.useTempFiles\n ? tempFileHandler(options, field, filename) // Upload into temporary file.\n : memHandler(options, field, filename) // Upload into RAM.\n\n const writePromise = options.useTempFiles\n ? getWritePromise().catch(() => {\n busboy.end()\n cleanup()\n })\n : getWritePromise()\n\n const uploadTimer = createUploadTimer(options.uploadTimeout, () => {\n return abortAndDestroyFile(\n file,\n new APIError(`Upload timeout for ${field}->${filename}, bytes:${getFileSize()}`),\n )\n })\n\n file.on('limit', () => {\n debugLog(options, `Size limit reached for ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.clear()\n\n if (isFunc(options.limitHandler)) {\n options.limitHandler({ request, size: getFileSize() })\n }\n\n // Return error and cleanup files if abortOnLimit set.\n if (options.abortOnLimit) {\n debugLog(options, `Upload file size limit reached ${field}->${filename}.`)\n cleanup()\n abortAndDestroyFile(\n file,\n new APIError(options.responseOnLimit!, httpStatus.REQUEST_ENTITY_TOO_LARGE, {\n size: getFileSize(),\n }),\n )\n }\n })\n\n file.on('data', (data) => {\n uploadTimer.set()\n dataHandler(data)\n })\n\n file.on('end', () => {\n const size = getFileSize()\n debugLog(options, `Upload finished ${field}->${filename}, bytes:${size}`)\n uploadTimer.clear()\n\n if (!name && size === 0) {\n fileCount -= 1\n if (options.useTempFiles) {\n cleanup()\n debugLog(options, `Removing the empty file ${field}->${filename}`)\n }\n return debugLog(options, `Don't add file instance if original name and size are empty`)\n }\n\n filesCompleted += 1\n\n result.files = buildFields(\n result.files,\n field,\n fileFactory(\n {\n name: filename,\n buffer: complete(),\n encoding,\n hash: getHash(),\n mimetype: inferredMimeType,\n size,\n tempFilePath: getFilePath(),\n truncated: Boolean('truncated' in file && file.truncated) || false,\n },\n options,\n ),\n )\n\n if (!request[waitFlushProperty]) {\n request[waitFlushProperty] = []\n }\n request[waitFlushProperty].push(writePromise)\n\n if (filesCompleted === fileCount) {\n allFilesHaveResolved()\n }\n })\n\n file.on('error', (err) => {\n uploadTimer.clear()\n debugLog(options, `File Error: ${err.message}`)\n cleanup()\n failedResolvingFiles(err)\n })\n\n // Start upload process.\n debugLog(options, `New upload started ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.set()\n })\n\n busboy.on('finish', async () => {\n debugLog(options, `Busboy finished parsing request.`)\n if (options.parseNested) {\n result.fields = processNested(result.fields)\n result.files = processNested(result.files)\n }\n\n if (request[waitFlushProperty]) {\n try {\n await Promise.all(request[waitFlushProperty]).then(() => {\n delete request[waitFlushProperty]\n })\n } catch (err) {\n debugLog(options, `Error waiting for file write promises: ${err}`)\n }\n }\n\n return result\n })\n\n busboy.on(\n 'error',\n (err = new APIError('Busboy error parsing multipart request', httpStatus.BAD_REQUEST)) => {\n debugLog(options, `Busboy error`)\n throw err\n },\n )\n\n while (parsingRequest) {\n const { done, value } = await reader!.read()\n\n if (done) {\n parsingRequest = false\n }\n\n if (value && !shouldAbortProccessing) {\n busboy.write(value)\n }\n }\n\n if (fileCount !== 0) {\n await allFilesComplete.catch((e) => {\n throw e\n })\n }\n\n return result\n}\n"],"names":["Busboy","status","httpStatus","APIError","fileFactory","memHandler","tempFileHandler","processNested","createUploadTimer","buildFields","debugLog","isFunc","parseFileName","waitFlushProperty","Symbol","processMultipart","options","request","parsingRequest","shouldAbortProccessing","fileCount","filesCompleted","allFilesHaveResolved","failedResolvingFiles","allFilesComplete","Promise","res","rej","result","fields","undefined","files","headersObject","headers","forEach","value","name","reader","body","getReader","busboy","abortAndDestroyFile","file","err","destroy","on","field","val","info","encoding","filename","mimeType","mime","inferredMimeType","endsWith","cleanup","complete","dataHandler","getFilePath","getFileSize","getHash","getWritePromise","useTempFiles","writePromise","catch","end","uploadTimer","uploadTimeout","clear","limitHandler","size","abortOnLimit","responseOnLimit","REQUEST_ENTITY_TOO_LARGE","data","set","buffer","hash","mimetype","tempFilePath","truncated","Boolean","push","message","parseNested","all","then","BAD_REQUEST","done","read","write","e"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const processNested: (data: any) => any;
|
|
1
|
+
export declare const processNested: (data: Record<string, any>) => any;
|
|
2
2
|
//# sourceMappingURL=processNested.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processNested.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processNested.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"processNested.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processNested.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,SAAmB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAiC/D,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/processNested.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/processNested.ts"],"sourcesContent":["import { isSafeFromPollution } from './utilities.js'\n\nexport const processNested = function (data: Record<string, any>) {\n if (!data || data.length < 1) {\n return Object.create(null)\n }\n\n const d = Object.create(null),\n keys = Object.keys(data)\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]!,\n keyParts = key?.replace(new RegExp(/\\[/g), '.').replace(new RegExp(/\\]/g), '').split('.'),\n value = data[key]\n let current = d\n\n for (let index = 0; index < keyParts.length; index++) {\n const k = keyParts[index]!\n\n // Ensure we don't allow prototype pollution\n if (!isSafeFromPollution(current, k)) {\n continue\n }\n\n if (index >= keyParts.length - 1) {\n current[k] = value\n } else {\n if (!current[k]) {\n current[k] = !keyParts[index + 1] ? [] : Object.create(null)\n }\n current = current[k]\n }\n }\n }\n return d\n}\n"],"names":["isSafeFromPollution","processNested","data","length","Object","create","d","keys","i","key","keyParts","replace","RegExp","split","value","current","index","k"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,iBAAgB;AAEpD,OAAO,MAAMC,gBAAgB,SAAUC,IAAyB;IAC9D,IAAI,CAACA,QAAQA,KAAKC,MAAM,GAAG,GAAG;QAC5B,OAAOC,OAAOC,MAAM,CAAC;IACvB;IAEA,MAAMC,IAAIF,OAAOC,MAAM,CAAC,OACtBE,OAAOH,OAAOG,IAAI,CAACL;IAErB,IAAK,IAAIM,IAAI,GAAGA,IAAID,KAAKJ,MAAM,EAAEK,IAAK;QACpC,MAAMC,MAAMF,IAAI,CAACC,EAAE,EACjBE,WAAWD,KAAKE,QAAQ,IAAIC,OAAO,QAAQ,KAAKD,QAAQ,IAAIC,OAAO,QAAQ,IAAIC,MAAM,MACrFC,QAAQZ,IAAI,CAACO,IAAI;QACnB,IAAIM,UAAUT;QAEd,IAAK,IAAIU,QAAQ,GAAGA,QAAQN,SAASP,MAAM,EAAEa,QAAS;YACpD,MAAMC,IAAIP,QAAQ,CAACM,MAAM;YAEzB,4CAA4C;YAC5C,IAAI,CAAChB,oBAAoBe,SAASE,IAAI;gBACpC;YACF;YAEA,IAAID,SAASN,SAASP,MAAM,GAAG,GAAG;gBAChCY,OAAO,CAACE,EAAE,GAAGH;YACf,OAAO;gBACL,IAAI,CAACC,OAAO,CAACE,EAAE,EAAE;oBACfF,OAAO,CAACE,EAAE,GAAG,CAACP,QAAQ,CAACM,QAAQ,EAAE,GAAG,EAAE,GAAGZ,OAAOC,MAAM,CAAC;gBACzD;gBACAU,UAAUA,OAAO,CAACE,EAAE;YACtB;QACF;IACF;IACA,OAAOX;AACT,EAAC"}
|
|
@@ -47,7 +47,7 @@ export declare const moveFile: MoveFile;
|
|
|
47
47
|
* @param {Buffer} buffer - buffer to save to a file.
|
|
48
48
|
* @param {string} filePath - path to a file.
|
|
49
49
|
*/
|
|
50
|
-
export declare const saveBufferToFile: (buffer:
|
|
50
|
+
export declare const saveBufferToFile: (buffer: Buffer, filePath: string, callback: (err?: Error) => void) => void;
|
|
51
51
|
/**
|
|
52
52
|
* Parses filename and extension and returns object {name, extension}.
|
|
53
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/utilities.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/utilities.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAWtE;;GAEG;AACH,eAAO,MAAM,QAAQ,YAAa,yBAAyB,OAAO,MAAM,YAOvE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,YAAY,MAAM,WAG7C,CAAA;AAED,KAAK,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;AACvC,eAAO,MAAM,MAAM,UAAW,GAAG,KAAG,KAAK,IAAI,QAE5C,CAAA;AAQD;;;GAGG;AACH,KAAK,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;AAClG,eAAO,MAAM,eAAe,EAAE,eAU7B,CAAA;AAOD;;GAEG;AACH,KAAK,mBAAmB,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;AAC9D,eAAO,MAAM,mBAAmB,EAAE,mBAQjC,CAAA;AAED;;GAEG;AACH,KAAK,WAAW,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAA;AACpE,eAAO,MAAM,WAAW,EAAE,WAsBzB,CAAA;AAED;;;GAGG;AACH,KAAK,eAAe,GAAG,CAAC,iBAAiB,EAAE,yBAAyB,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;AAClG,eAAO,MAAM,eAAe,EAAE,eAY7B,CAAA;AAED;;GAEG;AACH,KAAK,UAAU,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,CAAA;AAC3E,eAAO,MAAM,UAAU,EAAE,UAAkE,CAAA;AA8B3F;;;GAGG;AACH,KAAK,QAAQ,GAAG,CACd,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,KAC9C,IAAI,CAAA;AACT,eAAO,MAAM,QAAQ,EAAE,QASnB,CAAA;AAEJ;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,WACnB,MAAM,YACJ,MAAM,YACN,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,SAyBhC,CAAA;AA+BD;;GAEG;AACH,KAAK,sBAAsB,GAAG,CAC5B,iBAAiB,EAAE,OAAO,GAAG,MAAM,EACnC,QAAQ,EAAE,MAAM,KACb;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AACD,eAAO,MAAM,sBAAsB,EAAE,sBA4BpC,CAAA;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,CAAC,IAAI,EAAE,yBAAyB,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;AAClF,eAAO,MAAM,aAAa,EAAE,aAyB3B,CAAA"}
|