@shopnex/cj-plugin 1.0.2 → 1.0.3

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 ADDED
@@ -0,0 +1,110 @@
1
+ # CJ Dropshipping Plugin for Payload CMS
2
+
3
+ This plugin integrates **CJ Dropshipping** into your **Payload CMS** project by:
4
+
5
+ - Adding "CJ" as a product source.
6
+ - Automatically creating CJ orders after local orders are created.
7
+ - (Optionally) generating a `cj-settings` collection for managing API credentials dynamically.
8
+ - Syncing CJ credentials on app initialization.
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm install @shopnex/cj-plugin
16
+ ```
17
+
18
+ or
19
+
20
+ ```bash
21
+ npm install @shopnex/cj-plugin
22
+ ```
23
+
24
+ or
25
+
26
+ ```bash
27
+ yarn add @shopnex/cj-plugin
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Usage
33
+
34
+ Import and add the `cjPlugin` to your Payload config:
35
+
36
+ ```ts
37
+ import { buildConfig } from "payload/config";
38
+ import { cjPlugin } from "@shopnex/cj-plugin";
39
+
40
+ export default buildConfig({
41
+ collections: [
42
+ // your collections
43
+ ],
44
+ plugins: [
45
+ cjPlugin({
46
+ cjApiKey: "your-cj-api-key",
47
+ cjEmailAddress: "your-email@example.com",
48
+ cjRefreshToken: "optional-refresh-token", // optional
49
+ asCollection: true, // optional - creates a cj-settings collection
50
+ collectionOverrides: {
51
+ // optional - override fields or settings for the cj-settings collection
52
+ },
53
+ }),
54
+ ],
55
+ });
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Plugin Options
61
+
62
+ | Option | Type | Required | Description |
63
+ | --------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------- |
64
+ | `cjApiKey` | `string` | Yes | Your CJ Dropshipping API key. |
65
+ | `cjEmailAddress` | `string` | Yes | Your CJ account email address. |
66
+ | `cjRefreshToken` | `string` | No | Your CJ refresh token if available. |
67
+ | `asCollection` | `boolean` | No | If true, automatically creates a `cj-settings` collection to manage CJ API credentials per tenant/shop. |
68
+ | `collectionOverrides` | `object` | No | Allows overriding the default `cj-settings` collection config (fields, hooks, etc). |
69
+
70
+ ---
71
+
72
+ ## What the Plugin Does
73
+
74
+ - **Modifies the `products` collection**:
75
+ - Adds a `source` option: `{ label: 'CJ', value: 'cj' }`.
76
+ - **Hooks into the `orders` collection**:
77
+ - On every new order or update, triggers the CJ order creation logic automatically.
78
+ - **Manages CJ credentials dynamically**:
79
+ - On Payload startup (`onInit`), loads all `cj-settings` documents and sets up credentials per shop.
80
+ - **Optional `cj-settings` collection**:
81
+ - If `asCollection` is true, a new `cj-settings` collection will be added automatically.
82
+ - Useful for multi-tenant setups or dynamically changing credentials.
83
+
84
+ ---
85
+
86
+ ## Example: cj-settings Collection
87
+
88
+ If `asCollection: true`, the following collection will be generated by default:
89
+
90
+ | Field | Type | Description |
91
+ | ---------- | -------- | --------------------------------- |
92
+ | `shop` | Relation | Reference to your shop or tenant. |
93
+ | `email` | Text | Your CJ email address. |
94
+ | `apiToken` | Text | Your CJ API key. |
95
+
96
+ You can override this structure with `collectionOverrides`.
97
+
98
+ ---
99
+
100
+ ## Notes
101
+
102
+ - The plugin assumes you have a `products` collection with a `source` select field already created.
103
+ - It assumes you have an `orders` collection.
104
+ - Make sure the `source` field in `products` uses a `select` type with `options` array.
105
+
106
+ ---
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,7 @@
1
+ import { CollectionConfig } from "payload";
2
+ export type CjCollectionProps = {
3
+ overrides?: {
4
+ access: CollectionConfig["access"];
5
+ };
6
+ };
7
+ export declare const CjConfigCollection: ({ overrides }: CjCollectionProps) => CollectionConfig;
@@ -0,0 +1,93 @@
1
+ import { decryptToken, encryptToken } from "./util/manage-tokens";
2
+ import { syncProducts } from "./service/sync-products";
3
+ export const CjConfigCollection = ({ overrides })=>({
4
+ slug: "cj-settings",
5
+ access: {
6
+ ...overrides?.access
7
+ },
8
+ admin: {
9
+ group: "Plugins"
10
+ },
11
+ fields: [
12
+ {
13
+ label: "Credentials",
14
+ type: "collapsible",
15
+ fields: [
16
+ {
17
+ type: "row",
18
+ fields: [
19
+ {
20
+ name: "emailAddress",
21
+ type: "text"
22
+ },
23
+ {
24
+ name: "apiToken",
25
+ type: "text",
26
+ admin: {
27
+ components: {
28
+ Field: "@shopnex/cj-plugin/rsc#ApiToken"
29
+ }
30
+ }
31
+ }
32
+ ]
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ label: "Logo Area POD",
38
+ name: "pod",
39
+ type: "upload",
40
+ relationTo: "media"
41
+ },
42
+ {
43
+ name: "items",
44
+ type: "array",
45
+ admin: {
46
+ description: "A list of product URLs to sync with CJ Dropshipping"
47
+ },
48
+ fields: [
49
+ {
50
+ name: "productUrl",
51
+ type: "text"
52
+ }
53
+ ],
54
+ label: "Products",
55
+ labels: {
56
+ plural: "Product URLs",
57
+ singular: "Product URL"
58
+ }
59
+ }
60
+ ],
61
+ hooks: {
62
+ beforeChange: [
63
+ ({ data })=>{
64
+ const tokenToEncrypt = data.apiToken;
65
+ const encryptedToken = encryptToken(tokenToEncrypt);
66
+ data.apiToken = encryptedToken;
67
+ }
68
+ ],
69
+ beforeRead: [
70
+ ({ doc })=>{
71
+ doc.apiToken = doc?.apiToken && decryptToken(doc.apiToken);
72
+ }
73
+ ],
74
+ afterChange: [
75
+ async ({ doc, req: { payload } })=>{
76
+ const productIds = doc.items.map((item)=>{
77
+ const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\.html)/);
78
+ return match ? match[0] : null;
79
+ });
80
+ await syncProducts(productIds, payload);
81
+ },
82
+ ({ doc })=>{
83
+ doc.apiToken = doc.apiToken && decryptToken(doc.apiToken);
84
+ }
85
+ ]
86
+ },
87
+ labels: {
88
+ singular: "CJ Dropshipping",
89
+ plural: "CJ Configs"
90
+ }
91
+ });
92
+
93
+ //# sourceMappingURL=CjConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/CjConfig.ts"],"sourcesContent":["import { CollectionConfig } from \"payload\";\nimport { decryptToken, encryptToken } from \"./util/manage-tokens\";\nimport { syncProducts } from \"./service/sync-products\";\n\nexport type CjCollectionProps = {\n overrides?: {\n access: CollectionConfig[\"access\"];\n };\n};\n\nexport const CjConfigCollection = ({ overrides }: CjCollectionProps): CollectionConfig => ({\n slug: \"cj-settings\",\n access: {\n ...overrides?.access,\n },\n admin: {\n group: \"Plugins\",\n },\n fields: [\n {\n label: \"Credentials\",\n type: \"collapsible\",\n fields: [\n {\n type: \"row\",\n fields: [\n {\n name: \"emailAddress\",\n type: \"text\",\n },\n {\n name: \"apiToken\",\n type: \"text\",\n admin: {\n components: {\n Field: \"@shopnex/cj-plugin/rsc#ApiToken\",\n },\n },\n },\n ],\n },\n ],\n },\n {\n label: \"Logo Area POD\",\n name: \"pod\",\n type: \"upload\",\n relationTo: \"media\",\n },\n {\n name: \"items\",\n type: \"array\",\n admin: {\n description: \"A list of product URLs to sync with CJ Dropshipping\",\n },\n fields: [\n {\n name: \"productUrl\",\n type: \"text\",\n },\n ],\n label: \"Products\",\n labels: {\n plural: \"Product URLs\",\n singular: \"Product URL\",\n },\n },\n ],\n hooks: {\n beforeChange: [\n ({ data }) => {\n const tokenToEncrypt = data.apiToken;\n const encryptedToken = encryptToken(tokenToEncrypt);\n data.apiToken = encryptedToken;\n },\n ],\n beforeRead: [\n ({ doc }) => {\n doc.apiToken = doc?.apiToken && decryptToken(doc.apiToken);\n },\n ],\n afterChange: [\n async ({ doc, req: { payload } }) => {\n const productIds = doc.items.map((item: any) => {\n const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\\.html)/);\n return match ? match[0] : null;\n });\n await syncProducts(productIds, payload);\n },\n ({ doc }) => {\n doc.apiToken = doc.apiToken && decryptToken(doc.apiToken);\n },\n ],\n },\n labels: {\n singular: \"CJ Dropshipping\",\n plural: \"CJ Configs\",\n },\n});\n"],"names":["decryptToken","encryptToken","syncProducts","CjConfigCollection","overrides","slug","access","admin","group","fields","label","type","name","components","Field","relationTo","description","labels","plural","singular","hooks","beforeChange","data","tokenToEncrypt","apiToken","encryptedToken","beforeRead","doc","afterChange","req","payload","productIds","items","map","item","match","productUrl"],"mappings":"AACA,SAASA,YAAY,EAAEC,YAAY,QAAQ,uBAAuB;AAClE,SAASC,YAAY,QAAQ,0BAA0B;AAQvD,OAAO,MAAMC,qBAAqB,CAAC,EAAEC,SAAS,EAAqB,GAAwB,CAAA;QACvFC,MAAM;QACNC,QAAQ;YACJ,GAAGF,WAAWE,MAAM;QACxB;QACAC,OAAO;YACHC,OAAO;QACX;QACAC,QAAQ;YACJ;gBACIC,OAAO;gBACPC,MAAM;gBACNF,QAAQ;oBACJ;wBACIE,MAAM;wBACNF,QAAQ;4BACJ;gCACIG,MAAM;gCACND,MAAM;4BACV;4BACA;gCACIC,MAAM;gCACND,MAAM;gCACNJ,OAAO;oCACHM,YAAY;wCACRC,OAAO;oCACX;gCACJ;4BACJ;yBACH;oBACL;iBACH;YACL;YACA;gBACIJ,OAAO;gBACPE,MAAM;gBACND,MAAM;gBACNI,YAAY;YAChB;YACA;gBACIH,MAAM;gBACND,MAAM;gBACNJ,OAAO;oBACHS,aAAa;gBACjB;gBACAP,QAAQ;oBACJ;wBACIG,MAAM;wBACND,MAAM;oBACV;iBACH;gBACDD,OAAO;gBACPO,QAAQ;oBACJC,QAAQ;oBACRC,UAAU;gBACd;YACJ;SACH;QACDC,OAAO;YACHC,cAAc;gBACV,CAAC,EAAEC,IAAI,EAAE;oBACL,MAAMC,iBAAiBD,KAAKE,QAAQ;oBACpC,MAAMC,iBAAiBxB,aAAasB;oBACpCD,KAAKE,QAAQ,GAAGC;gBACpB;aACH;YACDC,YAAY;gBACR,CAAC,EAAEC,GAAG,EAAE;oBACJA,IAAIH,QAAQ,GAAGG,KAAKH,YAAYxB,aAAa2B,IAAIH,QAAQ;gBAC7D;aACH;YACDI,aAAa;gBACT,OAAO,EAAED,GAAG,EAAEE,KAAK,EAAEC,OAAO,EAAE,EAAE;oBAC5B,MAAMC,aAAaJ,IAAIK,KAAK,CAACC,GAAG,CAAC,CAACC;wBAC9B,MAAMC,QAAQD,KAAKE,UAAU,CAACD,KAAK,CAAC;wBACpC,OAAOA,QAAQA,KAAK,CAAC,EAAE,GAAG;oBAC9B;oBACA,MAAMjC,aAAa6B,YAAYD;gBACnC;gBACA,CAAC,EAAEH,GAAG,EAAE;oBACJA,IAAIH,QAAQ,GAAGG,IAAIH,QAAQ,IAAIxB,aAAa2B,IAAIH,QAAQ;gBAC5D;aACH;QACL;QACAP,QAAQ;YACJE,UAAU;YACVD,QAAQ;QACZ;IACJ,CAAA,EAAG"}
@@ -1,14 +1,38 @@
1
1
  import { syncProducts } from "./service/sync-products";
2
+ import { decryptToken, encryptToken } from "./util/manage-tokens";
2
3
  export const CjSettings = {
3
4
  slug: "cj-settings",
4
5
  access: {
5
- read: ()=>true,
6
- update: ({ req })=>!!req.user?.roles?.includes("user")
6
+ read: ()=>true
7
7
  },
8
8
  admin: {
9
9
  group: "Plugins"
10
10
  },
11
11
  fields: [
12
+ {
13
+ label: "Credentials",
14
+ type: "collapsible",
15
+ fields: [
16
+ {
17
+ type: "row",
18
+ fields: [
19
+ {
20
+ name: "emailAddress",
21
+ type: "text"
22
+ },
23
+ {
24
+ name: "apiToken",
25
+ type: "text",
26
+ admin: {
27
+ components: {
28
+ Field: "@shopnex/cj-plugin/rsc#ApiToken"
29
+ }
30
+ }
31
+ }
32
+ ]
33
+ }
34
+ ]
35
+ },
12
36
  {
13
37
  label: "Logo Area POD",
14
38
  name: "pod",
@@ -35,6 +59,18 @@ export const CjSettings = {
35
59
  }
36
60
  ],
37
61
  hooks: {
62
+ beforeChange: [
63
+ ({ data })=>{
64
+ const tokenToEncrypt = data.apiToken;
65
+ const encryptedToken = encryptToken(tokenToEncrypt);
66
+ data.apiToken = encryptedToken;
67
+ }
68
+ ],
69
+ beforeRead: [
70
+ ({ doc })=>{
71
+ doc.apiToken = doc.apiToken && decryptToken(doc.apiToken);
72
+ }
73
+ ],
38
74
  afterChange: [
39
75
  async ({ doc, req: { payload } })=>{
40
76
  const productIds = doc.items.map((item)=>{
@@ -42,6 +78,9 @@ export const CjSettings = {
42
78
  return match ? match[0] : null;
43
79
  });
44
80
  await syncProducts(productIds, payload);
81
+ },
82
+ ({ doc })=>{
83
+ doc.apiToken = doc.apiToken && decryptToken(doc.apiToken);
45
84
  }
46
85
  ]
47
86
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cj-settings.ts"],"sourcesContent":["import type { GlobalConfig } from \"payload\";\n\nimport { syncProducts } from \"./service/sync-products\";\n\nexport const CjSettings: GlobalConfig = {\n slug: \"cj-settings\",\n access: {\n read: () => true,\n update: ({ req }) => !!req.user?.roles?.includes(\"user\"),\n },\n admin: {\n group: \"Plugins\",\n },\n fields: [\n {\n label: \"Logo Area POD\",\n name: \"pod\",\n type: \"upload\",\n relationTo: \"media\",\n },\n {\n name: \"items\",\n type: \"array\",\n admin: {\n description: \"A list of product URLs to sync with CJ Dropshipping\",\n },\n fields: [\n {\n name: \"productUrl\",\n type: \"text\",\n },\n ],\n label: \"Products\",\n labels: {\n plural: \"Product URLs\",\n singular: \"Product URL\",\n },\n },\n ],\n hooks: {\n afterChange: [\n async ({ doc, req: { payload } }) => {\n const productIds = doc.items.map((item: any) => {\n const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\\.html)/);\n return match ? match[0] : null;\n });\n await syncProducts(productIds, payload);\n },\n ],\n },\n label: \"CJ Dropshipping\",\n};\n"],"names":["syncProducts","CjSettings","slug","access","read","update","req","user","roles","includes","admin","group","fields","label","name","type","relationTo","description","labels","plural","singular","hooks","afterChange","doc","payload","productIds","items","map","item","match","productUrl"],"mappings":"AAEA,SAASA,YAAY,QAAQ,0BAA0B;AAEvD,OAAO,MAAMC,aAA2B;IACpCC,MAAM;IACNC,QAAQ;QACJC,MAAM,IAAM;QACZC,QAAQ,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI,EAAEC,OAAOC,SAAS;IACrD;IACAC,OAAO;QACHC,OAAO;IACX;IACAC,QAAQ;QACJ;YACIC,OAAO;YACPC,MAAM;YACNC,MAAM;YACNC,YAAY;QAChB;QACA;YACIF,MAAM;YACNC,MAAM;YACNL,OAAO;gBACHO,aAAa;YACjB;YACAL,QAAQ;gBACJ;oBACIE,MAAM;oBACNC,MAAM;gBACV;aACH;YACDF,OAAO;YACPK,QAAQ;gBACJC,QAAQ;gBACRC,UAAU;YACd;QACJ;KACH;IACDC,OAAO;QACHC,aAAa;YACT,OAAO,EAAEC,GAAG,EAAEjB,KAAK,EAAEkB,OAAO,EAAE,EAAE;gBAC5B,MAAMC,aAAaF,IAAIG,KAAK,CAACC,GAAG,CAAC,CAACC;oBAC9B,MAAMC,QAAQD,KAAKE,UAAU,CAACD,KAAK,CAAC;oBACpC,OAAOA,QAAQA,KAAK,CAAC,EAAE,GAAG;gBAC9B;gBACA,MAAM7B,aAAayB,YAAYD;YACnC;SACH;IACL;IACAX,OAAO;AACX,EAAE"}
1
+ {"version":3,"sources":["../src/cj-settings.ts"],"sourcesContent":["import type { GlobalConfig } from \"payload\";\n\nimport { syncProducts } from \"./service/sync-products\";\nimport { decryptToken, encryptToken } from \"./util/manage-tokens\";\n\nexport const CjSettings: GlobalConfig = {\n slug: \"cj-settings\",\n access: {\n read: () => true,\n // update: ({ req }) => !!req.user?.roles?.includes(\"user\"),\n },\n admin: {\n group: \"Plugins\",\n },\n fields: [\n {\n label: \"Credentials\",\n type: \"collapsible\",\n fields: [\n {\n type: \"row\",\n fields: [\n {\n name: \"emailAddress\",\n type: \"text\",\n },\n {\n name: \"apiToken\",\n type: \"text\",\n admin: {\n components: {\n Field: \"@shopnex/cj-plugin/rsc#ApiToken\",\n },\n },\n },\n ],\n },\n ],\n },\n {\n label: \"Logo Area POD\",\n name: \"pod\",\n type: \"upload\",\n relationTo: \"media\",\n },\n {\n name: \"items\",\n type: \"array\",\n admin: {\n description: \"A list of product URLs to sync with CJ Dropshipping\",\n },\n fields: [\n {\n name: \"productUrl\",\n type: \"text\",\n },\n ],\n label: \"Products\",\n labels: {\n plural: \"Product URLs\",\n singular: \"Product URL\",\n },\n },\n ],\n hooks: {\n beforeChange: [\n ({ data }) => {\n const tokenToEncrypt = data.apiToken;\n const encryptedToken = encryptToken(tokenToEncrypt);\n data.apiToken = encryptedToken;\n },\n ],\n beforeRead: [\n ({ doc }) => {\n doc.apiToken = doc.apiToken && decryptToken(doc.apiToken);\n },\n ],\n afterChange: [\n async ({ doc, req: { payload } }) => {\n const productIds = doc.items.map((item: any) => {\n const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\\.html)/);\n return match ? match[0] : null;\n });\n await syncProducts(productIds, payload);\n },\n ({ doc }) => {\n doc.apiToken = doc.apiToken && decryptToken(doc.apiToken);\n },\n ],\n },\n label: \"CJ Dropshipping\",\n};\n"],"names":["syncProducts","decryptToken","encryptToken","CjSettings","slug","access","read","admin","group","fields","label","type","name","components","Field","relationTo","description","labels","plural","singular","hooks","beforeChange","data","tokenToEncrypt","apiToken","encryptedToken","beforeRead","doc","afterChange","req","payload","productIds","items","map","item","match","productUrl"],"mappings":"AAEA,SAASA,YAAY,QAAQ,0BAA0B;AACvD,SAASC,YAAY,EAAEC,YAAY,QAAQ,uBAAuB;AAElE,OAAO,MAAMC,aAA2B;IACpCC,MAAM;IACNC,QAAQ;QACJC,MAAM,IAAM;IAEhB;IACAC,OAAO;QACHC,OAAO;IACX;IACAC,QAAQ;QACJ;YACIC,OAAO;YACPC,MAAM;YACNF,QAAQ;gBACJ;oBACIE,MAAM;oBACNF,QAAQ;wBACJ;4BACIG,MAAM;4BACND,MAAM;wBACV;wBACA;4BACIC,MAAM;4BACND,MAAM;4BACNJ,OAAO;gCACHM,YAAY;oCACRC,OAAO;gCACX;4BACJ;wBACJ;qBACH;gBACL;aACH;QACL;QACA;YACIJ,OAAO;YACPE,MAAM;YACND,MAAM;YACNI,YAAY;QAChB;QACA;YACIH,MAAM;YACND,MAAM;YACNJ,OAAO;gBACHS,aAAa;YACjB;YACAP,QAAQ;gBACJ;oBACIG,MAAM;oBACND,MAAM;gBACV;aACH;YACDD,OAAO;YACPO,QAAQ;gBACJC,QAAQ;gBACRC,UAAU;YACd;QACJ;KACH;IACDC,OAAO;QACHC,cAAc;YACV,CAAC,EAAEC,IAAI,EAAE;gBACL,MAAMC,iBAAiBD,KAAKE,QAAQ;gBACpC,MAAMC,iBAAiBvB,aAAaqB;gBACpCD,KAAKE,QAAQ,GAAGC;YACpB;SACH;QACDC,YAAY;YACR,CAAC,EAAEC,GAAG,EAAE;gBACJA,IAAIH,QAAQ,GAAGG,IAAIH,QAAQ,IAAIvB,aAAa0B,IAAIH,QAAQ;YAC5D;SACH;QACDI,aAAa;YACT,OAAO,EAAED,GAAG,EAAEE,KAAK,EAAEC,OAAO,EAAE,EAAE;gBAC5B,MAAMC,aAAaJ,IAAIK,KAAK,CAACC,GAAG,CAAC,CAACC;oBAC9B,MAAMC,QAAQD,KAAKE,UAAU,CAACD,KAAK,CAAC;oBACpC,OAAOA,QAAQA,KAAK,CAAC,EAAE,GAAG;gBAC9B;gBACA,MAAMnC,aAAa+B,YAAYD;YACnC;YACA,CAAC,EAAEH,GAAG,EAAE;gBACJA,IAAIH,QAAQ,GAAGG,IAAIH,QAAQ,IAAIvB,aAAa0B,IAAIH,QAAQ;YAC5D;SACH;IACL;IACAd,OAAO;AACX,EAAE"}
@@ -0,0 +1 @@
1
+ export { ApiToken } from "../rsc/ApiToken";
@@ -0,0 +1,3 @@
1
+ export { ApiToken } from "../rsc/ApiToken";
2
+
3
+ //# sourceMappingURL=rsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { ApiToken } from \"../rsc/ApiToken\";\n"],"names":["ApiToken"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,kBAAkB"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- import type { Config } from 'payload';
1
+ import type { Config } from "payload";
2
+ import { CjCollectionProps } from "./CjConfig";
2
3
  interface PluginOptions {
3
4
  cjApiKey: string;
4
5
  cjEmailAddress: string;
5
6
  cjRefreshToken?: string;
7
+ asCollection?: boolean;
8
+ collectionOverrides?: CjCollectionProps["overrides"];
6
9
  }
7
10
  export declare const cjPlugin: (pluginOptions: PluginOptions) => (config: Config) => Config;
8
11
  export {};
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { CjSettings } from './cj-settings';
2
- import { setCurrentAccessToken } from './sdk/access-token';
3
- import { createOrderHook } from './service/create-order.hook';
1
+ import { setTenantCredentials } from "./sdk/access-token";
2
+ import { createOrderHook } from "./service/create-order.hook";
3
+ import { CjConfigCollection } from "./CjConfig";
4
4
  const updateCollection = (collection)=>{
5
- if (collection.slug === 'orders') {
5
+ if (collection.slug === "orders") {
6
6
  return {
7
7
  ...collection,
8
8
  hooks: {
@@ -17,18 +17,38 @@ const updateCollection = (collection)=>{
17
17
  return collection;
18
18
  };
19
19
  export const cjPlugin = (pluginOptions)=>(config)=>{
20
- const updatedCollections = config.collections?.map(updateCollection);
21
- setCurrentAccessToken({
22
- emailAddress: pluginOptions.cjEmailAddress,
23
- password: pluginOptions.cjApiKey,
24
- refreshToken: pluginOptions.cjRefreshToken
20
+ const updatedCollections = config.collections?.map(updateCollection) || [];
21
+ if (pluginOptions.asCollection) {
22
+ updatedCollections.push(CjConfigCollection({
23
+ overrides: pluginOptions.collectionOverrides
24
+ }));
25
+ }
26
+ const productCollection = updatedCollections.find((collection)=>collection.slug === "products");
27
+ const sourceField = productCollection?.fields?.find((field)=>field.name === "source");
28
+ sourceField.options.push({
29
+ label: "CJ",
30
+ value: "cj"
25
31
  });
32
+ const incomingOnInit = config.onInit;
33
+ config.onInit = async (payload)=>{
34
+ if (incomingOnInit) {
35
+ await incomingOnInit(payload);
36
+ }
37
+ const cjSettings = await payload.find({
38
+ collection: "cj-settings"
39
+ });
40
+ cjSettings.docs.forEach((config)=>{
41
+ setTenantCredentials(config?.shop?.slug || "default", {
42
+ emailAddress: config.email,
43
+ password: config.apiToken
44
+ });
45
+ });
46
+ };
26
47
  return {
27
48
  ...config,
28
49
  collections: updatedCollections,
29
50
  globals: [
30
- ...config.globals || [],
31
- CjSettings
51
+ ...config.globals || []
32
52
  ]
33
53
  };
34
54
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\n\nimport { CjSettings } from './cj-settings'\nimport { setCurrentAccessToken } from './sdk/access-token'\nimport { createOrderHook } from './service/create-order.hook'\n\ninterface PluginOptions {\n cjApiKey: string\n cjEmailAddress: string\n cjRefreshToken?: string\n}\n\nconst updateCollection = (collection: CollectionConfig) => {\n if (collection.slug === 'orders') {\n return {\n ...collection,\n hooks: {\n ...collection.hooks,\n afterChange: [...(collection.hooks?.afterChange || []), createOrderHook],\n },\n }\n }\n return collection\n}\n\nexport const cjPlugin =\n (pluginOptions: PluginOptions) =>\n (config: Config): Config => {\n const updatedCollections = config.collections?.map(updateCollection)\n\n setCurrentAccessToken({\n emailAddress: pluginOptions.cjEmailAddress,\n password: pluginOptions.cjApiKey,\n refreshToken: pluginOptions.cjRefreshToken,\n })\n\n return {\n ...config,\n collections: updatedCollections,\n globals: [...(config.globals || []), CjSettings],\n }\n }\n"],"names":["CjSettings","setCurrentAccessToken","createOrderHook","updateCollection","collection","slug","hooks","afterChange","cjPlugin","pluginOptions","config","updatedCollections","collections","map","emailAddress","cjEmailAddress","password","cjApiKey","refreshToken","cjRefreshToken","globals"],"mappings":"AAEA,SAASA,UAAU,QAAQ,gBAAe;AAC1C,SAASC,qBAAqB,QAAQ,qBAAoB;AAC1D,SAASC,eAAe,QAAQ,8BAA6B;AAQ7D,MAAMC,mBAAmB,CAACC;IACxB,IAAIA,WAAWC,IAAI,KAAK,UAAU;QAChC,OAAO;YACL,GAAGD,UAAU;YACbE,OAAO;gBACL,GAAGF,WAAWE,KAAK;gBACnBC,aAAa;uBAAKH,WAAWE,KAAK,EAAEC,eAAe,EAAE;oBAAGL;iBAAgB;YAC1E;QACF;IACF;IACA,OAAOE;AACT;AAEA,OAAO,MAAMI,WACX,CAACC,gBACD,CAACC;QACC,MAAMC,qBAAqBD,OAAOE,WAAW,EAAEC,IAAIV;QAEnDF,sBAAsB;YACpBa,cAAcL,cAAcM,cAAc;YAC1CC,UAAUP,cAAcQ,QAAQ;YAChCC,cAAcT,cAAcU,cAAc;QAC5C;QAEA,OAAO;YACL,GAAGT,MAAM;YACTE,aAAaD;YACbS,SAAS;mBAAKV,OAAOU,OAAO,IAAI,EAAE;gBAAGpB;aAAW;QAClD;IACF,EAAC"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config, FieldBase, SelectField } from \"payload\";\nimport { setTenantCredentials } from \"./sdk/access-token\";\nimport { createOrderHook } from \"./service/create-order.hook\";\nimport { CjConfigCollection, CjCollectionProps } from \"./CjConfig\";\n\ninterface PluginOptions {\n cjApiKey: string;\n cjEmailAddress: string;\n cjRefreshToken?: string;\n asCollection?: boolean;\n collectionOverrides?: CjCollectionProps[\"overrides\"];\n}\n\nconst updateCollection = (collection: CollectionConfig) => {\n if (collection.slug === \"orders\") {\n return {\n ...collection,\n hooks: {\n ...collection.hooks,\n afterChange: [...(collection.hooks?.afterChange || []), createOrderHook],\n },\n };\n }\n return collection;\n};\n\nexport const cjPlugin =\n (pluginOptions: PluginOptions) =>\n (config: Config): Config => {\n const updatedCollections = config.collections?.map(updateCollection) || [];\n\n if (pluginOptions.asCollection) {\n updatedCollections.push(\n CjConfigCollection({ overrides: pluginOptions.collectionOverrides }),\n );\n }\n\n const productCollection = updatedCollections.find(\n (collection) => collection.slug === \"products\",\n );\n\n const sourceField = productCollection?.fields?.find(\n (field) => (field as SelectField).name === \"source\",\n ) as SelectField;\n\n sourceField.options.push({\n label: \"CJ\",\n value: \"cj\",\n });\n\n const incomingOnInit = config.onInit;\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload);\n }\n const cjSettings = await payload.find({\n collection: \"cj-settings\",\n });\n cjSettings.docs.forEach((config: any) => {\n setTenantCredentials(config?.shop?.slug || \"default\", {\n emailAddress: config.email,\n password: config.apiToken,\n });\n });\n };\n\n return {\n ...config,\n collections: updatedCollections,\n globals: [...(config.globals || [])],\n };\n };\n"],"names":["setTenantCredentials","createOrderHook","CjConfigCollection","updateCollection","collection","slug","hooks","afterChange","cjPlugin","pluginOptions","config","updatedCollections","collections","map","asCollection","push","overrides","collectionOverrides","productCollection","find","sourceField","fields","field","name","options","label","value","incomingOnInit","onInit","payload","cjSettings","docs","forEach","shop","emailAddress","email","password","apiToken","globals"],"mappings":"AACA,SAASA,oBAAoB,QAAQ,qBAAqB;AAC1D,SAASC,eAAe,QAAQ,8BAA8B;AAC9D,SAASC,kBAAkB,QAA2B,aAAa;AAUnE,MAAMC,mBAAmB,CAACC;IACtB,IAAIA,WAAWC,IAAI,KAAK,UAAU;QAC9B,OAAO;YACH,GAAGD,UAAU;YACbE,OAAO;gBACH,GAAGF,WAAWE,KAAK;gBACnBC,aAAa;uBAAKH,WAAWE,KAAK,EAAEC,eAAe,EAAE;oBAAGN;iBAAgB;YAC5E;QACJ;IACJ;IACA,OAAOG;AACX;AAEA,OAAO,MAAMI,WACT,CAACC,gBACD,CAACC;QACG,MAAMC,qBAAqBD,OAAOE,WAAW,EAAEC,IAAIV,qBAAqB,EAAE;QAE1E,IAAIM,cAAcK,YAAY,EAAE;YAC5BH,mBAAmBI,IAAI,CACnBb,mBAAmB;gBAAEc,WAAWP,cAAcQ,mBAAmB;YAAC;QAE1E;QAEA,MAAMC,oBAAoBP,mBAAmBQ,IAAI,CAC7C,CAACf,aAAeA,WAAWC,IAAI,KAAK;QAGxC,MAAMe,cAAcF,mBAAmBG,QAAQF,KAC3C,CAACG,QAAU,AAACA,MAAsBC,IAAI,KAAK;QAG/CH,YAAYI,OAAO,CAACT,IAAI,CAAC;YACrBU,OAAO;YACPC,OAAO;QACX;QAEA,MAAMC,iBAAiBjB,OAAOkB,MAAM;QAEpClB,OAAOkB,MAAM,GAAG,OAAOC;YACnB,IAAIF,gBAAgB;gBAChB,MAAMA,eAAeE;YACzB;YACA,MAAMC,aAAa,MAAMD,QAAQV,IAAI,CAAC;gBAClCf,YAAY;YAChB;YACA0B,WAAWC,IAAI,CAACC,OAAO,CAAC,CAACtB;gBACrBV,qBAAqBU,QAAQuB,MAAM5B,QAAQ,WAAW;oBAClD6B,cAAcxB,OAAOyB,KAAK;oBAC1BC,UAAU1B,OAAO2B,QAAQ;gBAC7B;YACJ;QACJ;QAEA,OAAO;YACH,GAAG3B,MAAM;YACTE,aAAaD;YACb2B,SAAS;mBAAK5B,OAAO4B,OAAO,IAAI,EAAE;aAAE;QACxC;IACJ,EAAE"}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import "./ApiToken.scss";
3
+ interface ApiTokenProps {
4
+ path: string;
5
+ readOnly?: boolean;
6
+ label?: string;
7
+ }
8
+ export declare function ApiToken({ path, readOnly, label }: ApiTokenProps): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import React from "react";
4
+ import { PasswordField } from "@payloadcms/ui";
5
+ import "./ApiToken.scss";
6
+ export function ApiToken({ path, readOnly, label = "API Token" }) {
7
+ return /*#__PURE__*/ _jsx(PasswordField, {
8
+ autoComplete: "new-password",
9
+ field: {
10
+ name: "password",
11
+ label: "API Token"
12
+ },
13
+ indexPath: "",
14
+ parentPath: "",
15
+ parentSchemaPath: "",
16
+ path: path,
17
+ schemaPath: "password"
18
+ });
19
+ }
20
+
21
+ //# sourceMappingURL=ApiToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/rsc/ApiToken.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { PasswordField } from \"@payloadcms/ui\";\nimport \"./ApiToken.scss\";\n\ninterface ApiTokenProps {\n path: string;\n readOnly?: boolean;\n label?: string;\n}\n\nexport function ApiToken({ path, readOnly, label = \"API Token\" }: ApiTokenProps) {\n return (\n <PasswordField\n autoComplete=\"new-password\"\n field={{\n name: \"password\",\n label: \"API Token\",\n }}\n indexPath=\"\"\n parentPath=\"\"\n parentSchemaPath=\"\"\n path={path}\n schemaPath=\"password\"\n />\n );\n}\n"],"names":["React","PasswordField","ApiToken","path","readOnly","label","autoComplete","field","name","indexPath","parentPath","parentSchemaPath","schemaPath"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAQ;AAC1B,SAASC,aAAa,QAAQ,iBAAiB;AAC/C,OAAO,kBAAkB;AAQzB,OAAO,SAASC,SAAS,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,QAAQ,WAAW,EAAiB;IAC3E,qBACI,KAACJ;QACGK,cAAa;QACbC,OAAO;YACHC,MAAM;YACNH,OAAO;QACX;QACAI,WAAU;QACVC,YAAW;QACXC,kBAAiB;QACjBR,MAAMA;QACNS,YAAW;;AAGvB"}
@@ -0,0 +1,5 @@
1
+
2
+ .api-token {
3
+ display: flex;
4
+ flex: 1;
5
+ }
@@ -4,5 +4,6 @@ type Credentials = {
4
4
  refreshToken?: string;
5
5
  };
6
6
  export declare const getCurrentAccessToken: () => Promise<string>;
7
- export declare const setCurrentAccessToken: ({ emailAddress, password, refreshToken }: Credentials) => void;
7
+ export declare const setTenantCredentials: (shopId: string, creds: Credentials) => void;
8
+ export declare const getTenantAccessToken: (shopId: string) => Promise<string>;
8
9
  export {};
@@ -1,22 +1,24 @@
1
- import * as cjSdk from './cj-sdk';
2
- let credentials = null;
1
+ import * as cjSdk from "./cj-sdk";
2
+ const tenantCredentialsMap = new Map();
3
3
  export const getCurrentAccessToken = async ()=>{
4
- if (!credentials?.emailAddress || !credentials?.password) {
5
- throw new Error('Email address and password token are required');
4
+ const shopId = '1';
5
+ const accessToken = await getTenantAccessToken(shopId);
6
+ return accessToken;
7
+ };
8
+ export const setTenantCredentials = (shopId, creds)=>{
9
+ tenantCredentialsMap.set(shopId, creds);
10
+ };
11
+ export const getTenantAccessToken = async (shopId)=>{
12
+ const creds = tenantCredentialsMap.get(shopId);
13
+ if (!creds?.emailAddress || !creds?.password) {
14
+ throw new Error(`Credentials for tenant ${shopId} are missing or incomplete`);
6
15
  }
7
- const { emailAddress, password, refreshToken } = credentials;
8
- let accessToken = (await cjSdk.refreshAccessToken(refreshToken || '')).accessToken;
16
+ const { emailAddress, password, refreshToken } = creds;
17
+ let accessToken = (await cjSdk.refreshAccessToken(refreshToken || "")).accessToken;
9
18
  if (!accessToken) {
10
19
  accessToken = (await cjSdk.getAccessToken(emailAddress, password)).accessToken;
11
20
  }
12
21
  return accessToken;
13
22
  };
14
- export const setCurrentAccessToken = ({ emailAddress, password, refreshToken })=>{
15
- credentials = {
16
- emailAddress,
17
- password,
18
- refreshToken
19
- };
20
- };
21
23
 
22
24
  //# sourceMappingURL=access-token.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sdk/access-token.ts"],"sourcesContent":["import * as cjSdk from './cj-sdk'\n\ntype Credentials = {\n emailAddress: string\n password: string\n refreshToken?: string\n}\n\nlet credentials: Credentials | null = null\n\nexport const getCurrentAccessToken = async () => {\n if (!credentials?.emailAddress || !credentials?.password) {\n throw new Error('Email address and password token are required')\n }\n const { emailAddress, password, refreshToken } = credentials\n let accessToken = (await cjSdk.refreshAccessToken(refreshToken || '')).accessToken\n if (!accessToken) {\n accessToken = (await cjSdk.getAccessToken(emailAddress, password)).accessToken\n }\n return accessToken\n}\n\nexport const setCurrentAccessToken = ({ emailAddress, password, refreshToken }: Credentials) => {\n credentials = { emailAddress, password, refreshToken }\n}\n"],"names":["cjSdk","credentials","getCurrentAccessToken","emailAddress","password","Error","refreshToken","accessToken","refreshAccessToken","getAccessToken","setCurrentAccessToken"],"mappings":"AAAA,YAAYA,WAAW,WAAU;AAQjC,IAAIC,cAAkC;AAEtC,OAAO,MAAMC,wBAAwB;IACnC,IAAI,CAACD,aAAaE,gBAAgB,CAACF,aAAaG,UAAU;QACxD,MAAM,IAAIC,MAAM;IAClB;IACA,MAAM,EAAEF,YAAY,EAAEC,QAAQ,EAAEE,YAAY,EAAE,GAAGL;IACjD,IAAIM,cAAc,AAAC,CAAA,MAAMP,MAAMQ,kBAAkB,CAACF,gBAAgB,GAAE,EAAGC,WAAW;IAClF,IAAI,CAACA,aAAa;QAChBA,cAAc,AAAC,CAAA,MAAMP,MAAMS,cAAc,CAACN,cAAcC,SAAQ,EAAGG,WAAW;IAChF;IACA,OAAOA;AACT,EAAC;AAED,OAAO,MAAMG,wBAAwB,CAAC,EAAEP,YAAY,EAAEC,QAAQ,EAAEE,YAAY,EAAe;IACzFL,cAAc;QAAEE;QAAcC;QAAUE;IAAa;AACvD,EAAC"}
1
+ {"version":3,"sources":["../../src/sdk/access-token.ts"],"sourcesContent":["import * as cjSdk from \"./cj-sdk\";\n\ntype Credentials = {\n emailAddress: string;\n password: string;\n refreshToken?: string;\n};\n\nconst tenantCredentialsMap = new Map<string, Credentials>();\n\nexport const getCurrentAccessToken = async () => {\n const shopId = '1'\n const accessToken = await getTenantAccessToken(shopId);\n return accessToken\n};\n\nexport const setTenantCredentials = (shopId: string, creds: Credentials) => {\n tenantCredentialsMap.set(shopId, creds);\n};\n\nexport const getTenantAccessToken = async (shopId: string) => {\n const creds = tenantCredentialsMap.get(shopId);\n\n if (!creds?.emailAddress || !creds?.password) {\n throw new Error(`Credentials for tenant ${shopId} are missing or incomplete`);\n }\n\n const { emailAddress, password, refreshToken } = creds;\n let accessToken = (await cjSdk.refreshAccessToken(refreshToken || \"\")).accessToken;\n if (!accessToken) {\n accessToken = (await cjSdk.getAccessToken(emailAddress, password)).accessToken;\n }\n return accessToken;\n};\n"],"names":["cjSdk","tenantCredentialsMap","Map","getCurrentAccessToken","shopId","accessToken","getTenantAccessToken","setTenantCredentials","creds","set","get","emailAddress","password","Error","refreshToken","refreshAccessToken","getAccessToken"],"mappings":"AAAA,YAAYA,WAAW,WAAW;AAQlC,MAAMC,uBAAuB,IAAIC;AAEjC,OAAO,MAAMC,wBAAwB;IACjC,MAAMC,SAAS;IACf,MAAMC,cAAc,MAAMC,qBAAqBF;IAC/C,OAAOC;AACX,EAAE;AAEF,OAAO,MAAME,uBAAuB,CAACH,QAAgBI;IACjDP,qBAAqBQ,GAAG,CAACL,QAAQI;AACrC,EAAE;AAEF,OAAO,MAAMF,uBAAuB,OAAOF;IACvC,MAAMI,QAAQP,qBAAqBS,GAAG,CAACN;IAEvC,IAAI,CAACI,OAAOG,gBAAgB,CAACH,OAAOI,UAAU;QAC1C,MAAM,IAAIC,MAAM,CAAC,uBAAuB,EAAET,OAAO,0BAA0B,CAAC;IAChF;IAEA,MAAM,EAAEO,YAAY,EAAEC,QAAQ,EAAEE,YAAY,EAAE,GAAGN;IACjD,IAAIH,cAAc,AAAC,CAAA,MAAML,MAAMe,kBAAkB,CAACD,gBAAgB,GAAE,EAAGT,WAAW;IAClF,IAAI,CAACA,aAAa;QACdA,cAAc,AAAC,CAAA,MAAML,MAAMgB,cAAc,CAACL,cAAcC,SAAQ,EAAGP,WAAW;IAClF;IACA,OAAOA;AACX,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/sdk/products/products.ts"],"sourcesContent":["import type { APIResponse } from '../../error-types'\nimport type {\n CategoryFirstLevel,\n CategoryListResponse,\n Product,\n ProductDetails,\n ProductListResponse,\n} from './product-types.ts'\n\nimport { cjApiClient } from '../../api-client'\nimport { getCurrentAccessToken } from '../access-token'\n\nexport async function getProductCategory(\n accessToken: string,\n params: any,\n): Promise<APIResponse<CategoryFirstLevel[]>> {\n try {\n const response = await cjApiClient.get<CategoryListResponse>('/product/getCategory', {\n headers: { 'CJ-Access-Token': accessToken },\n params,\n })\n\n const data = response.data.data\n if (!data) {\n return { error: 'No categories found' }\n }\n\n return { data }\n } catch (error: any) {\n console.error(`Error fetching categories [${error.code}]: ${error.message}`)\n return { error: error.message || 'Failed to fetch categories' }\n }\n}\n\nexport async function getProductList(\n params: Record<string, any> = {},\n): Promise<APIResponse<Product[]>> {\n const defaultParams = {\n pageNum: 1,\n pageSize: 20,\n }\n const query = { ...defaultParams, ...params }\n\n try {\n const accessToken = await getCurrentAccessToken()\n const response = await cjApiClient.get<ProductListResponse>(\n 'https://developers.cjdropshipping.com/api2.0/v1/product/list',\n {\n headers: {\n 'CJ-Access-Token': accessToken,\n },\n params: query,\n },\n )\n\n const data = response.data\n\n if (!data.result) {\n return { error: data.message || 'Failed to fetch product list' }\n }\n\n if (!data.data?.list) {\n return { error: 'No products found' }\n }\n\n return { data: data.data.list }\n } catch (error: any) {\n console.error(`Error fetching product list [${error.code}]: ${error.message}`)\n return { error: error.message || 'Failed to fetch product list' }\n }\n}\n\nexport async function getProductDetails(queryParams: {\n pid?: string\n productSku?: string\n variantSku?: string\n}): Promise<APIResponse<ProductDetails>> {\n const { pid, productSku, variantSku } = queryParams\n if (!pid && !productSku && !variantSku) {\n return {\n error: 'One of pid, productSku, or variantSku must be provided.',\n }\n }\n\n try {\n const accessToken = await getCurrentAccessToken()\n const response = await cjApiClient.get<{\n code: number\n data: ProductDetails\n message: string\n result: boolean\n }>('https://developers.cjdropshipping.com/api2.0/v1/product/query', {\n headers: {\n 'CJ-Access-Token': accessToken,\n },\n params: queryParams,\n })\n\n if (!response.data.result) {\n return {\n error: response.data.message || 'Failed to fetch product details',\n }\n }\n\n return { data: response.data.data }\n } catch (error: any) {\n console.error(`Error fetching product details [${error.code}]: ${error.message}`)\n return { error: error.message || 'Failed to fetch product details' }\n }\n}\n"],"names":["cjApiClient","getCurrentAccessToken","getProductCategory","accessToken","params","response","get","headers","data","error","console","code","message","getProductList","defaultParams","pageNum","pageSize","query","result","list","getProductDetails","queryParams","pid","productSku","variantSku"],"mappings":"AASA,SAASA,WAAW,QAAQ,mBAAkB;AAC9C,SAASC,qBAAqB,QAAQ,kBAAiB;AAEvD,OAAO,eAAeC,mBACpBC,WAAmB,EACnBC,MAAW;IAEX,IAAI;QACF,MAAMC,WAAW,MAAML,YAAYM,GAAG,CAAuB,wBAAwB;YACnFC,SAAS;gBAAE,mBAAmBJ;YAAY;YAC1CC;QACF;QAEA,MAAMI,OAAOH,SAASG,IAAI,CAACA,IAAI;QAC/B,IAAI,CAACA,MAAM;YACT,OAAO;gBAAEC,OAAO;YAAsB;QACxC;QAEA,OAAO;YAAED;QAAK;IAChB,EAAE,OAAOC,OAAY;QACnBC,QAAQD,KAAK,CAAC,CAAC,2BAA2B,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAC3E,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAA6B;IAChE;AACF;AAEA,OAAO,eAAeC,eACpBT,SAA8B,CAAC,CAAC;IAEhC,MAAMU,gBAAgB;QACpBC,SAAS;QACTC,UAAU;IACZ;IACA,MAAMC,QAAQ;QAAE,GAAGH,aAAa;QAAE,GAAGV,MAAM;IAAC;IAE5C,IAAI;QACF,MAAMD,cAAc,MAAMF;QAC1B,MAAMI,WAAW,MAAML,YAAYM,GAAG,CACpC,gEACA;YACEC,SAAS;gBACP,mBAAmBJ;YACrB;YACAC,QAAQa;QACV;QAGF,MAAMT,OAAOH,SAASG,IAAI;QAE1B,IAAI,CAACA,KAAKU,MAAM,EAAE;YAChB,OAAO;gBAAET,OAAOD,KAAKI,OAAO,IAAI;YAA+B;QACjE;QAEA,IAAI,CAACJ,KAAKA,IAAI,EAAEW,MAAM;YACpB,OAAO;gBAAEV,OAAO;YAAoB;QACtC;QAEA,OAAO;YAAED,MAAMA,KAAKA,IAAI,CAACW,IAAI;QAAC;IAChC,EAAE,OAAOV,OAAY;QACnBC,QAAQD,KAAK,CAAC,CAAC,6BAA6B,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAC7E,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAA+B;IAClE;AACF;AAEA,OAAO,eAAeQ,kBAAkBC,WAIvC;IACC,MAAM,EAAEC,GAAG,EAAEC,UAAU,EAAEC,UAAU,EAAE,GAAGH;IACxC,IAAI,CAACC,OAAO,CAACC,cAAc,CAACC,YAAY;QACtC,OAAO;YACLf,OAAO;QACT;IACF;IAEA,IAAI;QACF,MAAMN,cAAc,MAAMF;QAC1B,MAAMI,WAAW,MAAML,YAAYM,GAAG,CAKnC,iEAAiE;YAClEC,SAAS;gBACP,mBAAmBJ;YACrB;YACAC,QAAQiB;QACV;QAEA,IAAI,CAAChB,SAASG,IAAI,CAACU,MAAM,EAAE;YACzB,OAAO;gBACLT,OAAOJ,SAASG,IAAI,CAACI,OAAO,IAAI;YAClC;QACF;QAEA,OAAO;YAAEJ,MAAMH,SAASG,IAAI,CAACA,IAAI;QAAC;IACpC,EAAE,OAAOC,OAAY;QACnBC,QAAQD,KAAK,CAAC,CAAC,gCAAgC,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAChF,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAAkC;IACrE;AACF"}
1
+ {"version":3,"sources":["../../../src/sdk/products/products.ts"],"sourcesContent":["import type { APIResponse } from '../../error-types'\nimport type {\n CategoryFirstLevel,\n CategoryListResponse,\n Product,\n ProductDetails,\n ProductListResponse,\n} from './product-types.ts'\n\nimport { cjApiClient } from '../../api-client'\nimport { getCurrentAccessToken } from '../access-token'\n\nexport async function getProductCategory(\n accessToken: string,\n params: any,\n): Promise<APIResponse<CategoryFirstLevel[]>> {\n try {\n const response = await cjApiClient.get<CategoryListResponse>('/product/getCategory', {\n headers: { 'CJ-Access-Token': accessToken },\n params,\n })\n\n const data = response.data.data\n if (!data) {\n return { error: 'No categories found' }\n }\n\n return { data }\n } catch (error: any) {\n console.error(`Error fetching categories [${error.code}]: ${error.message}`)\n return { error: error.message || 'Failed to fetch categories' }\n }\n}\n\nexport async function getProductList(\n params: Record<string, any> = {},\n): Promise<APIResponse<Product[]>> {\n const defaultParams = {\n pageNum: 1,\n pageSize: 20,\n }\n const query = { ...defaultParams, ...params }\n\n try {\n const accessToken = await getCurrentAccessToken();\n const response = await cjApiClient.get<ProductListResponse>(\n 'https://developers.cjdropshipping.com/api2.0/v1/product/list',\n {\n headers: {\n 'CJ-Access-Token': accessToken,\n },\n params: query,\n },\n )\n\n const data = response.data\n\n if (!data.result) {\n return { error: data.message || 'Failed to fetch product list' }\n }\n\n if (!data.data?.list) {\n return { error: 'No products found' }\n }\n\n return { data: data.data.list }\n } catch (error: any) {\n console.error(`Error fetching product list [${error.code}]: ${error.message}`)\n return { error: error.message || 'Failed to fetch product list' }\n }\n}\n\nexport async function getProductDetails(queryParams: {\n pid?: string\n productSku?: string\n variantSku?: string\n}): Promise<APIResponse<ProductDetails>> {\n const { pid, productSku, variantSku } = queryParams\n if (!pid && !productSku && !variantSku) {\n return {\n error: 'One of pid, productSku, or variantSku must be provided.',\n }\n }\n\n try {\n const accessToken = await getCurrentAccessToken()\n const response = await cjApiClient.get<{\n code: number\n data: ProductDetails\n message: string\n result: boolean\n }>('https://developers.cjdropshipping.com/api2.0/v1/product/query', {\n headers: {\n 'CJ-Access-Token': accessToken,\n },\n params: queryParams,\n })\n\n if (!response.data.result) {\n return {\n error: response.data.message || 'Failed to fetch product details',\n }\n }\n\n return { data: response.data.data }\n } catch (error: any) {\n console.error(`Error fetching product details [${error.code}]: ${error.message}`)\n return { error: error.message || 'Failed to fetch product details' }\n }\n}\n"],"names":["cjApiClient","getCurrentAccessToken","getProductCategory","accessToken","params","response","get","headers","data","error","console","code","message","getProductList","defaultParams","pageNum","pageSize","query","result","list","getProductDetails","queryParams","pid","productSku","variantSku"],"mappings":"AASA,SAASA,WAAW,QAAQ,mBAAkB;AAC9C,SAASC,qBAAqB,QAAQ,kBAAiB;AAEvD,OAAO,eAAeC,mBACpBC,WAAmB,EACnBC,MAAW;IAEX,IAAI;QACF,MAAMC,WAAW,MAAML,YAAYM,GAAG,CAAuB,wBAAwB;YACnFC,SAAS;gBAAE,mBAAmBJ;YAAY;YAC1CC;QACF;QAEA,MAAMI,OAAOH,SAASG,IAAI,CAACA,IAAI;QAC/B,IAAI,CAACA,MAAM;YACT,OAAO;gBAAEC,OAAO;YAAsB;QACxC;QAEA,OAAO;YAAED;QAAK;IAChB,EAAE,OAAOC,OAAY;QACnBC,QAAQD,KAAK,CAAC,CAAC,2BAA2B,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAC3E,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAA6B;IAChE;AACF;AAEA,OAAO,eAAeC,eACpBT,SAA8B,CAAC,CAAC;IAEhC,MAAMU,gBAAgB;QACpBC,SAAS;QACTC,UAAU;IACZ;IACA,MAAMC,QAAQ;QAAE,GAAGH,aAAa;QAAE,GAAGV,MAAM;IAAC;IAE5C,IAAI;QACF,MAAMD,cAAc,MAAMF;QAC1B,MAAMI,WAAW,MAAML,YAAYM,GAAG,CACpC,gEACA;YACEC,SAAS;gBACP,mBAAmBJ;YACrB;YACAC,QAAQa;QACV;QAGF,MAAMT,OAAOH,SAASG,IAAI;QAE1B,IAAI,CAACA,KAAKU,MAAM,EAAE;YAChB,OAAO;gBAAET,OAAOD,KAAKI,OAAO,IAAI;YAA+B;QACjE;QAEA,IAAI,CAACJ,KAAKA,IAAI,EAAEW,MAAM;YACpB,OAAO;gBAAEV,OAAO;YAAoB;QACtC;QAEA,OAAO;YAAED,MAAMA,KAAKA,IAAI,CAACW,IAAI;QAAC;IAChC,EAAE,OAAOV,OAAY;QACnBC,QAAQD,KAAK,CAAC,CAAC,6BAA6B,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAC7E,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAA+B;IAClE;AACF;AAEA,OAAO,eAAeQ,kBAAkBC,WAIvC;IACC,MAAM,EAAEC,GAAG,EAAEC,UAAU,EAAEC,UAAU,EAAE,GAAGH;IACxC,IAAI,CAACC,OAAO,CAACC,cAAc,CAACC,YAAY;QACtC,OAAO;YACLf,OAAO;QACT;IACF;IAEA,IAAI;QACF,MAAMN,cAAc,MAAMF;QAC1B,MAAMI,WAAW,MAAML,YAAYM,GAAG,CAKnC,iEAAiE;YAClEC,SAAS;gBACP,mBAAmBJ;YACrB;YACAC,QAAQiB;QACV;QAEA,IAAI,CAAChB,SAASG,IAAI,CAACU,MAAM,EAAE;YACzB,OAAO;gBACLT,OAAOJ,SAASG,IAAI,CAACI,OAAO,IAAI;YAClC;QACF;QAEA,OAAO;YAAEJ,MAAMH,SAASG,IAAI,CAACA,IAAI;QAAC;IACpC,EAAE,OAAOC,OAAY;QACnBC,QAAQD,KAAK,CAAC,CAAC,gCAAgC,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAChF,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAAkC;IACrE;AACF"}
@@ -4,14 +4,20 @@ export const createOrderHook = async ({ doc, req })=>{
4
4
  return;
5
5
  }
6
6
  const payload = req.payload;
7
- const cjSettings = await payload.findGlobal({
8
- slug: "cj-settings"
7
+ const cjSettings = await payload.find({
8
+ collection: "cj-settings",
9
+ where: {
10
+ shop: {
11
+ equals: doc.shopId
12
+ }
13
+ }
9
14
  });
10
- const podProperties = cjSettings?.pod?.url ? [
15
+ const cjConfig = cjSettings?.docs[0];
16
+ const podProperties = cjConfig?.pod?.url ? [
11
17
  {
12
18
  areaName: "LogoArea",
13
19
  links: [
14
- cjSettings?.pod?.url
20
+ cjConfig?.pod?.url
15
21
  ],
16
22
  type: "1",
17
23
  layer: []
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/service/create-order.hook.ts"],"sourcesContent":["import type { BasePayload, CollectionAfterChangeHook, Document } from \"payload\";\n\nimport * as cjSdk from \"../sdk/cj-sdk\";\n\nexport interface Orders extends Document {\n id: string;\n items: Array<{\n productUrl: string;\n quantity: number;\n variant: {\n variantId: string;\n };\n }>;\n}\n\nexport const createOrderHook: CollectionAfterChangeHook<Orders> = async ({ doc, req }) => {\n if (doc.orderStatus !== \"processing\") {\n return;\n }\n const payload: BasePayload = req.payload;\n const cjSettings: any = await payload.findGlobal({\n slug: \"cj-settings\",\n });\n const podProperties = cjSettings?.pod?.url\n ? [\n {\n areaName: \"LogoArea\",\n links: [cjSettings?.pod?.url],\n type: \"1\",\n layer: [],\n },\n ]\n : [];\n const result = await cjSdk.createOrder({\n consigneeID: doc.billingAddress?.name || \"\",\n email: doc.billingAddress?.email || \"\",\n fromCountryCode: \"CN\",\n houseNumber: doc.shippingAddress?.address?.line2 || \"\",\n iossType: 1,\n logisticName: \"CJPacket Liquid US\",\n orderNumber: doc.orderId,\n payType: 2,\n products: doc.items.map((item) => ({\n quantity: item.quantity,\n vid: item.variant.variantId,\n })),\n podProperties,\n remark: \"\",\n shippingAddress: doc.shippingAddress?.address?.line1 || \"\",\n shippingAddress2: doc.shippingAddress?.address?.line2 || \"\",\n shippingCity: doc.shippingAddress?.address?.city || \"\",\n shippingCountry: doc.shippingAddress?.address?.country || \"\",\n shippingCountryCode: doc.shippingAddress?.address?.country || \"\",\n shippingCounty: doc.shippingAddress?.address?.city || \"\",\n shippingCustomerName: doc.shippingAddress?.name || \"\",\n shippingPhone: doc.shippingAddress?.phone || \"+9999999999\",\n shippingProvince: doc.shippingAddress?.address?.state || \"\",\n shippingZip: doc.shippingAddress?.address?.postal_code || \"\",\n taxId: \"\",\n });\n\n const orderResult = await payload.update({\n collection: \"orders\",\n data: {\n orderStatus: \"shipped\",\n },\n where: {\n id: {\n equals: doc.orderId,\n },\n },\n });\n\n return {\n cjResult: result,\n orderResult,\n };\n};\n"],"names":["cjSdk","createOrderHook","doc","req","orderStatus","payload","cjSettings","findGlobal","slug","podProperties","pod","url","areaName","links","type","layer","result","createOrder","consigneeID","billingAddress","name","email","fromCountryCode","houseNumber","shippingAddress","address","line2","iossType","logisticName","orderNumber","orderId","payType","products","items","map","item","quantity","vid","variant","variantId","remark","line1","shippingAddress2","shippingCity","city","shippingCountry","country","shippingCountryCode","shippingCounty","shippingCustomerName","shippingPhone","phone","shippingProvince","state","shippingZip","postal_code","taxId","orderResult","update","collection","data","where","id","equals","cjResult"],"mappings":"AAEA,YAAYA,WAAW,gBAAgB;AAavC,OAAO,MAAMC,kBAAqD,OAAO,EAAEC,GAAG,EAAEC,GAAG,EAAE;IACjF,IAAID,IAAIE,WAAW,KAAK,cAAc;QAClC;IACJ;IACA,MAAMC,UAAuBF,IAAIE,OAAO;IACxC,MAAMC,aAAkB,MAAMD,QAAQE,UAAU,CAAC;QAC7CC,MAAM;IACV;IACA,MAAMC,gBAAgBH,YAAYI,KAAKC,MACjC;QACI;YACIC,UAAU;YACVC,OAAO;gBAACP,YAAYI,KAAKC;aAAI;YAC7BG,MAAM;YACNC,OAAO,EAAE;QACb;KACH,GACD,EAAE;IACR,MAAMC,SAAS,MAAMhB,MAAMiB,WAAW,CAAC;QACnCC,aAAahB,IAAIiB,cAAc,EAAEC,QAAQ;QACzCC,OAAOnB,IAAIiB,cAAc,EAAEE,SAAS;QACpCC,iBAAiB;QACjBC,aAAarB,IAAIsB,eAAe,EAAEC,SAASC,SAAS;QACpDC,UAAU;QACVC,cAAc;QACdC,aAAa3B,IAAI4B,OAAO;QACxBC,SAAS;QACTC,UAAU9B,IAAI+B,KAAK,CAACC,GAAG,CAAC,CAACC,OAAU,CAAA;gBAC/BC,UAAUD,KAAKC,QAAQ;gBACvBC,KAAKF,KAAKG,OAAO,CAACC,SAAS;YAC/B,CAAA;QACA9B;QACA+B,QAAQ;QACRhB,iBAAiBtB,IAAIsB,eAAe,EAAEC,SAASgB,SAAS;QACxDC,kBAAkBxC,IAAIsB,eAAe,EAAEC,SAASC,SAAS;QACzDiB,cAAczC,IAAIsB,eAAe,EAAEC,SAASmB,QAAQ;QACpDC,iBAAiB3C,IAAIsB,eAAe,EAAEC,SAASqB,WAAW;QAC1DC,qBAAqB7C,IAAIsB,eAAe,EAAEC,SAASqB,WAAW;QAC9DE,gBAAgB9C,IAAIsB,eAAe,EAAEC,SAASmB,QAAQ;QACtDK,sBAAsB/C,IAAIsB,eAAe,EAAEJ,QAAQ;QACnD8B,eAAehD,IAAIsB,eAAe,EAAE2B,SAAS;QAC7CC,kBAAkBlD,IAAIsB,eAAe,EAAEC,SAAS4B,SAAS;QACzDC,aAAapD,IAAIsB,eAAe,EAAEC,SAAS8B,eAAe;QAC1DC,OAAO;IACX;IAEA,MAAMC,cAAc,MAAMpD,QAAQqD,MAAM,CAAC;QACrCC,YAAY;QACZC,MAAM;YACFxD,aAAa;QACjB;QACAyD,OAAO;YACHC,IAAI;gBACAC,QAAQ7D,IAAI4B,OAAO;YACvB;QACJ;IACJ;IAEA,OAAO;QACHkC,UAAUhD;QACVyC;IACJ;AACJ,EAAE"}
1
+ {"version":3,"sources":["../../src/service/create-order.hook.ts"],"sourcesContent":["import type { BasePayload, CollectionAfterChangeHook, Document } from \"payload\";\n\nimport * as cjSdk from \"../sdk/cj-sdk\";\n\nexport interface Orders extends Document {\n id: string;\n items: Array<{\n productUrl: string;\n quantity: number;\n variant: {\n variantId: string;\n };\n }>;\n}\n\nexport const createOrderHook: CollectionAfterChangeHook<Orders> = async ({ doc, req }) => {\n if (doc.orderStatus !== \"processing\") {\n return;\n }\n const payload: BasePayload = req.payload;\n const cjSettings = await payload.find({\n collection: \"cj-settings\",\n where: {\n shop: {\n equals: doc.shopId,\n },\n },\n });\n const cjConfig: any = cjSettings?.docs[0];\n const podProperties = cjConfig?.pod?.url\n ? [\n {\n areaName: \"LogoArea\",\n links: [cjConfig?.pod?.url],\n type: \"1\",\n layer: [],\n },\n ]\n : [];\n const result = await cjSdk.createOrder({\n consigneeID: doc.billingAddress?.name || \"\",\n email: doc.billingAddress?.email || \"\",\n fromCountryCode: \"CN\",\n houseNumber: doc.shippingAddress?.address?.line2 || \"\",\n iossType: 1,\n logisticName: \"CJPacket Liquid US\",\n orderNumber: doc.orderId,\n payType: 2,\n products: doc.items.map((item) => ({\n quantity: item.quantity,\n vid: item.variant.variantId,\n })),\n podProperties,\n remark: \"\",\n shippingAddress: doc.shippingAddress?.address?.line1 || \"\",\n shippingAddress2: doc.shippingAddress?.address?.line2 || \"\",\n shippingCity: doc.shippingAddress?.address?.city || \"\",\n shippingCountry: doc.shippingAddress?.address?.country || \"\",\n shippingCountryCode: doc.shippingAddress?.address?.country || \"\",\n shippingCounty: doc.shippingAddress?.address?.city || \"\",\n shippingCustomerName: doc.shippingAddress?.name || \"\",\n shippingPhone: doc.shippingAddress?.phone || \"+9999999999\",\n shippingProvince: doc.shippingAddress?.address?.state || \"\",\n shippingZip: doc.shippingAddress?.address?.postal_code || \"\",\n taxId: \"\",\n });\n\n const orderResult = await payload.update({\n collection: \"orders\",\n data: {\n orderStatus: \"shipped\",\n },\n where: {\n id: {\n equals: doc.orderId,\n },\n },\n });\n\n return {\n cjResult: result,\n orderResult,\n };\n};\n"],"names":["cjSdk","createOrderHook","doc","req","orderStatus","payload","cjSettings","find","collection","where","shop","equals","shopId","cjConfig","docs","podProperties","pod","url","areaName","links","type","layer","result","createOrder","consigneeID","billingAddress","name","email","fromCountryCode","houseNumber","shippingAddress","address","line2","iossType","logisticName","orderNumber","orderId","payType","products","items","map","item","quantity","vid","variant","variantId","remark","line1","shippingAddress2","shippingCity","city","shippingCountry","country","shippingCountryCode","shippingCounty","shippingCustomerName","shippingPhone","phone","shippingProvince","state","shippingZip","postal_code","taxId","orderResult","update","data","id","cjResult"],"mappings":"AAEA,YAAYA,WAAW,gBAAgB;AAavC,OAAO,MAAMC,kBAAqD,OAAO,EAAEC,GAAG,EAAEC,GAAG,EAAE;IACjF,IAAID,IAAIE,WAAW,KAAK,cAAc;QAClC;IACJ;IACA,MAAMC,UAAuBF,IAAIE,OAAO;IACxC,MAAMC,aAAa,MAAMD,QAAQE,IAAI,CAAC;QAClCC,YAAY;QACZC,OAAO;YACHC,MAAM;gBACFC,QAAQT,IAAIU,MAAM;YACtB;QACJ;IACJ;IACA,MAAMC,WAAgBP,YAAYQ,IAAI,CAAC,EAAE;IACzC,MAAMC,gBAAgBF,UAAUG,KAAKC,MAC/B;QACI;YACIC,UAAU;YACVC,OAAO;gBAACN,UAAUG,KAAKC;aAAI;YAC3BG,MAAM;YACNC,OAAO,EAAE;QACb;KACH,GACD,EAAE;IACR,MAAMC,SAAS,MAAMtB,MAAMuB,WAAW,CAAC;QACnCC,aAAatB,IAAIuB,cAAc,EAAEC,QAAQ;QACzCC,OAAOzB,IAAIuB,cAAc,EAAEE,SAAS;QACpCC,iBAAiB;QACjBC,aAAa3B,IAAI4B,eAAe,EAAEC,SAASC,SAAS;QACpDC,UAAU;QACVC,cAAc;QACdC,aAAajC,IAAIkC,OAAO;QACxBC,SAAS;QACTC,UAAUpC,IAAIqC,KAAK,CAACC,GAAG,CAAC,CAACC,OAAU,CAAA;gBAC/BC,UAAUD,KAAKC,QAAQ;gBACvBC,KAAKF,KAAKG,OAAO,CAACC,SAAS;YAC/B,CAAA;QACA9B;QACA+B,QAAQ;QACRhB,iBAAiB5B,IAAI4B,eAAe,EAAEC,SAASgB,SAAS;QACxDC,kBAAkB9C,IAAI4B,eAAe,EAAEC,SAASC,SAAS;QACzDiB,cAAc/C,IAAI4B,eAAe,EAAEC,SAASmB,QAAQ;QACpDC,iBAAiBjD,IAAI4B,eAAe,EAAEC,SAASqB,WAAW;QAC1DC,qBAAqBnD,IAAI4B,eAAe,EAAEC,SAASqB,WAAW;QAC9DE,gBAAgBpD,IAAI4B,eAAe,EAAEC,SAASmB,QAAQ;QACtDK,sBAAsBrD,IAAI4B,eAAe,EAAEJ,QAAQ;QACnD8B,eAAetD,IAAI4B,eAAe,EAAE2B,SAAS;QAC7CC,kBAAkBxD,IAAI4B,eAAe,EAAEC,SAAS4B,SAAS;QACzDC,aAAa1D,IAAI4B,eAAe,EAAEC,SAAS8B,eAAe;QAC1DC,OAAO;IACX;IAEA,MAAMC,cAAc,MAAM1D,QAAQ2D,MAAM,CAAC;QACrCxD,YAAY;QACZyD,MAAM;YACF7D,aAAa;QACjB;QACAK,OAAO;YACHyD,IAAI;gBACAvD,QAAQT,IAAIkC,OAAO;YACvB;QACJ;IACJ;IAEA,OAAO;QACH+B,UAAU7C;QACVyC;IACJ;AACJ,EAAE"}
@@ -77,6 +77,7 @@ function mapMockProductToSchema(product, editorConfig, rate, payload) {
77
77
  html: product.description || "",
78
78
  JSDOM
79
79
  }),
80
+ source: "cj",
80
81
  pid: product.pid,
81
82
  title: product.productNameEn,
82
83
  variants: product.variants?.map((variant)=>({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/service/sync-products.ts"],"sourcesContent":["import type { DefaultNodeTypes, TypedEditorState } from \"@payloadcms/richtext-lexical\";\nimport type { BasePayload } from \"payload\";\n\nimport { convertHTMLToLexical, editorConfigFactory } from \"@payloadcms/richtext-lexical\";\nimport decimal from \"decimal.js\";\nimport { JSDOM } from \"jsdom\";\n\nimport type { ProductDetails } from \"../sdk/products/product-types\";\n\nimport * as cjSdk from \"../sdk/cj-sdk\";\nimport path, { dirname, join } from \"path\";\nimport fs from \"fs\";\nimport { promisify } from \"util\";\nimport { pipeline } from \"stream\";\nimport { writeFile } from \"fs/promises\";\nimport { fileURLToPath } from \"url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst streamPipeline = promisify(pipeline);\n\ninterface Product {\n description: TypedEditorState<DefaultNodeTypes>;\n pid: string;\n title: string;\n variants?: Array<{\n imageUrl?: string;\n options?: Array<{ option: string; value: string }>;\n price?: number;\n vid: string;\n }>;\n}\n\nconst delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst download = async (uri: string, filename: string): Promise<void> => {\n try {\n const response = await fetch(uri);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ${uri}: ${response.statusText}`);\n }\n\n const contentType = response.headers.get(\"content-type\");\n const contentLength = response.headers.get(\"content-length\");\n\n console.log(\"content-type:\", contentType);\n console.log(\"content-length:\", contentLength);\n\n const buffer = Buffer.from(await response.arrayBuffer());\n\n await writeFile(filename, buffer);\n\n console.log(\"Download complete:\", filename);\n } catch (error) {\n console.error(\"Error downloading file:\", error);\n }\n};\n\n\nasync function uploadImageToPayload(src: string, payload: BasePayload): Promise<any | null> {\n const tempFilePath = path.join(__dirname, \"temp-image.jpg\");\n\n try {\n // Fetch the image\n const response = await fetch(src);\n if (!response.ok) throw new Error(`Failed to fetch image: ${response.statusText}`);\n\n // Stream the response body to a temporary file\n await download(src, tempFilePath);\n\n // Upload the image using Payload's Local API\n const uploadedImage = await payload.create({\n collection: \"media\",\n data: {\n alt: \"Some alt text\",\n },\n\n filePath: tempFilePath,\n });\n\n console.log(\"Uploaded media document:\", uploadedImage);\n\n // Clean up: delete the temporary file\n fs.unlink(tempFilePath, (err) => {\n if (err) console.error(\"Error deleting temporary file:\", err);\n });\n\n return {\n id: uploadedImage.id,\n alt: uploadedImage.alt || \"\",\n prefix: \"media\",\n updatedAt: uploadedImage.updatedAt,\n createdAt: uploadedImage.createdAt,\n url: uploadedImage.url,\n thumbnailURL: uploadedImage.thumbnailURL || null,\n filename: uploadedImage.filename,\n mimeType: uploadedImage.mimeType,\n filesize: uploadedImage.filesize,\n width: uploadedImage.width,\n height: uploadedImage.height,\n focalX: 50,\n focalY: 50,\n };\n } catch (error) {\n console.error(\"Error uploading image:\", error);\n }\n}\nfunction mapMockProductToSchema(\n product: ProductDetails,\n editorConfig: any,\n rate: number,\n payload: BasePayload,\n) {\n return {\n description: convertHTMLToLexical({\n editorConfig,\n html: product.description || \"\",\n JSDOM,\n // uploadImage: async (src: string) => {\n // return uploadImageToPayload(src, payload);\n // },\n }),\n pid: product.pid,\n title: product.productNameEn,\n variants: product.variants?.map((variant) => ({\n imageUrl: variant.variantImage, // Map image URL to 'id' if using media collection\n options: variant.variantKey?.split(\"-\").map((key, index) => ({\n option: index === 0 ? \"Color\" : \"Size\", // Assuming 'Color' and 'Size', adjust keys if needed\n value: key,\n })),\n price: new decimal(variant.variantSellPrice || 0).mul(rate).toNumber().toFixed(2),\n vid: variant.vid,\n })),\n };\n}\n\nconst findProductById = async (productId: string) => {\n const result = await cjSdk.getProductDetails({\n pid: productId,\n });\n return result.data;\n};\n\nconst createOrUpdateProduct = async (\n product: Omit<Product, \"createdAt\" | \"id\" | \"updatedAt\">,\n payload: BasePayload,\n) => {\n const { totalDocs } = await payload.count({\n collection: \"products\",\n where: {\n pid: {\n equals: product.pid,\n },\n },\n });\n\n if (totalDocs === 0) {\n return payload.create({\n collection: \"products\",\n data: { ...product } as any,\n });\n }\n};\n\nexport const fetchExchangeRates = async () => {\n const response = await fetch(\"https://open.er-api.com/v6/latest/USD\");\n const data = await response.json();\n\n return data;\n};\n\nexport const syncProducts = async (productIds: string[], payload: BasePayload) => {\n const exchangeRates = await fetchExchangeRates();\n const storeSettings = await payload.findGlobal({\n slug: \"store-settings\",\n });\n const rate = exchangeRates.rates[storeSettings.currency || \"USD\"];\n\n const editorConfig = await editorConfigFactory.default({\n config: payload.config,\n });\n const products: ProductDetails[] = [];\n for (const productId of productIds) {\n const product = await findProductById(productId);\n if (!product) {\n continue;\n }\n products.push(product);\n await delay(1010);\n }\n const mappedProducts = products.map((product) => {\n return mapMockProductToSchema(product, editorConfig, rate, payload);\n });\n\n await Promise.all(\n mappedProducts.map((product) => createOrUpdateProduct(product as any, payload)),\n );\n\n return products;\n};\n"],"names":["convertHTMLToLexical","editorConfigFactory","decimal","JSDOM","cjSdk","path","dirname","fs","promisify","pipeline","writeFile","fileURLToPath","__filename","url","__dirname","streamPipeline","delay","ms","Promise","resolve","setTimeout","download","uri","filename","response","fetch","ok","Error","statusText","contentType","headers","get","contentLength","console","log","buffer","Buffer","from","arrayBuffer","error","uploadImageToPayload","src","payload","tempFilePath","join","uploadedImage","create","collection","data","alt","filePath","unlink","err","id","prefix","updatedAt","createdAt","thumbnailURL","mimeType","filesize","width","height","focalX","focalY","mapMockProductToSchema","product","editorConfig","rate","description","html","pid","title","productNameEn","variants","map","variant","imageUrl","variantImage","options","variantKey","split","key","index","option","value","price","variantSellPrice","mul","toNumber","toFixed","vid","findProductById","productId","result","getProductDetails","createOrUpdateProduct","totalDocs","count","where","equals","fetchExchangeRates","json","syncProducts","productIds","exchangeRates","storeSettings","findGlobal","slug","rates","currency","default","config","products","push","mappedProducts","all"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/service/sync-products.ts"],"sourcesContent":["import type { DefaultNodeTypes, TypedEditorState } from \"@payloadcms/richtext-lexical\";\nimport type { BasePayload } from \"payload\";\n\nimport { convertHTMLToLexical, editorConfigFactory } from \"@payloadcms/richtext-lexical\";\nimport decimal from \"decimal.js\";\nimport { JSDOM } from \"jsdom\";\n\nimport type { ProductDetails } from \"../sdk/products/product-types\";\n\nimport * as cjSdk from \"../sdk/cj-sdk\";\nimport path, { dirname, join } from \"path\";\nimport fs from \"fs\";\nimport { promisify } from \"util\";\nimport { pipeline } from \"stream\";\nimport { writeFile } from \"fs/promises\";\nimport { fileURLToPath } from \"url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst streamPipeline = promisify(pipeline);\n\ninterface Product {\n description: TypedEditorState<DefaultNodeTypes>;\n pid: string;\n title: string;\n source: \"manual\" | \"cj\";\n variants?: Array<{\n imageUrl?: string;\n options?: Array<{ option: string; value: string }>;\n price?: number;\n vid: string;\n }>;\n}\n\nconst delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst download = async (uri: string, filename: string): Promise<void> => {\n try {\n const response = await fetch(uri);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ${uri}: ${response.statusText}`);\n }\n\n const contentType = response.headers.get(\"content-type\");\n const contentLength = response.headers.get(\"content-length\");\n\n console.log(\"content-type:\", contentType);\n console.log(\"content-length:\", contentLength);\n\n const buffer = Buffer.from(await response.arrayBuffer());\n\n await writeFile(filename, buffer);\n\n console.log(\"Download complete:\", filename);\n } catch (error) {\n console.error(\"Error downloading file:\", error);\n }\n};\n\nasync function uploadImageToPayload(src: string, payload: BasePayload): Promise<any | null> {\n const tempFilePath = path.join(__dirname, \"temp-image.jpg\");\n\n try {\n // Fetch the image\n const response = await fetch(src);\n if (!response.ok) throw new Error(`Failed to fetch image: ${response.statusText}`);\n\n // Stream the response body to a temporary file\n await download(src, tempFilePath);\n\n // Upload the image using Payload's Local API\n const uploadedImage = await payload.create({\n collection: \"media\",\n data: {\n alt: \"Some alt text\",\n },\n\n filePath: tempFilePath,\n });\n\n console.log(\"Uploaded media document:\", uploadedImage);\n\n // Clean up: delete the temporary file\n fs.unlink(tempFilePath, (err) => {\n if (err) console.error(\"Error deleting temporary file:\", err);\n });\n\n return {\n id: uploadedImage.id,\n alt: uploadedImage.alt || \"\",\n prefix: \"media\",\n updatedAt: uploadedImage.updatedAt,\n createdAt: uploadedImage.createdAt,\n url: uploadedImage.url,\n thumbnailURL: uploadedImage.thumbnailURL || null,\n filename: uploadedImage.filename,\n mimeType: uploadedImage.mimeType,\n filesize: uploadedImage.filesize,\n width: uploadedImage.width,\n height: uploadedImage.height,\n focalX: 50,\n focalY: 50,\n };\n } catch (error) {\n console.error(\"Error uploading image:\", error);\n }\n}\nfunction mapMockProductToSchema(\n product: ProductDetails,\n editorConfig: any,\n rate: number,\n payload: BasePayload,\n) {\n return {\n description: convertHTMLToLexical({\n editorConfig,\n html: product.description || \"\",\n JSDOM,\n // uploadImage: async (src: string) => {\n // return uploadImageToPayload(src, payload);\n // },\n }),\n source: \"cj\",\n pid: product.pid,\n title: product.productNameEn,\n variants: product.variants?.map((variant) => ({\n imageUrl: variant.variantImage, // Map image URL to 'id' if using media collection\n options: variant.variantKey?.split(\"-\").map((key, index) => ({\n option: index === 0 ? \"Color\" : \"Size\", // Assuming 'Color' and 'Size', adjust keys if needed\n value: key,\n })),\n price: new decimal(variant.variantSellPrice || 0).mul(rate).toNumber().toFixed(2),\n vid: variant.vid,\n })),\n };\n}\n\nconst findProductById = async (productId: string) => {\n const result = await cjSdk.getProductDetails({\n pid: productId,\n });\n return result.data;\n};\n\nconst createOrUpdateProduct = async (\n product: Omit<Product, \"createdAt\" | \"id\" | \"updatedAt\">,\n payload: BasePayload,\n) => {\n const { totalDocs } = await payload.count({\n collection: \"products\",\n where: {\n pid: {\n equals: product.pid,\n },\n },\n });\n\n if (totalDocs === 0) {\n return payload.create({\n collection: \"products\",\n data: { ...product } as any,\n });\n }\n};\n\nexport const fetchExchangeRates = async () => {\n const response = await fetch(\"https://open.er-api.com/v6/latest/USD\");\n const data = await response.json();\n\n return data;\n};\n\nexport const syncProducts = async (productIds: string[], payload: BasePayload) => {\n const exchangeRates = await fetchExchangeRates();\n const storeSettings = await payload.findGlobal({\n slug: \"store-settings\",\n });\n const rate = exchangeRates.rates[storeSettings.currency || \"USD\"];\n\n const editorConfig = await editorConfigFactory.default({\n config: payload.config,\n });\n const products: ProductDetails[] = [];\n for (const productId of productIds) {\n const product = await findProductById(productId);\n if (!product) {\n continue;\n }\n products.push(product);\n await delay(1010);\n }\n const mappedProducts = products.map((product) => {\n return mapMockProductToSchema(product, editorConfig, rate, payload);\n });\n\n await Promise.all(\n mappedProducts.map((product) => createOrUpdateProduct(product as any, payload)),\n );\n\n return products;\n};\n"],"names":["convertHTMLToLexical","editorConfigFactory","decimal","JSDOM","cjSdk","path","dirname","fs","promisify","pipeline","writeFile","fileURLToPath","__filename","url","__dirname","streamPipeline","delay","ms","Promise","resolve","setTimeout","download","uri","filename","response","fetch","ok","Error","statusText","contentType","headers","get","contentLength","console","log","buffer","Buffer","from","arrayBuffer","error","uploadImageToPayload","src","payload","tempFilePath","join","uploadedImage","create","collection","data","alt","filePath","unlink","err","id","prefix","updatedAt","createdAt","thumbnailURL","mimeType","filesize","width","height","focalX","focalY","mapMockProductToSchema","product","editorConfig","rate","description","html","source","pid","title","productNameEn","variants","map","variant","imageUrl","variantImage","options","variantKey","split","key","index","option","value","price","variantSellPrice","mul","toNumber","toFixed","vid","findProductById","productId","result","getProductDetails","createOrUpdateProduct","totalDocs","count","where","equals","fetchExchangeRates","json","syncProducts","productIds","exchangeRates","storeSettings","findGlobal","slug","rates","currency","default","config","products","push","mappedProducts","all"],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["\nexport interface CJApiResponse<T> {\n code: number;\n result: boolean;\n message: string;\n data: T | null;\n requestId: string;\n}\n\nexport interface AccessTokenResponse {\n code: number;\n result: boolean;\n message: string;\n data: {\n accessToken: string;\n accessTokenExpiryDate: string | Date;\n refreshToken: string;\n refreshTokenExpiryDate: string | Date;\n createDate: string;\n } | null;\n requestId: string;\n}\n\n\n\nexport interface Variant {\n vid: string;\n pid: string;\n variantName: string | null;\n variantNameEn: string | null;\n variantSku: string;\n variantImage: string | null;\n variantStandard: string | null;\n variantUnit: string | null;\n variantProperty: string | null;\n variantKey: string;\n variantLength: number;\n variantWidth: number;\n variantHeight: number;\n variantVolume: number;\n variantWeight: number;\n variantSellPrice: number;\n variantSugSellPrice: number;\n createTime: string;\n}\n\nexport interface ProductDetailResponseData {\n pid: string;\n productName: string[];\n productNameEn: string;\n productSku: string;\n productImage: string;\n productWeight: number;\n productUnit: string;\n productType: string;\n categoryId: string;\n categoryName: string;\n entryCode: string;\n entryName: string;\n entryNameEn: string;\n materialName: string[];\n materialNameEn: string[];\n materialKey: string[];\n packingWeight: number;\n packingName: string[];\n packingNameEn: string[];\n packingKey: string[];\n productKey: string[];\n productKeyEn: string;\n sellPrice: number;\n sourceFrom: number;\n description: string;\n suggestSellPrice: string;\n listedNum: number;\n status: string;\n supplierName: string;\n supplierId: string;\n variants: Variant[];\n createrTime: string;\n}\n\n"],"names":[],"mappings":"AA8CA,WAiCC"}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["export interface CJApiResponse<T> {\n code: number;\n result: boolean;\n message: string;\n data: T | null;\n requestId: string;\n}\n\nexport interface AccessTokenResponse {\n code: number;\n result: boolean;\n message: string;\n data: {\n accessToken: string;\n accessTokenExpiryDate: string | Date;\n refreshToken: string;\n refreshTokenExpiryDate: string | Date;\n createDate: string;\n } | null;\n requestId: string;\n}\n\nexport interface Variant {\n vid: string;\n pid: string;\n variantName: string | null;\n variantNameEn: string | null;\n variantSku: string;\n variantImage: string | null;\n variantStandard: string | null;\n variantUnit: string | null;\n variantProperty: string | null;\n variantKey: string;\n variantLength: number;\n variantWidth: number;\n variantHeight: number;\n variantVolume: number;\n variantWeight: number;\n variantSellPrice: number;\n variantSugSellPrice: number;\n createTime: string;\n}\n\nexport interface ProductDetailResponseData {\n pid: string;\n productName: string[];\n productNameEn: string;\n productSku: string;\n productImage: string;\n productWeight: number;\n productUnit: string;\n productType: string;\n categoryId: string;\n categoryName: string;\n entryCode: string;\n entryName: string;\n entryNameEn: string;\n materialName: string[];\n materialNameEn: string[];\n materialKey: string[];\n packingWeight: number;\n packingName: string[];\n packingNameEn: string[];\n packingKey: string[];\n productKey: string[];\n productKeyEn: string;\n sellPrice: number;\n sourceFrom: number;\n description: string;\n suggestSellPrice: string;\n listedNum: number;\n status: string;\n supplierName: string;\n supplierId: string;\n variants: Variant[];\n createrTime: string;\n}\n"],"names":[],"mappings":"AA2CA,WAiCC"}
@@ -0,0 +1,4 @@
1
+ type TokenPayload = string;
2
+ export declare const encryptToken: (token: TokenPayload) => string;
3
+ export declare const decryptToken: (encryptedToken: string) => string;
4
+ export {};
@@ -0,0 +1,41 @@
1
+ import crypto from "crypto";
2
+ const getKey = (rawKey)=>{
3
+ return crypto.createHash("sha256").update(rawKey).digest();
4
+ };
5
+ const getTenantSecret = (tenantId)=>{
6
+ const key = tenantId;
7
+ if (!key) throw new Error(`Missing secret for tenant: ${tenantId}`);
8
+ return Buffer.from(key, "hex");
9
+ };
10
+ export const encryptToken = (token)=>{
11
+ const key = getKey(process.env.ENCRYPTION_KEY);
12
+ const iv = crypto.randomBytes(12);
13
+ const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
14
+ const encrypted = Buffer.concat([
15
+ cipher.update(token, "utf8"),
16
+ cipher.final()
17
+ ]);
18
+ const tag = cipher.getAuthTag();
19
+ const result = {
20
+ iv: iv.toString("hex"),
21
+ tag: tag.toString("hex"),
22
+ content: encrypted.toString("hex")
23
+ };
24
+ return Buffer.from(JSON.stringify(result)).toString("base64");
25
+ };
26
+ export const decryptToken = (encryptedToken)=>{
27
+ const key = getKey(process.env.ENCRYPTION_KEY);
28
+ const decoded = JSON.parse(Buffer.from(encryptedToken, "base64").toString("utf8"));
29
+ const iv = Buffer.from(decoded.iv, "hex");
30
+ const tag = Buffer.from(decoded.tag, "hex");
31
+ const content = Buffer.from(decoded.content, "hex");
32
+ const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
33
+ decipher.setAuthTag(tag);
34
+ const decrypted = Buffer.concat([
35
+ decipher.update(content),
36
+ decipher.final()
37
+ ]);
38
+ return decrypted.toString("utf8");
39
+ };
40
+
41
+ //# sourceMappingURL=manage-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/manage-tokens.ts"],"sourcesContent":["import crypto from \"crypto\";\n\ntype TokenPayload = string;\ntype EncryptedData = {\n iv: string;\n tag: string;\n content: string;\n};\n\nconst getKey = (rawKey: string): Buffer => {\n return crypto.createHash(\"sha256\").update(rawKey).digest();\n};\n\nconst getTenantSecret = (tenantId: string): Buffer => {\n const key = tenantId;\n if (!key) throw new Error(`Missing secret for tenant: ${tenantId}`);\n return Buffer.from(key, \"hex\");\n};\n\nexport const encryptToken = (token: TokenPayload): string => {\n const key = getKey(process.env.ENCRYPTION_KEY!);\n const iv = crypto.randomBytes(12);\n const cipher = crypto.createCipheriv(\"aes-256-gcm\", key, iv);\n\n const encrypted = Buffer.concat([cipher.update(token, \"utf8\"), cipher.final()]);\n\n const tag = cipher.getAuthTag();\n\n const result: EncryptedData = {\n iv: iv.toString(\"hex\"),\n tag: tag.toString(\"hex\"),\n content: encrypted.toString(\"hex\"),\n };\n\n return Buffer.from(JSON.stringify(result)).toString(\"base64\");\n};\n\nexport const decryptToken = (encryptedToken: string): string => {\n const key = getKey(process.env.ENCRYPTION_KEY!);\n const decoded = JSON.parse(\n Buffer.from(encryptedToken, \"base64\").toString(\"utf8\"),\n ) as EncryptedData;\n\n const iv = Buffer.from(decoded.iv, \"hex\");\n const tag = Buffer.from(decoded.tag, \"hex\");\n const content = Buffer.from(decoded.content, \"hex\");\n\n const decipher = crypto.createDecipheriv(\"aes-256-gcm\", key, iv);\n decipher.setAuthTag(tag);\n\n const decrypted = Buffer.concat([decipher.update(content), decipher.final()]);\n\n return decrypted.toString(\"utf8\");\n};\n"],"names":["crypto","getKey","rawKey","createHash","update","digest","getTenantSecret","tenantId","key","Error","Buffer","from","encryptToken","token","process","env","ENCRYPTION_KEY","iv","randomBytes","cipher","createCipheriv","encrypted","concat","final","tag","getAuthTag","result","toString","content","JSON","stringify","decryptToken","encryptedToken","decoded","parse","decipher","createDecipheriv","setAuthTag","decrypted"],"mappings":"AAAA,OAAOA,YAAY,SAAS;AAS5B,MAAMC,SAAS,CAACC;IACZ,OAAOF,OAAOG,UAAU,CAAC,UAAUC,MAAM,CAACF,QAAQG,MAAM;AAC5D;AAEA,MAAMC,kBAAkB,CAACC;IACrB,MAAMC,MAAMD;IACZ,IAAI,CAACC,KAAK,MAAM,IAAIC,MAAM,CAAC,2BAA2B,EAAEF,UAAU;IAClE,OAAOG,OAAOC,IAAI,CAACH,KAAK;AAC5B;AAEA,OAAO,MAAMI,eAAe,CAACC;IACzB,MAAML,MAAMP,OAAOa,QAAQC,GAAG,CAACC,cAAc;IAC7C,MAAMC,KAAKjB,OAAOkB,WAAW,CAAC;IAC9B,MAAMC,SAASnB,OAAOoB,cAAc,CAAC,eAAeZ,KAAKS;IAEzD,MAAMI,YAAYX,OAAOY,MAAM,CAAC;QAACH,OAAOf,MAAM,CAACS,OAAO;QAASM,OAAOI,KAAK;KAAG;IAE9E,MAAMC,MAAML,OAAOM,UAAU;IAE7B,MAAMC,SAAwB;QAC1BT,IAAIA,GAAGU,QAAQ,CAAC;QAChBH,KAAKA,IAAIG,QAAQ,CAAC;QAClBC,SAASP,UAAUM,QAAQ,CAAC;IAChC;IAEA,OAAOjB,OAAOC,IAAI,CAACkB,KAAKC,SAAS,CAACJ,SAASC,QAAQ,CAAC;AACxD,EAAE;AAEF,OAAO,MAAMI,eAAe,CAACC;IACzB,MAAMxB,MAAMP,OAAOa,QAAQC,GAAG,CAACC,cAAc;IAC7C,MAAMiB,UAAUJ,KAAKK,KAAK,CACtBxB,OAAOC,IAAI,CAACqB,gBAAgB,UAAUL,QAAQ,CAAC;IAGnD,MAAMV,KAAKP,OAAOC,IAAI,CAACsB,QAAQhB,EAAE,EAAE;IACnC,MAAMO,MAAMd,OAAOC,IAAI,CAACsB,QAAQT,GAAG,EAAE;IACrC,MAAMI,UAAUlB,OAAOC,IAAI,CAACsB,QAAQL,OAAO,EAAE;IAE7C,MAAMO,WAAWnC,OAAOoC,gBAAgB,CAAC,eAAe5B,KAAKS;IAC7DkB,SAASE,UAAU,CAACb;IAEpB,MAAMc,YAAY5B,OAAOY,MAAM,CAAC;QAACa,SAAS/B,MAAM,CAACwB;QAAUO,SAASZ,KAAK;KAAG;IAE5E,OAAOe,UAAUX,QAAQ,CAAC;AAC9B,EAAE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopnex/cj-plugin",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A blank template to get started with Payload 3.0",
5
5
  "type": "module",
6
6
  "exports": {