@xtr-dev/payload-automation 0.0.22 → 0.0.24
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/README.md +73 -2
- package/dist/collections/Workflow.js +187 -18
- package/dist/collections/Workflow.js.map +1 -1
- package/dist/collections/WorkflowRuns.js +14 -7
- package/dist/collections/WorkflowRuns.js.map +1 -1
- package/dist/components/StatusCell.d.ts +6 -0
- package/dist/components/StatusCell.js +75 -0
- package/dist/components/StatusCell.js.map +1 -0
- package/dist/components/WorkflowExecutionStatus.d.ts +6 -0
- package/dist/components/WorkflowExecutionStatus.js +287 -0
- package/dist/components/WorkflowExecutionStatus.js.map +1 -0
- package/dist/core/workflow-executor.d.ts +42 -2
- package/dist/core/workflow-executor.js +169 -14
- package/dist/core/workflow-executor.js.map +1 -1
- package/dist/exports/client.d.ts +2 -0
- package/dist/exports/client.js +4 -1
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/helpers.d.ts +26 -0
- package/dist/exports/helpers.js +30 -0
- package/dist/exports/helpers.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin/cron-scheduler.js +27 -27
- package/dist/plugin/cron-scheduler.js.map +1 -1
- package/dist/plugin/index.js +134 -43
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/init-step-tasks.js +15 -1
- package/dist/plugin/init-step-tasks.js.map +1 -1
- package/dist/plugin/init-webhook.js +1 -1
- package/dist/plugin/init-webhook.js.map +1 -1
- package/dist/steps/create-document.js +1 -1
- package/dist/steps/create-document.js.map +1 -1
- package/dist/steps/delete-document.js +2 -2
- package/dist/steps/delete-document.js.map +1 -1
- package/dist/steps/http-request-handler.js +229 -10
- package/dist/steps/http-request-handler.js.map +1 -1
- package/dist/steps/http-request.d.ts +147 -4
- package/dist/steps/http-request.js +189 -3
- package/dist/steps/http-request.js.map +1 -1
- package/dist/steps/read-document.js +2 -2
- package/dist/steps/read-document.js.map +1 -1
- package/dist/steps/send-email.js +5 -5
- package/dist/steps/send-email.js.map +1 -1
- package/dist/steps/update-document.js +2 -2
- package/dist/steps/update-document.js.map +1 -1
- package/dist/test/create-document-step.test.js +378 -0
- package/dist/test/create-document-step.test.js.map +1 -0
- package/dist/test/http-request-step.test.js +361 -0
- package/dist/test/http-request-step.test.js.map +1 -0
- package/dist/test/workflow-executor.test.js +530 -0
- package/dist/test/workflow-executor.test.js.map +1 -0
- package/dist/utils/trigger-helpers.d.ts +46 -0
- package/dist/utils/trigger-helpers.js +100 -0
- package/dist/utils/trigger-helpers.js.map +1 -0
- package/dist/utils/trigger-presets.d.ts +60 -0
- package/dist/utils/trigger-presets.js +172 -0
- package/dist/utils/trigger-presets.js.map +1 -0
- package/package.json +9 -1
- package/dist/test/basic.test.d.ts +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/steps/http-request.ts"],"sourcesContent":["import type {TaskConfig} from \"payload\"\n\nimport {httpStepHandler} from \"./http-request-handler.js\"\n\nexport const HttpRequestStepTask = {\n slug: 'http-request-step',\n handler: httpStepHandler,\n inputSchema: [\n {\n name: 'url',\n type: 'text',\n }\n ],\n outputSchema: [\n {\n name: '
|
|
1
|
+
{"version":3,"sources":["../../src/steps/http-request.ts"],"sourcesContent":["import type {TaskConfig} from \"payload\"\n\nimport {httpStepHandler} from \"./http-request-handler.js\"\n\nexport const HttpRequestStepTask = {\n slug: 'http-request-step',\n handler: httpStepHandler,\n inputSchema: [\n {\n name: 'url',\n type: 'text',\n admin: {\n description: 'The URL to make the HTTP request to'\n },\n required: true\n },\n {\n name: 'method',\n type: 'select',\n options: [\n { label: 'GET', value: 'GET' },\n { label: 'POST', value: 'POST' },\n { label: 'PUT', value: 'PUT' },\n { label: 'DELETE', value: 'DELETE' },\n { label: 'PATCH', value: 'PATCH' }\n ],\n defaultValue: 'GET',\n admin: {\n description: 'HTTP method to use'\n }\n },\n {\n name: 'headers',\n type: 'json',\n admin: {\n description: 'HTTP headers as JSON object (e.g., {\"Content-Type\": \"application/json\"})'\n }\n },\n {\n name: 'body',\n type: 'json',\n admin: {\n condition: (_, siblingData) => siblingData?.method !== 'GET' && siblingData?.method !== 'DELETE',\n description: 'Request body data. Use JSONPath to reference values (e.g., {\"postId\": \"$.trigger.doc.id\", \"title\": \"$.trigger.doc.title\"})'\n }\n },\n {\n name: 'timeout',\n type: 'number',\n defaultValue: 30000,\n admin: {\n description: 'Request timeout in milliseconds (default: 30000)'\n }\n },\n {\n name: 'authentication',\n type: 'group',\n fields: [\n {\n name: 'type',\n type: 'select',\n options: [\n { label: 'None', value: 'none' },\n { label: 'Bearer Token', value: 'bearer' },\n { label: 'Basic Auth', value: 'basic' },\n { label: 'API Key Header', value: 'apikey' }\n ],\n defaultValue: 'none',\n admin: {\n description: 'Authentication method'\n }\n },\n {\n name: 'token',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'bearer',\n description: 'Bearer token value'\n }\n },\n {\n name: 'username',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'basic',\n description: 'Basic auth username'\n }\n },\n {\n name: 'password',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'basic',\n description: 'Basic auth password'\n }\n },\n {\n name: 'headerName',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'apikey',\n description: 'API key header name (e.g., \"X-API-Key\")'\n }\n },\n {\n name: 'headerValue',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'apikey',\n description: 'API key value'\n }\n }\n ]\n },\n {\n name: 'retries',\n type: 'number',\n defaultValue: 0,\n min: 0,\n max: 5,\n admin: {\n description: 'Number of retry attempts on failure (max: 5)'\n }\n },\n {\n name: 'retryDelay',\n type: 'number',\n defaultValue: 1000,\n admin: {\n condition: (_, siblingData) => (siblingData?.retries || 0) > 0,\n description: 'Delay between retries in milliseconds'\n }\n }\n ],\n outputSchema: [\n {\n name: 'status',\n type: 'number',\n admin: {\n description: 'HTTP status code'\n }\n },\n {\n name: 'statusText',\n type: 'text',\n admin: {\n description: 'HTTP status text'\n }\n },\n {\n name: 'headers',\n type: 'json',\n admin: {\n description: 'Response headers'\n }\n },\n {\n name: 'body',\n type: 'textarea',\n admin: {\n description: 'Response body'\n }\n },\n {\n name: 'data',\n type: 'json',\n admin: {\n description: 'Parsed response data (if JSON)'\n }\n },\n {\n name: 'duration',\n type: 'number',\n admin: {\n description: 'Request duration in milliseconds'\n }\n }\n ]\n} satisfies TaskConfig<'http-request-step'>\n"],"names":["httpStepHandler","HttpRequestStepTask","slug","handler","inputSchema","name","type","admin","description","required","options","label","value","defaultValue","condition","_","siblingData","method","fields","min","max","retries","outputSchema"],"mappings":"AAEA,SAAQA,eAAe,QAAO,4BAA2B;AAEzD,OAAO,MAAMC,sBAAsB;IACjCC,MAAM;IACNC,SAASH;IACTI,aAAa;QACX;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNI,SAAS;gBACP;oBAAEC,OAAO;oBAAOC,OAAO;gBAAM;gBAC7B;oBAAED,OAAO;oBAAQC,OAAO;gBAAO;gBAC/B;oBAAED,OAAO;oBAAOC,OAAO;gBAAM;gBAC7B;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAASC,OAAO;gBAAQ;aAClC;YACDC,cAAc;YACdN,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLO,WAAW,CAACC,GAAGC,cAAgBA,aAAaC,WAAW,SAASD,aAAaC,WAAW;gBACxFT,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNO,cAAc;YACdN,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNY,QAAQ;gBACN;oBACEb,MAAM;oBACNC,MAAM;oBACNI,SAAS;wBACP;4BAAEC,OAAO;4BAAQC,OAAO;wBAAO;wBAC/B;4BAAED,OAAO;4BAAgBC,OAAO;wBAAS;wBACzC;4BAAED,OAAO;4BAAcC,OAAO;wBAAQ;wBACtC;4BAAED,OAAO;4BAAkBC,OAAO;wBAAS;qBAC5C;oBACDC,cAAc;oBACdN,OAAO;wBACLC,aAAa;oBACf;gBACF;gBACA;oBACEH,MAAM;oBACNC,MAAM;oBACNC,OAAO;wBACLO,WAAW,CAACC,GAAGC,cAAgBA,aAAaV,SAAS;wBACrDE,aAAa;oBACf;gBACF;gBACA;oBACEH,MAAM;oBACNC,MAAM;oBACNC,OAAO;wBACLO,WAAW,CAACC,GAAGC,cAAgBA,aAAaV,SAAS;wBACrDE,aAAa;oBACf;gBACF;gBACA;oBACEH,MAAM;oBACNC,MAAM;oBACNC,OAAO;wBACLO,WAAW,CAACC,GAAGC,cAAgBA,aAAaV,SAAS;wBACrDE,aAAa;oBACf;gBACF;gBACA;oBACEH,MAAM;oBACNC,MAAM;oBACNC,OAAO;wBACLO,WAAW,CAACC,GAAGC,cAAgBA,aAAaV,SAAS;wBACrDE,aAAa;oBACf;gBACF;gBACA;oBACEH,MAAM;oBACNC,MAAM;oBACNC,OAAO;wBACLO,WAAW,CAACC,GAAGC,cAAgBA,aAAaV,SAAS;wBACrDE,aAAa;oBACf;gBACF;aACD;QACH;QACA;YACEH,MAAM;YACNC,MAAM;YACNO,cAAc;YACdM,KAAK;YACLC,KAAK;YACLb,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNO,cAAc;YACdN,OAAO;gBACLO,WAAW,CAACC,GAAGC,cAAgB,AAACA,CAAAA,aAAaK,WAAW,CAAA,IAAK;gBAC7Db,aAAa;YACf;QACF;KACD;IACDc,cAAc;QACZ;YACEjB,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;AACH,EAA2C"}
|
|
@@ -15,14 +15,14 @@ export const ReadDocumentStepTask = {
|
|
|
15
15
|
name: 'id',
|
|
16
16
|
type: 'text',
|
|
17
17
|
admin: {
|
|
18
|
-
description: 'The ID of a specific document to read (
|
|
18
|
+
description: 'The ID of a specific document to read. Use JSONPath (e.g., "$.trigger.doc.relatedId"). Leave empty to find multiple.'
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
name: 'where',
|
|
23
23
|
type: 'json',
|
|
24
24
|
admin: {
|
|
25
|
-
description: 'Query conditions to find documents
|
|
25
|
+
description: 'Query conditions to find documents when ID is not provided. Use JSONPath in values (e.g., {"category": "$.trigger.doc.category", "status": "published"})'
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/steps/read-document.ts"],"sourcesContent":["import type { TaskConfig } from \"payload\"\n\nimport { readDocumentHandler } from \"./read-document-handler.js\"\n\nexport const ReadDocumentStepTask = {\n slug: 'read-document',\n handler: readDocumentHandler,\n inputSchema: [\n {\n name: 'collectionSlug',\n type: 'text',\n admin: {\n description: 'The collection slug to read from'\n },\n required: true\n },\n {\n name: 'id',\n type: 'text',\n admin: {\n description: 'The ID of a specific document to read (
|
|
1
|
+
{"version":3,"sources":["../../src/steps/read-document.ts"],"sourcesContent":["import type { TaskConfig } from \"payload\"\n\nimport { readDocumentHandler } from \"./read-document-handler.js\"\n\nexport const ReadDocumentStepTask = {\n slug: 'read-document',\n handler: readDocumentHandler,\n inputSchema: [\n {\n name: 'collectionSlug',\n type: 'text',\n admin: {\n description: 'The collection slug to read from'\n },\n required: true\n },\n {\n name: 'id',\n type: 'text',\n admin: {\n description: 'The ID of a specific document to read. Use JSONPath (e.g., \"$.trigger.doc.relatedId\"). Leave empty to find multiple.'\n }\n },\n {\n name: 'where',\n type: 'json',\n admin: {\n description: 'Query conditions to find documents when ID is not provided. Use JSONPath in values (e.g., {\"category\": \"$.trigger.doc.category\", \"status\": \"published\"})'\n }\n },\n {\n name: 'limit',\n type: 'number',\n admin: {\n description: 'Maximum number of documents to return (default: 10)'\n }\n },\n {\n name: 'sort',\n type: 'text',\n admin: {\n description: 'Field to sort by (prefix with - for descending order)'\n }\n },\n {\n name: 'locale',\n type: 'text',\n admin: {\n description: 'Locale for the document (if localization is enabled)'\n }\n },\n {\n name: 'depth',\n type: 'number',\n admin: {\n description: 'Depth of relationships to populate (0-10)'\n }\n }\n ],\n outputSchema: [\n {\n name: 'doc',\n type: 'json',\n admin: {\n description: 'The document(s) found'\n }\n },\n {\n name: 'totalDocs',\n type: 'number',\n admin: {\n description: 'Total number of documents matching the query'\n }\n }\n ]\n} satisfies TaskConfig<'read-document'>"],"names":["readDocumentHandler","ReadDocumentStepTask","slug","handler","inputSchema","name","type","admin","description","required","outputSchema"],"mappings":"AAEA,SAASA,mBAAmB,QAAQ,6BAA4B;AAEhE,OAAO,MAAMC,uBAAuB;IAClCC,MAAM;IACNC,SAASH;IACTI,aAAa;QACX;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;IACDE,cAAc;QACZ;YACEL,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;AACH,EAAuC"}
|
package/dist/steps/send-email.js
CHANGED
|
@@ -7,7 +7,7 @@ export const SendEmailStepTask = {
|
|
|
7
7
|
name: 'to',
|
|
8
8
|
type: 'text',
|
|
9
9
|
admin: {
|
|
10
|
-
description: 'Recipient email address'
|
|
10
|
+
description: 'Recipient email address. Use JSONPath for dynamic values (e.g., "$.trigger.doc.email" or "$.trigger.user.email")'
|
|
11
11
|
},
|
|
12
12
|
required: true
|
|
13
13
|
},
|
|
@@ -15,14 +15,14 @@ export const SendEmailStepTask = {
|
|
|
15
15
|
name: 'from',
|
|
16
16
|
type: 'text',
|
|
17
17
|
admin: {
|
|
18
|
-
description: 'Sender email address (
|
|
18
|
+
description: 'Sender email address. Use JSONPath if needed (e.g., "$.trigger.doc.senderEmail"). Uses default if not provided.'
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
name: 'subject',
|
|
23
23
|
type: 'text',
|
|
24
24
|
admin: {
|
|
25
|
-
description: 'Email subject line'
|
|
25
|
+
description: 'Email subject line. Can include JSONPath references (e.g., "Order #$.trigger.doc.orderNumber received")'
|
|
26
26
|
},
|
|
27
27
|
required: true
|
|
28
28
|
},
|
|
@@ -30,14 +30,14 @@ export const SendEmailStepTask = {
|
|
|
30
30
|
name: 'text',
|
|
31
31
|
type: 'textarea',
|
|
32
32
|
admin: {
|
|
33
|
-
description: 'Plain text email content'
|
|
33
|
+
description: 'Plain text email content. Use JSONPath to include dynamic content (e.g., "Dear $.trigger.doc.customerName, your order #$.trigger.doc.id has been received.")'
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
name: 'html',
|
|
38
38
|
type: 'textarea',
|
|
39
39
|
admin: {
|
|
40
|
-
description: 'HTML email content (
|
|
40
|
+
description: 'HTML email content. Use JSONPath for dynamic values (e.g., "<h1>Order #$.trigger.doc.orderNumber</h1>")'
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/steps/send-email.ts"],"sourcesContent":["import type { TaskConfig } from \"payload\"\n\nimport { sendEmailHandler } from \"./send-email-handler.js\"\n\nexport const SendEmailStepTask = {\n slug: 'send-email',\n handler: sendEmailHandler,\n inputSchema: [\n {\n name: 'to',\n type: 'text',\n admin: {\n description: 'Recipient email address'\n },\n required: true\n },\n {\n name: 'from',\n type: 'text',\n admin: {\n description: 'Sender email address (
|
|
1
|
+
{"version":3,"sources":["../../src/steps/send-email.ts"],"sourcesContent":["import type { TaskConfig } from \"payload\"\n\nimport { sendEmailHandler } from \"./send-email-handler.js\"\n\nexport const SendEmailStepTask = {\n slug: 'send-email',\n handler: sendEmailHandler,\n inputSchema: [\n {\n name: 'to',\n type: 'text',\n admin: {\n description: 'Recipient email address. Use JSONPath for dynamic values (e.g., \"$.trigger.doc.email\" or \"$.trigger.user.email\")'\n },\n required: true\n },\n {\n name: 'from',\n type: 'text',\n admin: {\n description: 'Sender email address. Use JSONPath if needed (e.g., \"$.trigger.doc.senderEmail\"). Uses default if not provided.'\n }\n },\n {\n name: 'subject',\n type: 'text',\n admin: {\n description: 'Email subject line. Can include JSONPath references (e.g., \"Order #$.trigger.doc.orderNumber received\")'\n },\n required: true\n },\n {\n name: 'text',\n type: 'textarea',\n admin: {\n description: 'Plain text email content. Use JSONPath to include dynamic content (e.g., \"Dear $.trigger.doc.customerName, your order #$.trigger.doc.id has been received.\")'\n }\n },\n {\n name: 'html',\n type: 'textarea',\n admin: {\n description: 'HTML email content. Use JSONPath for dynamic values (e.g., \"<h1>Order #$.trigger.doc.orderNumber</h1>\")'\n }\n },\n {\n name: 'cc',\n type: 'text',\n admin: {\n description: 'CC recipients'\n },\n hasMany: true\n },\n {\n name: 'bcc',\n type: 'text',\n admin: {\n description: 'BCC recipients'\n },\n hasMany: true\n }\n ],\n outputSchema: [\n {\n name: 'messageId',\n type: 'text',\n admin: {\n description: 'Email message ID from the mail server'\n }\n },\n {\n name: 'response',\n type: 'text',\n admin: {\n description: 'Response from the mail server'\n }\n }\n ]\n} satisfies TaskConfig<'send-email'>"],"names":["sendEmailHandler","SendEmailStepTask","slug","handler","inputSchema","name","type","admin","description","required","hasMany","outputSchema"],"mappings":"AAEA,SAASA,gBAAgB,QAAQ,0BAAyB;AAE1D,OAAO,MAAMC,oBAAoB;IAC/BC,MAAM;IACNC,SAASH;IACTI,aAAa;QACX;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAE,SAAS;QACX;QACA;YACEL,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAE,SAAS;QACX;KACD;IACDC,cAAc;QACZ;YACEN,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;AACH,EAAoC"}
|
|
@@ -15,7 +15,7 @@ export const UpdateDocumentStepTask = {
|
|
|
15
15
|
name: 'id',
|
|
16
16
|
type: 'text',
|
|
17
17
|
admin: {
|
|
18
|
-
description: 'The ID of the document to update'
|
|
18
|
+
description: 'The ID of the document to update. Use JSONPath to reference IDs (e.g., "$.trigger.doc.id" or "$.steps.previousStep.output.id")'
|
|
19
19
|
},
|
|
20
20
|
required: true
|
|
21
21
|
},
|
|
@@ -23,7 +23,7 @@ export const UpdateDocumentStepTask = {
|
|
|
23
23
|
name: 'data',
|
|
24
24
|
type: 'json',
|
|
25
25
|
admin: {
|
|
26
|
-
description: 'The data to update the document with'
|
|
26
|
+
description: 'The data to update the document with. Use JSONPath to reference values (e.g., {"status": "$.trigger.doc.status", "updatedBy": "$.trigger.user.id"})'
|
|
27
27
|
},
|
|
28
28
|
required: true
|
|
29
29
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/steps/update-document.ts"],"sourcesContent":["import type { TaskConfig } from \"payload\"\n\nimport { updateDocumentHandler } from \"./update-document-handler.js\"\n\nexport const UpdateDocumentStepTask = {\n slug: 'update-document',\n handler: updateDocumentHandler,\n inputSchema: [\n {\n name: 'collectionSlug',\n type: 'text',\n admin: {\n description: 'The collection slug to update a document in'\n },\n required: true\n },\n {\n name: 'id',\n type: 'text',\n admin: {\n description: 'The ID of the document to update'\n },\n required: true\n },\n {\n name: 'data',\n type: 'json',\n admin: {\n description: 'The data to update the document with'\n },\n required: true\n },\n {\n name: 'draft',\n type: 'checkbox',\n admin: {\n description: 'Update as draft (if collection has drafts enabled)'\n }\n },\n {\n name: 'locale',\n type: 'text',\n admin: {\n description: 'Locale for the document (if localization is enabled)'\n }\n }\n ],\n outputSchema: [\n {\n name: 'doc',\n type: 'json',\n admin: {\n description: 'The updated document'\n }\n },\n {\n name: 'id',\n type: 'text',\n admin: {\n description: 'The ID of the updated document'\n }\n }\n ]\n} satisfies TaskConfig<'update-document'>"],"names":["updateDocumentHandler","UpdateDocumentStepTask","slug","handler","inputSchema","name","type","admin","description","required","outputSchema"],"mappings":"AAEA,SAASA,qBAAqB,QAAQ,+BAA8B;AAEpE,OAAO,MAAMC,yBAAyB;IACpCC,MAAM;IACNC,SAASH;IACTI,aAAa;QACX;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;IACDE,cAAc;QACZ;YACEL,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;AACH,EAAyC"}
|
|
1
|
+
{"version":3,"sources":["../../src/steps/update-document.ts"],"sourcesContent":["import type { TaskConfig } from \"payload\"\n\nimport { updateDocumentHandler } from \"./update-document-handler.js\"\n\nexport const UpdateDocumentStepTask = {\n slug: 'update-document',\n handler: updateDocumentHandler,\n inputSchema: [\n {\n name: 'collectionSlug',\n type: 'text',\n admin: {\n description: 'The collection slug to update a document in'\n },\n required: true\n },\n {\n name: 'id',\n type: 'text',\n admin: {\n description: 'The ID of the document to update. Use JSONPath to reference IDs (e.g., \"$.trigger.doc.id\" or \"$.steps.previousStep.output.id\")'\n },\n required: true\n },\n {\n name: 'data',\n type: 'json',\n admin: {\n description: 'The data to update the document with. Use JSONPath to reference values (e.g., {\"status\": \"$.trigger.doc.status\", \"updatedBy\": \"$.trigger.user.id\"})'\n },\n required: true\n },\n {\n name: 'draft',\n type: 'checkbox',\n admin: {\n description: 'Update as draft (if collection has drafts enabled)'\n }\n },\n {\n name: 'locale',\n type: 'text',\n admin: {\n description: 'Locale for the document (if localization is enabled)'\n }\n }\n ],\n outputSchema: [\n {\n name: 'doc',\n type: 'json',\n admin: {\n description: 'The updated document'\n }\n },\n {\n name: 'id',\n type: 'text',\n admin: {\n description: 'The ID of the updated document'\n }\n }\n ]\n} satisfies TaskConfig<'update-document'>"],"names":["updateDocumentHandler","UpdateDocumentStepTask","slug","handler","inputSchema","name","type","admin","description","required","outputSchema"],"mappings":"AAEA,SAASA,qBAAqB,QAAQ,+BAA8B;AAEpE,OAAO,MAAMC,yBAAyB;IACpCC,MAAM;IACNC,SAASH;IACTI,aAAa;QACX;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;IACDE,cAAc;QACZ;YACEL,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;QACF;KACD;AACH,EAAyC"}
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { createDocumentHandler } from '../steps/create-document-handler.js';
|
|
3
|
+
describe('CreateDocumentStepHandler', ()=>{
|
|
4
|
+
let mockPayload;
|
|
5
|
+
let mockReq;
|
|
6
|
+
beforeEach(()=>{
|
|
7
|
+
mockPayload = {
|
|
8
|
+
create: vi.fn()
|
|
9
|
+
};
|
|
10
|
+
mockReq = {
|
|
11
|
+
payload: mockPayload,
|
|
12
|
+
user: {
|
|
13
|
+
id: 'user-123',
|
|
14
|
+
email: 'test@example.com'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
describe('Document creation', ()=>{
|
|
20
|
+
it('should create document successfully', async ()=>{
|
|
21
|
+
const createdDoc = {
|
|
22
|
+
id: 'doc-123',
|
|
23
|
+
title: 'Test Document',
|
|
24
|
+
content: 'Test content'
|
|
25
|
+
};
|
|
26
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
27
|
+
const input = {
|
|
28
|
+
collectionSlug: 'posts',
|
|
29
|
+
data: {
|
|
30
|
+
title: 'Test Document',
|
|
31
|
+
content: 'Test content'
|
|
32
|
+
},
|
|
33
|
+
stepName: 'test-create-step'
|
|
34
|
+
};
|
|
35
|
+
const result = await createDocumentHandler({
|
|
36
|
+
input,
|
|
37
|
+
req: mockReq
|
|
38
|
+
});
|
|
39
|
+
expect(result.state).toBe('succeeded');
|
|
40
|
+
expect(result.output.document).toEqual(createdDoc);
|
|
41
|
+
expect(result.output.id).toBe('doc-123');
|
|
42
|
+
expect(mockPayload.create).toHaveBeenCalledWith({
|
|
43
|
+
collection: 'posts',
|
|
44
|
+
data: {
|
|
45
|
+
title: 'Test Document',
|
|
46
|
+
content: 'Test content'
|
|
47
|
+
},
|
|
48
|
+
req: mockReq
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
it('should create document with relationship fields', async ()=>{
|
|
52
|
+
const createdDoc = {
|
|
53
|
+
id: 'doc-456',
|
|
54
|
+
title: 'Related Document',
|
|
55
|
+
author: 'user-123',
|
|
56
|
+
category: 'cat-789'
|
|
57
|
+
};
|
|
58
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
59
|
+
const input = {
|
|
60
|
+
collectionSlug: 'articles',
|
|
61
|
+
data: {
|
|
62
|
+
title: 'Related Document',
|
|
63
|
+
author: 'user-123',
|
|
64
|
+
category: 'cat-789'
|
|
65
|
+
},
|
|
66
|
+
stepName: 'test-create-with-relations'
|
|
67
|
+
};
|
|
68
|
+
const result = await createDocumentHandler({
|
|
69
|
+
input,
|
|
70
|
+
req: mockReq
|
|
71
|
+
});
|
|
72
|
+
expect(result.state).toBe('succeeded');
|
|
73
|
+
expect(result.output.document).toEqual(createdDoc);
|
|
74
|
+
expect(mockPayload.create).toHaveBeenCalledWith({
|
|
75
|
+
collection: 'articles',
|
|
76
|
+
data: {
|
|
77
|
+
title: 'Related Document',
|
|
78
|
+
author: 'user-123',
|
|
79
|
+
category: 'cat-789'
|
|
80
|
+
},
|
|
81
|
+
req: mockReq
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
it('should create document with complex nested data', async ()=>{
|
|
85
|
+
const complexData = {
|
|
86
|
+
title: 'Complex Document',
|
|
87
|
+
metadata: {
|
|
88
|
+
tags: [
|
|
89
|
+
'tag1',
|
|
90
|
+
'tag2'
|
|
91
|
+
],
|
|
92
|
+
settings: {
|
|
93
|
+
featured: true,
|
|
94
|
+
priority: 5
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
blocks: [
|
|
98
|
+
{
|
|
99
|
+
type: 'text',
|
|
100
|
+
content: 'Text block'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'image',
|
|
104
|
+
src: 'image.jpg',
|
|
105
|
+
alt: 'Test image'
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
const createdDoc = {
|
|
110
|
+
id: 'doc-complex',
|
|
111
|
+
...complexData
|
|
112
|
+
};
|
|
113
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
114
|
+
const input = {
|
|
115
|
+
collectionSlug: 'pages',
|
|
116
|
+
data: complexData,
|
|
117
|
+
stepName: 'test-create-complex'
|
|
118
|
+
};
|
|
119
|
+
const result = await createDocumentHandler({
|
|
120
|
+
input,
|
|
121
|
+
req: mockReq
|
|
122
|
+
});
|
|
123
|
+
expect(result.state).toBe('succeeded');
|
|
124
|
+
expect(result.output.document).toEqual(createdDoc);
|
|
125
|
+
expect(mockPayload.create).toHaveBeenCalledWith({
|
|
126
|
+
collection: 'pages',
|
|
127
|
+
data: complexData,
|
|
128
|
+
req: mockReq
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('Error handling', ()=>{
|
|
133
|
+
it('should handle PayloadCMS validation errors', async ()=>{
|
|
134
|
+
const validationError = new Error('Validation failed');
|
|
135
|
+
validationError.data = [
|
|
136
|
+
{
|
|
137
|
+
message: 'Title is required',
|
|
138
|
+
path: 'title',
|
|
139
|
+
value: undefined
|
|
140
|
+
}
|
|
141
|
+
];
|
|
142
|
+
mockPayload.create.mockRejectedValue(validationError);
|
|
143
|
+
const input = {
|
|
144
|
+
collectionSlug: 'posts',
|
|
145
|
+
data: {
|
|
146
|
+
content: 'Missing title'
|
|
147
|
+
},
|
|
148
|
+
stepName: 'test-validation-error'
|
|
149
|
+
};
|
|
150
|
+
const result = await createDocumentHandler({
|
|
151
|
+
input,
|
|
152
|
+
req: mockReq
|
|
153
|
+
});
|
|
154
|
+
expect(result.state).toBe('failed');
|
|
155
|
+
expect(result.error).toContain('Validation failed');
|
|
156
|
+
});
|
|
157
|
+
it('should handle permission errors', async ()=>{
|
|
158
|
+
const permissionError = new Error('Insufficient permissions');
|
|
159
|
+
permissionError.status = 403;
|
|
160
|
+
mockPayload.create.mockRejectedValue(permissionError);
|
|
161
|
+
const input = {
|
|
162
|
+
collectionSlug: 'admin-only',
|
|
163
|
+
data: {
|
|
164
|
+
secret: 'confidential data'
|
|
165
|
+
},
|
|
166
|
+
stepName: 'test-permission-error'
|
|
167
|
+
};
|
|
168
|
+
const result = await createDocumentHandler({
|
|
169
|
+
input,
|
|
170
|
+
req: mockReq
|
|
171
|
+
});
|
|
172
|
+
expect(result.state).toBe('failed');
|
|
173
|
+
expect(result.error).toContain('Insufficient permissions');
|
|
174
|
+
});
|
|
175
|
+
it('should handle database connection errors', async ()=>{
|
|
176
|
+
const dbError = new Error('Database connection failed');
|
|
177
|
+
mockPayload.create.mockRejectedValue(dbError);
|
|
178
|
+
const input = {
|
|
179
|
+
collectionSlug: 'posts',
|
|
180
|
+
data: {
|
|
181
|
+
title: 'Test'
|
|
182
|
+
},
|
|
183
|
+
stepName: 'test-db-error'
|
|
184
|
+
};
|
|
185
|
+
const result = await createDocumentHandler({
|
|
186
|
+
input,
|
|
187
|
+
req: mockReq
|
|
188
|
+
});
|
|
189
|
+
expect(result.state).toBe('failed');
|
|
190
|
+
expect(result.error).toContain('Database connection failed');
|
|
191
|
+
});
|
|
192
|
+
it('should handle unknown collection errors', async ()=>{
|
|
193
|
+
const collectionError = new Error('Collection "unknown" not found');
|
|
194
|
+
mockPayload.create.mockRejectedValue(collectionError);
|
|
195
|
+
const input = {
|
|
196
|
+
collectionSlug: 'unknown-collection',
|
|
197
|
+
data: {
|
|
198
|
+
title: 'Test'
|
|
199
|
+
},
|
|
200
|
+
stepName: 'test-unknown-collection'
|
|
201
|
+
};
|
|
202
|
+
const result = await createDocumentHandler({
|
|
203
|
+
input,
|
|
204
|
+
req: mockReq
|
|
205
|
+
});
|
|
206
|
+
expect(result.state).toBe('failed');
|
|
207
|
+
expect(result.error).toContain('Collection "unknown" not found');
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
describe('Input validation', ()=>{
|
|
211
|
+
it('should validate required collection slug', async ()=>{
|
|
212
|
+
const input = {
|
|
213
|
+
data: {
|
|
214
|
+
title: 'Test'
|
|
215
|
+
},
|
|
216
|
+
stepName: 'test-missing-collection'
|
|
217
|
+
};
|
|
218
|
+
const result = await createDocumentStepHandler({
|
|
219
|
+
input,
|
|
220
|
+
req: mockReq
|
|
221
|
+
});
|
|
222
|
+
expect(result.state).toBe('failed');
|
|
223
|
+
expect(result.error).toContain('Collection slug is required');
|
|
224
|
+
});
|
|
225
|
+
it('should validate required data field', async ()=>{
|
|
226
|
+
const input = {
|
|
227
|
+
collectionSlug: 'posts',
|
|
228
|
+
stepName: 'test-missing-data'
|
|
229
|
+
};
|
|
230
|
+
const result = await createDocumentStepHandler({
|
|
231
|
+
input,
|
|
232
|
+
req: mockReq
|
|
233
|
+
});
|
|
234
|
+
expect(result.state).toBe('failed');
|
|
235
|
+
expect(result.error).toContain('Data is required');
|
|
236
|
+
});
|
|
237
|
+
it('should validate data is an object', async ()=>{
|
|
238
|
+
const input = {
|
|
239
|
+
collectionSlug: 'posts',
|
|
240
|
+
data: 'invalid-data-type',
|
|
241
|
+
stepName: 'test-invalid-data-type'
|
|
242
|
+
};
|
|
243
|
+
const result = await createDocumentStepHandler({
|
|
244
|
+
input,
|
|
245
|
+
req: mockReq
|
|
246
|
+
});
|
|
247
|
+
expect(result.state).toBe('failed');
|
|
248
|
+
expect(result.error).toContain('Data must be an object');
|
|
249
|
+
});
|
|
250
|
+
it('should handle empty data object', async ()=>{
|
|
251
|
+
const createdDoc = {
|
|
252
|
+
id: 'empty-doc'
|
|
253
|
+
};
|
|
254
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
255
|
+
const input = {
|
|
256
|
+
collectionSlug: 'posts',
|
|
257
|
+
data: {},
|
|
258
|
+
stepName: 'test-empty-data'
|
|
259
|
+
};
|
|
260
|
+
const result = await createDocumentHandler({
|
|
261
|
+
input,
|
|
262
|
+
req: mockReq
|
|
263
|
+
});
|
|
264
|
+
expect(result.state).toBe('succeeded');
|
|
265
|
+
expect(result.output.document).toEqual(createdDoc);
|
|
266
|
+
expect(mockPayload.create).toHaveBeenCalledWith({
|
|
267
|
+
collection: 'posts',
|
|
268
|
+
data: {},
|
|
269
|
+
req: mockReq
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
describe('Request context', ()=>{
|
|
274
|
+
it('should pass user context from request', async ()=>{
|
|
275
|
+
const createdDoc = {
|
|
276
|
+
id: 'user-doc',
|
|
277
|
+
title: 'User Document'
|
|
278
|
+
};
|
|
279
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
280
|
+
const input = {
|
|
281
|
+
collectionSlug: 'posts',
|
|
282
|
+
data: {
|
|
283
|
+
title: 'User Document'
|
|
284
|
+
},
|
|
285
|
+
stepName: 'test-user-context'
|
|
286
|
+
};
|
|
287
|
+
await createDocumentStepHandler({
|
|
288
|
+
input,
|
|
289
|
+
req: mockReq
|
|
290
|
+
});
|
|
291
|
+
const createCall = mockPayload.create.mock.calls[0][0];
|
|
292
|
+
expect(createCall.req).toBe(mockReq);
|
|
293
|
+
expect(createCall.req.user).toEqual({
|
|
294
|
+
id: 'user-123',
|
|
295
|
+
email: 'test@example.com'
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
it('should handle requests without user context', async ()=>{
|
|
299
|
+
const reqWithoutUser = {
|
|
300
|
+
payload: mockPayload,
|
|
301
|
+
user: null
|
|
302
|
+
};
|
|
303
|
+
const createdDoc = {
|
|
304
|
+
id: 'anonymous-doc'
|
|
305
|
+
};
|
|
306
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
307
|
+
const input = {
|
|
308
|
+
collectionSlug: 'posts',
|
|
309
|
+
data: {
|
|
310
|
+
title: 'Anonymous Document'
|
|
311
|
+
},
|
|
312
|
+
stepName: 'test-anonymous'
|
|
313
|
+
};
|
|
314
|
+
const result = await createDocumentStepHandler({
|
|
315
|
+
input,
|
|
316
|
+
req: reqWithoutUser
|
|
317
|
+
});
|
|
318
|
+
expect(result.state).toBe('succeeded');
|
|
319
|
+
expect(mockPayload.create).toHaveBeenCalledWith({
|
|
320
|
+
collection: 'posts',
|
|
321
|
+
data: {
|
|
322
|
+
title: 'Anonymous Document'
|
|
323
|
+
},
|
|
324
|
+
req: reqWithoutUser
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
describe('Output structure', ()=>{
|
|
329
|
+
it('should return correct output structure on success', async ()=>{
|
|
330
|
+
const createdDoc = {
|
|
331
|
+
id: 'output-test-doc',
|
|
332
|
+
title: 'Output Test',
|
|
333
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
334
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
335
|
+
};
|
|
336
|
+
mockPayload.create.mockResolvedValue(createdDoc);
|
|
337
|
+
const input = {
|
|
338
|
+
collectionSlug: 'posts',
|
|
339
|
+
data: {
|
|
340
|
+
title: 'Output Test'
|
|
341
|
+
},
|
|
342
|
+
stepName: 'test-output-structure'
|
|
343
|
+
};
|
|
344
|
+
const result = await createDocumentHandler({
|
|
345
|
+
input,
|
|
346
|
+
req: mockReq
|
|
347
|
+
});
|
|
348
|
+
expect(result).toEqual({
|
|
349
|
+
state: 'succeeded',
|
|
350
|
+
output: {
|
|
351
|
+
document: createdDoc,
|
|
352
|
+
id: 'output-test-doc'
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
it('should return correct error structure on failure', async ()=>{
|
|
357
|
+
const error = new Error('Test error');
|
|
358
|
+
mockPayload.create.mockRejectedValue(error);
|
|
359
|
+
const input = {
|
|
360
|
+
collectionSlug: 'posts',
|
|
361
|
+
data: {
|
|
362
|
+
title: 'Error Test'
|
|
363
|
+
},
|
|
364
|
+
stepName: 'test-error-structure'
|
|
365
|
+
};
|
|
366
|
+
const result = await createDocumentHandler({
|
|
367
|
+
input,
|
|
368
|
+
req: mockReq
|
|
369
|
+
});
|
|
370
|
+
expect(result).toEqual({
|
|
371
|
+
state: 'failed',
|
|
372
|
+
error: 'Test error'
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
//# sourceMappingURL=create-document-step.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/test/create-document-step.test.ts"],"sourcesContent":["import { describe, it, expect, vi, beforeEach } from 'vitest'\nimport { createDocumentHandler } from '../steps/create-document-handler.js'\nimport type { Payload } from 'payload'\n\ndescribe('CreateDocumentStepHandler', () => {\n let mockPayload: Payload\n let mockReq: any\n\n beforeEach(() => {\n mockPayload = {\n create: vi.fn()\n } as any\n\n mockReq = {\n payload: mockPayload,\n user: { id: 'user-123', email: 'test@example.com' }\n }\n vi.clearAllMocks()\n })\n\n describe('Document creation', () => {\n it('should create document successfully', async () => {\n const createdDoc = {\n id: 'doc-123',\n title: 'Test Document',\n content: 'Test content'\n }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'posts',\n data: {\n title: 'Test Document',\n content: 'Test content'\n },\n stepName: 'test-create-step'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('succeeded')\n expect(result.output.document).toEqual(createdDoc)\n expect(result.output.id).toBe('doc-123')\n\n expect(mockPayload.create).toHaveBeenCalledWith({\n collection: 'posts',\n data: {\n title: 'Test Document',\n content: 'Test content'\n },\n req: mockReq\n })\n })\n\n it('should create document with relationship fields', async () => {\n const createdDoc = {\n id: 'doc-456',\n title: 'Related Document',\n author: 'user-123',\n category: 'cat-789'\n }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'articles',\n data: {\n title: 'Related Document',\n author: 'user-123',\n category: 'cat-789'\n },\n stepName: 'test-create-with-relations'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('succeeded')\n expect(result.output.document).toEqual(createdDoc)\n expect(mockPayload.create).toHaveBeenCalledWith({\n collection: 'articles',\n data: {\n title: 'Related Document',\n author: 'user-123',\n category: 'cat-789'\n },\n req: mockReq\n })\n })\n\n it('should create document with complex nested data', async () => {\n const complexData = {\n title: 'Complex Document',\n metadata: {\n tags: ['tag1', 'tag2'],\n settings: {\n featured: true,\n priority: 5\n }\n },\n blocks: [\n { type: 'text', content: 'Text block' },\n { type: 'image', src: 'image.jpg', alt: 'Test image' }\n ]\n }\n\n const createdDoc = { id: 'doc-complex', ...complexData }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'pages',\n data: complexData,\n stepName: 'test-create-complex'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('succeeded')\n expect(result.output.document).toEqual(createdDoc)\n expect(mockPayload.create).toHaveBeenCalledWith({\n collection: 'pages',\n data: complexData,\n req: mockReq\n })\n })\n })\n\n describe('Error handling', () => {\n it('should handle PayloadCMS validation errors', async () => {\n const validationError = new Error('Validation failed')\n ;(validationError as any).data = [\n {\n message: 'Title is required',\n path: 'title',\n value: undefined\n }\n ]\n ;(mockPayload.create as any).mockRejectedValue(validationError)\n\n const input = {\n collectionSlug: 'posts',\n data: {\n content: 'Missing title'\n },\n stepName: 'test-validation-error'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Validation failed')\n })\n\n it('should handle permission errors', async () => {\n const permissionError = new Error('Insufficient permissions')\n ;(permissionError as any).status = 403\n ;(mockPayload.create as any).mockRejectedValue(permissionError)\n\n const input = {\n collectionSlug: 'admin-only',\n data: {\n secret: 'confidential data'\n },\n stepName: 'test-permission-error'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Insufficient permissions')\n })\n\n it('should handle database connection errors', async () => {\n const dbError = new Error('Database connection failed')\n ;(mockPayload.create as any).mockRejectedValue(dbError)\n\n const input = {\n collectionSlug: 'posts',\n data: { title: 'Test' },\n stepName: 'test-db-error'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Database connection failed')\n })\n\n it('should handle unknown collection errors', async () => {\n const collectionError = new Error('Collection \"unknown\" not found')\n ;(mockPayload.create as any).mockRejectedValue(collectionError)\n\n const input = {\n collectionSlug: 'unknown-collection',\n data: { title: 'Test' },\n stepName: 'test-unknown-collection'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Collection \"unknown\" not found')\n })\n })\n\n describe('Input validation', () => {\n it('should validate required collection slug', async () => {\n const input = {\n data: { title: 'Test' },\n stepName: 'test-missing-collection'\n }\n\n const result = await createDocumentStepHandler({ input, req: mockReq } as any)\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Collection slug is required')\n })\n\n it('should validate required data field', async () => {\n const input = {\n collectionSlug: 'posts',\n stepName: 'test-missing-data'\n }\n\n const result = await createDocumentStepHandler({ input, req: mockReq } as any)\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Data is required')\n })\n\n it('should validate data is an object', async () => {\n const input = {\n collectionSlug: 'posts',\n data: 'invalid-data-type',\n stepName: 'test-invalid-data-type'\n }\n\n const result = await createDocumentStepHandler({ input, req: mockReq } as any)\n\n expect(result.state).toBe('failed')\n expect(result.error).toContain('Data must be an object')\n })\n\n it('should handle empty data object', async () => {\n const createdDoc = { id: 'empty-doc' }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'posts',\n data: {},\n stepName: 'test-empty-data'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result.state).toBe('succeeded')\n expect(result.output.document).toEqual(createdDoc)\n expect(mockPayload.create).toHaveBeenCalledWith({\n collection: 'posts',\n data: {},\n req: mockReq\n })\n })\n })\n\n describe('Request context', () => {\n it('should pass user context from request', async () => {\n const createdDoc = { id: 'user-doc', title: 'User Document' }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'posts',\n data: { title: 'User Document' },\n stepName: 'test-user-context'\n }\n\n await createDocumentStepHandler({ input, req: mockReq })\n\n const createCall = (mockPayload.create as any).mock.calls[0][0]\n expect(createCall.req).toBe(mockReq)\n expect(createCall.req.user).toEqual({\n id: 'user-123',\n email: 'test@example.com'\n })\n })\n\n it('should handle requests without user context', async () => {\n const reqWithoutUser = {\n payload: mockPayload,\n user: null\n }\n\n const createdDoc = { id: 'anonymous-doc' }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'posts',\n data: { title: 'Anonymous Document' },\n stepName: 'test-anonymous'\n }\n\n const result = await createDocumentStepHandler({ input, req: reqWithoutUser })\n\n expect(result.state).toBe('succeeded')\n expect(mockPayload.create).toHaveBeenCalledWith({\n collection: 'posts',\n data: { title: 'Anonymous Document' },\n req: reqWithoutUser\n })\n })\n })\n\n describe('Output structure', () => {\n it('should return correct output structure on success', async () => {\n const createdDoc = {\n id: 'output-test-doc',\n title: 'Output Test',\n createdAt: '2024-01-01T00:00:00.000Z',\n updatedAt: '2024-01-01T00:00:00.000Z'\n }\n ;(mockPayload.create as any).mockResolvedValue(createdDoc)\n\n const input = {\n collectionSlug: 'posts',\n data: { title: 'Output Test' },\n stepName: 'test-output-structure'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result).toEqual({\n state: 'succeeded',\n output: {\n document: createdDoc,\n id: 'output-test-doc'\n }\n })\n })\n\n it('should return correct error structure on failure', async () => {\n const error = new Error('Test error')\n ;(mockPayload.create as any).mockRejectedValue(error)\n\n const input = {\n collectionSlug: 'posts',\n data: { title: 'Error Test' },\n stepName: 'test-error-structure'\n }\n\n const result = await createDocumentHandler({ input, req: mockReq })\n\n expect(result).toEqual({\n state: 'failed',\n error: 'Test error'\n })\n })\n })\n})"],"names":["describe","it","expect","vi","beforeEach","createDocumentHandler","mockPayload","mockReq","create","fn","payload","user","id","email","clearAllMocks","createdDoc","title","content","mockResolvedValue","input","collectionSlug","data","stepName","result","req","state","toBe","output","document","toEqual","toHaveBeenCalledWith","collection","author","category","complexData","metadata","tags","settings","featured","priority","blocks","type","src","alt","validationError","Error","message","path","value","undefined","mockRejectedValue","error","toContain","permissionError","status","secret","dbError","collectionError","createDocumentStepHandler","createCall","mock","calls","reqWithoutUser","createdAt","updatedAt"],"mappings":"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"}
|