@payloadcms/plugin-form-builder 4.0.0-internal.c3ac604 → 4.0.0-internal.cb69780

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.
@@ -1 +1 @@
1
- {"version":3,"file":"handleUploads.d.ts","sourceRoot":"","sources":["../../../../src/collections/FormSubmissions/hooks/handleUploads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAK3B,MAAM,SAAS,CAAA;AAKhB,OAAO,KAAK,EACV,uBAAuB,EAIxB,MAAM,mBAAmB,CAAA;AAE1B,KAAK,kBAAkB,GAAG,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAA;AAOnE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,uBACJ,kBAAkB,cAC1B,uBAAuB,0BAiSpC,CAAA"}
1
+ {"version":3,"file":"handleUploads.d.ts","sourceRoot":"","sources":["../../../../src/collections/FormSubmissions/hooks/handleUploads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAK3B,MAAM,SAAS,CAAA;AAKhB,OAAO,KAAK,EACV,uBAAuB,EAIxB,MAAM,mBAAmB,CAAA;AAE1B,KAAK,kBAAkB,GAAG,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAA;AAOnE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,uBACJ,kBAAkB,cAC1B,uBAAuB,0BAoSpC,CAAA"}
@@ -28,6 +28,7 @@ import { validateMimeType } from 'payload/shared';
28
28
  form = await payload.findByID({
29
29
  id: formID,
30
30
  collection: formSlug,
31
+ overrideAccess: true,
31
32
  req
32
33
  });
33
34
  } catch {
@@ -124,6 +125,7 @@ import { validateMimeType } from 'payload/shared';
124
125
  mimetype: requestFile.mimetype,
125
126
  size: requestFile.size
126
127
  },
128
+ overrideAccess: true,
127
129
  req
128
130
  });
129
131
  createdDocs.push({
@@ -176,6 +178,7 @@ import { validateMimeType } from 'payload/shared';
176
178
  fileDoc = await payload.findByID({
177
179
  id: fileId,
178
180
  collection: uploadCollection,
181
+ overrideAccess: true,
179
182
  req
180
183
  });
181
184
  } catch {
@@ -242,6 +245,7 @@ import { validateMimeType } from 'payload/shared';
242
245
  await payload.delete({
243
246
  id: doc.id,
244
247
  collection: doc.collection,
248
+ overrideAccess: true,
245
249
  req
246
250
  });
247
251
  } catch {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/collections/FormSubmissions/hooks/handleUploads.ts"],"sourcesContent":["import type {\n CollectionBeforeChangeHook,\n File,\n FileData,\n TypeWithID,\n UploadCollectionSlug,\n} from 'payload'\n\nimport { ValidationError } from 'payload'\nimport { validateMimeType } from 'payload/shared'\n\nimport type {\n FormBuilderPluginConfig,\n SubmissionUploadItem,\n SubmissionValue,\n UploadField,\n} from '../../../types.js'\n\ntype BeforeChangeParams = Parameters<CollectionBeforeChangeHook>[0]\n\ninterface UploadError {\n field: string\n message: string\n}\n\n/**\n * Handles upload fields in form submissions.\n *\n * This hook:\n * 1. Checks req.files for files matching upload field names (supports multiple files per field)\n * 2. Validates MIME types and file sizes before uploading\n * 3. Creates media documents in the appropriate upload collection\n * 4. Populates submissionUploads with proper Payload upload relationships\n * 5. Strips upload fields from submissionData (they live in submissionUploads only)\n * 6. Validates pre-uploaded file IDs for backwards compatibility\n */\nexport const handleUploads = async (\n beforeChangeParams: BeforeChangeParams,\n formConfig: FormBuilderPluginConfig,\n) => {\n const { data, operation, req } = beforeChangeParams\n const { payload } = req\n\n // Only handle on create\n if (operation !== 'create') {\n return data\n }\n\n const { form: formID, submissionData } = data || {}\n\n if (!formID || !submissionData) {\n return data\n }\n\n const formSlug = formConfig?.formOverrides?.slug || 'forms'\n\n // Fetch the form to get field configurations\n let form\n try {\n form = await payload.findByID({\n id: formID,\n collection: formSlug,\n req,\n })\n } catch {\n // If form doesn't exist, let the form relationship validation handle it\n return data\n }\n\n const formFields = form?.fields || []\n const uploadFields = formFields.filter(\n (field: { blockType: string }) => field.blockType === 'upload',\n ) as UploadField[]\n\n if (uploadFields.length === 0) {\n return data\n }\n\n const submissionDataArray = submissionData as SubmissionValue[]\n\n // Build a map of pre-uploaded file IDs for backwards-compat lookup\n const submissionMap = new Map<string, { index: number; value: unknown }>()\n for (let i = 0; i < submissionDataArray.length; i++) {\n const item = submissionDataArray[i]\n if (item) {\n submissionMap.set(item.field, { index: i, value: item.value })\n }\n }\n\n // Get files from request (populated by addDataAndFileToRequest).\n // Multiple files with the same field name are stored as an array by buildFields.\n const requestFiles = req.files || {}\n\n const errors: UploadError[] = []\n // Accumulate upload items per field — one entry per upload field in the form\n const uploadsByField = new Map<string, SubmissionUploadItem[]>()\n // Track docs created during this hook so we can delete them if a later error causes rollback\n const createdDocs: Array<{ collection: string; id: number | string }> = []\n\n for (const uploadField of uploadFields) {\n const { name, maxFileSize, mimeTypes, multiple, required, uploadCollection } = uploadField\n const fieldLabel = uploadField.label || name\n\n uploadsByField.set(name, [])\n\n // Validate uploadCollection is configured in this plugin (defence-in-depth against tampered form docs)\n if (!formConfig.uploadCollections?.includes(uploadCollection)) {\n errors.push({\n field: name,\n message: `Upload collection \"${uploadCollection}\" is not configured in this plugin`,\n })\n continue\n }\n\n // Normalize: multiple files with the same field name arrive as an array\n const rawFile = requestFiles[name]\n const requestFileList: File[] = rawFile ? (Array.isArray(rawFile) ? rawFile : [rawFile]) : []\n\n const existingSubmission = submissionMap.get(name)\n\n if (requestFileList.length > 0) {\n // Guard: reject multiple files when the field doesn't allow them\n if (!multiple && requestFileList.length > 1) {\n errors.push({\n field: name,\n message: `${fieldLabel} does not allow multiple files`,\n })\n continue\n }\n\n // Direct file upload(s) from request\n for (const requestFile of requestFileList) {\n // Validate MIME type before uploading\n if (mimeTypes && mimeTypes.length > 0) {\n const allowedPatterns = mimeTypes.map((m) => m.mimeType)\n\n if (!validateMimeType(requestFile.mimetype, allowedPatterns)) {\n errors.push({\n field: name,\n message: `${fieldLabel}: File type \"${requestFile.mimetype}\" is not allowed. Allowed types: ${allowedPatterns.join(', ')}`,\n })\n continue\n }\n }\n\n // Validate file size before uploading\n if (maxFileSize && maxFileSize > 0 && requestFile.size > maxFileSize) {\n const maxSizeMB = (maxFileSize / (1024 * 1024)).toFixed(2)\n const fileSizeMB = (requestFile.size / (1024 * 1024)).toFixed(2)\n\n errors.push({\n field: name,\n message: `${fieldLabel}: File size (${fileSizeMB}MB) exceeds maximum allowed size (${maxSizeMB}MB)`,\n })\n continue\n }\n\n // Create the media document.\n // Note: payload.create writes the file to storage before the DB row exists. If\n // the DB write throws, createdDocs never records the entry and the file on disk\n // will not be cleaned up by the rollback loop below. Payload core owns that\n // rollback path — we only clean up docs we successfully created here.\n try {\n const mediaDoc = await payload.create({\n collection: uploadCollection,\n data: {},\n file: {\n name: requestFile.name,\n data: requestFile.data,\n mimetype: requestFile.mimetype,\n size: requestFile.size,\n },\n req,\n })\n\n createdDocs.push({ id: mediaDoc.id, collection: uploadCollection })\n uploadsByField.get(name)!.push({ relationTo: uploadCollection, value: mediaDoc.id })\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error'\n\n errors.push({\n field: name,\n message: `${fieldLabel}: Failed to upload file - ${errorMessage}`,\n })\n }\n }\n } else if (existingSubmission && existingSubmission.value) {\n // Backwards compatibility: validate pre-uploaded file IDs\n const submittedValue = existingSubmission.value\n const submittedValueStr =\n typeof submittedValue === 'string' || typeof submittedValue === 'number'\n ? String(submittedValue)\n : ''\n\n if (!submittedValueStr) {\n if (required) {\n errors.push({ field: name, message: `${fieldLabel} is required` })\n }\n continue\n }\n\n // Guard: reject comma-separated IDs when the field doesn't allow multiple files.\n // Assumes IDs never contain literal commas — true for ObjectIDs/UUIDs and any numeric ID.\n if (!multiple && submittedValueStr.includes(',')) {\n errors.push({\n field: name,\n message: `${fieldLabel} does not allow multiple files`,\n })\n continue\n }\n\n // Parse file IDs (comma-separated for multiple files)\n const fileIds = multiple\n ? submittedValueStr\n .split(',')\n .map((id) => id.trim())\n .filter(Boolean)\n : [submittedValueStr]\n\n // Validate each file\n for (const fileId of fileIds) {\n let fileDoc: (FileData & TypeWithID) | null = null\n let fileIsValid = true\n\n try {\n fileDoc = (await payload.findByID({\n id: fileId,\n collection: uploadCollection,\n req,\n })) as FileData & TypeWithID\n } catch {\n errors.push({\n field: name,\n message: `${fieldLabel}: File with ID \"${fileId}\" not found in collection \"${uploadCollection}\"`,\n })\n fileIsValid = false\n continue\n }\n\n if (!fileDoc) {\n errors.push({\n field: name,\n message: `${fieldLabel}: File with ID \"${fileId}\" not found`,\n })\n fileIsValid = false\n continue\n }\n\n // Validate mimeType\n if (mimeTypes && mimeTypes.length > 0) {\n const allowedPatterns = mimeTypes.map((m) => m.mimeType)\n const fileMimeType = fileDoc.mimeType\n\n if (fileMimeType && !validateMimeType(fileMimeType, allowedPatterns)) {\n errors.push({\n field: name,\n message: `${fieldLabel}: File type \"${fileMimeType}\" is not allowed. Allowed types: ${allowedPatterns.join(', ')}`,\n })\n fileIsValid = false\n continue\n }\n }\n\n // Validate file size\n if (maxFileSize && maxFileSize > 0) {\n const fileSize = fileDoc.filesize\n\n if (fileSize && fileSize > maxFileSize) {\n const maxSizeMB = (maxFileSize / (1024 * 1024)).toFixed(2)\n const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(2)\n\n errors.push({\n field: name,\n message: `${fieldLabel}: File size (${fileSizeMB}MB) exceeds maximum allowed size (${maxSizeMB}MB)`,\n })\n fileIsValid = false\n }\n }\n\n if (fileIsValid) {\n uploadsByField.get(name)!.push({ relationTo: uploadCollection, value: fileDoc.id })\n }\n }\n } else if (required) {\n // No file in request and no pre-uploaded file ID, but field is required\n errors.push({\n field: name,\n message: `${fieldLabel} is required`,\n })\n }\n }\n\n if (errors.length > 0) {\n // Best-effort cleanup of any docs created before the error was detected\n for (const doc of createdDocs) {\n try {\n await payload.delete({ id: doc.id, collection: doc.collection, req })\n } catch {\n // best-effort — don't mask the original validation error\n }\n }\n\n throw new ValidationError({\n collection: formConfig?.formSubmissionOverrides?.slug || 'form-submissions',\n errors: errors.map((error) => ({\n message: error.message,\n path: error.field,\n })),\n })\n }\n\n // Strip upload fields from submissionData — they are stored in submissionUploads only\n const uploadFieldNames = new Set(uploadFields.map((f) => f.name))\n const cleanedSubmissionData = submissionDataArray.filter(\n (item) => !uploadFieldNames.has(item.field),\n )\n\n // One entry per upload field; omit fields with no successful uploads\n const updatedSubmissionUploads = Array.from(uploadsByField.entries())\n .filter(([, items]) => items.length > 0)\n .map(([field, value]) => ({ field, value }))\n\n return {\n ...data,\n submissionData: cleanedSubmissionData,\n submissionUploads: updatedSubmissionUploads,\n }\n}\n"],"names":["ValidationError","validateMimeType","handleUploads","beforeChangeParams","formConfig","data","operation","req","payload","form","formID","submissionData","formSlug","formOverrides","slug","findByID","id","collection","formFields","fields","uploadFields","filter","field","blockType","length","submissionDataArray","submissionMap","Map","i","item","set","index","value","requestFiles","files","errors","uploadsByField","createdDocs","uploadField","name","maxFileSize","mimeTypes","multiple","required","uploadCollection","fieldLabel","label","uploadCollections","includes","push","message","rawFile","requestFileList","Array","isArray","existingSubmission","get","requestFile","allowedPatterns","map","m","mimeType","mimetype","join","size","maxSizeMB","toFixed","fileSizeMB","mediaDoc","create","file","relationTo","err","errorMessage","Error","submittedValue","submittedValueStr","String","fileIds","split","trim","Boolean","fileId","fileDoc","fileIsValid","fileMimeType","fileSize","filesize","doc","delete","formSubmissionOverrides","error","path","uploadFieldNames","Set","f","cleanedSubmissionData","has","updatedSubmissionUploads","from","entries","items","submissionUploads"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/collections/FormSubmissions/hooks/handleUploads.ts"],"sourcesContent":["import type {\n CollectionBeforeChangeHook,\n File,\n FileData,\n TypeWithID,\n UploadCollectionSlug,\n} from 'payload'\n\nimport { ValidationError } from 'payload'\nimport { validateMimeType } from 'payload/shared'\n\nimport type {\n FormBuilderPluginConfig,\n SubmissionUploadItem,\n SubmissionValue,\n UploadField,\n} from '../../../types.js'\n\ntype BeforeChangeParams = Parameters<CollectionBeforeChangeHook>[0]\n\ninterface UploadError {\n field: string\n message: string\n}\n\n/**\n * Handles upload fields in form submissions.\n *\n * This hook:\n * 1. Checks req.files for files matching upload field names (supports multiple files per field)\n * 2. Validates MIME types and file sizes before uploading\n * 3. Creates media documents in the appropriate upload collection\n * 4. Populates submissionUploads with proper Payload upload relationships\n * 5. Strips upload fields from submissionData (they live in submissionUploads only)\n * 6. Validates pre-uploaded file IDs for backwards compatibility\n */\nexport const handleUploads = async (\n beforeChangeParams: BeforeChangeParams,\n formConfig: FormBuilderPluginConfig,\n) => {\n const { data, operation, req } = beforeChangeParams\n const { payload } = req\n\n // Only handle on create\n if (operation !== 'create') {\n return data\n }\n\n const { form: formID, submissionData } = data || {}\n\n if (!formID || !submissionData) {\n return data\n }\n\n const formSlug = formConfig?.formOverrides?.slug || 'forms'\n\n // Fetch the form to get field configurations\n let form\n try {\n form = await payload.findByID({\n id: formID,\n collection: formSlug,\n overrideAccess: true,\n req,\n })\n } catch {\n // If form doesn't exist, let the form relationship validation handle it\n return data\n }\n\n const formFields = form?.fields || []\n const uploadFields = formFields.filter(\n (field: { blockType: string }) => field.blockType === 'upload',\n ) as UploadField[]\n\n if (uploadFields.length === 0) {\n return data\n }\n\n const submissionDataArray = submissionData as SubmissionValue[]\n\n // Build a map of pre-uploaded file IDs for backwards-compat lookup\n const submissionMap = new Map<string, { index: number; value: unknown }>()\n for (let i = 0; i < submissionDataArray.length; i++) {\n const item = submissionDataArray[i]\n if (item) {\n submissionMap.set(item.field, { index: i, value: item.value })\n }\n }\n\n // Get files from request (populated by addDataAndFileToRequest).\n // Multiple files with the same field name are stored as an array by buildFields.\n const requestFiles = req.files || {}\n\n const errors: UploadError[] = []\n // Accumulate upload items per field — one entry per upload field in the form\n const uploadsByField = new Map<string, SubmissionUploadItem[]>()\n // Track docs created during this hook so we can delete them if a later error causes rollback\n const createdDocs: Array<{ collection: string; id: number | string }> = []\n\n for (const uploadField of uploadFields) {\n const { name, maxFileSize, mimeTypes, multiple, required, uploadCollection } = uploadField\n const fieldLabel = uploadField.label || name\n\n uploadsByField.set(name, [])\n\n // Validate uploadCollection is configured in this plugin (defence-in-depth against tampered form docs)\n if (!formConfig.uploadCollections?.includes(uploadCollection)) {\n errors.push({\n field: name,\n message: `Upload collection \"${uploadCollection}\" is not configured in this plugin`,\n })\n continue\n }\n\n // Normalize: multiple files with the same field name arrive as an array\n const rawFile = requestFiles[name]\n const requestFileList: File[] = rawFile ? (Array.isArray(rawFile) ? rawFile : [rawFile]) : []\n\n const existingSubmission = submissionMap.get(name)\n\n if (requestFileList.length > 0) {\n // Guard: reject multiple files when the field doesn't allow them\n if (!multiple && requestFileList.length > 1) {\n errors.push({\n field: name,\n message: `${fieldLabel} does not allow multiple files`,\n })\n continue\n }\n\n // Direct file upload(s) from request\n for (const requestFile of requestFileList) {\n // Validate MIME type before uploading\n if (mimeTypes && mimeTypes.length > 0) {\n const allowedPatterns = mimeTypes.map((m) => m.mimeType)\n\n if (!validateMimeType(requestFile.mimetype, allowedPatterns)) {\n errors.push({\n field: name,\n message: `${fieldLabel}: File type \"${requestFile.mimetype}\" is not allowed. Allowed types: ${allowedPatterns.join(', ')}`,\n })\n continue\n }\n }\n\n // Validate file size before uploading\n if (maxFileSize && maxFileSize > 0 && requestFile.size > maxFileSize) {\n const maxSizeMB = (maxFileSize / (1024 * 1024)).toFixed(2)\n const fileSizeMB = (requestFile.size / (1024 * 1024)).toFixed(2)\n\n errors.push({\n field: name,\n message: `${fieldLabel}: File size (${fileSizeMB}MB) exceeds maximum allowed size (${maxSizeMB}MB)`,\n })\n continue\n }\n\n // Create the media document.\n // Note: payload.create writes the file to storage before the DB row exists. If\n // the DB write throws, createdDocs never records the entry and the file on disk\n // will not be cleaned up by the rollback loop below. Payload core owns that\n // rollback path — we only clean up docs we successfully created here.\n try {\n const mediaDoc = await payload.create({\n collection: uploadCollection,\n data: {},\n file: {\n name: requestFile.name,\n data: requestFile.data,\n mimetype: requestFile.mimetype,\n size: requestFile.size,\n },\n overrideAccess: true,\n req,\n })\n\n createdDocs.push({ id: mediaDoc.id, collection: uploadCollection })\n uploadsByField.get(name)!.push({ relationTo: uploadCollection, value: mediaDoc.id })\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error'\n\n errors.push({\n field: name,\n message: `${fieldLabel}: Failed to upload file - ${errorMessage}`,\n })\n }\n }\n } else if (existingSubmission && existingSubmission.value) {\n // Backwards compatibility: validate pre-uploaded file IDs\n const submittedValue = existingSubmission.value\n const submittedValueStr =\n typeof submittedValue === 'string' || typeof submittedValue === 'number'\n ? String(submittedValue)\n : ''\n\n if (!submittedValueStr) {\n if (required) {\n errors.push({ field: name, message: `${fieldLabel} is required` })\n }\n continue\n }\n\n // Guard: reject comma-separated IDs when the field doesn't allow multiple files.\n // Assumes IDs never contain literal commas — true for ObjectIDs/UUIDs and any numeric ID.\n if (!multiple && submittedValueStr.includes(',')) {\n errors.push({\n field: name,\n message: `${fieldLabel} does not allow multiple files`,\n })\n continue\n }\n\n // Parse file IDs (comma-separated for multiple files)\n const fileIds = multiple\n ? submittedValueStr\n .split(',')\n .map((id) => id.trim())\n .filter(Boolean)\n : [submittedValueStr]\n\n // Validate each file\n for (const fileId of fileIds) {\n let fileDoc: (FileData & TypeWithID) | null = null\n let fileIsValid = true\n\n try {\n fileDoc = (await payload.findByID({\n id: fileId,\n collection: uploadCollection,\n overrideAccess: true,\n req,\n })) as FileData & TypeWithID\n } catch {\n errors.push({\n field: name,\n message: `${fieldLabel}: File with ID \"${fileId}\" not found in collection \"${uploadCollection}\"`,\n })\n fileIsValid = false\n continue\n }\n\n if (!fileDoc) {\n errors.push({\n field: name,\n message: `${fieldLabel}: File with ID \"${fileId}\" not found`,\n })\n fileIsValid = false\n continue\n }\n\n // Validate mimeType\n if (mimeTypes && mimeTypes.length > 0) {\n const allowedPatterns = mimeTypes.map((m) => m.mimeType)\n const fileMimeType = fileDoc.mimeType\n\n if (fileMimeType && !validateMimeType(fileMimeType, allowedPatterns)) {\n errors.push({\n field: name,\n message: `${fieldLabel}: File type \"${fileMimeType}\" is not allowed. Allowed types: ${allowedPatterns.join(', ')}`,\n })\n fileIsValid = false\n continue\n }\n }\n\n // Validate file size\n if (maxFileSize && maxFileSize > 0) {\n const fileSize = fileDoc.filesize\n\n if (fileSize && fileSize > maxFileSize) {\n const maxSizeMB = (maxFileSize / (1024 * 1024)).toFixed(2)\n const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(2)\n\n errors.push({\n field: name,\n message: `${fieldLabel}: File size (${fileSizeMB}MB) exceeds maximum allowed size (${maxSizeMB}MB)`,\n })\n fileIsValid = false\n }\n }\n\n if (fileIsValid) {\n uploadsByField.get(name)!.push({ relationTo: uploadCollection, value: fileDoc.id })\n }\n }\n } else if (required) {\n // No file in request and no pre-uploaded file ID, but field is required\n errors.push({\n field: name,\n message: `${fieldLabel} is required`,\n })\n }\n }\n\n if (errors.length > 0) {\n // Best-effort cleanup of any docs created before the error was detected\n for (const doc of createdDocs) {\n try {\n await payload.delete({ id: doc.id, collection: doc.collection, overrideAccess: true, req })\n } catch {\n // best-effort — don't mask the original validation error\n }\n }\n\n throw new ValidationError({\n collection: formConfig?.formSubmissionOverrides?.slug || 'form-submissions',\n errors: errors.map((error) => ({\n message: error.message,\n path: error.field,\n })),\n })\n }\n\n // Strip upload fields from submissionData — they are stored in submissionUploads only\n const uploadFieldNames = new Set(uploadFields.map((f) => f.name))\n const cleanedSubmissionData = submissionDataArray.filter(\n (item) => !uploadFieldNames.has(item.field),\n )\n\n // One entry per upload field; omit fields with no successful uploads\n const updatedSubmissionUploads = Array.from(uploadsByField.entries())\n .filter(([, items]) => items.length > 0)\n .map(([field, value]) => ({ field, value }))\n\n return {\n ...data,\n submissionData: cleanedSubmissionData,\n submissionUploads: updatedSubmissionUploads,\n }\n}\n"],"names":["ValidationError","validateMimeType","handleUploads","beforeChangeParams","formConfig","data","operation","req","payload","form","formID","submissionData","formSlug","formOverrides","slug","findByID","id","collection","overrideAccess","formFields","fields","uploadFields","filter","field","blockType","length","submissionDataArray","submissionMap","Map","i","item","set","index","value","requestFiles","files","errors","uploadsByField","createdDocs","uploadField","name","maxFileSize","mimeTypes","multiple","required","uploadCollection","fieldLabel","label","uploadCollections","includes","push","message","rawFile","requestFileList","Array","isArray","existingSubmission","get","requestFile","allowedPatterns","map","m","mimeType","mimetype","join","size","maxSizeMB","toFixed","fileSizeMB","mediaDoc","create","file","relationTo","err","errorMessage","Error","submittedValue","submittedValueStr","String","fileIds","split","trim","Boolean","fileId","fileDoc","fileIsValid","fileMimeType","fileSize","filesize","doc","delete","formSubmissionOverrides","error","path","uploadFieldNames","Set","f","cleanedSubmissionData","has","updatedSubmissionUploads","from","entries","items","submissionUploads"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sendEmail.d.ts","sourceRoot":"","sources":["../../../../src/collections/FormSubmissions/hooks/sendEmail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAExD,OAAO,KAAK,EAAyB,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAKvF,KAAK,iBAAiB,GAAG,UAAU,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAA;AAEjE,eAAO,MAAM,SAAS,0BACG,iBAAiB,cAC5B,uBAAuB,kBA8FpC,CAAA"}
1
+ {"version":3,"file":"sendEmail.d.ts","sourceRoot":"","sources":["../../../../src/collections/FormSubmissions/hooks/sendEmail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAExD,OAAO,KAAK,EAAyB,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAKvF,KAAK,iBAAiB,GAAG,UAAU,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAA;AAEjE,eAAO,MAAM,SAAS,0BACG,iBAAiB,cAC5B,uBAAuB,kBA+FpC,CAAA"}
@@ -10,6 +10,7 @@ export const sendEmail = async (afterChangeParameters, formConfig)=>{
10
10
  id: formID,
11
11
  collection: formOverrides?.slug || 'forms',
12
12
  locale,
13
+ overrideAccess: true,
13
14
  req
14
15
  });
15
16
  const emails = form.emails;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/collections/FormSubmissions/hooks/sendEmail.ts"],"sourcesContent":["import type { CollectionAfterChangeHook } from 'payload'\n\nimport type { Email, FormattedEmail, FormBuilderPluginConfig } from '../../../types.js'\n\nimport { serializeLexical } from '../../../utilities/lexical/serializeLexical.js'\nimport { replaceDoubleCurlys } from '../../../utilities/replaceDoubleCurlys.js'\n\ntype AfterChangeParams = Parameters<CollectionAfterChangeHook>[0]\n\nexport const sendEmail = async (\n afterChangeParameters: AfterChangeParams,\n formConfig: FormBuilderPluginConfig,\n) => {\n if (afterChangeParameters.operation === 'create') {\n const {\n data,\n doc: { id: formSubmissionID },\n req: { locale, payload },\n req,\n } = afterChangeParameters\n\n const { form: formID, submissionData: submissionDataFromProps } = data || {}\n const { beforeEmail, defaultToEmail, formOverrides } = formConfig || {}\n\n try {\n const form = await payload.findByID({\n id: formID,\n collection: formOverrides?.slug || 'forms',\n locale,\n req,\n })\n\n const emails = form.emails as Email[]\n\n const submissionData = [\n ...submissionDataFromProps,\n {\n field: 'formSubmissionID',\n value: String(formSubmissionID),\n },\n ]\n\n if (emails && emails.length) {\n const formattedEmails: FormattedEmail[] = await Promise.all(\n emails.map(async (email: Email): Promise<FormattedEmail> => {\n const {\n bcc: emailBCC,\n cc: emailCC,\n emailFrom,\n emailTo: emailToFromConfig,\n message,\n replyTo: emailReplyTo,\n subject,\n } = email\n\n const emailTo = emailToFromConfig || defaultToEmail || payload.email.defaultFromAddress\n\n const to = replaceDoubleCurlys(emailTo, submissionData)\n const cc = emailCC ? replaceDoubleCurlys(emailCC, submissionData) : ''\n const bcc = emailBCC ? replaceDoubleCurlys(emailBCC, submissionData) : ''\n const from = replaceDoubleCurlys(emailFrom, submissionData)\n const replyTo = replaceDoubleCurlys(emailReplyTo || emailFrom, submissionData)\n\n const serializedMessage = await serializeLexical(message, submissionData)\n\n return {\n bcc,\n cc,\n from,\n html: `<div>${serializedMessage}</div>`,\n replyTo,\n subject: replaceDoubleCurlys(subject, submissionData),\n to,\n }\n }),\n )\n\n let emailsToSend = formattedEmails\n\n if (typeof beforeEmail === 'function') {\n emailsToSend = await beforeEmail(formattedEmails, afterChangeParameters)\n }\n\n await Promise.all(\n emailsToSend.map(async (email) => {\n const { to } = email\n try {\n const emailPromise = await payload.sendEmail(email)\n return emailPromise\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error while sending email to address: ${to}. Email not sent.`,\n })\n }\n }),\n )\n } else {\n payload.logger.info({ msg: 'No emails to send.' })\n }\n } catch (err: unknown) {\n const msg = `Error while sending one or more emails in form submission id: ${formSubmissionID}.`\n payload.logger.error({ err, msg })\n }\n }\n}\n"],"names":["serializeLexical","replaceDoubleCurlys","sendEmail","afterChangeParameters","formConfig","operation","data","doc","id","formSubmissionID","req","locale","payload","form","formID","submissionData","submissionDataFromProps","beforeEmail","defaultToEmail","formOverrides","findByID","collection","slug","emails","field","value","String","length","formattedEmails","Promise","all","map","email","bcc","emailBCC","cc","emailCC","emailFrom","emailTo","emailToFromConfig","message","replyTo","emailReplyTo","subject","defaultFromAddress","to","from","serializedMessage","html","emailsToSend","emailPromise","err","logger","error","msg","info"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,iDAAgD;AACjF,SAASC,mBAAmB,QAAQ,4CAA2C;AAI/E,OAAO,MAAMC,YAAY,OACvBC,uBACAC;IAEA,IAAID,sBAAsBE,SAAS,KAAK,UAAU;QAChD,MAAM,EACJC,IAAI,EACJC,KAAK,EAAEC,IAAIC,gBAAgB,EAAE,EAC7BC,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAE,EACxBF,GAAG,EACJ,GAAGP;QAEJ,MAAM,EAAEU,MAAMC,MAAM,EAAEC,gBAAgBC,uBAAuB,EAAE,GAAGV,QAAQ,CAAC;QAC3E,MAAM,EAAEW,WAAW,EAAEC,cAAc,EAAEC,aAAa,EAAE,GAAGf,cAAc,CAAC;QAEtE,IAAI;YACF,MAAMS,OAAO,MAAMD,QAAQQ,QAAQ,CAAC;gBAClCZ,IAAIM;gBACJO,YAAYF,eAAeG,QAAQ;gBACnCX;gBACAD;YACF;YAEA,MAAMa,SAASV,KAAKU,MAAM;YAE1B,MAAMR,iBAAiB;mBAClBC;gBACH;oBACEQ,OAAO;oBACPC,OAAOC,OAAOjB;gBAChB;aACD;YAED,IAAIc,UAAUA,OAAOI,MAAM,EAAE;gBAC3B,MAAMC,kBAAoC,MAAMC,QAAQC,GAAG,CACzDP,OAAOQ,GAAG,CAAC,OAAOC;oBAChB,MAAM,EACJC,KAAKC,QAAQ,EACbC,IAAIC,OAAO,EACXC,SAAS,EACTC,SAASC,iBAAiB,EAC1BC,OAAO,EACPC,SAASC,YAAY,EACrBC,OAAO,EACR,GAAGX;oBAEJ,MAAMM,UAAUC,qBAAqBrB,kBAAkBN,QAAQoB,KAAK,CAACY,kBAAkB;oBAEvF,MAAMC,KAAK5C,oBAAoBqC,SAASvB;oBACxC,MAAMoB,KAAKC,UAAUnC,oBAAoBmC,SAASrB,kBAAkB;oBACpE,MAAMkB,MAAMC,WAAWjC,oBAAoBiC,UAAUnB,kBAAkB;oBACvE,MAAM+B,OAAO7C,oBAAoBoC,WAAWtB;oBAC5C,MAAM0B,UAAUxC,oBAAoByC,gBAAgBL,WAAWtB;oBAE/D,MAAMgC,oBAAoB,MAAM/C,iBAAiBwC,SAASzB;oBAE1D,OAAO;wBACLkB;wBACAE;wBACAW;wBACAE,MAAM,CAAC,KAAK,EAAED,kBAAkB,MAAM,CAAC;wBACvCN;wBACAE,SAAS1C,oBAAoB0C,SAAS5B;wBACtC8B;oBACF;gBACF;gBAGF,IAAII,eAAerB;gBAEnB,IAAI,OAAOX,gBAAgB,YAAY;oBACrCgC,eAAe,MAAMhC,YAAYW,iBAAiBzB;gBACpD;gBAEA,MAAM0B,QAAQC,GAAG,CACfmB,aAAalB,GAAG,CAAC,OAAOC;oBACtB,MAAM,EAAEa,EAAE,EAAE,GAAGb;oBACf,IAAI;wBACF,MAAMkB,eAAe,MAAMtC,QAAQV,SAAS,CAAC8B;wBAC7C,OAAOkB;oBACT,EAAE,OAAOC,KAAc;wBACrBvC,QAAQwC,MAAM,CAACC,KAAK,CAAC;4BACnBF;4BACAG,KAAK,CAAC,sCAAsC,EAAET,GAAG,iBAAiB,CAAC;wBACrE;oBACF;gBACF;YAEJ,OAAO;gBACLjC,QAAQwC,MAAM,CAACG,IAAI,CAAC;oBAAED,KAAK;gBAAqB;YAClD;QACF,EAAE,OAAOH,KAAc;YACrB,MAAMG,MAAM,CAAC,8DAA8D,EAAE7C,iBAAiB,CAAC,CAAC;YAChGG,QAAQwC,MAAM,CAACC,KAAK,CAAC;gBAAEF;gBAAKG;YAAI;QAClC;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../../src/collections/FormSubmissions/hooks/sendEmail.ts"],"sourcesContent":["import type { CollectionAfterChangeHook } from 'payload'\n\nimport type { Email, FormattedEmail, FormBuilderPluginConfig } from '../../../types.js'\n\nimport { serializeLexical } from '../../../utilities/lexical/serializeLexical.js'\nimport { replaceDoubleCurlys } from '../../../utilities/replaceDoubleCurlys.js'\n\ntype AfterChangeParams = Parameters<CollectionAfterChangeHook>[0]\n\nexport const sendEmail = async (\n afterChangeParameters: AfterChangeParams,\n formConfig: FormBuilderPluginConfig,\n) => {\n if (afterChangeParameters.operation === 'create') {\n const {\n data,\n doc: { id: formSubmissionID },\n req: { locale, payload },\n req,\n } = afterChangeParameters\n\n const { form: formID, submissionData: submissionDataFromProps } = data || {}\n const { beforeEmail, defaultToEmail, formOverrides } = formConfig || {}\n\n try {\n const form = await payload.findByID({\n id: formID,\n collection: formOverrides?.slug || 'forms',\n locale,\n overrideAccess: true,\n req,\n })\n\n const emails = form.emails as Email[]\n\n const submissionData = [\n ...submissionDataFromProps,\n {\n field: 'formSubmissionID',\n value: String(formSubmissionID),\n },\n ]\n\n if (emails && emails.length) {\n const formattedEmails: FormattedEmail[] = await Promise.all(\n emails.map(async (email: Email): Promise<FormattedEmail> => {\n const {\n bcc: emailBCC,\n cc: emailCC,\n emailFrom,\n emailTo: emailToFromConfig,\n message,\n replyTo: emailReplyTo,\n subject,\n } = email\n\n const emailTo = emailToFromConfig || defaultToEmail || payload.email.defaultFromAddress\n\n const to = replaceDoubleCurlys(emailTo, submissionData)\n const cc = emailCC ? replaceDoubleCurlys(emailCC, submissionData) : ''\n const bcc = emailBCC ? replaceDoubleCurlys(emailBCC, submissionData) : ''\n const from = replaceDoubleCurlys(emailFrom, submissionData)\n const replyTo = replaceDoubleCurlys(emailReplyTo || emailFrom, submissionData)\n\n const serializedMessage = await serializeLexical(message, submissionData)\n\n return {\n bcc,\n cc,\n from,\n html: `<div>${serializedMessage}</div>`,\n replyTo,\n subject: replaceDoubleCurlys(subject, submissionData),\n to,\n }\n }),\n )\n\n let emailsToSend = formattedEmails\n\n if (typeof beforeEmail === 'function') {\n emailsToSend = await beforeEmail(formattedEmails, afterChangeParameters)\n }\n\n await Promise.all(\n emailsToSend.map(async (email) => {\n const { to } = email\n try {\n const emailPromise = await payload.sendEmail(email)\n return emailPromise\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error while sending email to address: ${to}. Email not sent.`,\n })\n }\n }),\n )\n } else {\n payload.logger.info({ msg: 'No emails to send.' })\n }\n } catch (err: unknown) {\n const msg = `Error while sending one or more emails in form submission id: ${formSubmissionID}.`\n payload.logger.error({ err, msg })\n }\n }\n}\n"],"names":["serializeLexical","replaceDoubleCurlys","sendEmail","afterChangeParameters","formConfig","operation","data","doc","id","formSubmissionID","req","locale","payload","form","formID","submissionData","submissionDataFromProps","beforeEmail","defaultToEmail","formOverrides","findByID","collection","slug","overrideAccess","emails","field","value","String","length","formattedEmails","Promise","all","map","email","bcc","emailBCC","cc","emailCC","emailFrom","emailTo","emailToFromConfig","message","replyTo","emailReplyTo","subject","defaultFromAddress","to","from","serializedMessage","html","emailsToSend","emailPromise","err","logger","error","msg","info"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,iDAAgD;AACjF,SAASC,mBAAmB,QAAQ,4CAA2C;AAI/E,OAAO,MAAMC,YAAY,OACvBC,uBACAC;IAEA,IAAID,sBAAsBE,SAAS,KAAK,UAAU;QAChD,MAAM,EACJC,IAAI,EACJC,KAAK,EAAEC,IAAIC,gBAAgB,EAAE,EAC7BC,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAE,EACxBF,GAAG,EACJ,GAAGP;QAEJ,MAAM,EAAEU,MAAMC,MAAM,EAAEC,gBAAgBC,uBAAuB,EAAE,GAAGV,QAAQ,CAAC;QAC3E,MAAM,EAAEW,WAAW,EAAEC,cAAc,EAAEC,aAAa,EAAE,GAAGf,cAAc,CAAC;QAEtE,IAAI;YACF,MAAMS,OAAO,MAAMD,QAAQQ,QAAQ,CAAC;gBAClCZ,IAAIM;gBACJO,YAAYF,eAAeG,QAAQ;gBACnCX;gBACAY,gBAAgB;gBAChBb;YACF;YAEA,MAAMc,SAASX,KAAKW,MAAM;YAE1B,MAAMT,iBAAiB;mBAClBC;gBACH;oBACES,OAAO;oBACPC,OAAOC,OAAOlB;gBAChB;aACD;YAED,IAAIe,UAAUA,OAAOI,MAAM,EAAE;gBAC3B,MAAMC,kBAAoC,MAAMC,QAAQC,GAAG,CACzDP,OAAOQ,GAAG,CAAC,OAAOC;oBAChB,MAAM,EACJC,KAAKC,QAAQ,EACbC,IAAIC,OAAO,EACXC,SAAS,EACTC,SAASC,iBAAiB,EAC1BC,OAAO,EACPC,SAASC,YAAY,EACrBC,OAAO,EACR,GAAGX;oBAEJ,MAAMM,UAAUC,qBAAqBtB,kBAAkBN,QAAQqB,KAAK,CAACY,kBAAkB;oBAEvF,MAAMC,KAAK7C,oBAAoBsC,SAASxB;oBACxC,MAAMqB,KAAKC,UAAUpC,oBAAoBoC,SAAStB,kBAAkB;oBACpE,MAAMmB,MAAMC,WAAWlC,oBAAoBkC,UAAUpB,kBAAkB;oBACvE,MAAMgC,OAAO9C,oBAAoBqC,WAAWvB;oBAC5C,MAAM2B,UAAUzC,oBAAoB0C,gBAAgBL,WAAWvB;oBAE/D,MAAMiC,oBAAoB,MAAMhD,iBAAiByC,SAAS1B;oBAE1D,OAAO;wBACLmB;wBACAE;wBACAW;wBACAE,MAAM,CAAC,KAAK,EAAED,kBAAkB,MAAM,CAAC;wBACvCN;wBACAE,SAAS3C,oBAAoB2C,SAAS7B;wBACtC+B;oBACF;gBACF;gBAGF,IAAII,eAAerB;gBAEnB,IAAI,OAAOZ,gBAAgB,YAAY;oBACrCiC,eAAe,MAAMjC,YAAYY,iBAAiB1B;gBACpD;gBAEA,MAAM2B,QAAQC,GAAG,CACfmB,aAAalB,GAAG,CAAC,OAAOC;oBACtB,MAAM,EAAEa,EAAE,EAAE,GAAGb;oBACf,IAAI;wBACF,MAAMkB,eAAe,MAAMvC,QAAQV,SAAS,CAAC+B;wBAC7C,OAAOkB;oBACT,EAAE,OAAOC,KAAc;wBACrBxC,QAAQyC,MAAM,CAACC,KAAK,CAAC;4BACnBF;4BACAG,KAAK,CAAC,sCAAsC,EAAET,GAAG,iBAAiB,CAAC;wBACrE;oBACF;gBACF;YAEJ,OAAO;gBACLlC,QAAQyC,MAAM,CAACG,IAAI,CAAC;oBAAED,KAAK;gBAAqB;YAClD;QACF,EAAE,OAAOH,KAAc;YACrB,MAAMG,MAAM,CAAC,8DAA8D,EAAE9C,iBAAiB,CAAC,CAAC;YAChGG,QAAQyC,MAAM,CAACC,KAAK,CAAC;gBAAEF;gBAAKG;YAAI;QAClC;IACF;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/FormSubmissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAElF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAQ7D,eAAO,MAAM,4BAA4B,eAC3B,uBAAuB,KAClC,gBAiIF,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/FormSubmissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAElF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAQ7D,eAAO,MAAM,4BAA4B,eAC3B,uBAAuB,KAClC,gBAkIF,CAAA"}
@@ -24,6 +24,7 @@ export const generateSubmissionCollection = (formConfig)=>{
24
24
  _existingForm = await payload.findByID({
25
25
  id: value,
26
26
  collection: formSlug,
27
+ overrideAccess: true,
27
28
  req
28
29
  });
29
30
  return true;
@@ -91,7 +92,7 @@ export const generateSubmissionCollection = (formConfig)=>{
91
92
  slug: formConfig?.formSubmissionOverrides?.slug || 'form-submissions',
92
93
  access: {
93
94
  create: ()=>true,
94
- read: ({ req: { user } })=>!!user,
95
+ read: ({ req })=>req.user?.collection === req.payload.config.admin.user,
95
96
  update: ()=>false,
96
97
  ...formConfig?.formSubmissionOverrides?.access || {}
97
98
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/FormSubmissions/index.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook, CollectionConfig, Field } from 'payload'\n\nimport type { FormBuilderPluginConfig } from '../../types.js'\n\nimport { defaultPaymentFields } from './fields/defaultPaymentFields.js'\nimport { createCharge } from './hooks/createCharge.js'\nimport { handleUploads } from './hooks/handleUploads.js'\nimport { sendEmail } from './hooks/sendEmail.js'\n\n// all settings can be overridden by the config\nexport const generateSubmissionCollection = (\n formConfig: FormBuilderPluginConfig,\n): CollectionConfig => {\n const formSlug = formConfig?.formOverrides?.slug || 'forms'\n\n const enablePaymentFields = Boolean(formConfig?.fields?.payment)\n\n const uploadCollections = formConfig?.uploadCollections\n\n const defaultFields: Field[] = [\n {\n name: 'form',\n type: 'relationship',\n relationTo: formSlug,\n required: true,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n validate: async (value, { req: { payload }, req }) => {\n /* Don't run in the client side */\n if (!payload) {\n return true\n }\n\n if (payload) {\n let _existingForm\n\n try {\n _existingForm = await payload.findByID({\n id: value,\n collection: formSlug,\n req,\n })\n\n return true\n } catch (_error) {\n return 'Cannot create this submission because this form does not exist.'\n }\n }\n },\n },\n {\n name: 'submissionData',\n type: 'array',\n fields: [\n {\n name: 'field',\n type: 'text',\n required: true,\n },\n {\n name: 'value',\n type: 'textarea',\n required: true,\n validate: (value: unknown) => {\n // TODO:\n // create a validation function that dynamically\n // relies on the field type and its options as configured.\n\n // How to access sibling data from this field?\n // Need the `name` of the field in order to validate it.\n\n // Might not be possible to use this validation function.\n // Instead, might need to do all validation in a `beforeValidate` collection hook.\n\n if (typeof value !== 'undefined') {\n return true\n }\n\n return 'This field is required.'\n },\n },\n ],\n },\n ...(uploadCollections && uploadCollections.length > 0\n ? ([\n {\n name: 'submissionUploads',\n type: 'array',\n fields: [\n {\n name: 'field',\n type: 'text',\n required: true,\n },\n {\n name: 'value',\n type: 'upload',\n hasMany: true,\n relationTo: uploadCollections,\n required: true,\n },\n ],\n },\n ] as Field[])\n : []),\n ...(enablePaymentFields ? [defaultPaymentFields] : []),\n ]\n\n const newConfig: CollectionConfig = {\n ...(formConfig?.formSubmissionOverrides || {}),\n slug: formConfig?.formSubmissionOverrides?.slug || 'form-submissions',\n access: {\n create: () => true,\n read: ({ req: { user } }) => !!user, // logged-in users,\n update: () => false,\n ...(formConfig?.formSubmissionOverrides?.access || {}),\n },\n admin: {\n ...(formConfig?.formSubmissionOverrides?.admin || {}),\n enableRichTextRelationship: false,\n },\n fields:\n formConfig?.formSubmissionOverrides?.fields &&\n typeof formConfig?.formSubmissionOverrides?.fields === 'function'\n ? formConfig.formSubmissionOverrides.fields({ defaultFields })\n : defaultFields,\n hooks: {\n ...(formConfig?.formSubmissionOverrides?.hooks || {}),\n afterChange: [\n (data) => sendEmail(data, formConfig),\n ...(formConfig?.formSubmissionOverrides?.hooks?.afterChange || []),\n ],\n beforeChange: [\n ...(uploadCollections && uploadCollections.length > 0\n ? [(data: Parameters<CollectionBeforeChangeHook>[0]) => handleUploads(data, formConfig)]\n : []),\n (data) => createCharge(data, formConfig),\n ...(formConfig?.formSubmissionOverrides?.hooks?.beforeChange || []),\n ],\n },\n }\n return newConfig\n}\n"],"names":["defaultPaymentFields","createCharge","handleUploads","sendEmail","generateSubmissionCollection","formConfig","formSlug","formOverrides","slug","enablePaymentFields","Boolean","fields","payment","uploadCollections","defaultFields","name","type","relationTo","required","validate","value","req","payload","_existingForm","findByID","id","collection","_error","length","hasMany","newConfig","formSubmissionOverrides","access","create","read","user","update","admin","enableRichTextRelationship","hooks","afterChange","data","beforeChange"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/collections/FormSubmissions/index.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook, CollectionConfig, Field } from 'payload'\n\nimport type { FormBuilderPluginConfig } from '../../types.js'\n\nimport { defaultPaymentFields } from './fields/defaultPaymentFields.js'\nimport { createCharge } from './hooks/createCharge.js'\nimport { handleUploads } from './hooks/handleUploads.js'\nimport { sendEmail } from './hooks/sendEmail.js'\n\n// all settings can be overridden by the config\nexport const generateSubmissionCollection = (\n formConfig: FormBuilderPluginConfig,\n): CollectionConfig => {\n const formSlug = formConfig?.formOverrides?.slug || 'forms'\n\n const enablePaymentFields = Boolean(formConfig?.fields?.payment)\n\n const uploadCollections = formConfig?.uploadCollections\n\n const defaultFields: Field[] = [\n {\n name: 'form',\n type: 'relationship',\n relationTo: formSlug,\n required: true,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n validate: async (value, { req: { payload }, req }) => {\n /* Don't run in the client side */\n if (!payload) {\n return true\n }\n\n if (payload) {\n let _existingForm\n\n try {\n _existingForm = await payload.findByID({\n id: value,\n collection: formSlug,\n overrideAccess: true,\n req,\n })\n\n return true\n } catch (_error) {\n return 'Cannot create this submission because this form does not exist.'\n }\n }\n },\n },\n {\n name: 'submissionData',\n type: 'array',\n fields: [\n {\n name: 'field',\n type: 'text',\n required: true,\n },\n {\n name: 'value',\n type: 'textarea',\n required: true,\n validate: (value: unknown) => {\n // TODO:\n // create a validation function that dynamically\n // relies on the field type and its options as configured.\n\n // How to access sibling data from this field?\n // Need the `name` of the field in order to validate it.\n\n // Might not be possible to use this validation function.\n // Instead, might need to do all validation in a `beforeValidate` collection hook.\n\n if (typeof value !== 'undefined') {\n return true\n }\n\n return 'This field is required.'\n },\n },\n ],\n },\n ...(uploadCollections && uploadCollections.length > 0\n ? ([\n {\n name: 'submissionUploads',\n type: 'array',\n fields: [\n {\n name: 'field',\n type: 'text',\n required: true,\n },\n {\n name: 'value',\n type: 'upload',\n hasMany: true,\n relationTo: uploadCollections,\n required: true,\n },\n ],\n },\n ] as Field[])\n : []),\n ...(enablePaymentFields ? [defaultPaymentFields] : []),\n ]\n\n const newConfig: CollectionConfig = {\n ...(formConfig?.formSubmissionOverrides || {}),\n slug: formConfig?.formSubmissionOverrides?.slug || 'form-submissions',\n access: {\n create: () => true,\n read: ({ req }) => req.user?.collection === req.payload.config.admin.user,\n update: () => false,\n ...(formConfig?.formSubmissionOverrides?.access || {}),\n },\n admin: {\n ...(formConfig?.formSubmissionOverrides?.admin || {}),\n enableRichTextRelationship: false,\n },\n fields:\n formConfig?.formSubmissionOverrides?.fields &&\n typeof formConfig?.formSubmissionOverrides?.fields === 'function'\n ? formConfig.formSubmissionOverrides.fields({ defaultFields })\n : defaultFields,\n hooks: {\n ...(formConfig?.formSubmissionOverrides?.hooks || {}),\n afterChange: [\n (data) => sendEmail(data, formConfig),\n ...(formConfig?.formSubmissionOverrides?.hooks?.afterChange || []),\n ],\n beforeChange: [\n ...(uploadCollections && uploadCollections.length > 0\n ? [(data: Parameters<CollectionBeforeChangeHook>[0]) => handleUploads(data, formConfig)]\n : []),\n (data) => createCharge(data, formConfig),\n ...(formConfig?.formSubmissionOverrides?.hooks?.beforeChange || []),\n ],\n },\n }\n return newConfig\n}\n"],"names":["defaultPaymentFields","createCharge","handleUploads","sendEmail","generateSubmissionCollection","formConfig","formSlug","formOverrides","slug","enablePaymentFields","Boolean","fields","payment","uploadCollections","defaultFields","name","type","relationTo","required","validate","value","req","payload","_existingForm","findByID","id","collection","overrideAccess","_error","length","hasMany","newConfig","formSubmissionOverrides","access","create","read","user","config","admin","update","enableRichTextRelationship","hooks","afterChange","data","beforeChange"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
- import type { TextFieldClientComponent } from 'payload';
2
- export declare const DynamicPriceSelector: TextFieldClientComponent;
1
+ import type { TextFieldClientProps } from 'payload';
2
+ import React from 'react';
3
+ export declare const DynamicPriceSelector: React.FC<TextFieldClientProps>;
3
4
  //# sourceMappingURL=DynamicPriceSelector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DynamicPriceSelector.d.ts","sourceRoot":"","sources":["../../../src/collections/Forms/DynamicPriceSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAQ,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAU7D,eAAO,MAAM,oBAAoB,EAAE,wBA2DlC,CAAA"}
1
+ {"version":3,"file":"DynamicPriceSelector.d.ts","sourceRoot":"","sources":["../../../src/collections/Forms/DynamicPriceSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAQ,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAGzD,OAAO,KAA8B,MAAM,OAAO,CAAA;AAOlD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA2D/D,CAAA"}
@@ -36,7 +36,7 @@ export const DynamicPriceSelector = (props)=>{
36
36
  ...props
37
37
  });
38
38
  }
39
- const localeCode = typeof locale === 'object' && 'code' in locale ? locale.code : locale;
39
+ const localeCode = locale?.code ?? 'en';
40
40
  const localLabels = typeof field.label === 'object' ? field.label : {
41
41
  [localeCode]: field.label
42
42
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/Forms/DynamicPriceSelector.tsx"],"sourcesContent":["'use client'\n\nimport type { Data, TextFieldClientComponent } from 'payload'\n\nimport { TextField, useLocale, useWatchForm } from '@payloadcms/ui'\nimport React, { useEffect, useState } from 'react'\n\ntype FieldWithID = {\n id: string\n name: string\n}\n\nexport const DynamicPriceSelector: TextFieldClientComponent = (props) => {\n const { field, path } = props\n\n const { fields, getData, getDataByPath } = useWatchForm()\n\n const locale = useLocale()\n\n const [isNumberField, setIsNumberField] = useState<boolean>()\n const [valueType, setValueType] = useState<'static' | 'valueOfField'>()\n\n // only number fields can use 'valueOfField`\n useEffect(() => {\n if (path) {\n const parentPath = path.split('.').slice(0, -1).join('.')\n const paymentFieldData: any = getDataByPath(parentPath)\n\n if (paymentFieldData) {\n const { fieldToUse, valueType } = paymentFieldData\n\n setValueType(valueType)\n\n const { fields: allFields }: Data = getData()\n const field = allFields.find((field: FieldWithID) => field.name === fieldToUse)\n\n if (field) {\n const { blockType } = field\n setIsNumberField(blockType === 'number')\n }\n }\n }\n }, [fields, getDataByPath, getData, path])\n\n // TODO: make this a number field, block by Payload\n if (valueType === 'static') {\n return <TextField {...props} />\n }\n\n const localeCode = typeof locale === 'object' && 'code' in locale ? locale.code : locale\n\n const localLabels = typeof field.label === 'object' ? field.label : { [localeCode]: field.label }\n\n const labelValue = localLabels[localeCode] || localLabels['en'] || ''\n\n if (valueType === 'valueOfField' && !isNumberField) {\n return (\n <div>\n <div>{String(labelValue)}</div>\n <div\n style={{\n color: '#9A9A9A',\n }}\n >\n The selected field must be a number field.\n </div>\n </div>\n )\n }\n\n return null\n}\n"],"names":["TextField","useLocale","useWatchForm","React","useEffect","useState","DynamicPriceSelector","props","field","path","fields","getData","getDataByPath","locale","isNumberField","setIsNumberField","valueType","setValueType","parentPath","split","slice","join","paymentFieldData","fieldToUse","allFields","find","name","blockType","localeCode","code","localLabels","label","labelValue","div","String","style","color"],"mappings":"AAAA;;AAIA,SAASA,SAAS,EAAEC,SAAS,EAAEC,YAAY,QAAQ,iBAAgB;AACnE,OAAOC,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAOlD,OAAO,MAAMC,uBAAiD,CAACC;IAC7D,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGF;IAExB,MAAM,EAAEG,MAAM,EAAEC,OAAO,EAAEC,aAAa,EAAE,GAAGV;IAE3C,MAAMW,SAASZ;IAEf,MAAM,CAACa,eAAeC,iBAAiB,GAAGV;IAC1C,MAAM,CAACW,WAAWC,aAAa,GAAGZ;IAElC,4CAA4C;IAC5CD,UAAU;QACR,IAAIK,MAAM;YACR,MAAMS,aAAaT,KAAKU,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,CAAC,GAAGC,IAAI,CAAC;YACrD,MAAMC,mBAAwBV,cAAcM;YAE5C,IAAII,kBAAkB;gBACpB,MAAM,EAAEC,UAAU,EAAEP,SAAS,EAAE,GAAGM;gBAElCL,aAAaD;gBAEb,MAAM,EAAEN,QAAQc,SAAS,EAAE,GAASb;gBACpC,MAAMH,QAAQgB,UAAUC,IAAI,CAAC,CAACjB,QAAuBA,MAAMkB,IAAI,KAAKH;gBAEpE,IAAIf,OAAO;oBACT,MAAM,EAAEmB,SAAS,EAAE,GAAGnB;oBACtBO,iBAAiBY,cAAc;gBACjC;YACF;QACF;IACF,GAAG;QAACjB;QAAQE;QAAeD;QAASF;KAAK;IAEzC,mDAAmD;IACnD,IAAIO,cAAc,UAAU;QAC1B,qBAAO,KAAChB;YAAW,GAAGO,KAAK;;IAC7B;IAEA,MAAMqB,aAAa,OAAOf,WAAW,YAAY,UAAUA,SAASA,OAAOgB,IAAI,GAAGhB;IAElF,MAAMiB,cAAc,OAAOtB,MAAMuB,KAAK,KAAK,WAAWvB,MAAMuB,KAAK,GAAG;QAAE,CAACH,WAAW,EAAEpB,MAAMuB,KAAK;IAAC;IAEhG,MAAMC,aAAaF,WAAW,CAACF,WAAW,IAAIE,WAAW,CAAC,KAAK,IAAI;IAEnE,IAAId,cAAc,kBAAkB,CAACF,eAAe;QAClD,qBACE,MAACmB;;8BACC,KAACA;8BAAKC,OAAOF;;8BACb,KAACC;oBACCE,OAAO;wBACLC,OAAO;oBACT;8BACD;;;;IAKP;IAEA,OAAO;AACT,EAAC"}
1
+ {"version":3,"sources":["../../../src/collections/Forms/DynamicPriceSelector.tsx"],"sourcesContent":["'use client'\n\nimport type { Data, TextFieldClientProps } from 'payload'\n\nimport { TextField, useLocale, useWatchForm } from '@payloadcms/ui'\nimport React, { useEffect, useState } from 'react'\n\ntype FieldWithID = {\n id: string\n name: string\n}\n\nexport const DynamicPriceSelector: React.FC<TextFieldClientProps> = (props) => {\n const { field, path } = props\n\n const { fields, getData, getDataByPath } = useWatchForm()\n\n const locale = useLocale()\n\n const [isNumberField, setIsNumberField] = useState<boolean>()\n const [valueType, setValueType] = useState<'static' | 'valueOfField'>()\n\n // only number fields can use 'valueOfField`\n useEffect(() => {\n if (path) {\n const parentPath = path.split('.').slice(0, -1).join('.')\n const paymentFieldData: any = getDataByPath(parentPath)\n\n if (paymentFieldData) {\n const { fieldToUse, valueType } = paymentFieldData\n\n setValueType(valueType)\n\n const { fields: allFields }: Data = getData()\n const field = allFields.find((field: FieldWithID) => field.name === fieldToUse)\n\n if (field) {\n const { blockType } = field\n setIsNumberField(blockType === 'number')\n }\n }\n }\n }, [fields, getDataByPath, getData, path])\n\n // TODO: make this a number field, block by Payload\n if (valueType === 'static') {\n return <TextField {...props} />\n }\n\n const localeCode = locale?.code ?? 'en'\n\n const localLabels = typeof field.label === 'object' ? field.label : { [localeCode]: field.label }\n\n const labelValue = localLabels[localeCode] || localLabels['en'] || ''\n\n if (valueType === 'valueOfField' && !isNumberField) {\n return (\n <div>\n <div>{String(labelValue)}</div>\n <div\n style={{\n color: '#9A9A9A',\n }}\n >\n The selected field must be a number field.\n </div>\n </div>\n )\n }\n\n return null\n}\n"],"names":["TextField","useLocale","useWatchForm","React","useEffect","useState","DynamicPriceSelector","props","field","path","fields","getData","getDataByPath","locale","isNumberField","setIsNumberField","valueType","setValueType","parentPath","split","slice","join","paymentFieldData","fieldToUse","allFields","find","name","blockType","localeCode","code","localLabels","label","labelValue","div","String","style","color"],"mappings":"AAAA;;AAIA,SAASA,SAAS,EAAEC,SAAS,EAAEC,YAAY,QAAQ,iBAAgB;AACnE,OAAOC,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAOlD,OAAO,MAAMC,uBAAuD,CAACC;IACnE,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGF;IAExB,MAAM,EAAEG,MAAM,EAAEC,OAAO,EAAEC,aAAa,EAAE,GAAGV;IAE3C,MAAMW,SAASZ;IAEf,MAAM,CAACa,eAAeC,iBAAiB,GAAGV;IAC1C,MAAM,CAACW,WAAWC,aAAa,GAAGZ;IAElC,4CAA4C;IAC5CD,UAAU;QACR,IAAIK,MAAM;YACR,MAAMS,aAAaT,KAAKU,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,CAAC,GAAGC,IAAI,CAAC;YACrD,MAAMC,mBAAwBV,cAAcM;YAE5C,IAAII,kBAAkB;gBACpB,MAAM,EAAEC,UAAU,EAAEP,SAAS,EAAE,GAAGM;gBAElCL,aAAaD;gBAEb,MAAM,EAAEN,QAAQc,SAAS,EAAE,GAASb;gBACpC,MAAMH,QAAQgB,UAAUC,IAAI,CAAC,CAACjB,QAAuBA,MAAMkB,IAAI,KAAKH;gBAEpE,IAAIf,OAAO;oBACT,MAAM,EAAEmB,SAAS,EAAE,GAAGnB;oBACtBO,iBAAiBY,cAAc;gBACjC;YACF;QACF;IACF,GAAG;QAACjB;QAAQE;QAAeD;QAASF;KAAK;IAEzC,mDAAmD;IACnD,IAAIO,cAAc,UAAU;QAC1B,qBAAO,KAAChB;YAAW,GAAGO,KAAK;;IAC7B;IAEA,MAAMqB,aAAaf,QAAQgB,QAAQ;IAEnC,MAAMC,cAAc,OAAOtB,MAAMuB,KAAK,KAAK,WAAWvB,MAAMuB,KAAK,GAAG;QAAE,CAACH,WAAW,EAAEpB,MAAMuB,KAAK;IAAC;IAEhG,MAAMC,aAAaF,WAAW,CAACF,WAAW,IAAIE,WAAW,CAAC,KAAK,IAAI;IAEnE,IAAId,cAAc,kBAAkB,CAACF,eAAe;QAClD,qBACE,MAACmB;;8BACC,KAACA;8BAAKC,OAAOF;;8BACb,KAACC;oBACCE,OAAO;wBACLC,OAAO;oBACT;8BACD;;;;IAKP;IAEA,OAAO;AACT,EAAC"}
@@ -178,7 +178,7 @@ export const generateFormCollection = (formConfig, collections)=>{
178
178
  name: 'emails',
179
179
  type: 'array',
180
180
  access: {
181
- read: ({ req: { user } })=>!!user
181
+ read: ({ req })=>req.user?.collection === req.payload.config.admin.user
182
182
  },
183
183
  admin: {
184
184
  description: ({ t })=>// @ts-expect-error - translations are not typed in plugins yet
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/Forms/index.ts"],"sourcesContent":["import type { Block, CollectionConfig, Config, Field } from 'payload'\n\nimport { deepMergeWithSourceArrays } from 'payload'\n\nimport type { FormBuilderPluginConfig } from '../../types.js'\n\nimport { fields } from './fields.js'\n\nconst applyUploadCollectionLabels = (args: {\n block: Block\n collections: Config['collections']\n uploadCollections: FormBuilderPluginConfig['uploadCollections']\n}): Block => {\n const { block, collections, uploadCollections } = args\n const collectionsBySlug = new Map(\n (collections || []).map((collection) => [collection.slug, collection]),\n )\n\n for (const field of block.fields) {\n if ('name' in field && field.name === 'uploadCollection' && field.type === 'select') {\n // Replace the default slug labels with the source collection's labels.singular.\n // Select option labels accept strings, locale records and label functions —\n // Payload's admin resolves them at render time via getTranslation.\n field.options = (uploadCollections || []).map((slug) => {\n const singular = collectionsBySlug.get(slug)?.labels?.singular\n return { label: singular ?? slug, value: slug }\n })\n break\n }\n }\n\n return block\n}\n\n// all settings can be overridden by the config\nexport const generateFormCollection = (\n formConfig: FormBuilderPluginConfig,\n collections?: Config['collections'],\n): CollectionConfig => {\n const redirect: Field = {\n name: 'redirect',\n type: 'group',\n admin: {\n condition: (_, siblingData) => siblingData?.confirmationType === 'redirect',\n hideGutter: true,\n },\n fields: [\n {\n name: 'url',\n type: 'text',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:urlToRedirectTo'),\n required: true,\n },\n ],\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:redirect'),\n }\n\n if (formConfig.redirectRelationships) {\n redirect.fields.unshift({\n name: 'reference',\n type: 'relationship',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'reference',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:documentToLinkTo'),\n maxDepth: 2,\n relationTo: formConfig.redirectRelationships,\n required: true,\n })\n\n redirect.fields.unshift({\n name: 'type',\n type: 'radio',\n admin: {\n layout: 'horizontal',\n },\n defaultValue: 'reference',\n options: [\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:internalLink'),\n value: 'reference',\n },\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:customURL'),\n value: 'custom',\n },\n ],\n })\n\n if (redirect.fields[2]!.type !== 'row') {\n redirect.fields[2]!.label = ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:customURL')\n }\n\n redirect.fields[2]!.admin = {\n condition: (_, siblingData) => siblingData?.type === 'custom',\n }\n }\n\n const defaultFields: Field[] = [\n {\n name: 'title',\n type: 'text',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:title'),\n required: true,\n },\n {\n name: 'fields',\n type: 'blocks',\n blocks: Object.entries(formConfig?.fields || {})\n .map(([fieldKey, fieldConfig]) => {\n // let the config enable/disable fields with either boolean values or objects\n if (fieldConfig !== false) {\n const block = fields[fieldKey]\n\n if (block === undefined && typeof fieldConfig === 'object') {\n return fieldConfig\n }\n\n if (typeof block === 'object' && typeof fieldConfig === 'object') {\n return deepMergeWithSourceArrays(block, fieldConfig)\n }\n\n if (typeof block === 'function') {\n // Special handling for upload field - factory takes slug list; after it runs,\n // inject resolved collection labels into the uploadCollection select.\n if (fieldKey === 'upload') {\n return applyUploadCollectionLabels({\n block: block(formConfig.uploadCollections || []),\n collections,\n uploadCollections: formConfig.uploadCollections,\n })\n }\n return block(fieldConfig)\n }\n\n return block\n }\n\n return null\n })\n .filter(Boolean) as Block[],\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:fields'),\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:fields'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:field'),\n },\n },\n {\n name: 'submitButtonLabel',\n type: 'text',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:submitButton'),\n localized: true,\n },\n {\n name: 'confirmationType',\n type: 'radio',\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:chooseConfirmationType'),\n layout: 'horizontal',\n },\n defaultValue: 'message',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:confirmationType'),\n options: [\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:message'),\n value: 'message',\n },\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:redirect'),\n value: 'redirect',\n },\n ],\n },\n {\n name: 'confirmationMessage',\n type: 'richText',\n admin: {\n condition: (_, siblingData) => siblingData?.confirmationType === 'message',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:confirmationMessage'),\n localized: true,\n required: true,\n },\n redirect,\n {\n name: 'emails',\n type: 'array',\n access: {\n read: ({ req: { user } }) => !!user,\n },\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:emailsDescription'),\n },\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'emailTo',\n type: 'text',\n admin: {\n placeholder: '\"Email Sender\" <sender@email.com>',\n width: '100%',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:emailTo'),\n },\n {\n name: 'cc',\n type: 'text',\n admin: {\n style: {\n maxWidth: '50%',\n },\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:cc'),\n },\n {\n name: 'bcc',\n type: 'text',\n admin: {\n style: {\n maxWidth: '50%',\n },\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:bcc'),\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'replyTo',\n type: 'text',\n admin: {\n placeholder: '\"Reply To\" <reply-to@email.com>',\n width: '50%',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:replyTo'),\n },\n {\n name: 'emailFrom',\n type: 'text',\n admin: {\n placeholder: '\"Email From\" <email-from@email.com>',\n width: '50%',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:emailFrom'),\n },\n ],\n },\n {\n name: 'subject',\n type: 'text',\n defaultValue: \"You've received a new message.\",\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:subject'),\n localized: true,\n required: true,\n },\n {\n name: 'message',\n type: 'richText',\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:messageDescription'),\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:message'),\n localized: true,\n },\n ],\n },\n ]\n\n const config: CollectionConfig = {\n ...(formConfig?.formOverrides || {}),\n slug: formConfig?.formOverrides?.slug || 'forms',\n access: {\n read: () => true,\n ...(formConfig?.formOverrides?.access || {}),\n },\n admin: {\n enableRichTextRelationship: false,\n useAsTitle: 'title',\n ...(formConfig?.formOverrides?.admin || {}),\n },\n fields:\n formConfig?.formOverrides?.fields && typeof formConfig?.formOverrides?.fields === 'function'\n ? formConfig.formOverrides.fields({ defaultFields })\n : defaultFields,\n }\n\n return config\n}\n"],"names":["deepMergeWithSourceArrays","fields","applyUploadCollectionLabels","args","block","collections","uploadCollections","collectionsBySlug","Map","map","collection","slug","field","name","type","options","singular","get","labels","label","value","generateFormCollection","formConfig","redirect","admin","condition","_","siblingData","confirmationType","hideGutter","t","required","redirectRelationships","unshift","maxDepth","relationTo","layout","defaultValue","defaultFields","blocks","Object","entries","fieldKey","fieldConfig","undefined","filter","Boolean","plural","localized","description","access","read","req","user","placeholder","width","style","maxWidth","config","formOverrides","enableRichTextRelationship","useAsTitle"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/collections/Forms/index.ts"],"sourcesContent":["import type { Block, CollectionConfig, Config, Field } from 'payload'\n\nimport { deepMergeWithSourceArrays } from 'payload'\n\nimport type { FormBuilderPluginConfig } from '../../types.js'\n\nimport { fields } from './fields.js'\n\nconst applyUploadCollectionLabels = (args: {\n block: Block\n collections: Config['collections']\n uploadCollections: FormBuilderPluginConfig['uploadCollections']\n}): Block => {\n const { block, collections, uploadCollections } = args\n const collectionsBySlug = new Map(\n (collections || []).map((collection) => [collection.slug, collection]),\n )\n\n for (const field of block.fields) {\n if ('name' in field && field.name === 'uploadCollection' && field.type === 'select') {\n // Replace the default slug labels with the source collection's labels.singular.\n // Select option labels accept strings, locale records and label functions —\n // Payload's admin resolves them at render time via getTranslation.\n field.options = (uploadCollections || []).map((slug) => {\n const singular = collectionsBySlug.get(slug)?.labels?.singular\n return { label: singular ?? slug, value: slug }\n })\n break\n }\n }\n\n return block\n}\n\n// all settings can be overridden by the config\nexport const generateFormCollection = (\n formConfig: FormBuilderPluginConfig,\n collections?: Config['collections'],\n): CollectionConfig => {\n const redirect: Field = {\n name: 'redirect',\n type: 'group',\n admin: {\n condition: (_, siblingData) => siblingData?.confirmationType === 'redirect',\n hideGutter: true,\n },\n fields: [\n {\n name: 'url',\n type: 'text',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:urlToRedirectTo'),\n required: true,\n },\n ],\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:redirect'),\n }\n\n if (formConfig.redirectRelationships) {\n redirect.fields.unshift({\n name: 'reference',\n type: 'relationship',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'reference',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:documentToLinkTo'),\n maxDepth: 2,\n relationTo: formConfig.redirectRelationships,\n required: true,\n })\n\n redirect.fields.unshift({\n name: 'type',\n type: 'radio',\n admin: {\n layout: 'horizontal',\n },\n defaultValue: 'reference',\n options: [\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:internalLink'),\n value: 'reference',\n },\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:customURL'),\n value: 'custom',\n },\n ],\n })\n\n if (redirect.fields[2]!.type !== 'row') {\n redirect.fields[2]!.label = ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:customURL')\n }\n\n redirect.fields[2]!.admin = {\n condition: (_, siblingData) => siblingData?.type === 'custom',\n }\n }\n\n const defaultFields: Field[] = [\n {\n name: 'title',\n type: 'text',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:title'),\n required: true,\n },\n {\n name: 'fields',\n type: 'blocks',\n blocks: Object.entries(formConfig?.fields || {})\n .map(([fieldKey, fieldConfig]) => {\n // let the config enable/disable fields with either boolean values or objects\n if (fieldConfig !== false) {\n const block = fields[fieldKey]\n\n if (block === undefined && typeof fieldConfig === 'object') {\n return fieldConfig\n }\n\n if (typeof block === 'object' && typeof fieldConfig === 'object') {\n return deepMergeWithSourceArrays(block, fieldConfig)\n }\n\n if (typeof block === 'function') {\n // Special handling for upload field - factory takes slug list; after it runs,\n // inject resolved collection labels into the uploadCollection select.\n if (fieldKey === 'upload') {\n return applyUploadCollectionLabels({\n block: block(formConfig.uploadCollections || []),\n collections,\n uploadCollections: formConfig.uploadCollections,\n })\n }\n return block(fieldConfig)\n }\n\n return block\n }\n\n return null\n })\n .filter(Boolean) as Block[],\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:fields'),\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:fields'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:field'),\n },\n },\n {\n name: 'submitButtonLabel',\n type: 'text',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:submitButton'),\n localized: true,\n },\n {\n name: 'confirmationType',\n type: 'radio',\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:chooseConfirmationType'),\n layout: 'horizontal',\n },\n defaultValue: 'message',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:confirmationType'),\n options: [\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:message'),\n value: 'message',\n },\n {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:redirect'),\n value: 'redirect',\n },\n ],\n },\n {\n name: 'confirmationMessage',\n type: 'richText',\n admin: {\n condition: (_, siblingData) => siblingData?.confirmationType === 'message',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:confirmationMessage'),\n localized: true,\n required: true,\n },\n redirect,\n {\n name: 'emails',\n type: 'array',\n access: {\n read: ({ req }) => req.user?.collection === req.payload.config.admin.user,\n },\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:emailsDescription'),\n },\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'emailTo',\n type: 'text',\n admin: {\n placeholder: '\"Email Sender\" <sender@email.com>',\n width: '100%',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:emailTo'),\n },\n {\n name: 'cc',\n type: 'text',\n admin: {\n style: {\n maxWidth: '50%',\n },\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:cc'),\n },\n {\n name: 'bcc',\n type: 'text',\n admin: {\n style: {\n maxWidth: '50%',\n },\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:bcc'),\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'replyTo',\n type: 'text',\n admin: {\n placeholder: '\"Reply To\" <reply-to@email.com>',\n width: '50%',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:replyTo'),\n },\n {\n name: 'emailFrom',\n type: 'text',\n admin: {\n placeholder: '\"Email From\" <email-from@email.com>',\n width: '50%',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:emailFrom'),\n },\n ],\n },\n {\n name: 'subject',\n type: 'text',\n defaultValue: \"You've received a new message.\",\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:subject'),\n localized: true,\n required: true,\n },\n {\n name: 'message',\n type: 'richText',\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:messageDescription'),\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-form-builder:message'),\n localized: true,\n },\n ],\n },\n ]\n\n const config: CollectionConfig = {\n ...(formConfig?.formOverrides || {}),\n slug: formConfig?.formOverrides?.slug || 'forms',\n access: {\n read: () => true,\n ...(formConfig?.formOverrides?.access || {}),\n },\n admin: {\n enableRichTextRelationship: false,\n useAsTitle: 'title',\n ...(formConfig?.formOverrides?.admin || {}),\n },\n fields:\n formConfig?.formOverrides?.fields && typeof formConfig?.formOverrides?.fields === 'function'\n ? formConfig.formOverrides.fields({ defaultFields })\n : defaultFields,\n }\n\n return config\n}\n"],"names":["deepMergeWithSourceArrays","fields","applyUploadCollectionLabels","args","block","collections","uploadCollections","collectionsBySlug","Map","map","collection","slug","field","name","type","options","singular","get","labels","label","value","generateFormCollection","formConfig","redirect","admin","condition","_","siblingData","confirmationType","hideGutter","t","required","redirectRelationships","unshift","maxDepth","relationTo","layout","defaultValue","defaultFields","blocks","Object","entries","fieldKey","fieldConfig","undefined","filter","Boolean","plural","localized","description","access","read","req","user","payload","config","placeholder","width","style","maxWidth","formOverrides","enableRichTextRelationship","useAsTitle"],"mappings":"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"}
@@ -21,6 +21,7 @@ export const LinkHTMLConverter = {
21
21
  return `<a href="${safeHref}"${node.fields.newTab ? ' rel="noopener noreferrer" target="_blank"' : ''}>${childrenText}</a>`;
22
22
  },
23
23
  nodeTypes: [
24
+ 'autolink',
24
25
  'link'
25
26
  ]
26
27
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/utilities/lexical/converters/link.ts"],"sourcesContent":["import escapeHTML from 'escape-html'\nimport { sanitizeUrl } from 'payload/shared'\n\nimport type { HTMLConverter } from '../types.js'\n\nimport { replaceDoubleCurlys } from '../../replaceDoubleCurlys.js'\nimport { convertLexicalNodesToHTML } from '../serializeLexical.js'\n\nexport const LinkHTMLConverter: HTMLConverter<any> = {\n async converter({ converters, node, parent, submissionData }) {\n const childrenText = await convertLexicalNodesToHTML({\n converters,\n lexicalNodes: node.children,\n parent: {\n ...node,\n parent,\n },\n submissionData,\n })\n\n let href: string =\n node.fields.linkType === 'custom'\n ? (node.fields.url ?? '')\n : (node.fields.doc?.value?.id ?? '')\n\n if (submissionData) {\n href = replaceDoubleCurlys(href, submissionData)\n }\n\n const safeHref = escapeHTML(sanitizeUrl(href))\n\n return `<a href=\"${safeHref}\"${node.fields.newTab ? ' rel=\"noopener noreferrer\" target=\"_blank\"' : ''}>${childrenText}</a>`\n },\n nodeTypes: ['link'],\n}\n"],"names":["escapeHTML","sanitizeUrl","replaceDoubleCurlys","convertLexicalNodesToHTML","LinkHTMLConverter","converter","converters","node","parent","submissionData","childrenText","lexicalNodes","children","href","fields","linkType","url","doc","value","id","safeHref","newTab","nodeTypes"],"mappings":"AAAA,OAAOA,gBAAgB,cAAa;AACpC,SAASC,WAAW,QAAQ,iBAAgB;AAI5C,SAASC,mBAAmB,QAAQ,+BAA8B;AAClE,SAASC,yBAAyB,QAAQ,yBAAwB;AAElE,OAAO,MAAMC,oBAAwC;IACnD,MAAMC,WAAU,EAAEC,UAAU,EAAEC,IAAI,EAAEC,MAAM,EAAEC,cAAc,EAAE;QAC1D,MAAMC,eAAe,MAAMP,0BAA0B;YACnDG;YACAK,cAAcJ,KAAKK,QAAQ;YAC3BJ,QAAQ;gBACN,GAAGD,IAAI;gBACPC;YACF;YACAC;QACF;QAEA,IAAII,OACFN,KAAKO,MAAM,CAACC,QAAQ,KAAK,WACpBR,KAAKO,MAAM,CAACE,GAAG,IAAI,KACnBT,KAAKO,MAAM,CAACG,GAAG,EAAEC,OAAOC,MAAM;QAErC,IAAIV,gBAAgB;YAClBI,OAAOX,oBAAoBW,MAAMJ;QACnC;QAEA,MAAMW,WAAWpB,WAAWC,YAAYY;QAExC,OAAO,CAAC,SAAS,EAAEO,SAAS,CAAC,EAAEb,KAAKO,MAAM,CAACO,MAAM,GAAG,+CAA+C,GAAG,CAAC,EAAEX,aAAa,IAAI,CAAC;IAC7H;IACAY,WAAW;QAAC;KAAO;AACrB,EAAC"}
1
+ {"version":3,"sources":["../../../../src/utilities/lexical/converters/link.ts"],"sourcesContent":["import escapeHTML from 'escape-html'\nimport { sanitizeUrl } from 'payload/shared'\n\nimport type { HTMLConverter } from '../types.js'\n\nimport { replaceDoubleCurlys } from '../../replaceDoubleCurlys.js'\nimport { convertLexicalNodesToHTML } from '../serializeLexical.js'\n\nexport const LinkHTMLConverter: HTMLConverter<any> = {\n async converter({ converters, node, parent, submissionData }) {\n const childrenText = await convertLexicalNodesToHTML({\n converters,\n lexicalNodes: node.children,\n parent: {\n ...node,\n parent,\n },\n submissionData,\n })\n\n let href: string =\n node.fields.linkType === 'custom'\n ? (node.fields.url ?? '')\n : (node.fields.doc?.value?.id ?? '')\n\n if (submissionData) {\n href = replaceDoubleCurlys(href, submissionData)\n }\n\n const safeHref = escapeHTML(sanitizeUrl(href))\n\n return `<a href=\"${safeHref}\"${node.fields.newTab ? ' rel=\"noopener noreferrer\" target=\"_blank\"' : ''}>${childrenText}</a>`\n },\n nodeTypes: ['autolink', 'link'],\n}\n"],"names":["escapeHTML","sanitizeUrl","replaceDoubleCurlys","convertLexicalNodesToHTML","LinkHTMLConverter","converter","converters","node","parent","submissionData","childrenText","lexicalNodes","children","href","fields","linkType","url","doc","value","id","safeHref","newTab","nodeTypes"],"mappings":"AAAA,OAAOA,gBAAgB,cAAa;AACpC,SAASC,WAAW,QAAQ,iBAAgB;AAI5C,SAASC,mBAAmB,QAAQ,+BAA8B;AAClE,SAASC,yBAAyB,QAAQ,yBAAwB;AAElE,OAAO,MAAMC,oBAAwC;IACnD,MAAMC,WAAU,EAAEC,UAAU,EAAEC,IAAI,EAAEC,MAAM,EAAEC,cAAc,EAAE;QAC1D,MAAMC,eAAe,MAAMP,0BAA0B;YACnDG;YACAK,cAAcJ,KAAKK,QAAQ;YAC3BJ,QAAQ;gBACN,GAAGD,IAAI;gBACPC;YACF;YACAC;QACF;QAEA,IAAII,OACFN,KAAKO,MAAM,CAACC,QAAQ,KAAK,WACpBR,KAAKO,MAAM,CAACE,GAAG,IAAI,KACnBT,KAAKO,MAAM,CAACG,GAAG,EAAEC,OAAOC,MAAM;QAErC,IAAIV,gBAAgB;YAClBI,OAAOX,oBAAoBW,MAAMJ;QACnC;QAEA,MAAMW,WAAWpB,WAAWC,YAAYY;QAExC,OAAO,CAAC,SAAS,EAAEO,SAAS,CAAC,EAAEb,KAAKO,MAAM,CAACO,MAAM,GAAG,+CAA+C,GAAG,CAAC,EAAEX,aAAa,IAAI,CAAC;IAC7H;IACAY,WAAW;QAAC;QAAY;KAAO;AACjC,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-form-builder",
3
- "version": "4.0.0-internal.c3ac604",
3
+ "version": "4.0.0-internal.cb69780",
4
4
  "description": "Form builder plugin for Payload CMS",
5
5
  "keywords": [
6
6
  "payload",
@@ -63,22 +63,22 @@
63
63
  ],
64
64
  "dependencies": {
65
65
  "escape-html": "^1.0.3",
66
- "@payloadcms/translations": "4.0.0-internal.c3ac604",
67
- "@payloadcms/ui": "4.0.0-internal.c3ac604"
66
+ "@payloadcms/ui": "4.0.0-internal.cb69780",
67
+ "@payloadcms/translations": "4.0.0-internal.cb69780"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/escape-html": "^1.0.4",
71
71
  "@types/react": "19.2.14",
72
72
  "@types/react-dom": "19.2.3",
73
- "copyfiles": "^2.4.1",
73
+ "copyfiles": "2.4.1",
74
74
  "cross-env": "10.1.0",
75
75
  "@payloadcms/eslint-config": "3.28.0",
76
- "payload": "4.0.0-internal.c3ac604"
76
+ "payload": "4.0.0-internal.cb69780"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
80
80
  "react-dom": "^19.0.1 || ^19.1.2 || ^19.2.1",
81
- "payload": "4.0.0-internal.c3ac604"
81
+ "payload": "4.0.0-internal.cb69780"
82
82
  },
83
83
  "publishConfig": {
84
84
  "registry": "https://registry.npmjs.org/"