payload 3.68.0-internal.35482da → 3.68.0-internal.6fa474a
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/auth/strategies/local/incrementLoginAttempts.js +1 -2
- package/dist/auth/strategies/local/incrementLoginAttempts.js.map +1 -1
- package/dist/bin/generateImportMap/iterateFields.js +1 -2
- package/dist/bin/generateImportMap/iterateFields.js.map +1 -1
- package/dist/bin/index.js +2 -4
- package/dist/bin/index.js.map +1 -1
- package/dist/bin/migrate.js +1 -2
- package/dist/bin/migrate.js.map +1 -1
- package/dist/collections/config/defaults.js +1 -2
- package/dist/collections/config/defaults.js.map +1 -1
- package/dist/config/find.js +1 -2
- package/dist/config/find.js.map +1 -1
- package/dist/errors/APIError.js +1 -2
- package/dist/errors/APIError.js.map +1 -1
- package/dist/errors/AuthenticationError.js.map +1 -1
- package/dist/errors/DuplicateCollection.js.map +1 -1
- package/dist/errors/DuplicateFieldName.js.map +1 -1
- package/dist/errors/DuplicateGlobal.js.map +1 -1
- package/dist/errors/ErrorDeletingFile.js.map +1 -1
- package/dist/errors/FileRetrievalError.js.map +1 -1
- package/dist/errors/FileUploadError.js.map +1 -1
- package/dist/errors/Forbidden.js.map +1 -1
- package/dist/errors/InvalidConfiguration.js.map +1 -1
- package/dist/errors/InvalidFieldJoin.js.map +1 -1
- package/dist/errors/InvalidFieldName.js.map +1 -1
- package/dist/errors/InvalidFieldRelationship.js.map +1 -1
- package/dist/errors/InvalidSchema.js.map +1 -1
- package/dist/errors/Locked.js.map +1 -1
- package/dist/errors/LockedAuth.js.map +1 -1
- package/dist/errors/MissingCollectionLabel.js.map +1 -1
- package/dist/errors/MissingEditorProp.js.map +1 -1
- package/dist/errors/MissingFieldInputOptions.js.map +1 -1
- package/dist/errors/MissingFieldType.js.map +1 -1
- package/dist/errors/MissingFile.js.map +1 -1
- package/dist/errors/NotFound.js.map +1 -1
- package/dist/errors/QueryError.js.map +1 -1
- package/dist/errors/ReservedFieldName.js.map +1 -1
- package/dist/errors/TimestampsRequired.js.map +1 -1
- package/dist/errors/UnauthorizedError.js.map +1 -1
- package/dist/errors/UnverifiedEmail.js.map +1 -1
- package/dist/errors/ValidationError.js.map +1 -1
- package/dist/fields/config/client.js +1 -2
- package/dist/fields/config/client.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -10
- package/dist/index.js.map +1 -1
- package/dist/kv/adapters/DatabaseKVAdapter.js.map +1 -1
- package/dist/queues/errors/index.js.map +1 -1
- package/dist/queues/operations/runJobs/index.js +1 -2
- package/dist/queues/operations/runJobs/index.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/utilities.js +1 -2
- package/dist/uploads/fetchAPI-multipart/utilities.js.map +1 -1
- package/dist/uploads/generateFileData.js +4 -8
- package/dist/uploads/generateFileData.js.map +1 -1
- package/dist/utilities/createLocalReq.js.map +1 -1
- package/dist/utilities/deepCopyObject.js.map +1 -1
- package/dist/utilities/findUp.js +4 -8
- package/dist/utilities/findUp.js.map +1 -1
- package/dist/utilities/formatErrors.js.map +1 -1
- package/dist/utilities/getFieldPermissions.spec.js +2 -4
- package/dist/utilities/getFieldPermissions.spec.js.map +1 -1
- package/dist/utilities/parseParams/index.spec.js +5 -10
- package/dist/utilities/parseParams/index.spec.js.map +1 -1
- package/dist/utilities/telemetry/conf/index.js.map +1 -1
- package/dist/utilities/transformColumnPreferences.js +1 -2
- package/dist/utilities/transformColumnPreferences.js.map +1 -1
- package/dist/utilities/unflatten.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/queues/operations/runJobs/index.ts"],"sourcesContent":["import type { Job } from '../../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../../types/index.js'\nimport type { WorkflowJSON } from '../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig, WorkflowHandler } from '../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../localAPI.js'\nimport type { RunJobResult } from './runJob/index.js'\n\nimport { Forbidden } from '../../../errors/Forbidden.js'\nimport { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js'\nimport { jobsCollectionSlug } from '../../config/collection.js'\nimport { JobCancelledError } from '../../errors/index.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\nimport { updateJob, updateJobs } from '../../utilities/updateJob.js'\nimport { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js'\nimport { importHandlerPath } from './runJob/importHandlerPath.js'\nimport { runJob } from './runJob/index.js'\nimport { runJSONJob } from './runJSONJob/index.js'\n\nexport type RunJobsArgs = {\n /**\n * If you want to run jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * ID of the job to run\n */\n id?: number | string\n /**\n * The maximum number of jobs to run in this invocation\n *\n * @default 10\n */\n limit?: number\n overrideAccess?: boolean\n /**\n * Adjust the job processing order\n *\n * FIFO would equal `createdAt` and LIFO would equal `-createdAt`.\n *\n * @default all jobs for all queues will be executed in FIFO order.\n */\n processingOrder?: Sort\n /**\n * If you want to run jobs from a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n /**\n * By default, jobs are run in parallel.\n * If you want to run them in sequence, set this to true.\n */\n sequential?: boolean\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n where?: Where\n}\n\nexport type RunJobsResult = {\n jobStatus?: Record<string, RunJobResult>\n /**\n * If this is false, there for sure are no jobs remaining, regardless of the limit\n */\n noJobsRemaining?: boolean\n /**\n * Out of the jobs that were queried & processed (within the set limit), how many are remaining and retryable?\n */\n remainingJobsFromQueried: number\n}\n\nexport const runJobs = async (args: RunJobsArgs): Promise<RunJobsResult> => {\n const {\n id,\n allQueues = false,\n limit = 10,\n overrideAccess,\n processingOrder,\n queue = 'default',\n req,\n req: {\n payload,\n payload: {\n config: { jobs: jobsConfig },\n },\n },\n sequential,\n silent = false,\n where: whereFromProps,\n } = args\n\n if (!overrideAccess) {\n /**\n * By default, jobsConfig.access.run will be `defaultAccess` which is a function that returns `true` if the user is logged in.\n */\n const accessFn = jobsConfig?.access?.run ?? (() => true)\n const hasAccess = await accessFn({ req })\n if (!hasAccess) {\n throw new Forbidden(req.t)\n }\n }\n const and: Where[] = [\n {\n completedAt: {\n exists: false,\n },\n },\n {\n hasError: {\n not_equals: true,\n },\n },\n {\n processing: {\n equals: false,\n },\n },\n {\n or: [\n {\n waitUntil: {\n exists: false,\n },\n },\n {\n waitUntil: {\n less_than: getCurrentDate().toISOString(),\n },\n },\n ],\n },\n ]\n\n if (allQueues !== true) {\n and.push({\n queue: {\n equals: queue ?? 'default',\n },\n })\n }\n\n if (whereFromProps) {\n and.push(whereFromProps)\n }\n\n // Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of\n // the same job being picked up by another worker\n let jobs: Job[] = []\n\n if (id) {\n // Only one job to run\n const job = await updateJob({\n id,\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n req,\n returning: true,\n })\n if (job) {\n jobs = [job]\n }\n } else {\n let defaultProcessingOrder: Sort =\n payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt'\n\n const processingOrderConfig = jobsConfig.processingOrder\n if (typeof processingOrderConfig === 'function') {\n defaultProcessingOrder = await processingOrderConfig(args)\n } else if (typeof processingOrderConfig === 'object' && !Array.isArray(processingOrderConfig)) {\n if (\n !allQueues &&\n queue &&\n processingOrderConfig.queues &&\n processingOrderConfig.queues[queue]\n ) {\n defaultProcessingOrder = processingOrderConfig.queues[queue]\n } else if (processingOrderConfig.default) {\n defaultProcessingOrder = processingOrderConfig.default\n }\n } else if (typeof processingOrderConfig === 'string') {\n defaultProcessingOrder = processingOrderConfig\n }\n const updatedDocs = await updateJobs({\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n limit,\n req,\n returning: true,\n sort: processingOrder ?? defaultProcessingOrder,\n where: { and },\n })\n\n if (updatedDocs) {\n jobs = updatedDocs\n }\n }\n\n /**\n * Just for logging purposes, we want to know how many jobs are new and how many are existing (= already been tried).\n * This is only for logs - in the end we still want to run all jobs, regardless of whether they are new or existing.\n */\n const { existingJobs, newJobs } = jobs.reduce(\n (acc, job) => {\n if (job.totalTried > 0) {\n acc.existingJobs.push(job)\n } else {\n acc.newJobs.push(job)\n }\n return acc\n },\n { existingJobs: [] as Job[], newJobs: [] as Job[] },\n )\n\n if (!jobs.length) {\n return {\n noJobsRemaining: true,\n remainingJobsFromQueried: 0,\n }\n }\n\n if (!silent || (typeof silent === 'object' && !silent.info)) {\n payload.logger.info({\n msg: `Running ${jobs.length} jobs.`,\n new: newJobs?.length,\n retrying: existingJobs?.length,\n })\n }\n\n const successfullyCompletedJobs: (number | string)[] = []\n\n const runSingleJob = async (\n job: Job,\n ): Promise<{\n id: number | string\n result: RunJobResult\n }> => {\n if (!job.workflowSlug && !job.taskSlug) {\n throw new Error('Job must have either a workflowSlug or a taskSlug')\n }\n const jobReq = isolateObjectProperty(req, 'transactionID')\n\n const workflowConfig: WorkflowConfig =\n job.workflowSlug && jobsConfig.workflows?.length\n ? jobsConfig.workflows.find(({ slug }) => slug === job.workflowSlug)!\n : {\n slug: 'singleTask',\n handler: async ({ job, tasks }) => {\n await tasks[job.taskSlug as string]!('1', {\n input: job.input,\n })\n },\n }\n\n if (!workflowConfig) {\n return {\n id: job.id,\n result: {\n status: 'error',\n },\n } // Skip jobs with no workflow configuration\n }\n\n try {\n const updateJob = getUpdateJobFunction(job, jobReq)\n\n // the runner will either be passed to the config\n // OR it will be a path, which we will need to import via eval to avoid\n // Next.js compiler dynamic import expression errors\n let workflowHandler: WorkflowHandler | WorkflowJSON\n if (\n typeof workflowConfig.handler === 'function' ||\n (typeof workflowConfig.handler === 'object' && Array.isArray(workflowConfig.handler))\n ) {\n workflowHandler = workflowConfig.handler\n } else {\n workflowHandler = await importHandlerPath<typeof workflowHandler>(workflowConfig.handler)\n\n if (!workflowHandler) {\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n const errorMessage = `Can't find runner while importing with the path ${workflowConfig.handler} in job type ${jobLabel}.`\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error(errorMessage)\n }\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n processing: false,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n }\n\n if (typeof workflowHandler === 'function') {\n const result = await runJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n } else {\n const result = await runJSONJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n }\n } catch (error) {\n if (error instanceof JobCancelledError) {\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n throw error\n }\n }\n\n let resultsArray: { id: number | string; result: RunJobResult }[] = []\n if (sequential) {\n for (const job of jobs) {\n const result = await runSingleJob(job)\n if (result) {\n resultsArray.push(result)\n }\n }\n } else {\n const jobPromises = jobs.map(runSingleJob)\n resultsArray = (await Promise.all(jobPromises)) as {\n id: number | string\n result: RunJobResult\n }[]\n }\n\n if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {\n try {\n if (jobsConfig.runHooks) {\n await payload.delete({\n collection: jobsCollectionSlug,\n depth: 0, // can be 0 since we're not returning anything\n disableTransaction: true,\n where: { id: { in: successfullyCompletedJobs } },\n })\n } else {\n await payload.db.deleteMany({\n collection: jobsCollectionSlug,\n where: { id: { in: successfullyCompletedJobs } },\n })\n }\n } catch (err) {\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n err,\n msg: `Failed to delete jobs ${successfullyCompletedJobs.join(', ')} on complete`,\n })\n }\n }\n }\n\n const resultsObject: RunJobsResult['jobStatus'] = resultsArray.reduce(\n (acc, cur) => {\n if (cur !== null) {\n // Check if there's a valid result to include\n acc[cur.id] = cur.result\n }\n return acc\n },\n {} as Record<string, RunJobResult>,\n )\n\n let remainingJobsFromQueried = 0\n for (const jobID in resultsObject) {\n const jobResult = resultsObject[jobID]\n if (jobResult?.status === 'error') {\n remainingJobsFromQueried++ // Can be retried\n }\n }\n\n return {\n jobStatus: resultsObject,\n remainingJobsFromQueried,\n }\n}\n"],"names":["Forbidden","isolateObjectProperty","jobsCollectionSlug","JobCancelledError","getCurrentDate","updateJob","updateJobs","getUpdateJobFunction","importHandlerPath","runJob","runJSONJob","runJobs","args","id","allQueues","limit","overrideAccess","processingOrder","queue","req","payload","config","jobs","jobsConfig","sequential","silent","where","whereFromProps","accessFn","access","run","hasAccess","t","and","completedAt","exists","hasError","not_equals","processing","equals","or","waitUntil","less_than","toISOString","push","job","data","depth","disableTransaction","returning","defaultProcessingOrder","collections","defaultSort","processingOrderConfig","Array","isArray","queues","default","updatedDocs","sort","existingJobs","newJobs","reduce","acc","totalTried","length","noJobsRemaining","remainingJobsFromQueried","info","logger","msg","new","retrying","successfullyCompletedJobs","runSingleJob","workflowSlug","taskSlug","Error","jobReq","workflowConfig","workflows","find","slug","handler","tasks","input","result","status","workflowHandler","jobLabel","errorMessage","error","resultsArray","jobPromises","map","Promise","all","deleteJobOnComplete","runHooks","delete","collection","in","db","deleteMany","err","join","resultsObject","cur","jobID","jobResult","jobStatus"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/queues/operations/runJobs/index.ts"],"sourcesContent":["import type { Job } from '../../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../../types/index.js'\nimport type { WorkflowJSON } from '../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig, WorkflowHandler } from '../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../localAPI.js'\nimport type { RunJobResult } from './runJob/index.js'\n\nimport { Forbidden } from '../../../errors/Forbidden.js'\nimport { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js'\nimport { jobsCollectionSlug } from '../../config/collection.js'\nimport { JobCancelledError } from '../../errors/index.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\nimport { updateJob, updateJobs } from '../../utilities/updateJob.js'\nimport { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js'\nimport { importHandlerPath } from './runJob/importHandlerPath.js'\nimport { runJob } from './runJob/index.js'\nimport { runJSONJob } from './runJSONJob/index.js'\n\nexport type RunJobsArgs = {\n /**\n * If you want to run jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * ID of the job to run\n */\n id?: number | string\n /**\n * The maximum number of jobs to run in this invocation\n *\n * @default 10\n */\n limit?: number\n overrideAccess?: boolean\n /**\n * Adjust the job processing order\n *\n * FIFO would equal `createdAt` and LIFO would equal `-createdAt`.\n *\n * @default all jobs for all queues will be executed in FIFO order.\n */\n processingOrder?: Sort\n /**\n * If you want to run jobs from a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n /**\n * By default, jobs are run in parallel.\n * If you want to run them in sequence, set this to true.\n */\n sequential?: boolean\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n where?: Where\n}\n\nexport type RunJobsResult = {\n jobStatus?: Record<string, RunJobResult>\n /**\n * If this is false, there for sure are no jobs remaining, regardless of the limit\n */\n noJobsRemaining?: boolean\n /**\n * Out of the jobs that were queried & processed (within the set limit), how many are remaining and retryable?\n */\n remainingJobsFromQueried: number\n}\n\nexport const runJobs = async (args: RunJobsArgs): Promise<RunJobsResult> => {\n const {\n id,\n allQueues = false,\n limit = 10,\n overrideAccess,\n processingOrder,\n queue = 'default',\n req,\n req: {\n payload,\n payload: {\n config: { jobs: jobsConfig },\n },\n },\n sequential,\n silent = false,\n where: whereFromProps,\n } = args\n\n if (!overrideAccess) {\n /**\n * By default, jobsConfig.access.run will be `defaultAccess` which is a function that returns `true` if the user is logged in.\n */\n const accessFn = jobsConfig?.access?.run ?? (() => true)\n const hasAccess = await accessFn({ req })\n if (!hasAccess) {\n throw new Forbidden(req.t)\n }\n }\n const and: Where[] = [\n {\n completedAt: {\n exists: false,\n },\n },\n {\n hasError: {\n not_equals: true,\n },\n },\n {\n processing: {\n equals: false,\n },\n },\n {\n or: [\n {\n waitUntil: {\n exists: false,\n },\n },\n {\n waitUntil: {\n less_than: getCurrentDate().toISOString(),\n },\n },\n ],\n },\n ]\n\n if (allQueues !== true) {\n and.push({\n queue: {\n equals: queue ?? 'default',\n },\n })\n }\n\n if (whereFromProps) {\n and.push(whereFromProps)\n }\n\n // Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of\n // the same job being picked up by another worker\n let jobs: Job[] = []\n\n if (id) {\n // Only one job to run\n const job = await updateJob({\n id,\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n req,\n returning: true,\n })\n if (job) {\n jobs = [job]\n }\n } else {\n let defaultProcessingOrder: Sort =\n payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt'\n\n const processingOrderConfig = jobsConfig.processingOrder\n if (typeof processingOrderConfig === 'function') {\n defaultProcessingOrder = await processingOrderConfig(args)\n } else if (typeof processingOrderConfig === 'object' && !Array.isArray(processingOrderConfig)) {\n if (\n !allQueues &&\n queue &&\n processingOrderConfig.queues &&\n processingOrderConfig.queues[queue]\n ) {\n defaultProcessingOrder = processingOrderConfig.queues[queue]\n } else if (processingOrderConfig.default) {\n defaultProcessingOrder = processingOrderConfig.default\n }\n } else if (typeof processingOrderConfig === 'string') {\n defaultProcessingOrder = processingOrderConfig\n }\n const updatedDocs = await updateJobs({\n data: {\n processing: true,\n },\n depth: jobsConfig.depth,\n disableTransaction: true,\n limit,\n req,\n returning: true,\n sort: processingOrder ?? defaultProcessingOrder,\n where: { and },\n })\n\n if (updatedDocs) {\n jobs = updatedDocs\n }\n }\n\n /**\n * Just for logging purposes, we want to know how many jobs are new and how many are existing (= already been tried).\n * This is only for logs - in the end we still want to run all jobs, regardless of whether they are new or existing.\n */\n const { existingJobs, newJobs } = jobs.reduce(\n (acc, job) => {\n if (job.totalTried > 0) {\n acc.existingJobs.push(job)\n } else {\n acc.newJobs.push(job)\n }\n return acc\n },\n { existingJobs: [] as Job[], newJobs: [] as Job[] },\n )\n\n if (!jobs.length) {\n return {\n noJobsRemaining: true,\n remainingJobsFromQueried: 0,\n }\n }\n\n if (!silent || (typeof silent === 'object' && !silent.info)) {\n payload.logger.info({\n msg: `Running ${jobs.length} jobs.`,\n new: newJobs?.length,\n retrying: existingJobs?.length,\n })\n }\n\n const successfullyCompletedJobs: (number | string)[] = []\n\n const runSingleJob = async (\n job: Job,\n ): Promise<{\n id: number | string\n result: RunJobResult\n }> => {\n if (!job.workflowSlug && !job.taskSlug) {\n throw new Error('Job must have either a workflowSlug or a taskSlug')\n }\n const jobReq = isolateObjectProperty(req, 'transactionID')\n\n const workflowConfig: WorkflowConfig =\n job.workflowSlug && jobsConfig.workflows?.length\n ? jobsConfig.workflows.find(({ slug }) => slug === job.workflowSlug)!\n : {\n slug: 'singleTask',\n handler: async ({ job, tasks }) => {\n await tasks[job.taskSlug as string]!('1', {\n input: job.input,\n })\n },\n }\n\n if (!workflowConfig) {\n return {\n id: job.id,\n result: {\n status: 'error',\n },\n } // Skip jobs with no workflow configuration\n }\n\n try {\n const updateJob = getUpdateJobFunction(job, jobReq)\n\n // the runner will either be passed to the config\n // OR it will be a path, which we will need to import via eval to avoid\n // Next.js compiler dynamic import expression errors\n let workflowHandler: WorkflowHandler | WorkflowJSON\n if (\n typeof workflowConfig.handler === 'function' ||\n (typeof workflowConfig.handler === 'object' && Array.isArray(workflowConfig.handler))\n ) {\n workflowHandler = workflowConfig.handler\n } else {\n workflowHandler = await importHandlerPath<typeof workflowHandler>(workflowConfig.handler)\n\n if (!workflowHandler) {\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n const errorMessage = `Can't find runner while importing with the path ${workflowConfig.handler} in job type ${jobLabel}.`\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error(errorMessage)\n }\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n processing: false,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n }\n\n if (typeof workflowHandler === 'function') {\n const result = await runJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n } else {\n const result = await runJSONJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n }\n } catch (error) {\n if (error instanceof JobCancelledError) {\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n throw error\n }\n }\n\n let resultsArray: { id: number | string; result: RunJobResult }[] = []\n if (sequential) {\n for (const job of jobs) {\n const result = await runSingleJob(job)\n if (result) {\n resultsArray.push(result)\n }\n }\n } else {\n const jobPromises = jobs.map(runSingleJob)\n resultsArray = (await Promise.all(jobPromises)) as {\n id: number | string\n result: RunJobResult\n }[]\n }\n\n if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {\n try {\n if (jobsConfig.runHooks) {\n await payload.delete({\n collection: jobsCollectionSlug,\n depth: 0, // can be 0 since we're not returning anything\n disableTransaction: true,\n where: { id: { in: successfullyCompletedJobs } },\n })\n } else {\n await payload.db.deleteMany({\n collection: jobsCollectionSlug,\n where: { id: { in: successfullyCompletedJobs } },\n })\n }\n } catch (err) {\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n err,\n msg: `Failed to delete jobs ${successfullyCompletedJobs.join(', ')} on complete`,\n })\n }\n }\n }\n\n const resultsObject: RunJobsResult['jobStatus'] = resultsArray.reduce(\n (acc, cur) => {\n if (cur !== null) {\n // Check if there's a valid result to include\n acc[cur.id] = cur.result\n }\n return acc\n },\n {} as Record<string, RunJobResult>,\n )\n\n let remainingJobsFromQueried = 0\n for (const jobID in resultsObject) {\n const jobResult = resultsObject[jobID]\n if (jobResult?.status === 'error') {\n remainingJobsFromQueried++ // Can be retried\n }\n }\n\n return {\n jobStatus: resultsObject,\n remainingJobsFromQueried,\n }\n}\n"],"names":["Forbidden","isolateObjectProperty","jobsCollectionSlug","JobCancelledError","getCurrentDate","updateJob","updateJobs","getUpdateJobFunction","importHandlerPath","runJob","runJSONJob","runJobs","args","id","allQueues","limit","overrideAccess","processingOrder","queue","req","payload","config","jobs","jobsConfig","sequential","silent","where","whereFromProps","accessFn","access","run","hasAccess","t","and","completedAt","exists","hasError","not_equals","processing","equals","or","waitUntil","less_than","toISOString","push","job","data","depth","disableTransaction","returning","defaultProcessingOrder","collections","defaultSort","processingOrderConfig","Array","isArray","queues","default","updatedDocs","sort","existingJobs","newJobs","reduce","acc","totalTried","length","noJobsRemaining","remainingJobsFromQueried","info","logger","msg","new","retrying","successfullyCompletedJobs","runSingleJob","workflowSlug","taskSlug","Error","jobReq","workflowConfig","workflows","find","slug","handler","tasks","input","result","status","workflowHandler","jobLabel","errorMessage","error","resultsArray","jobPromises","map","Promise","all","deleteJobOnComplete","runHooks","delete","collection","in","db","deleteMany","err","join","resultsObject","cur","jobID","jobResult","jobStatus"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/utilities.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { Readable } from 'stream'\n\nimport type { FetchAPIFileUploadOptions } from '../../config/types.js'\n\n// Parameters for safe file name parsing.\nconst SAFE_FILE_NAME_REGEX = /[^\\w-]/g\nconst MAX_EXTENSION_LENGTH = 3\n\n// Parameters to generate unique temporary file names:\nconst TEMP_COUNTER_MAX = 65536\nconst TEMP_PREFIX = 'tmp'\nlet tempCounter = 0\n\n/**\n * Logs message to console if options.debug option set to true.\n */\nexport const debugLog = (options: FetchAPIFileUploadOptions, msg: string) => {\n const opts = options || {}\n if (!opts.debug) {\n return false\n }\n console.log(`Next-file-upload: ${msg}`) // eslint-disable-line\n return true\n}\n\n/**\n * Generates unique temporary file name. e.g. tmp-5000-156788789789.\n */\nexport const getTempFilename = (prefix: string = TEMP_PREFIX) => {\n tempCounter = tempCounter >= TEMP_COUNTER_MAX ? 1 : tempCounter + 1\n return `${prefix}-${tempCounter}-${Date.now()}`\n}\n\ntype FuncType = (...args: any[]) => any\nexport const isFunc = (value: any): value is FuncType => {\n return typeof value === 'function'\n}\n\n/**\n * Set errorFunc to the same value as successFunc for callback mode.\n */\ntype ErrorFunc = (resolve: () => void, reject: (err: Error) => void) => (err: Error) => void\nconst errorFunc: ErrorFunc = (resolve, reject) => (isFunc(reject) ? reject : resolve)\n\n/**\n * Return a callback function for promise resole/reject args.\n * Ensures that callback is called only once.\n */\ntype PromiseCallback = (resolve: () => void, reject: (err: Error) => void) => (err: Error) => void\nexport const promiseCallback: PromiseCallback = (resolve, reject) => {\n let hasFired = false\n return (err: Error) => {\n if (hasFired) {\n return\n }\n\n hasFired = true\n return err ? errorFunc(resolve, reject)(err) : resolve()\n }\n}\n\n// The default prototypes for both objects and arrays.\n// Used by isSafeFromPollution\nconst OBJECT_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Object.prototype)\nconst ARRAY_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Array.prototype)\n\n/**\n * Determines whether a key insertion into an object could result in a prototype pollution\n */\ntype IsSafeFromPollution = (base: any, key: string) => boolean\nexport const isSafeFromPollution: IsSafeFromPollution = (base, key) => {\n // We perform an instanceof check instead of Array.isArray as the former is more\n // permissive for cases in which the object as an Array prototype but was not constructed\n // via an Array constructor or literal.\n const TOUCHES_ARRAY_PROTOTYPE = base instanceof Array && ARRAY_PROTOTYPE_KEYS.includes(key)\n const TOUCHES_OBJECT_PROTOTYPE = OBJECT_PROTOTYPE_KEYS.includes(key)\n\n return !TOUCHES_ARRAY_PROTOTYPE && !TOUCHES_OBJECT_PROTOTYPE\n}\n\n/**\n * Build request field/file objects to return\n */\ntype BuildFields = (instance: any, field: string, value: any) => any\nexport const buildFields: BuildFields = (instance, field, value) => {\n // Do nothing if value is not set.\n if (value === null || value === undefined) {\n return instance\n }\n instance = instance || Object.create(null)\n\n if (!isSafeFromPollution(instance, field)) {\n return instance\n }\n // Non-array fields\n if (!instance[field]) {\n instance[field] = value\n return instance\n }\n // Array fields\n if (instance[field] instanceof Array) {\n instance[field].push(value)\n } else {\n instance[field] = [instance[field], value]\n }\n return instance\n}\n\n/**\n * Creates a folder if it does not exist\n * for file specified in the path variable\n */\ntype CheckAndMakeDir = (fileUploadOptions: FetchAPIFileUploadOptions, filePath: string) => boolean\nexport const checkAndMakeDir: CheckAndMakeDir = (fileUploadOptions, filePath) => {\n if (!fileUploadOptions.createParentPath) {\n return false\n }\n // Check whether folder for the file exists.\n const parentPath = path.dirname(filePath)\n // Create folder if it doesn't exist.\n if (!fs.existsSync(parentPath)) {\n fs.mkdirSync(parentPath, { recursive: true })\n }\n // Checks folder again and return a results.\n return fs.existsSync(parentPath)\n}\n\n/**\n * Delete a file.\n */\ntype DeleteFile = (filePath: string, callback: (args: any) => void) => void\nexport const deleteFile: DeleteFile = (filePath, callback) => fs.unlink(filePath, callback)\n\n/**\n * Copy file via streams\n */\ntype CopyFile = (src: string, dst: string, callback: (err: Error) => void) => void\nconst copyFile: CopyFile = (src, dst, callback) => {\n // cbCalled flag and runCb helps to run cb only once.\n let cbCalled = false\n const runCb = (err?: Error) => {\n if (cbCalled) {\n return\n }\n cbCalled = true\n callback(err!)\n }\n // Create read stream\n const readable = fs.createReadStream(src)\n readable.on('error', runCb)\n // Create write stream\n const writable = fs.createWriteStream(dst)\n writable.on('error', (err: Error) => {\n readable.destroy()\n runCb(err)\n })\n writable.on('close', () => runCb())\n // Copy file via piping streams.\n readable.pipe(writable)\n}\n\n/**\n * moveFile: moves the file from src to dst.\n * Firstly trying to rename the file if no luck copying it to dst and then deleting src.\n */\ntype MoveFile = (\n src: string,\n dst: string,\n callback: (err: Error, renamed?: boolean) => void,\n) => void\nexport const moveFile: MoveFile = (src, dst, callback) =>\n fs.rename(src, dst, (err) => {\n if (err) {\n // Try to copy file if rename didn't work.\n copyFile(src, dst, (cpErr) => (cpErr ? callback(cpErr) : deleteFile(src, callback)))\n return\n }\n // File was renamed successfully: Add true to the callback to indicate that.\n callback(null!, true)\n })\n\n/**\n * Save buffer data to a file.\n * @param {Buffer} buffer - buffer to save to a file.\n * @param {string} filePath - path to a file.\n */\nexport const saveBufferToFile = (\n buffer: Buffer,\n filePath: string,\n callback: (err?: Error) => void,\n) => {\n if (!Buffer.isBuffer(buffer)) {\n return callback(new Error('buffer variable should be type of Buffer!'))\n }\n // Setup readable stream from buffer.\n let streamData = buffer\n const readStream = new Readable()\n readStream._read = () => {\n readStream.push(streamData)\n streamData = null!\n }\n // Setup file system writable stream.\n const fstream = fs.createWriteStream(filePath)\n // console.log(\"Calling saveBuffer\");\n fstream.on('error', (err) => {\n // console.log(\"err cb\")\n callback(err)\n })\n fstream.on('close', () => {\n // console.log(\"close cb\");\n callback()\n })\n // Copy file via piping streams.\n readStream.pipe(fstream)\n}\n\n/**\n * Decodes uriEncoded file names.\n * @param {Object} opts - middleware options.\n * @param fileName {String} - file name to decode.\n * @returns {String}\n */\nconst uriDecodeFileName = (opts: FetchAPIFileUploadOptions, fileName: string) => {\n if (!opts || !opts.uriDecodeFileNames) {\n return fileName\n }\n // Decode file name from URI with checking URI malformed errors.\n // See Issue https://github.com/richardgirges/express-fileupload/issues/342.\n try {\n return decodeURIComponent(fileName)\n } catch (ignore) {\n const matcher = /(%[a-f\\d]{2})/gi\n return fileName\n .split(matcher)\n .map((str) => {\n try {\n return decodeURIComponent(str)\n } catch (ignore) {\n return ''\n }\n })\n .join('')\n }\n}\n\n/**\n * Parses filename and extension and returns object {name, extension}.\n */\ntype ParseFileNameExtension = (\n preserveExtension: boolean | number,\n fileName: string,\n) => {\n extension: string\n name: string\n}\nexport const parseFileNameExtension: ParseFileNameExtension = (preserveExtension, fileName) => {\n const defaultResult = {\n name: fileName,\n extension: '',\n }\n if (!preserveExtension) {\n return defaultResult\n }\n\n // Define maximum extension length\n const maxExtLength =\n typeof preserveExtension === 'boolean' ? MAX_EXTENSION_LENGTH : preserveExtension\n\n const nameParts = fileName.split('.')\n if (nameParts.length < 2) {\n return defaultResult\n }\n\n let extension = nameParts.pop()\n if (extension!.length > maxExtLength && maxExtLength > 0) {\n nameParts[nameParts.length - 1] += '.' + extension!.substr(0, extension!.length - maxExtLength)\n extension = extension!.substr(-maxExtLength)\n }\n\n return {\n name: nameParts.join('.'),\n extension: maxExtLength ? extension! : '',\n }\n}\n\n/**\n * Parse file name and extension.\n */\ntype ParseFileName = (opts: FetchAPIFileUploadOptions, fileName: string) => string\nexport const parseFileName: ParseFileName = (opts, fileName) => {\n // Check fileName argument\n if (!fileName || typeof fileName !== 'string') {\n return getTempFilename()\n }\n // Cut off file name if it's length more then 255.\n let parsedName = fileName.length <= 255 ? fileName : fileName.substr(0, 255)\n // Decode file name if uriDecodeFileNames option set true.\n parsedName = uriDecodeFileName(opts, parsedName)\n // Stop parsing file name if safeFileNames options hasn't been set.\n if (!opts.safeFileNames) {\n return parsedName\n }\n // Set regular expression for the file name.\n const nameRegex =\n typeof opts.safeFileNames === 'object' && opts.safeFileNames instanceof RegExp\n ? opts.safeFileNames\n : SAFE_FILE_NAME_REGEX\n // Parse file name extension.\n const parsedFileName = parseFileNameExtension(opts.preserveExtension!, parsedName)\n if (parsedFileName.extension.length) {\n parsedFileName.extension = '.' + parsedFileName.extension.replace(nameRegex, '')\n }\n\n return parsedFileName.name.replace(nameRegex, '').concat(parsedFileName.extension)\n}\n"],"names":["fs","path","Readable","SAFE_FILE_NAME_REGEX","MAX_EXTENSION_LENGTH","TEMP_COUNTER_MAX","TEMP_PREFIX","tempCounter","debugLog","options","msg","opts","debug","console","log","getTempFilename","prefix","Date","now","isFunc","value","errorFunc","resolve","reject","promiseCallback","hasFired","err","OBJECT_PROTOTYPE_KEYS","Object","getOwnPropertyNames","prototype","ARRAY_PROTOTYPE_KEYS","Array","isSafeFromPollution","base","key","TOUCHES_ARRAY_PROTOTYPE","includes","TOUCHES_OBJECT_PROTOTYPE","buildFields","instance","field","undefined","create","push","checkAndMakeDir","fileUploadOptions","filePath","createParentPath","parentPath","dirname","existsSync","mkdirSync","recursive","deleteFile","callback","unlink","copyFile","src","dst","cbCalled","runCb","readable","createReadStream","on","writable","createWriteStream","destroy","pipe","moveFile","rename","cpErr","saveBufferToFile","buffer","Buffer","isBuffer","Error","streamData","readStream","_read","fstream","uriDecodeFileName","fileName","uriDecodeFileNames","decodeURIComponent","ignore","matcher","split","map","str","join","parseFileNameExtension","preserveExtension","defaultResult","name","extension","maxExtLength","nameParts","length","pop","substr","parseFileName","parsedName","safeFileNames","nameRegex","RegExp","parsedFileName","replace","concat"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/utilities.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { Readable } from 'stream'\n\nimport type { FetchAPIFileUploadOptions } from '../../config/types.js'\n\n// Parameters for safe file name parsing.\nconst SAFE_FILE_NAME_REGEX = /[^\\w-]/g\nconst MAX_EXTENSION_LENGTH = 3\n\n// Parameters to generate unique temporary file names:\nconst TEMP_COUNTER_MAX = 65536\nconst TEMP_PREFIX = 'tmp'\nlet tempCounter = 0\n\n/**\n * Logs message to console if options.debug option set to true.\n */\nexport const debugLog = (options: FetchAPIFileUploadOptions, msg: string) => {\n const opts = options || {}\n if (!opts.debug) {\n return false\n }\n console.log(`Next-file-upload: ${msg}`) // eslint-disable-line\n return true\n}\n\n/**\n * Generates unique temporary file name. e.g. tmp-5000-156788789789.\n */\nexport const getTempFilename = (prefix: string = TEMP_PREFIX) => {\n tempCounter = tempCounter >= TEMP_COUNTER_MAX ? 1 : tempCounter + 1\n return `${prefix}-${tempCounter}-${Date.now()}`\n}\n\ntype FuncType = (...args: any[]) => any\nexport const isFunc = (value: any): value is FuncType => {\n return typeof value === 'function'\n}\n\n/**\n * Set errorFunc to the same value as successFunc for callback mode.\n */\ntype ErrorFunc = (resolve: () => void, reject: (err: Error) => void) => (err: Error) => void\nconst errorFunc: ErrorFunc = (resolve, reject) => (isFunc(reject) ? reject : resolve)\n\n/**\n * Return a callback function for promise resole/reject args.\n * Ensures that callback is called only once.\n */\ntype PromiseCallback = (resolve: () => void, reject: (err: Error) => void) => (err: Error) => void\nexport const promiseCallback: PromiseCallback = (resolve, reject) => {\n let hasFired = false\n return (err: Error) => {\n if (hasFired) {\n return\n }\n\n hasFired = true\n return err ? errorFunc(resolve, reject)(err) : resolve()\n }\n}\n\n// The default prototypes for both objects and arrays.\n// Used by isSafeFromPollution\nconst OBJECT_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Object.prototype)\nconst ARRAY_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Array.prototype)\n\n/**\n * Determines whether a key insertion into an object could result in a prototype pollution\n */\ntype IsSafeFromPollution = (base: any, key: string) => boolean\nexport const isSafeFromPollution: IsSafeFromPollution = (base, key) => {\n // We perform an instanceof check instead of Array.isArray as the former is more\n // permissive for cases in which the object as an Array prototype but was not constructed\n // via an Array constructor or literal.\n const TOUCHES_ARRAY_PROTOTYPE = base instanceof Array && ARRAY_PROTOTYPE_KEYS.includes(key)\n const TOUCHES_OBJECT_PROTOTYPE = OBJECT_PROTOTYPE_KEYS.includes(key)\n\n return !TOUCHES_ARRAY_PROTOTYPE && !TOUCHES_OBJECT_PROTOTYPE\n}\n\n/**\n * Build request field/file objects to return\n */\ntype BuildFields = (instance: any, field: string, value: any) => any\nexport const buildFields: BuildFields = (instance, field, value) => {\n // Do nothing if value is not set.\n if (value === null || value === undefined) {\n return instance\n }\n instance = instance || Object.create(null)\n\n if (!isSafeFromPollution(instance, field)) {\n return instance\n }\n // Non-array fields\n if (!instance[field]) {\n instance[field] = value\n return instance\n }\n // Array fields\n if (instance[field] instanceof Array) {\n instance[field].push(value)\n } else {\n instance[field] = [instance[field], value]\n }\n return instance\n}\n\n/**\n * Creates a folder if it does not exist\n * for file specified in the path variable\n */\ntype CheckAndMakeDir = (fileUploadOptions: FetchAPIFileUploadOptions, filePath: string) => boolean\nexport const checkAndMakeDir: CheckAndMakeDir = (fileUploadOptions, filePath) => {\n if (!fileUploadOptions.createParentPath) {\n return false\n }\n // Check whether folder for the file exists.\n const parentPath = path.dirname(filePath)\n // Create folder if it doesn't exist.\n if (!fs.existsSync(parentPath)) {\n fs.mkdirSync(parentPath, { recursive: true })\n }\n // Checks folder again and return a results.\n return fs.existsSync(parentPath)\n}\n\n/**\n * Delete a file.\n */\ntype DeleteFile = (filePath: string, callback: (args: any) => void) => void\nexport const deleteFile: DeleteFile = (filePath, callback) => fs.unlink(filePath, callback)\n\n/**\n * Copy file via streams\n */\ntype CopyFile = (src: string, dst: string, callback: (err: Error) => void) => void\nconst copyFile: CopyFile = (src, dst, callback) => {\n // cbCalled flag and runCb helps to run cb only once.\n let cbCalled = false\n const runCb = (err?: Error) => {\n if (cbCalled) {\n return\n }\n cbCalled = true\n callback(err!)\n }\n // Create read stream\n const readable = fs.createReadStream(src)\n readable.on('error', runCb)\n // Create write stream\n const writable = fs.createWriteStream(dst)\n writable.on('error', (err: Error) => {\n readable.destroy()\n runCb(err)\n })\n writable.on('close', () => runCb())\n // Copy file via piping streams.\n readable.pipe(writable)\n}\n\n/**\n * moveFile: moves the file from src to dst.\n * Firstly trying to rename the file if no luck copying it to dst and then deleting src.\n */\ntype MoveFile = (\n src: string,\n dst: string,\n callback: (err: Error, renamed?: boolean) => void,\n) => void\nexport const moveFile: MoveFile = (src, dst, callback) =>\n fs.rename(src, dst, (err) => {\n if (err) {\n // Try to copy file if rename didn't work.\n copyFile(src, dst, (cpErr) => (cpErr ? callback(cpErr) : deleteFile(src, callback)))\n return\n }\n // File was renamed successfully: Add true to the callback to indicate that.\n callback(null!, true)\n })\n\n/**\n * Save buffer data to a file.\n * @param {Buffer} buffer - buffer to save to a file.\n * @param {string} filePath - path to a file.\n */\nexport const saveBufferToFile = (\n buffer: Buffer,\n filePath: string,\n callback: (err?: Error) => void,\n) => {\n if (!Buffer.isBuffer(buffer)) {\n return callback(new Error('buffer variable should be type of Buffer!'))\n }\n // Setup readable stream from buffer.\n let streamData = buffer\n const readStream = new Readable()\n readStream._read = () => {\n readStream.push(streamData)\n streamData = null!\n }\n // Setup file system writable stream.\n const fstream = fs.createWriteStream(filePath)\n // console.log(\"Calling saveBuffer\");\n fstream.on('error', (err) => {\n // console.log(\"err cb\")\n callback(err)\n })\n fstream.on('close', () => {\n // console.log(\"close cb\");\n callback()\n })\n // Copy file via piping streams.\n readStream.pipe(fstream)\n}\n\n/**\n * Decodes uriEncoded file names.\n * @param {Object} opts - middleware options.\n * @param fileName {String} - file name to decode.\n * @returns {String}\n */\nconst uriDecodeFileName = (opts: FetchAPIFileUploadOptions, fileName: string) => {\n if (!opts || !opts.uriDecodeFileNames) {\n return fileName\n }\n // Decode file name from URI with checking URI malformed errors.\n // See Issue https://github.com/richardgirges/express-fileupload/issues/342.\n try {\n return decodeURIComponent(fileName)\n } catch (ignore) {\n const matcher = /(%[a-f\\d]{2})/gi\n return fileName\n .split(matcher)\n .map((str) => {\n try {\n return decodeURIComponent(str)\n } catch (ignore) {\n return ''\n }\n })\n .join('')\n }\n}\n\n/**\n * Parses filename and extension and returns object {name, extension}.\n */\ntype ParseFileNameExtension = (\n preserveExtension: boolean | number,\n fileName: string,\n) => {\n extension: string\n name: string\n}\nexport const parseFileNameExtension: ParseFileNameExtension = (preserveExtension, fileName) => {\n const defaultResult = {\n name: fileName,\n extension: '',\n }\n if (!preserveExtension) {\n return defaultResult\n }\n\n // Define maximum extension length\n const maxExtLength =\n typeof preserveExtension === 'boolean' ? MAX_EXTENSION_LENGTH : preserveExtension\n\n const nameParts = fileName.split('.')\n if (nameParts.length < 2) {\n return defaultResult\n }\n\n let extension = nameParts.pop()\n if (extension!.length > maxExtLength && maxExtLength > 0) {\n nameParts[nameParts.length - 1] += '.' + extension!.substr(0, extension!.length - maxExtLength)\n extension = extension!.substr(-maxExtLength)\n }\n\n return {\n name: nameParts.join('.'),\n extension: maxExtLength ? extension! : '',\n }\n}\n\n/**\n * Parse file name and extension.\n */\ntype ParseFileName = (opts: FetchAPIFileUploadOptions, fileName: string) => string\nexport const parseFileName: ParseFileName = (opts, fileName) => {\n // Check fileName argument\n if (!fileName || typeof fileName !== 'string') {\n return getTempFilename()\n }\n // Cut off file name if it's length more then 255.\n let parsedName = fileName.length <= 255 ? fileName : fileName.substr(0, 255)\n // Decode file name if uriDecodeFileNames option set true.\n parsedName = uriDecodeFileName(opts, parsedName)\n // Stop parsing file name if safeFileNames options hasn't been set.\n if (!opts.safeFileNames) {\n return parsedName\n }\n // Set regular expression for the file name.\n const nameRegex =\n typeof opts.safeFileNames === 'object' && opts.safeFileNames instanceof RegExp\n ? opts.safeFileNames\n : SAFE_FILE_NAME_REGEX\n // Parse file name extension.\n const parsedFileName = parseFileNameExtension(opts.preserveExtension!, parsedName)\n if (parsedFileName.extension.length) {\n parsedFileName.extension = '.' + parsedFileName.extension.replace(nameRegex, '')\n }\n\n return parsedFileName.name.replace(nameRegex, '').concat(parsedFileName.extension)\n}\n"],"names":["fs","path","Readable","SAFE_FILE_NAME_REGEX","MAX_EXTENSION_LENGTH","TEMP_COUNTER_MAX","TEMP_PREFIX","tempCounter","debugLog","options","msg","opts","debug","console","log","getTempFilename","prefix","Date","now","isFunc","value","errorFunc","resolve","reject","promiseCallback","hasFired","err","OBJECT_PROTOTYPE_KEYS","Object","getOwnPropertyNames","prototype","ARRAY_PROTOTYPE_KEYS","Array","isSafeFromPollution","base","key","TOUCHES_ARRAY_PROTOTYPE","includes","TOUCHES_OBJECT_PROTOTYPE","buildFields","instance","field","undefined","create","push","checkAndMakeDir","fileUploadOptions","filePath","createParentPath","parentPath","dirname","existsSync","mkdirSync","recursive","deleteFile","callback","unlink","copyFile","src","dst","cbCalled","runCb","readable","createReadStream","on","writable","createWriteStream","destroy","pipe","moveFile","rename","cpErr","saveBufferToFile","buffer","Buffer","isBuffer","Error","streamData","readStream","_read","fstream","uriDecodeFileName","fileName","uriDecodeFileNames","decodeURIComponent","ignore","matcher","split","map","str","join","parseFileNameExtension","preserveExtension","defaultResult","name","extension","maxExtLength","nameParts","length","pop","substr","parseFileName","parsedName","safeFileNames","nameRegex","RegExp","parsedFileName","replace","concat"],"mappings":"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"}
|
|
@@ -120,11 +120,9 @@ export const generateFileData = async ({ collection: { config: collectionConfig
|
|
|
120
120
|
}
|
|
121
121
|
if (sharp && (fileIsAnimatedType || fileHasAdjustments)) {
|
|
122
122
|
if (file.tempFilePath) {
|
|
123
|
-
sharpFile = sharp(file.tempFilePath, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081
|
|
124
|
-
;
|
|
123
|
+
sharpFile = sharp(file.tempFilePath, sharpOptions).rotate(); // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081
|
|
125
124
|
} else {
|
|
126
|
-
sharpFile = sharp(file.data, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081
|
|
127
|
-
;
|
|
125
|
+
sharpFile = sharp(file.data, sharpOptions).rotate(); // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081
|
|
128
126
|
}
|
|
129
127
|
if (fileHasAdjustments) {
|
|
130
128
|
if (resizeOptions) {
|
|
@@ -246,8 +244,7 @@ export const generateFileData = async ({ collection: { config: collectionConfig
|
|
|
246
244
|
fileData.filesize = info.size;
|
|
247
245
|
}
|
|
248
246
|
if (file.tempFilePath) {
|
|
249
|
-
await fs.writeFile(file.tempFilePath, croppedImage) // write fileBuffer to the temp path
|
|
250
|
-
;
|
|
247
|
+
await fs.writeFile(file.tempFilePath, croppedImage); // write fileBuffer to the temp path
|
|
251
248
|
} else {
|
|
252
249
|
req.file = fileForResize;
|
|
253
250
|
}
|
|
@@ -259,8 +256,7 @@ export const generateFileData = async ({ collection: { config: collectionConfig
|
|
|
259
256
|
// If using temp files and the image is being resized, write the file to the temp path
|
|
260
257
|
if (fileBuffer?.data || file.data.length > 0) {
|
|
261
258
|
if (file.tempFilePath) {
|
|
262
|
-
await fs.writeFile(file.tempFilePath, fileBuffer?.data || file.data) // write fileBuffer to the temp path
|
|
263
|
-
;
|
|
259
|
+
await fs.writeFile(file.tempFilePath, fileBuffer?.data || file.data); // write fileBuffer to the temp path
|
|
264
260
|
} else {
|
|
265
261
|
// Assign the _possibly modified_ file to the request object
|
|
266
262
|
req.file = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/generateFileData.ts"],"sourcesContent":["import type { OutputInfo, Sharp, SharpOptions } from 'sharp'\n\nimport { fileTypeFromBuffer } from 'file-type'\nimport fs from 'fs/promises'\nimport sanitize from 'sanitize-filename'\n\nimport type { Collection } from '../collections/config/types.js'\nimport type { SanitizedConfig } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { FileData, FileToSave, ProbedImageSize, UploadEdits } from './types.js'\n\nimport { FileRetrievalError, FileUploadError, Forbidden, MissingFile } from '../errors/index.js'\nimport { canResizeImage } from './canResizeImage.js'\nimport { checkFileRestrictions } from './checkFileRestrictions.js'\nimport { cropImage } from './cropImage.js'\nimport { getExternalFile } from './getExternalFile.js'\nimport { getFileByPath } from './getFileByPath.js'\nimport { getImageSize } from './getImageSize.js'\nimport { getSafeFileName } from './getSafeFilename.js'\nimport { resizeAndTransformImageSizes } from './imageResizer.js'\nimport { isImage } from './isImage.js'\nimport { optionallyAppendMetadata } from './optionallyAppendMetadata.js'\ntype Args<T> = {\n collection: Collection\n config: SanitizedConfig\n data: T\n isDuplicating?: boolean\n operation: 'create' | 'update'\n originalDoc?: T\n overwriteExistingFiles?: boolean\n req: PayloadRequest\n throwOnMissingFile?: boolean\n}\n\ntype Result<T> = Promise<{\n data: T\n files: FileToSave[]\n}>\n\nconst shouldReupload = (\n uploadEdits: UploadEdits,\n fileData: Record<string, unknown> | undefined,\n) => {\n if (!fileData) {\n return false\n }\n\n if (uploadEdits.crop || uploadEdits.heightInPixels || uploadEdits.widthInPixels) {\n return true\n }\n\n // Since uploadEdits always has focalPoint, compare to the value in the data if it was changed\n if (uploadEdits.focalPoint) {\n const incomingFocalX = uploadEdits.focalPoint.x\n const incomingFocalY = uploadEdits.focalPoint.y\n\n const currentFocalX = 'focalX' in fileData && fileData.focalX\n const currentFocalY = 'focalY' in fileData && fileData.focalY\n\n const isEqual = incomingFocalX === currentFocalX && incomingFocalY === currentFocalY\n return !isEqual\n }\n\n return false\n}\n\nexport const generateFileData = async <T>({\n collection: { config: collectionConfig },\n data,\n isDuplicating,\n operation,\n originalDoc,\n overwriteExistingFiles,\n req,\n throwOnMissingFile,\n}: Args<T>): Result<T> => {\n if (!collectionConfig.upload) {\n return {\n data,\n files: [],\n }\n }\n\n const { sharp } = req.payload.config\n\n let file = req.file\n\n const uploadEdits = parseUploadEditsFromReqOrIncomingData({\n data,\n isDuplicating,\n operation,\n originalDoc,\n req,\n })\n\n const {\n constructorOptions,\n disableLocalStorage,\n focalPoint: focalPointEnabled = true,\n formatOptions,\n imageSizes,\n resizeOptions,\n staticDir,\n trimOptions,\n withMetadata,\n } = collectionConfig.upload\n\n const staticPath = staticDir\n\n const incomingFileData = isDuplicating ? originalDoc : data\n\n if (\n !file &&\n (isDuplicating || shouldReupload(uploadEdits, incomingFileData as Record<string, unknown>))\n ) {\n const { filename, url } = incomingFileData as unknown as FileData\n\n if (filename && (filename.includes('../') || filename.includes('..\\\\'))) {\n throw new Forbidden(req.t)\n }\n\n try {\n if (url && url.startsWith('/') && !disableLocalStorage) {\n const filePath = `${staticPath}/${filename}`\n const response = await getFileByPath(filePath)\n file = response\n overwriteExistingFiles = true\n } else if (filename && url) {\n file = await getExternalFile({\n data: incomingFileData as unknown as FileData,\n req,\n uploadConfig: collectionConfig.upload,\n })\n overwriteExistingFiles = true\n }\n } catch (err: unknown) {\n throw new FileRetrievalError(req.t, err instanceof Error ? err.message : undefined)\n }\n }\n\n if (isDuplicating) {\n overwriteExistingFiles = false\n }\n\n if (!file) {\n if (throwOnMissingFile) {\n throw new MissingFile(req.t)\n }\n\n return {\n data,\n files: [],\n }\n }\n\n await checkFileRestrictions({\n collection: collectionConfig,\n file,\n req,\n })\n\n if (!disableLocalStorage) {\n await fs.mkdir(staticPath!, { recursive: true })\n }\n\n let newData = data\n const filesToSave: FileToSave[] = []\n const fileData: Partial<FileData> = {}\n const fileIsAnimatedType = ['image/avif', 'image/gif', 'image/webp'].includes(file.mimetype)\n const cropData =\n typeof uploadEdits === 'object' && 'crop' in uploadEdits ? uploadEdits.crop : undefined\n\n try {\n const fileSupportsResize = canResizeImage(file.mimetype)\n let fsSafeName: string\n let sharpFile: Sharp | undefined\n let dimensions: ProbedImageSize | undefined\n let fileBuffer!: { data: Buffer; info: OutputInfo }\n let ext\n let mime: string\n const fileHasAdjustments =\n fileSupportsResize &&\n Boolean(\n resizeOptions || formatOptions || trimOptions || constructorOptions || file.tempFilePath,\n )\n\n const sharpOptions: SharpOptions = { ...constructorOptions }\n\n if (fileIsAnimatedType) {\n sharpOptions.animated = true\n }\n\n if (sharp && (fileIsAnimatedType || fileHasAdjustments)) {\n if (file.tempFilePath) {\n sharpFile = sharp(file.tempFilePath, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081\n } else {\n sharpFile = sharp(file.data, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081\n }\n\n if (fileHasAdjustments) {\n if (resizeOptions) {\n sharpFile = sharpFile.resize(resizeOptions)\n }\n if (formatOptions) {\n sharpFile = sharpFile.toFormat(formatOptions.format, formatOptions.options)\n }\n if (trimOptions) {\n sharpFile = sharpFile.trim(trimOptions)\n }\n }\n }\n\n if (fileSupportsResize || isImage(file.mimetype)) {\n dimensions = await getImageSize(file)\n fileData.width = dimensions.width\n fileData.height = dimensions.height\n }\n\n if (sharpFile) {\n const metadata = await sharpFile.metadata()\n sharpFile = await optionallyAppendMetadata({\n req,\n sharpFile,\n withMetadata: withMetadata!,\n })\n fileBuffer = await sharpFile.toBuffer({ resolveWithObject: true })\n ;({ ext, mime } = (await fileTypeFromBuffer(fileBuffer.data))!) // This is getting an incorrect gif height back.\n fileData.width = fileBuffer.info.width\n fileData.height = fileBuffer.info.height\n fileData.filesize = fileBuffer.info.size\n\n // Animated GIFs + WebP aggregate the height from every frame, so we need to use divide by number of pages\n if (metadata.pages) {\n fileData.height = fileBuffer.info.height / metadata.pages\n fileData.filesize = fileBuffer.data.length\n }\n } else {\n mime = file.mimetype\n fileData.filesize = file.size\n\n if (file.name.includes('.')) {\n ext = file.name.split('.').pop()?.split('?')[0]\n } else {\n ext = ''\n }\n }\n\n // Adjust SVG mime type. fromBuffer modifies it.\n if (mime === 'application/xml' && ext === 'svg') {\n mime = 'image/svg+xml'\n }\n fileData.mimeType = mime\n\n const baseFilename = sanitize(file.name.substring(0, file.name.lastIndexOf('.')) || file.name)\n fsSafeName = `${baseFilename}${ext ? `.${ext}` : ''}`\n\n if (!overwriteExistingFiles) {\n fsSafeName = await getSafeFileName({\n collectionSlug: collectionConfig.slug,\n desiredFilename: fsSafeName,\n req,\n staticPath: staticPath!,\n })\n }\n\n fileData.filename = fsSafeName\n let fileForResize = file\n\n if (cropData && sharp) {\n const { data: croppedImage, info } = await cropImage({\n cropData,\n dimensions: dimensions!,\n file,\n heightInPixels: uploadEdits.heightInPixels!,\n req,\n sharp,\n widthInPixels: uploadEdits.widthInPixels!,\n withMetadata,\n })\n\n // Apply resize after cropping to ensure it conforms to resizeOptions\n if (resizeOptions && !resizeOptions.withoutEnlargement) {\n const resizedAfterCrop = await sharp(croppedImage)\n .resize({\n fit: resizeOptions?.fit || 'cover',\n height: resizeOptions?.height,\n position: resizeOptions?.position || 'center',\n width: resizeOptions?.width,\n })\n .toBuffer({ resolveWithObject: true })\n\n filesToSave.push({\n buffer: resizedAfterCrop.data,\n path: `${staticPath}/${fsSafeName}`,\n })\n\n fileForResize = {\n ...fileForResize,\n data: resizedAfterCrop.data,\n size: resizedAfterCrop.info.size,\n }\n\n fileData.width = resizedAfterCrop.info.width\n fileData.height = resizedAfterCrop.info.height\n if (fileIsAnimatedType) {\n const metadata = await sharpFile!.metadata()\n fileData.height = metadata.pages\n ? resizedAfterCrop.info.height / metadata.pages\n : resizedAfterCrop.info.height\n }\n fileData.filesize = resizedAfterCrop.info.size\n } else {\n // If resizeOptions is not present, just save the cropped image\n filesToSave.push({\n buffer: croppedImage,\n path: `${staticPath}/${fsSafeName}`,\n })\n\n fileForResize = {\n ...file,\n data: croppedImage,\n size: info.size,\n }\n\n fileData.width = info.width\n fileData.height = info.height\n if (fileIsAnimatedType) {\n const metadata = await sharpFile!.metadata()\n fileData.height = metadata.pages ? info.height / metadata.pages : info.height\n }\n fileData.filesize = info.size\n }\n\n if (file.tempFilePath) {\n await fs.writeFile(file.tempFilePath, croppedImage) // write fileBuffer to the temp path\n } else {\n req.file = fileForResize\n }\n } else {\n filesToSave.push({\n buffer: fileBuffer?.data || file.data,\n path: `${staticPath}/${fsSafeName}`,\n })\n\n // If using temp files and the image is being resized, write the file to the temp path\n if (fileBuffer?.data || file.data.length > 0) {\n if (file.tempFilePath) {\n await fs.writeFile(file.tempFilePath, fileBuffer?.data || file.data) // write fileBuffer to the temp path\n } else {\n // Assign the _possibly modified_ file to the request object\n req.file = {\n ...file,\n data: fileBuffer?.data || file.data,\n size: fileBuffer?.info.size,\n }\n }\n }\n }\n\n if (fileSupportsResize && (Array.isArray(imageSizes) || focalPointEnabled !== false)) {\n req.payloadUploadSizes = {}\n const { focalPoint, sizeData, sizesToSave } = await resizeAndTransformImageSizes({\n config: collectionConfig,\n dimensions: !cropData\n ? dimensions!\n : {\n ...dimensions,\n height: fileData.height!,\n width: fileData.width!,\n },\n file: fileForResize,\n mimeType: fileData.mimeType,\n req,\n savedFilename: fsSafeName || file.name,\n sharp,\n staticPath: staticPath!,\n uploadEdits,\n withMetadata,\n })\n\n fileData.sizes = sizeData\n fileData.focalX = focalPoint?.x\n fileData.focalY = focalPoint?.y\n filesToSave.push(...sizesToSave)\n }\n } catch (err) {\n req.payload.logger.error(err)\n throw new FileUploadError(req.t)\n }\n\n newData = {\n ...newData,\n ...fileData,\n }\n\n return {\n data: newData,\n files: filesToSave,\n }\n}\n\n/**\n * Parse upload edits from req or incoming data\n */\nfunction parseUploadEditsFromReqOrIncomingData(args: {\n data: unknown\n isDuplicating?: boolean\n operation: 'create' | 'update'\n originalDoc: unknown\n req: PayloadRequest\n}): UploadEdits {\n const { data, isDuplicating, operation, originalDoc, req } = args\n\n // Get intended focal point change from query string or incoming data\n const uploadEdits =\n req.query?.uploadEdits && typeof req.query.uploadEdits === 'object'\n ? (req.query.uploadEdits as UploadEdits)\n : {}\n\n if (uploadEdits.focalPoint) {\n return uploadEdits\n }\n\n const incomingData = data as FileData\n const origDoc = originalDoc as FileData\n\n if (origDoc && 'focalX' in origDoc && 'focalY' in origDoc) {\n // If no change in focal point, return undefined.\n // This prevents a refocal operation triggered from admin, because it always sends the focal point.\n if (incomingData.focalX === origDoc.focalX && incomingData.focalY === origDoc.focalY) {\n return undefined!\n }\n\n if (isDuplicating) {\n uploadEdits.focalPoint = {\n x: incomingData?.focalX || origDoc.focalX!,\n y: incomingData?.focalY || origDoc.focalX!,\n }\n }\n }\n\n if (incomingData?.focalX && incomingData?.focalY) {\n uploadEdits.focalPoint = {\n x: incomingData.focalX,\n y: incomingData.focalY,\n }\n return uploadEdits\n }\n\n // If no focal point is set, default to center\n if (operation === 'create') {\n uploadEdits.focalPoint = {\n x: 50,\n y: 50,\n }\n }\n\n return uploadEdits\n}\n"],"names":["fileTypeFromBuffer","fs","sanitize","FileRetrievalError","FileUploadError","Forbidden","MissingFile","canResizeImage","checkFileRestrictions","cropImage","getExternalFile","getFileByPath","getImageSize","getSafeFileName","resizeAndTransformImageSizes","isImage","optionallyAppendMetadata","shouldReupload","uploadEdits","fileData","crop","heightInPixels","widthInPixels","focalPoint","incomingFocalX","x","incomingFocalY","y","currentFocalX","focalX","currentFocalY","focalY","isEqual","generateFileData","collection","config","collectionConfig","data","isDuplicating","operation","originalDoc","overwriteExistingFiles","req","throwOnMissingFile","upload","files","sharp","payload","file","parseUploadEditsFromReqOrIncomingData","constructorOptions","disableLocalStorage","focalPointEnabled","formatOptions","imageSizes","resizeOptions","staticDir","trimOptions","withMetadata","staticPath","incomingFileData","filename","url","includes","t","startsWith","filePath","response","uploadConfig","err","Error","message","undefined","mkdir","recursive","newData","filesToSave","fileIsAnimatedType","mimetype","cropData","fileSupportsResize","fsSafeName","sharpFile","dimensions","fileBuffer","ext","mime","fileHasAdjustments","Boolean","tempFilePath","sharpOptions","animated","rotate","resize","toFormat","format","options","trim","width","height","metadata","toBuffer","resolveWithObject","info","filesize","size","pages","length","name","split","pop","mimeType","baseFilename","substring","lastIndexOf","collectionSlug","slug","desiredFilename","fileForResize","croppedImage","withoutEnlargement","resizedAfterCrop","fit","position","push","buffer","path","writeFile","Array","isArray","payloadUploadSizes","sizeData","sizesToSave","savedFilename","sizes","logger","error","args","query","incomingData","origDoc"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/generateFileData.ts"],"sourcesContent":["import type { OutputInfo, Sharp, SharpOptions } from 'sharp'\n\nimport { fileTypeFromBuffer } from 'file-type'\nimport fs from 'fs/promises'\nimport sanitize from 'sanitize-filename'\n\nimport type { Collection } from '../collections/config/types.js'\nimport type { SanitizedConfig } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { FileData, FileToSave, ProbedImageSize, UploadEdits } from './types.js'\n\nimport { FileRetrievalError, FileUploadError, Forbidden, MissingFile } from '../errors/index.js'\nimport { canResizeImage } from './canResizeImage.js'\nimport { checkFileRestrictions } from './checkFileRestrictions.js'\nimport { cropImage } from './cropImage.js'\nimport { getExternalFile } from './getExternalFile.js'\nimport { getFileByPath } from './getFileByPath.js'\nimport { getImageSize } from './getImageSize.js'\nimport { getSafeFileName } from './getSafeFilename.js'\nimport { resizeAndTransformImageSizes } from './imageResizer.js'\nimport { isImage } from './isImage.js'\nimport { optionallyAppendMetadata } from './optionallyAppendMetadata.js'\ntype Args<T> = {\n collection: Collection\n config: SanitizedConfig\n data: T\n isDuplicating?: boolean\n operation: 'create' | 'update'\n originalDoc?: T\n overwriteExistingFiles?: boolean\n req: PayloadRequest\n throwOnMissingFile?: boolean\n}\n\ntype Result<T> = Promise<{\n data: T\n files: FileToSave[]\n}>\n\nconst shouldReupload = (\n uploadEdits: UploadEdits,\n fileData: Record<string, unknown> | undefined,\n) => {\n if (!fileData) {\n return false\n }\n\n if (uploadEdits.crop || uploadEdits.heightInPixels || uploadEdits.widthInPixels) {\n return true\n }\n\n // Since uploadEdits always has focalPoint, compare to the value in the data if it was changed\n if (uploadEdits.focalPoint) {\n const incomingFocalX = uploadEdits.focalPoint.x\n const incomingFocalY = uploadEdits.focalPoint.y\n\n const currentFocalX = 'focalX' in fileData && fileData.focalX\n const currentFocalY = 'focalY' in fileData && fileData.focalY\n\n const isEqual = incomingFocalX === currentFocalX && incomingFocalY === currentFocalY\n return !isEqual\n }\n\n return false\n}\n\nexport const generateFileData = async <T>({\n collection: { config: collectionConfig },\n data,\n isDuplicating,\n operation,\n originalDoc,\n overwriteExistingFiles,\n req,\n throwOnMissingFile,\n}: Args<T>): Result<T> => {\n if (!collectionConfig.upload) {\n return {\n data,\n files: [],\n }\n }\n\n const { sharp } = req.payload.config\n\n let file = req.file\n\n const uploadEdits = parseUploadEditsFromReqOrIncomingData({\n data,\n isDuplicating,\n operation,\n originalDoc,\n req,\n })\n\n const {\n constructorOptions,\n disableLocalStorage,\n focalPoint: focalPointEnabled = true,\n formatOptions,\n imageSizes,\n resizeOptions,\n staticDir,\n trimOptions,\n withMetadata,\n } = collectionConfig.upload\n\n const staticPath = staticDir\n\n const incomingFileData = isDuplicating ? originalDoc : data\n\n if (\n !file &&\n (isDuplicating || shouldReupload(uploadEdits, incomingFileData as Record<string, unknown>))\n ) {\n const { filename, url } = incomingFileData as unknown as FileData\n\n if (filename && (filename.includes('../') || filename.includes('..\\\\'))) {\n throw new Forbidden(req.t)\n }\n\n try {\n if (url && url.startsWith('/') && !disableLocalStorage) {\n const filePath = `${staticPath}/${filename}`\n const response = await getFileByPath(filePath)\n file = response\n overwriteExistingFiles = true\n } else if (filename && url) {\n file = await getExternalFile({\n data: incomingFileData as unknown as FileData,\n req,\n uploadConfig: collectionConfig.upload,\n })\n overwriteExistingFiles = true\n }\n } catch (err: unknown) {\n throw new FileRetrievalError(req.t, err instanceof Error ? err.message : undefined)\n }\n }\n\n if (isDuplicating) {\n overwriteExistingFiles = false\n }\n\n if (!file) {\n if (throwOnMissingFile) {\n throw new MissingFile(req.t)\n }\n\n return {\n data,\n files: [],\n }\n }\n\n await checkFileRestrictions({\n collection: collectionConfig,\n file,\n req,\n })\n\n if (!disableLocalStorage) {\n await fs.mkdir(staticPath!, { recursive: true })\n }\n\n let newData = data\n const filesToSave: FileToSave[] = []\n const fileData: Partial<FileData> = {}\n const fileIsAnimatedType = ['image/avif', 'image/gif', 'image/webp'].includes(file.mimetype)\n const cropData =\n typeof uploadEdits === 'object' && 'crop' in uploadEdits ? uploadEdits.crop : undefined\n\n try {\n const fileSupportsResize = canResizeImage(file.mimetype)\n let fsSafeName: string\n let sharpFile: Sharp | undefined\n let dimensions: ProbedImageSize | undefined\n let fileBuffer!: { data: Buffer; info: OutputInfo }\n let ext\n let mime: string\n const fileHasAdjustments =\n fileSupportsResize &&\n Boolean(\n resizeOptions || formatOptions || trimOptions || constructorOptions || file.tempFilePath,\n )\n\n const sharpOptions: SharpOptions = { ...constructorOptions }\n\n if (fileIsAnimatedType) {\n sharpOptions.animated = true\n }\n\n if (sharp && (fileIsAnimatedType || fileHasAdjustments)) {\n if (file.tempFilePath) {\n sharpFile = sharp(file.tempFilePath, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081\n } else {\n sharpFile = sharp(file.data, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081\n }\n\n if (fileHasAdjustments) {\n if (resizeOptions) {\n sharpFile = sharpFile.resize(resizeOptions)\n }\n if (formatOptions) {\n sharpFile = sharpFile.toFormat(formatOptions.format, formatOptions.options)\n }\n if (trimOptions) {\n sharpFile = sharpFile.trim(trimOptions)\n }\n }\n }\n\n if (fileSupportsResize || isImage(file.mimetype)) {\n dimensions = await getImageSize(file)\n fileData.width = dimensions.width\n fileData.height = dimensions.height\n }\n\n if (sharpFile) {\n const metadata = await sharpFile.metadata()\n sharpFile = await optionallyAppendMetadata({\n req,\n sharpFile,\n withMetadata: withMetadata!,\n })\n fileBuffer = await sharpFile.toBuffer({ resolveWithObject: true })\n ;({ ext, mime } = (await fileTypeFromBuffer(fileBuffer.data))!) // This is getting an incorrect gif height back.\n fileData.width = fileBuffer.info.width\n fileData.height = fileBuffer.info.height\n fileData.filesize = fileBuffer.info.size\n\n // Animated GIFs + WebP aggregate the height from every frame, so we need to use divide by number of pages\n if (metadata.pages) {\n fileData.height = fileBuffer.info.height / metadata.pages\n fileData.filesize = fileBuffer.data.length\n }\n } else {\n mime = file.mimetype\n fileData.filesize = file.size\n\n if (file.name.includes('.')) {\n ext = file.name.split('.').pop()?.split('?')[0]\n } else {\n ext = ''\n }\n }\n\n // Adjust SVG mime type. fromBuffer modifies it.\n if (mime === 'application/xml' && ext === 'svg') {\n mime = 'image/svg+xml'\n }\n fileData.mimeType = mime\n\n const baseFilename = sanitize(file.name.substring(0, file.name.lastIndexOf('.')) || file.name)\n fsSafeName = `${baseFilename}${ext ? `.${ext}` : ''}`\n\n if (!overwriteExistingFiles) {\n fsSafeName = await getSafeFileName({\n collectionSlug: collectionConfig.slug,\n desiredFilename: fsSafeName,\n req,\n staticPath: staticPath!,\n })\n }\n\n fileData.filename = fsSafeName\n let fileForResize = file\n\n if (cropData && sharp) {\n const { data: croppedImage, info } = await cropImage({\n cropData,\n dimensions: dimensions!,\n file,\n heightInPixels: uploadEdits.heightInPixels!,\n req,\n sharp,\n widthInPixels: uploadEdits.widthInPixels!,\n withMetadata,\n })\n\n // Apply resize after cropping to ensure it conforms to resizeOptions\n if (resizeOptions && !resizeOptions.withoutEnlargement) {\n const resizedAfterCrop = await sharp(croppedImage)\n .resize({\n fit: resizeOptions?.fit || 'cover',\n height: resizeOptions?.height,\n position: resizeOptions?.position || 'center',\n width: resizeOptions?.width,\n })\n .toBuffer({ resolveWithObject: true })\n\n filesToSave.push({\n buffer: resizedAfterCrop.data,\n path: `${staticPath}/${fsSafeName}`,\n })\n\n fileForResize = {\n ...fileForResize,\n data: resizedAfterCrop.data,\n size: resizedAfterCrop.info.size,\n }\n\n fileData.width = resizedAfterCrop.info.width\n fileData.height = resizedAfterCrop.info.height\n if (fileIsAnimatedType) {\n const metadata = await sharpFile!.metadata()\n fileData.height = metadata.pages\n ? resizedAfterCrop.info.height / metadata.pages\n : resizedAfterCrop.info.height\n }\n fileData.filesize = resizedAfterCrop.info.size\n } else {\n // If resizeOptions is not present, just save the cropped image\n filesToSave.push({\n buffer: croppedImage,\n path: `${staticPath}/${fsSafeName}`,\n })\n\n fileForResize = {\n ...file,\n data: croppedImage,\n size: info.size,\n }\n\n fileData.width = info.width\n fileData.height = info.height\n if (fileIsAnimatedType) {\n const metadata = await sharpFile!.metadata()\n fileData.height = metadata.pages ? info.height / metadata.pages : info.height\n }\n fileData.filesize = info.size\n }\n\n if (file.tempFilePath) {\n await fs.writeFile(file.tempFilePath, croppedImage) // write fileBuffer to the temp path\n } else {\n req.file = fileForResize\n }\n } else {\n filesToSave.push({\n buffer: fileBuffer?.data || file.data,\n path: `${staticPath}/${fsSafeName}`,\n })\n\n // If using temp files and the image is being resized, write the file to the temp path\n if (fileBuffer?.data || file.data.length > 0) {\n if (file.tempFilePath) {\n await fs.writeFile(file.tempFilePath, fileBuffer?.data || file.data) // write fileBuffer to the temp path\n } else {\n // Assign the _possibly modified_ file to the request object\n req.file = {\n ...file,\n data: fileBuffer?.data || file.data,\n size: fileBuffer?.info.size,\n }\n }\n }\n }\n\n if (fileSupportsResize && (Array.isArray(imageSizes) || focalPointEnabled !== false)) {\n req.payloadUploadSizes = {}\n const { focalPoint, sizeData, sizesToSave } = await resizeAndTransformImageSizes({\n config: collectionConfig,\n dimensions: !cropData\n ? dimensions!\n : {\n ...dimensions,\n height: fileData.height!,\n width: fileData.width!,\n },\n file: fileForResize,\n mimeType: fileData.mimeType,\n req,\n savedFilename: fsSafeName || file.name,\n sharp,\n staticPath: staticPath!,\n uploadEdits,\n withMetadata,\n })\n\n fileData.sizes = sizeData\n fileData.focalX = focalPoint?.x\n fileData.focalY = focalPoint?.y\n filesToSave.push(...sizesToSave)\n }\n } catch (err) {\n req.payload.logger.error(err)\n throw new FileUploadError(req.t)\n }\n\n newData = {\n ...newData,\n ...fileData,\n }\n\n return {\n data: newData,\n files: filesToSave,\n }\n}\n\n/**\n * Parse upload edits from req or incoming data\n */\nfunction parseUploadEditsFromReqOrIncomingData(args: {\n data: unknown\n isDuplicating?: boolean\n operation: 'create' | 'update'\n originalDoc: unknown\n req: PayloadRequest\n}): UploadEdits {\n const { data, isDuplicating, operation, originalDoc, req } = args\n\n // Get intended focal point change from query string or incoming data\n const uploadEdits =\n req.query?.uploadEdits && typeof req.query.uploadEdits === 'object'\n ? (req.query.uploadEdits as UploadEdits)\n : {}\n\n if (uploadEdits.focalPoint) {\n return uploadEdits\n }\n\n const incomingData = data as FileData\n const origDoc = originalDoc as FileData\n\n if (origDoc && 'focalX' in origDoc && 'focalY' in origDoc) {\n // If no change in focal point, return undefined.\n // This prevents a refocal operation triggered from admin, because it always sends the focal point.\n if (incomingData.focalX === origDoc.focalX && incomingData.focalY === origDoc.focalY) {\n return undefined!\n }\n\n if (isDuplicating) {\n uploadEdits.focalPoint = {\n x: incomingData?.focalX || origDoc.focalX!,\n y: incomingData?.focalY || origDoc.focalX!,\n }\n }\n }\n\n if (incomingData?.focalX && incomingData?.focalY) {\n uploadEdits.focalPoint = {\n x: incomingData.focalX,\n y: incomingData.focalY,\n }\n return uploadEdits\n }\n\n // If no focal point is set, default to center\n if (operation === 'create') {\n uploadEdits.focalPoint = {\n x: 50,\n y: 50,\n }\n }\n\n return uploadEdits\n}\n"],"names":["fileTypeFromBuffer","fs","sanitize","FileRetrievalError","FileUploadError","Forbidden","MissingFile","canResizeImage","checkFileRestrictions","cropImage","getExternalFile","getFileByPath","getImageSize","getSafeFileName","resizeAndTransformImageSizes","isImage","optionallyAppendMetadata","shouldReupload","uploadEdits","fileData","crop","heightInPixels","widthInPixels","focalPoint","incomingFocalX","x","incomingFocalY","y","currentFocalX","focalX","currentFocalY","focalY","isEqual","generateFileData","collection","config","collectionConfig","data","isDuplicating","operation","originalDoc","overwriteExistingFiles","req","throwOnMissingFile","upload","files","sharp","payload","file","parseUploadEditsFromReqOrIncomingData","constructorOptions","disableLocalStorage","focalPointEnabled","formatOptions","imageSizes","resizeOptions","staticDir","trimOptions","withMetadata","staticPath","incomingFileData","filename","url","includes","t","startsWith","filePath","response","uploadConfig","err","Error","message","undefined","mkdir","recursive","newData","filesToSave","fileIsAnimatedType","mimetype","cropData","fileSupportsResize","fsSafeName","sharpFile","dimensions","fileBuffer","ext","mime","fileHasAdjustments","Boolean","tempFilePath","sharpOptions","animated","rotate","resize","toFormat","format","options","trim","width","height","metadata","toBuffer","resolveWithObject","info","filesize","size","pages","length","name","split","pop","mimeType","baseFilename","substring","lastIndexOf","collectionSlug","slug","desiredFilename","fileForResize","croppedImage","withoutEnlargement","resizedAfterCrop","fit","position","push","buffer","path","writeFile","Array","isArray","payloadUploadSizes","sizeData","sizesToSave","savedFilename","sizes","logger","error","args","query","incomingData","origDoc"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/createLocalReq.ts"],"sourcesContent":["import type { Payload, RequestContext, TypedLocale, TypedUser } from '../index.js'\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { getDataLoader } from '../collections/dataloader.js'\nimport { getLocalI18n } from '../translations/getLocalI18n.js'\nimport { sanitizeFallbackLocale } from '../utilities/sanitizeFallbackLocale.js'\n\nfunction getRequestContext(\n req: Partial<PayloadRequest> = { context: null } as unknown as PayloadRequest,\n context: RequestContext = {},\n): RequestContext {\n if (req.context) {\n if (Object.keys(req.context).length === 0 && req.context.constructor === Object) {\n // if req.context is `{}` avoid unnecessary spread\n return context\n } else {\n return { ...req.context, ...context }\n }\n } else {\n return context\n }\n}\n\nconst attachFakeURLProperties = (req: Partial<PayloadRequest>, urlSuffix?: string) => {\n /**\n * *NOTE*\n * If no URL is provided, the local API was called outside\n * the context of a request. Therefore we create a fake URL object.\n * `ts-expect-error` is used below for properties that are 'read-only'.\n * Since they do not exist yet we can safely ignore the error.\n */\n let urlObject: undefined | URL\n\n function getURLObject() {\n if (urlObject) {\n return urlObject\n }\n\n const fallbackURL = `http://${req.host || 'localhost'}${urlSuffix || ''}`\n\n const urlToUse =\n req?.url || req.payload?.config?.serverURL\n ? `${req.payload?.config.serverURL}${urlSuffix || ''}`\n : fallbackURL\n\n try {\n urlObject = new URL(urlToUse)\n } catch (_err) {\n req.payload?.logger.error(\n `Failed to create URL object from URL: ${urlToUse}, falling back to ${fallbackURL}`,\n )\n\n urlObject = new URL(fallbackURL)\n }\n\n return urlObject\n }\n\n if (!req.host) {\n req.host = getURLObject().host\n }\n\n if (!req.protocol) {\n req.protocol = getURLObject().protocol\n }\n\n if (!req.pathname) {\n req.pathname = getURLObject().pathname\n }\n\n if (!req.searchParams) {\n // @ts-expect-error eslint-disable-next-line no-param-reassign\n req.searchParams = getURLObject().searchParams\n }\n\n if (!req.origin) {\n // @ts-expect-error eslint-disable-next-line no-param-reassign\n req.origin = getURLObject().origin\n }\n\n if (!req?.url) {\n // @ts-expect-error eslint-disable-next-line no-param-reassign\n req.url = getURLObject().href\n }\n}\n\nexport type CreateLocalReqOptions = {\n context?: RequestContext\n fallbackLocale?: false | TypedLocale\n locale?: string\n req?: Partial<PayloadRequest>\n urlSuffix?: string\n user?: TypedUser\n}\n\ntype CreateLocalReq = (options: CreateLocalReqOptions, payload: Payload) => Promise<PayloadRequest>\n\nexport const createLocalReq: CreateLocalReq = async (\n { context, fallbackLocale, locale: localeArg, req = {} as PayloadRequest, urlSuffix, user },\n payload,\n): Promise<PayloadRequest> => {\n const localization = payload.config?.localization\n\n if (localization) {\n const locale = localeArg === '*' ? 'all' : localeArg\n const defaultLocale = localization.defaultLocale\n const localeCandidate = locale || req?.locale || req?.query?.locale\n\n req.locale =\n localeCandidate && typeof localeCandidate === 'string' ? localeCandidate : defaultLocale\n\n const sanitizedFallback = sanitizeFallbackLocale({\n fallbackLocale: fallbackLocale!,\n locale: req.locale,\n localization,\n })\n\n req.fallbackLocale = sanitizedFallback!\n }\n\n const i18n =\n req?.i18n ||\n (await getLocalI18n({ config: payload.config, language: payload.config.i18n.fallbackLanguage }))\n\n if (!req.headers) {\n req.headers = new Headers()\n }\n\n req.context = getRequestContext(req, context)\n req.payloadAPI = req?.payloadAPI || 'local'\n req.payload = payload\n req.i18n = i18n\n req.t = i18n.t\n req.user = user || req?.user || null\n req.payloadDataLoader = req?.payloadDataLoader || getDataLoader(req as PayloadRequest)\n req.routeParams = req?.routeParams || {}\n req.query = req?.query || {}\n\n attachFakeURLProperties(req, urlSuffix)\n\n return req as PayloadRequest\n}\n"],"names":["getDataLoader","getLocalI18n","sanitizeFallbackLocale","getRequestContext","req","context","Object","keys","length","
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/createLocalReq.ts"],"sourcesContent":["import type { Payload, RequestContext, TypedLocale, TypedUser } from '../index.js'\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { getDataLoader } from '../collections/dataloader.js'\nimport { getLocalI18n } from '../translations/getLocalI18n.js'\nimport { sanitizeFallbackLocale } from '../utilities/sanitizeFallbackLocale.js'\n\nfunction getRequestContext(\n req: Partial<PayloadRequest> = { context: null } as unknown as PayloadRequest,\n context: RequestContext = {},\n): RequestContext {\n if (req.context) {\n if (Object.keys(req.context).length === 0 && req.context.constructor === Object) {\n // if req.context is `{}` avoid unnecessary spread\n return context\n } else {\n return { ...req.context, ...context }\n }\n } else {\n return context\n }\n}\n\nconst attachFakeURLProperties = (req: Partial<PayloadRequest>, urlSuffix?: string) => {\n /**\n * *NOTE*\n * If no URL is provided, the local API was called outside\n * the context of a request. Therefore we create a fake URL object.\n * `ts-expect-error` is used below for properties that are 'read-only'.\n * Since they do not exist yet we can safely ignore the error.\n */\n let urlObject: undefined | URL\n\n function getURLObject() {\n if (urlObject) {\n return urlObject\n }\n\n const fallbackURL = `http://${req.host || 'localhost'}${urlSuffix || ''}`\n\n const urlToUse =\n req?.url || req.payload?.config?.serverURL\n ? `${req.payload?.config.serverURL}${urlSuffix || ''}`\n : fallbackURL\n\n try {\n urlObject = new URL(urlToUse)\n } catch (_err) {\n req.payload?.logger.error(\n `Failed to create URL object from URL: ${urlToUse}, falling back to ${fallbackURL}`,\n )\n\n urlObject = new URL(fallbackURL)\n }\n\n return urlObject\n }\n\n if (!req.host) {\n req.host = getURLObject().host\n }\n\n if (!req.protocol) {\n req.protocol = getURLObject().protocol\n }\n\n if (!req.pathname) {\n req.pathname = getURLObject().pathname\n }\n\n if (!req.searchParams) {\n // @ts-expect-error eslint-disable-next-line no-param-reassign\n req.searchParams = getURLObject().searchParams\n }\n\n if (!req.origin) {\n // @ts-expect-error eslint-disable-next-line no-param-reassign\n req.origin = getURLObject().origin\n }\n\n if (!req?.url) {\n // @ts-expect-error eslint-disable-next-line no-param-reassign\n req.url = getURLObject().href\n }\n}\n\nexport type CreateLocalReqOptions = {\n context?: RequestContext\n fallbackLocale?: false | TypedLocale\n locale?: string\n req?: Partial<PayloadRequest>\n urlSuffix?: string\n user?: TypedUser\n}\n\ntype CreateLocalReq = (options: CreateLocalReqOptions, payload: Payload) => Promise<PayloadRequest>\n\nexport const createLocalReq: CreateLocalReq = async (\n { context, fallbackLocale, locale: localeArg, req = {} as PayloadRequest, urlSuffix, user },\n payload,\n): Promise<PayloadRequest> => {\n const localization = payload.config?.localization\n\n if (localization) {\n const locale = localeArg === '*' ? 'all' : localeArg\n const defaultLocale = localization.defaultLocale\n const localeCandidate = locale || req?.locale || req?.query?.locale\n\n req.locale =\n localeCandidate && typeof localeCandidate === 'string' ? localeCandidate : defaultLocale\n\n const sanitizedFallback = sanitizeFallbackLocale({\n fallbackLocale: fallbackLocale!,\n locale: req.locale,\n localization,\n })\n\n req.fallbackLocale = sanitizedFallback!\n }\n\n const i18n =\n req?.i18n ||\n (await getLocalI18n({ config: payload.config, language: payload.config.i18n.fallbackLanguage }))\n\n if (!req.headers) {\n req.headers = new Headers()\n }\n\n req.context = getRequestContext(req, context)\n req.payloadAPI = req?.payloadAPI || 'local'\n req.payload = payload\n req.i18n = i18n\n req.t = i18n.t\n req.user = user || req?.user || null\n req.payloadDataLoader = req?.payloadDataLoader || getDataLoader(req as PayloadRequest)\n req.routeParams = req?.routeParams || {}\n req.query = req?.query || {}\n\n attachFakeURLProperties(req, urlSuffix)\n\n return req as PayloadRequest\n}\n"],"names":["getDataLoader","getLocalI18n","sanitizeFallbackLocale","getRequestContext","req","context","Object","keys","length","attachFakeURLProperties","urlSuffix","urlObject","getURLObject","fallbackURL","host","urlToUse","url","payload","config","serverURL","URL","_err","logger","error","protocol","pathname","searchParams","origin","href","createLocalReq","fallbackLocale","locale","localeArg","user","localization","defaultLocale","localeCandidate","query","sanitizedFallback","i18n","language","fallbackLanguage","headers","Headers","payloadAPI","t","payloadDataLoader","routeParams"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/deepCopyObject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { JsonValue } from '../types/index.js'\n\n/*\nMain deepCopyObject handling - from rfdc: https://github.com/davidmarkclements/rfdc/blob/master/index.js\n\nCopyright 2019 \"David Mark Clements <david.mark.clements@gmail.com>\"\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and\nto permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\nTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\nCONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n*/\n\nfunction copyBuffer(cur: any) {\n if (cur instanceof Buffer) {\n return Buffer.from(cur)\n }\n\n return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n}\n\nconst constructorHandlers = new Map()\nconstructorHandlers.set(Date, (o: any) => new Date(o))\nconstructorHandlers.set(Map, (o: any, fn: any) => new Map(cloneArray<any>(Array.from(o), fn)))\nconstructorHandlers.set(Set, (o: any, fn: any) => new Set(cloneArray(Array.from(o), fn)))\nconstructorHandlers.set(RegExp, (regex: RegExp) => new RegExp(regex.source, regex.flags))\n\nlet handler: ((o: any, fn: any) => any) | null = null\n\nfunction cloneArray<T extends object>(a: T, fn: (o: any) => any): T {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as T\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i] as keyof typeof a\n const cur = a[k] as any\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur instanceof RegExp) {\n a2[k] = new RegExp(cur.source, cur.flags) as any\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur)\n } else {\n a2[k] = fn(cur)\n }\n }\n return a2\n}\n\nexport const deepCopyObject = <T>(o: T): T => {\n if (typeof o !== 'object' || o === null) {\n return o\n }\n if (Array.isArray(o)) {\n return cloneArray(o, deepCopyObject)\n }\n if (o instanceof RegExp) {\n return new RegExp(o.source, o.flags) as T\n }\n\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, deepCopyObject)\n }\n const o2 = {} as T\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) {\n continue\n }\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur instanceof RegExp) {\n o2[k] = new RegExp(cur.source, cur.flags) as any\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, deepCopyObject)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n o2[k] = deepCopyObject(cur)\n }\n }\n return o2\n}\n\n/*\nFast deepCopyObjectSimple handling - from fast-json-clone: https://github.com/rhysd/fast-json-clone\n\nBenchmark: https://github.com/AlessioGr/fastest-deep-clone-json/blob/main/test/benchmark.js\n*/\n\n/**\n * A deepCopyObject implementation which only works for JSON objects and arrays, and is faster than\n * JSON.parse(JSON.stringify(obj))\n *\n * @param value The JSON value to be cloned. There are two invariants. 1) It must not contain circles\n * as JSON does not allow it. This function will cause infinite loop for such values by\n * design. 2) It must contain JSON values only. Other values like `Date`, `Regexp`, `Map`,\n * `Set`, `Buffer`, ... are not allowed.\n * @returns The cloned JSON value.\n */\nexport function deepCopyObjectSimple<T extends JsonValue>(value: T, filterUndefined = false): T {\n if (typeof value !== 'object' || value === null) {\n return value\n } else if (Array.isArray(value)) {\n return value.map((e) =>\n typeof e !== 'object' || e === null ? e : deepCopyObjectSimple(e, filterUndefined),\n ) as T\n } else {\n if (value instanceof Date) {\n return new Date(value) as unknown as T\n }\n const ret: { [key: string]: T } = {}\n for (const k in value) {\n const v = value[k]\n if (filterUndefined && v === undefined) {\n continue\n }\n ret[k] =\n typeof v !== 'object' || v === null\n ? v\n : (deepCopyObjectSimple(v as T, filterUndefined) as any)\n }\n return ret as unknown as T\n }\n}\n\nexport function deepCopyObjectSimpleWithoutReactComponents<T extends JsonValue>(value: T): T {\n if (\n typeof value === 'object' &&\n value !== null &&\n '$$typeof' in value &&\n typeof value.$$typeof === 'symbol'\n ) {\n return undefined!\n } else if (typeof value !== 'object' || value === null) {\n return value\n } else if (Array.isArray(value)) {\n return value.map((e) =>\n typeof e !== 'object' || e === null ? e : deepCopyObjectSimpleWithoutReactComponents(e),\n ) as T\n } else {\n if (value instanceof Date) {\n return new Date(value) as unknown as T\n }\n const ret: { [key: string]: T } = {}\n for (const k in value) {\n const v = value[k]\n ret[k] =\n typeof v !== 'object' || v === null\n ? v\n : (deepCopyObjectSimpleWithoutReactComponents(v as T) as any)\n }\n return ret as unknown as T\n }\n}\n\n/**\n * A deepCopyObject implementation which is slower than deepCopyObject, but more correct.\n * Can be used if correctness is more important than speed. Supports circular dependencies\n */\nexport function deepCopyObjectComplex<T>(object: T, cache: WeakMap<any, any> = new WeakMap()): T {\n if (object === null) {\n return null!\n }\n\n if (cache.has(object)) {\n return cache.get(object)\n }\n\n // Handle File\n if (object instanceof File) {\n return object as unknown as T\n }\n\n // Handle Date\n if (object instanceof Date) {\n return new Date(object.getTime()) as unknown as T\n }\n\n // Handle RegExp\n if (object instanceof RegExp) {\n return new RegExp(object.source, object.flags) as unknown as T\n }\n\n // Handle Map\n if (object instanceof Map) {\n const clonedMap = new Map()\n cache.set(object, clonedMap)\n for (const [key, value] of object.entries()) {\n clonedMap.set(key, deepCopyObjectComplex(value, cache))\n }\n return clonedMap as unknown as T\n }\n\n // Handle Set\n if (object instanceof Set) {\n const clonedSet = new Set()\n cache.set(object, clonedSet)\n for (const value of object.values()) {\n clonedSet.add(deepCopyObjectComplex(value, cache))\n }\n return clonedSet as unknown as T\n }\n\n // Handle Array and Object\n if (typeof object === 'object' && object !== null) {\n if ('$$typeof' in object && typeof object.$$typeof === 'symbol') {\n return object\n }\n\n const clonedObject: any = Array.isArray(object)\n ? []\n : Object.create(Object.getPrototypeOf(object))\n cache.set(object, clonedObject)\n\n for (const key in object) {\n if (\n Object.prototype.hasOwnProperty.call(object, key) ||\n Object.getOwnPropertySymbols(object).includes(key as any)\n ) {\n clonedObject[key] = deepCopyObjectComplex(object[key], cache)\n }\n }\n\n return clonedObject as T\n }\n\n // Handle all other cases\n return object\n}\n"],"names":["copyBuffer","cur","Buffer","from","constructor","buffer","slice","byteOffset","length","constructorHandlers","Map","set","Date","o","fn","cloneArray","Array","Set","RegExp","regex","source","flags","handler","a","keys","Object","a2","i","k","get","ArrayBuffer","isView","deepCopyObject","isArray","o2","hasOwnProperty","call","deepCopyObjectSimple","value","filterUndefined","map","e","ret","v","undefined","deepCopyObjectSimpleWithoutReactComponents","$$typeof","deepCopyObjectComplex","object","cache","WeakMap","has","File","getTime","clonedMap","key","entries","clonedSet","values","add","clonedObject","create","getPrototypeOf","prototype","getOwnPropertySymbols","includes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/deepCopyObject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { JsonValue } from '../types/index.js'\n\n/*\nMain deepCopyObject handling - from rfdc: https://github.com/davidmarkclements/rfdc/blob/master/index.js\n\nCopyright 2019 \"David Mark Clements <david.mark.clements@gmail.com>\"\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and\nto permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\nTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\nCONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n*/\n\nfunction copyBuffer(cur: any) {\n if (cur instanceof Buffer) {\n return Buffer.from(cur)\n }\n\n return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n}\n\nconst constructorHandlers = new Map()\nconstructorHandlers.set(Date, (o: any) => new Date(o))\nconstructorHandlers.set(Map, (o: any, fn: any) => new Map(cloneArray<any>(Array.from(o), fn)))\nconstructorHandlers.set(Set, (o: any, fn: any) => new Set(cloneArray(Array.from(o), fn)))\nconstructorHandlers.set(RegExp, (regex: RegExp) => new RegExp(regex.source, regex.flags))\n\nlet handler: ((o: any, fn: any) => any) | null = null\n\nfunction cloneArray<T extends object>(a: T, fn: (o: any) => any): T {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as T\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i] as keyof typeof a\n const cur = a[k] as any\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur instanceof RegExp) {\n a2[k] = new RegExp(cur.source, cur.flags) as any\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur)\n } else {\n a2[k] = fn(cur)\n }\n }\n return a2\n}\n\nexport const deepCopyObject = <T>(o: T): T => {\n if (typeof o !== 'object' || o === null) {\n return o\n }\n if (Array.isArray(o)) {\n return cloneArray(o, deepCopyObject)\n }\n if (o instanceof RegExp) {\n return new RegExp(o.source, o.flags) as T\n }\n\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, deepCopyObject)\n }\n const o2 = {} as T\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) {\n continue\n }\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur instanceof RegExp) {\n o2[k] = new RegExp(cur.source, cur.flags) as any\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, deepCopyObject)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n o2[k] = deepCopyObject(cur)\n }\n }\n return o2\n}\n\n/*\nFast deepCopyObjectSimple handling - from fast-json-clone: https://github.com/rhysd/fast-json-clone\n\nBenchmark: https://github.com/AlessioGr/fastest-deep-clone-json/blob/main/test/benchmark.js\n*/\n\n/**\n * A deepCopyObject implementation which only works for JSON objects and arrays, and is faster than\n * JSON.parse(JSON.stringify(obj))\n *\n * @param value The JSON value to be cloned. There are two invariants. 1) It must not contain circles\n * as JSON does not allow it. This function will cause infinite loop for such values by\n * design. 2) It must contain JSON values only. Other values like `Date`, `Regexp`, `Map`,\n * `Set`, `Buffer`, ... are not allowed.\n * @returns The cloned JSON value.\n */\nexport function deepCopyObjectSimple<T extends JsonValue>(value: T, filterUndefined = false): T {\n if (typeof value !== 'object' || value === null) {\n return value\n } else if (Array.isArray(value)) {\n return value.map((e) =>\n typeof e !== 'object' || e === null ? e : deepCopyObjectSimple(e, filterUndefined),\n ) as T\n } else {\n if (value instanceof Date) {\n return new Date(value) as unknown as T\n }\n const ret: { [key: string]: T } = {}\n for (const k in value) {\n const v = value[k]\n if (filterUndefined && v === undefined) {\n continue\n }\n ret[k] =\n typeof v !== 'object' || v === null\n ? v\n : (deepCopyObjectSimple(v as T, filterUndefined) as any)\n }\n return ret as unknown as T\n }\n}\n\nexport function deepCopyObjectSimpleWithoutReactComponents<T extends JsonValue>(value: T): T {\n if (\n typeof value === 'object' &&\n value !== null &&\n '$$typeof' in value &&\n typeof value.$$typeof === 'symbol'\n ) {\n return undefined!\n } else if (typeof value !== 'object' || value === null) {\n return value\n } else if (Array.isArray(value)) {\n return value.map((e) =>\n typeof e !== 'object' || e === null ? e : deepCopyObjectSimpleWithoutReactComponents(e),\n ) as T\n } else {\n if (value instanceof Date) {\n return new Date(value) as unknown as T\n }\n const ret: { [key: string]: T } = {}\n for (const k in value) {\n const v = value[k]\n ret[k] =\n typeof v !== 'object' || v === null\n ? v\n : (deepCopyObjectSimpleWithoutReactComponents(v as T) as any)\n }\n return ret as unknown as T\n }\n}\n\n/**\n * A deepCopyObject implementation which is slower than deepCopyObject, but more correct.\n * Can be used if correctness is more important than speed. Supports circular dependencies\n */\nexport function deepCopyObjectComplex<T>(object: T, cache: WeakMap<any, any> = new WeakMap()): T {\n if (object === null) {\n return null!\n }\n\n if (cache.has(object)) {\n return cache.get(object)\n }\n\n // Handle File\n if (object instanceof File) {\n return object as unknown as T\n }\n\n // Handle Date\n if (object instanceof Date) {\n return new Date(object.getTime()) as unknown as T\n }\n\n // Handle RegExp\n if (object instanceof RegExp) {\n return new RegExp(object.source, object.flags) as unknown as T\n }\n\n // Handle Map\n if (object instanceof Map) {\n const clonedMap = new Map()\n cache.set(object, clonedMap)\n for (const [key, value] of object.entries()) {\n clonedMap.set(key, deepCopyObjectComplex(value, cache))\n }\n return clonedMap as unknown as T\n }\n\n // Handle Set\n if (object instanceof Set) {\n const clonedSet = new Set()\n cache.set(object, clonedSet)\n for (const value of object.values()) {\n clonedSet.add(deepCopyObjectComplex(value, cache))\n }\n return clonedSet as unknown as T\n }\n\n // Handle Array and Object\n if (typeof object === 'object' && object !== null) {\n if ('$$typeof' in object && typeof object.$$typeof === 'symbol') {\n return object\n }\n\n const clonedObject: any = Array.isArray(object)\n ? []\n : Object.create(Object.getPrototypeOf(object))\n cache.set(object, clonedObject)\n\n for (const key in object) {\n if (\n Object.prototype.hasOwnProperty.call(object, key) ||\n Object.getOwnPropertySymbols(object).includes(key as any)\n ) {\n clonedObject[key] = deepCopyObjectComplex(object[key], cache)\n }\n }\n\n return clonedObject as T\n }\n\n // Handle all other cases\n return object\n}\n"],"names":["copyBuffer","cur","Buffer","from","buffer","slice","byteOffset","length","constructorHandlers","Map","set","Date","o","fn","cloneArray","Array","Set","RegExp","regex","source","flags","handler","a","keys","Object","a2","i","k","get","ArrayBuffer","isView","deepCopyObject","isArray","o2","hasOwnProperty","call","deepCopyObjectSimple","value","filterUndefined","map","e","ret","v","undefined","deepCopyObjectSimpleWithoutReactComponents","$$typeof","deepCopyObjectComplex","object","cache","WeakMap","has","File","getTime","clonedMap","key","entries","clonedSet","values","add","clonedObject","create","getPrototypeOf","prototype","getOwnPropertySymbols","includes"],"mappings":"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"}
|
package/dist/utilities/findUp.js
CHANGED
|
@@ -19,8 +19,7 @@ import path from 'path';
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
if (!found && dir !== root) {
|
|
22
|
-
dir = path.dirname(dir) // Move up one directory level.
|
|
23
|
-
;
|
|
22
|
+
dir = path.dirname(dir); // Move up one directory level.
|
|
24
23
|
continue;
|
|
25
24
|
}
|
|
26
25
|
}
|
|
@@ -35,8 +34,7 @@ import path from 'path';
|
|
|
35
34
|
return null // Reached the root directory without a match.
|
|
36
35
|
;
|
|
37
36
|
}
|
|
38
|
-
dir = path.dirname(dir) // Move up one directory level.
|
|
39
|
-
;
|
|
37
|
+
dir = path.dirname(dir); // Move up one directory level.
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
/**
|
|
@@ -58,8 +56,7 @@ import path from 'path';
|
|
|
58
56
|
}
|
|
59
57
|
}
|
|
60
58
|
if (!found && dir !== root) {
|
|
61
|
-
dir = path.dirname(dir) // Move up one directory level.
|
|
62
|
-
;
|
|
59
|
+
dir = path.dirname(dir); // Move up one directory level.
|
|
63
60
|
continue;
|
|
64
61
|
}
|
|
65
62
|
}
|
|
@@ -74,8 +71,7 @@ import path from 'path';
|
|
|
74
71
|
return null // Reached the root directory without a match.
|
|
75
72
|
;
|
|
76
73
|
}
|
|
77
|
-
dir = path.dirname(dir) // Move up one directory level.
|
|
78
|
-
;
|
|
74
|
+
dir = path.dirname(dir); // Move up one directory level.
|
|
79
75
|
}
|
|
80
76
|
}
|
|
81
77
|
// From https://github.com/sindresorhus/path-exists/blob/main/index.js
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/findUp.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\n\n/**\n * Synchronously walks up parent directories until a condition is met and/or one of the file names within the fileNames array is found.\n */\nexport function findUpSync({\n condition,\n dir,\n fileNames,\n}: {\n condition?: (dir: string) => boolean | Promise<boolean | string> | string\n dir: string\n fileNames?: string[]\n}): null | string {\n const { root } = path.parse(dir)\n\n while (true) {\n if (fileNames?.length) {\n let found = false\n for (const fileName of fileNames) {\n const filePath = path.join(dir, fileName)\n const exists = pathExistsAndIsAccessibleSync(filePath)\n if (exists) {\n if (!condition) {\n return filePath\n }\n found = true\n break\n }\n }\n if (!found && dir !== root) {\n dir = path.dirname(dir) // Move up one directory level.\n continue\n }\n }\n const result = condition?.(dir)\n if (result === true) {\n return dir\n }\n if (typeof result === 'string' && result?.length) {\n return result\n }\n if (dir === root) {\n return null // Reached the root directory without a match.\n }\n dir = path.dirname(dir) // Move up one directory level.\n }\n}\n\n/**\n * Asynchronously walks up parent directories until a condition is met and/or one of the file names within the fileNames array is found.\n */\nexport async function findUp({\n condition,\n dir,\n fileNames,\n}: {\n condition?: (dir: string) => boolean | Promise<boolean | string> | string\n dir: string\n fileNames?: string[]\n}): Promise<null | string> {\n const { root } = path.parse(dir)\n\n while (true) {\n if (fileNames?.length) {\n let found = false\n for (const fileName of fileNames) {\n const filePath = path.resolve(dir, fileName)\n const exists = await pathExistsAndIsAccessible(filePath)\n if (exists) {\n if (!condition) {\n return filePath\n }\n found = true\n break\n }\n }\n if (!found && dir !== root) {\n dir = path.dirname(dir) // Move up one directory level.\n continue\n }\n }\n const result = await condition?.(dir)\n if (result === true) {\n return dir\n }\n if (typeof result === 'string' && result?.length) {\n return result\n }\n if (dir === root) {\n return null // Reached the root directory without a match.\n }\n dir = path.dirname(dir) // Move up one directory level.\n }\n}\n\n// From https://github.com/sindresorhus/path-exists/blob/main/index.js\n// fs.accessSync is preferred over fs.existsSync as it's usually a good idea\n// to check if the process has permission to read/write to a file before doing so.\n// Also see https://github.com/nodejs/node/issues/39960\nexport function pathExistsAndIsAccessibleSync(path: string) {\n try {\n fs.accessSync(path)\n return true\n } catch {\n return false\n }\n}\n\nexport async function pathExistsAndIsAccessible(path: string) {\n try {\n await fs.promises.access(path)\n return true\n } catch {\n return false\n }\n}\n"],"names":["fs","path","findUpSync","condition","dir","fileNames","root","parse","length","found","fileName","filePath","join","exists","pathExistsAndIsAccessibleSync","dirname","result","findUp","resolve","pathExistsAndIsAccessible","accessSync","promises","access"],"mappings":"AAAA,OAAOA,QAAQ,KAAI;AACnB,OAAOC,UAAU,OAAM;AAEvB;;CAEC,GACD,OAAO,SAASC,WAAW,EACzBC,SAAS,EACTC,GAAG,EACHC,SAAS,EAKV;IACC,MAAM,EAAEC,IAAI,EAAE,GAAGL,KAAKM,KAAK,CAACH;IAE5B,MAAO,KAAM;QACX,IAAIC,WAAWG,QAAQ;YACrB,IAAIC,QAAQ;YACZ,KAAK,MAAMC,YAAYL,UAAW;gBAChC,MAAMM,WAAWV,KAAKW,IAAI,CAACR,KAAKM;gBAChC,MAAMG,SAASC,8BAA8BH;gBAC7C,IAAIE,QAAQ;oBACV,IAAI,CAACV,WAAW;wBACd,OAAOQ;oBACT;oBACAF,QAAQ;oBACR;gBACF;YACF;YACA,IAAI,CAACA,SAASL,QAAQE,MAAM;gBAC1BF,MAAMH,KAAKc,OAAO,CAACX,
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/findUp.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\n\n/**\n * Synchronously walks up parent directories until a condition is met and/or one of the file names within the fileNames array is found.\n */\nexport function findUpSync({\n condition,\n dir,\n fileNames,\n}: {\n condition?: (dir: string) => boolean | Promise<boolean | string> | string\n dir: string\n fileNames?: string[]\n}): null | string {\n const { root } = path.parse(dir)\n\n while (true) {\n if (fileNames?.length) {\n let found = false\n for (const fileName of fileNames) {\n const filePath = path.join(dir, fileName)\n const exists = pathExistsAndIsAccessibleSync(filePath)\n if (exists) {\n if (!condition) {\n return filePath\n }\n found = true\n break\n }\n }\n if (!found && dir !== root) {\n dir = path.dirname(dir) // Move up one directory level.\n continue\n }\n }\n const result = condition?.(dir)\n if (result === true) {\n return dir\n }\n if (typeof result === 'string' && result?.length) {\n return result\n }\n if (dir === root) {\n return null // Reached the root directory without a match.\n }\n dir = path.dirname(dir) // Move up one directory level.\n }\n}\n\n/**\n * Asynchronously walks up parent directories until a condition is met and/or one of the file names within the fileNames array is found.\n */\nexport async function findUp({\n condition,\n dir,\n fileNames,\n}: {\n condition?: (dir: string) => boolean | Promise<boolean | string> | string\n dir: string\n fileNames?: string[]\n}): Promise<null | string> {\n const { root } = path.parse(dir)\n\n while (true) {\n if (fileNames?.length) {\n let found = false\n for (const fileName of fileNames) {\n const filePath = path.resolve(dir, fileName)\n const exists = await pathExistsAndIsAccessible(filePath)\n if (exists) {\n if (!condition) {\n return filePath\n }\n found = true\n break\n }\n }\n if (!found && dir !== root) {\n dir = path.dirname(dir) // Move up one directory level.\n continue\n }\n }\n const result = await condition?.(dir)\n if (result === true) {\n return dir\n }\n if (typeof result === 'string' && result?.length) {\n return result\n }\n if (dir === root) {\n return null // Reached the root directory without a match.\n }\n dir = path.dirname(dir) // Move up one directory level.\n }\n}\n\n// From https://github.com/sindresorhus/path-exists/blob/main/index.js\n// fs.accessSync is preferred over fs.existsSync as it's usually a good idea\n// to check if the process has permission to read/write to a file before doing so.\n// Also see https://github.com/nodejs/node/issues/39960\nexport function pathExistsAndIsAccessibleSync(path: string) {\n try {\n fs.accessSync(path)\n return true\n } catch {\n return false\n }\n}\n\nexport async function pathExistsAndIsAccessible(path: string) {\n try {\n await fs.promises.access(path)\n return true\n } catch {\n return false\n }\n}\n"],"names":["fs","path","findUpSync","condition","dir","fileNames","root","parse","length","found","fileName","filePath","join","exists","pathExistsAndIsAccessibleSync","dirname","result","findUp","resolve","pathExistsAndIsAccessible","accessSync","promises","access"],"mappings":"AAAA,OAAOA,QAAQ,KAAI;AACnB,OAAOC,UAAU,OAAM;AAEvB;;CAEC,GACD,OAAO,SAASC,WAAW,EACzBC,SAAS,EACTC,GAAG,EACHC,SAAS,EAKV;IACC,MAAM,EAAEC,IAAI,EAAE,GAAGL,KAAKM,KAAK,CAACH;IAE5B,MAAO,KAAM;QACX,IAAIC,WAAWG,QAAQ;YACrB,IAAIC,QAAQ;YACZ,KAAK,MAAMC,YAAYL,UAAW;gBAChC,MAAMM,WAAWV,KAAKW,IAAI,CAACR,KAAKM;gBAChC,MAAMG,SAASC,8BAA8BH;gBAC7C,IAAIE,QAAQ;oBACV,IAAI,CAACV,WAAW;wBACd,OAAOQ;oBACT;oBACAF,QAAQ;oBACR;gBACF;YACF;YACA,IAAI,CAACA,SAASL,QAAQE,MAAM;gBAC1BF,MAAMH,KAAKc,OAAO,CAACX,MAAK,+BAA+B;gBACvD;YACF;QACF;QACA,MAAMY,SAASb,YAAYC;QAC3B,IAAIY,WAAW,MAAM;YACnB,OAAOZ;QACT;QACA,IAAI,OAAOY,WAAW,YAAYA,QAAQR,QAAQ;YAChD,OAAOQ;QACT;QACA,IAAIZ,QAAQE,MAAM;YAChB,OAAO,KAAK,8CAA8C;;QAC5D;QACAF,MAAMH,KAAKc,OAAO,CAACX,MAAK,+BAA+B;IACzD;AACF;AAEA;;CAEC,GACD,OAAO,eAAea,OAAO,EAC3Bd,SAAS,EACTC,GAAG,EACHC,SAAS,EAKV;IACC,MAAM,EAAEC,IAAI,EAAE,GAAGL,KAAKM,KAAK,CAACH;IAE5B,MAAO,KAAM;QACX,IAAIC,WAAWG,QAAQ;YACrB,IAAIC,QAAQ;YACZ,KAAK,MAAMC,YAAYL,UAAW;gBAChC,MAAMM,WAAWV,KAAKiB,OAAO,CAACd,KAAKM;gBACnC,MAAMG,SAAS,MAAMM,0BAA0BR;gBAC/C,IAAIE,QAAQ;oBACV,IAAI,CAACV,WAAW;wBACd,OAAOQ;oBACT;oBACAF,QAAQ;oBACR;gBACF;YACF;YACA,IAAI,CAACA,SAASL,QAAQE,MAAM;gBAC1BF,MAAMH,KAAKc,OAAO,CAACX,MAAK,+BAA+B;gBACvD;YACF;QACF;QACA,MAAMY,SAAS,MAAMb,YAAYC;QACjC,IAAIY,WAAW,MAAM;YACnB,OAAOZ;QACT;QACA,IAAI,OAAOY,WAAW,YAAYA,QAAQR,QAAQ;YAChD,OAAOQ;QACT;QACA,IAAIZ,QAAQE,MAAM;YAChB,OAAO,KAAK,8CAA8C;;QAC5D;QACAF,MAAMH,KAAKc,OAAO,CAACX,MAAK,+BAA+B;IACzD;AACF;AAEA,sEAAsE;AACtE,4EAA4E;AAC5E,kFAAkF;AAClF,uDAAuD;AACvD,OAAO,SAASU,8BAA8Bb,IAAY;IACxD,IAAI;QACFD,GAAGoB,UAAU,CAACnB;QACd,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA,OAAO,eAAekB,0BAA0BlB,IAAY;IAC1D,IAAI;QACF,MAAMD,GAAGqB,QAAQ,CAACC,MAAM,CAACrB;QACzB,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/formatErrors.ts"],"sourcesContent":["import type { ErrorResult } from '../config/types.js'\nimport type { APIError } from '../errors/APIError.js'\n\nimport { APIErrorName } from '../errors/APIError.js'\nimport { ValidationErrorName } from '../errors/ValidationError.js'\n\nexport const formatErrors = (incoming: { [key: string]: unknown } | APIError): ErrorResult => {\n if (incoming) {\n // Cannot use `instanceof` to check error type: https://github.com/microsoft/TypeScript/issues/13965\n // Instead, get the prototype of the incoming error and check its constructor name\n const proto = Object.getPrototypeOf(incoming)\n\n // Payload 'ValidationError' and 'APIError'\n if (\n (proto.constructor.name === ValidationErrorName || proto.constructor.name === APIErrorName) &&\n incoming.data\n ) {\n return {\n errors: [\n {\n name: incoming.name,\n data: incoming.data,\n message: incoming.message,\n },\n ],\n }\n }\n\n // Mongoose 'ValidationError': https://mongoosejs.com/docs/api/error.html#Error.ValidationError\n if (proto.constructor.name === ValidationErrorName && 'errors' in incoming && incoming.errors) {\n return {\n errors: Object.keys(incoming.errors).reduce(\n (acc, key) => {\n acc.push({\n field: (incoming.errors as any)[key].path,\n message: (incoming.errors as any)[key].message,\n })\n return acc\n },\n [] as { field: string; message: string }[],\n ),\n }\n }\n\n if (Array.isArray(incoming.message)) {\n return {\n errors: incoming.message,\n }\n }\n\n if (incoming.name) {\n return {\n errors: [\n {\n message: incoming.message,\n },\n ],\n }\n }\n }\n\n return {\n errors: [\n {\n message: 'An unknown error occurred.',\n },\n ],\n }\n}\n"],"names":["APIErrorName","ValidationErrorName","formatErrors","incoming","proto","Object","getPrototypeOf","
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/formatErrors.ts"],"sourcesContent":["import type { ErrorResult } from '../config/types.js'\nimport type { APIError } from '../errors/APIError.js'\n\nimport { APIErrorName } from '../errors/APIError.js'\nimport { ValidationErrorName } from '../errors/ValidationError.js'\n\nexport const formatErrors = (incoming: { [key: string]: unknown } | APIError): ErrorResult => {\n if (incoming) {\n // Cannot use `instanceof` to check error type: https://github.com/microsoft/TypeScript/issues/13965\n // Instead, get the prototype of the incoming error and check its constructor name\n const proto = Object.getPrototypeOf(incoming)\n\n // Payload 'ValidationError' and 'APIError'\n if (\n (proto.constructor.name === ValidationErrorName || proto.constructor.name === APIErrorName) &&\n incoming.data\n ) {\n return {\n errors: [\n {\n name: incoming.name,\n data: incoming.data,\n message: incoming.message,\n },\n ],\n }\n }\n\n // Mongoose 'ValidationError': https://mongoosejs.com/docs/api/error.html#Error.ValidationError\n if (proto.constructor.name === ValidationErrorName && 'errors' in incoming && incoming.errors) {\n return {\n errors: Object.keys(incoming.errors).reduce(\n (acc, key) => {\n acc.push({\n field: (incoming.errors as any)[key].path,\n message: (incoming.errors as any)[key].message,\n })\n return acc\n },\n [] as { field: string; message: string }[],\n ),\n }\n }\n\n if (Array.isArray(incoming.message)) {\n return {\n errors: incoming.message,\n }\n }\n\n if (incoming.name) {\n return {\n errors: [\n {\n message: incoming.message,\n },\n ],\n }\n }\n }\n\n return {\n errors: [\n {\n message: 'An unknown error occurred.',\n },\n ],\n }\n}\n"],"names":["APIErrorName","ValidationErrorName","formatErrors","incoming","proto","Object","getPrototypeOf","name","data","errors","message","keys","reduce","acc","key","push","field","path","Array","isArray"],"mappings":"AAGA,SAASA,YAAY,QAAQ,wBAAuB;AACpD,SAASC,mBAAmB,QAAQ,+BAA8B;AAElE,OAAO,MAAMC,eAAe,CAACC;IAC3B,IAAIA,UAAU;QACZ,oGAAoG;QACpG,kFAAkF;QAClF,MAAMC,QAAQC,OAAOC,cAAc,CAACH;QAEpC,2CAA2C;QAC3C,IACE,AAACC,CAAAA,MAAM,WAAW,CAACG,IAAI,KAAKN,uBAAuBG,MAAM,WAAW,CAACG,IAAI,KAAKP,YAAW,KACzFG,SAASK,IAAI,EACb;YACA,OAAO;gBACLC,QAAQ;oBACN;wBACEF,MAAMJ,SAASI,IAAI;wBACnBC,MAAML,SAASK,IAAI;wBACnBE,SAASP,SAASO,OAAO;oBAC3B;iBACD;YACH;QACF;QAEA,+FAA+F;QAC/F,IAAIN,MAAM,WAAW,CAACG,IAAI,KAAKN,uBAAuB,YAAYE,YAAYA,SAASM,MAAM,EAAE;YAC7F,OAAO;gBACLA,QAAQJ,OAAOM,IAAI,CAACR,SAASM,MAAM,EAAEG,MAAM,CACzC,CAACC,KAAKC;oBACJD,IAAIE,IAAI,CAAC;wBACPC,OAAO,AAACb,SAASM,MAAM,AAAQ,CAACK,IAAI,CAACG,IAAI;wBACzCP,SAAS,AAACP,SAASM,MAAM,AAAQ,CAACK,IAAI,CAACJ,OAAO;oBAChD;oBACA,OAAOG;gBACT,GACA,EAAE;YAEN;QACF;QAEA,IAAIK,MAAMC,OAAO,CAAChB,SAASO,OAAO,GAAG;YACnC,OAAO;gBACLD,QAAQN,SAASO,OAAO;YAC1B;QACF;QAEA,IAAIP,SAASI,IAAI,EAAE;YACjB,OAAO;gBACLE,QAAQ;oBACN;wBACEC,SAASP,SAASO,OAAO;oBAC3B;iBACD;YACH;QACF;IACF;IAEA,OAAO;QACLD,QAAQ;YACN;gBACEC,SAAS;YACX;SACD;IACH;AACF,EAAC"}
|
|
@@ -20,8 +20,7 @@ describe('getFieldPermissions with collection fallback', ()=>{
|
|
|
20
20
|
collectionPermissions
|
|
21
21
|
});
|
|
22
22
|
expect(result.read).toBe(true);
|
|
23
|
-
expect(result.operation).toBe(false) // Should be read-only
|
|
24
|
-
;
|
|
23
|
+
expect(result.operation).toBe(false); // Should be read-only
|
|
25
24
|
expect(result.permissions).toEqual({
|
|
26
25
|
read: true
|
|
27
26
|
});
|
|
@@ -40,8 +39,7 @@ describe('getFieldPermissions with collection fallback', ()=>{
|
|
|
40
39
|
permissions: fieldPermissions
|
|
41
40
|
});
|
|
42
41
|
expect(result.read).toBe(true);
|
|
43
|
-
expect(result.operation).toBe(true) // Should have operation permission
|
|
44
|
-
;
|
|
42
|
+
expect(result.operation).toBe(true); // Should have operation permission
|
|
45
43
|
expect(result.permissions).toBe(true);
|
|
46
44
|
});
|
|
47
45
|
it('should not provide access when neither field nor collection has read permission', ()=>{
|