@shopnex/cj-plugin 1.0.2 → 1.0.4

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
@@ -1,2 +1,9 @@
1
- import type { GlobalConfig } from "payload";
2
- export declare const CjSettings: GlobalConfig;
1
+ import type { CollectionConfig, GlobalConfig } from "payload";
2
+ export type CjCollectionProps = {
3
+ overrides?: Partial<CollectionConfig>;
4
+ };
5
+ export type CjGlobalProps = {
6
+ overrides?: Partial<GlobalConfig>;
7
+ };
8
+ export declare const CjSettings: ({ overrides }: CjGlobalProps) => GlobalConfig;
9
+ export declare const CjConfigCollection: ({ overrides }: CjCollectionProps) => CollectionConfig;
@@ -1,51 +1,99 @@
1
1
  import { syncProducts } from "./service/sync-products";
2
- export const CjSettings = {
3
- slug: "cj-settings",
4
- access: {
5
- read: ()=>true,
6
- update: ({ req })=>!!req.user?.roles?.includes("user")
7
- },
8
- admin: {
9
- group: "Plugins"
10
- },
11
- fields: [
12
- {
13
- label: "Logo Area POD",
14
- name: "pod",
15
- type: "upload",
16
- relationTo: "media"
2
+ // Shared fields definition
3
+ const sharedFields = [
4
+ // {
5
+ // label: "Credentials",
6
+ // type: "collapsible",
7
+ // fields: [
8
+ // {
9
+ // type: "row",
10
+ // fields: [
11
+ // {
12
+ // name: "emailAddress",
13
+ // type: "text",
14
+ // },
15
+ // {
16
+ // name: "apiToken",
17
+ // type: "text",
18
+ // admin: {
19
+ // components: {
20
+ // Field: "@shopnex/cj-plugin/rsc#ApiToken",
21
+ // },
22
+ // },
23
+ // },
24
+ // ],
25
+ // },
26
+ // ],
27
+ // },
28
+ // {
29
+ // label: "Logo Area POD",
30
+ // name: "pod",
31
+ // type: "upload",
32
+ // relationTo: "media",
33
+ // },
34
+ {
35
+ name: "items",
36
+ type: "array",
37
+ admin: {
38
+ description: "A list of product URLs to sync with CJ Dropshipping"
17
39
  },
18
- {
19
- name: "items",
20
- type: "array",
21
- admin: {
22
- description: "A list of product URLs to sync with CJ Dropshipping"
23
- },
24
- fields: [
25
- {
26
- name: "productUrl",
27
- type: "text"
28
- }
29
- ],
30
- label: "Products",
31
- labels: {
32
- plural: "Product URLs",
33
- singular: "Product URL"
40
+ fields: [
41
+ {
42
+ name: "productUrl",
43
+ type: "text"
34
44
  }
45
+ ],
46
+ label: "Products",
47
+ labels: {
48
+ plural: "Product URLs",
49
+ singular: "Product URL"
35
50
  }
36
- ],
37
- hooks: {
38
- afterChange: [
39
- async ({ doc, req: { payload } })=>{
40
- const productIds = doc.items.map((item)=>{
41
- const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\.html)/);
42
- return match ? match[0] : null;
43
- });
44
- await syncProducts(productIds, payload);
45
- }
46
- ]
47
- },
48
- label: "CJ Dropshipping"
51
+ }
52
+ ];
53
+ // Shared hooks definition
54
+ const sharedHooks = {
55
+ afterChange: [
56
+ async ({ doc, req })=>{
57
+ const productIds = doc.items.map((item)=>{
58
+ const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\.html)/);
59
+ return match ? match[0] : null;
60
+ });
61
+ const shopId = req.user?.shops?.[0]?.shop?.id;
62
+ await syncProducts(productIds, req.payload, shopId);
63
+ }
64
+ ]
49
65
  };
66
+ // Global Config
67
+ export const CjSettings = ({ overrides })=>({
68
+ slug: "cj-settings",
69
+ access: {
70
+ ...overrides?.access
71
+ },
72
+ admin: {
73
+ group: "Plugins",
74
+ ...overrides?.admin
75
+ },
76
+ fields: sharedFields,
77
+ hooks: sharedHooks,
78
+ label: "CJ Dropshipping",
79
+ ...overrides || {}
80
+ });
81
+ export const CjConfigCollection = ({ overrides })=>({
82
+ slug: "cj-settings",
83
+ access: {
84
+ ...overrides?.access
85
+ },
86
+ admin: {
87
+ group: "Plugins",
88
+ ...overrides?.admin
89
+ },
90
+ fields: sharedFields,
91
+ hooks: sharedHooks,
92
+ labels: {
93
+ singular: "CJ Dropshipping",
94
+ plural: "CJ Configs"
95
+ },
96
+ ...overrides || {}
97
+ });
50
98
 
51
99
  //# sourceMappingURL=cj-settings.js.map
@@ -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 { CollectionConfig, Field, GlobalConfig } from \"payload\";\nimport { syncProducts } from \"./service/sync-products\";\n\n// Collection Config\nexport type CjCollectionProps = {\n overrides?: Partial<CollectionConfig>;\n};\n\nexport type CjGlobalProps = {\n overrides?: Partial<GlobalConfig>;\n};\n\n// Shared fields definition\nconst sharedFields: Field[] = [\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\n// Shared hooks definition\nconst sharedHooks = {\n afterChange: [\n async ({ doc, req }) => {\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 const shopId = req.user?.shops?.[0]?.shop?.id;\n await syncProducts(productIds, req.payload, shopId);\n },\n ],\n};\n\n// Global Config\nexport const CjSettings = ({ overrides }: CjGlobalProps): GlobalConfig => ({\n slug: \"cj-settings\",\n access: {\n ...overrides?.access,\n },\n admin: {\n group: \"Plugins\",\n ...overrides?.admin,\n },\n fields: sharedFields,\n hooks: sharedHooks,\n label: \"CJ Dropshipping\",\n ...(overrides || {}),\n});\n\nexport const CjConfigCollection = ({ overrides }: CjCollectionProps): CollectionConfig => ({\n slug: \"cj-settings\",\n access: {\n ...overrides?.access,\n },\n admin: {\n group: \"Plugins\",\n ...overrides?.admin,\n },\n fields: sharedFields,\n hooks: sharedHooks,\n labels: {\n singular: \"CJ Dropshipping\",\n plural: \"CJ Configs\",\n },\n ...(overrides || {}),\n});\n"],"names":["syncProducts","sharedFields","name","type","admin","description","fields","label","labels","plural","singular","sharedHooks","afterChange","doc","req","productIds","items","map","item","match","productUrl","shopId","user","shops","shop","id","payload","CjSettings","overrides","slug","access","group","hooks","CjConfigCollection"],"mappings":"AACA,SAASA,YAAY,QAAQ,0BAA0B;AAWvD,2BAA2B;AAC3B,MAAMC,eAAwB;IAC1B,IAAI;IACJ,4BAA4B;IAC5B,2BAA2B;IAC3B,gBAAgB;IAChB,YAAY;IACZ,2BAA2B;IAC3B,wBAAwB;IACxB,oBAAoB;IACpB,4CAA4C;IAC5C,oCAAoC;IACpC,qBAAqB;IACrB,oBAAoB;IACpB,wCAAwC;IACxC,oCAAoC;IACpC,+BAA+B;IAC/B,wCAAwC;IACxC,wEAAwE;IACxE,6BAA6B;IAC7B,yBAAyB;IACzB,qBAAqB;IACrB,iBAAiB;IACjB,aAAa;IACb,SAAS;IACT,KAAK;IACL,IAAI;IACJ,8BAA8B;IAC9B,mBAAmB;IACnB,sBAAsB;IACtB,2BAA2B;IAC3B,KAAK;IACL;QACIC,MAAM;QACNC,MAAM;QACNC,OAAO;YACHC,aAAa;QACjB;QACAC,QAAQ;YACJ;gBACIJ,MAAM;gBACNC,MAAM;YACV;SACH;QACDI,OAAO;QACPC,QAAQ;YACJC,QAAQ;YACRC,UAAU;QACd;IACJ;CACH;AAED,0BAA0B;AAC1B,MAAMC,cAAc;IAChBC,aAAa;QACT,OAAO,EAAEC,GAAG,EAAEC,GAAG,EAAE;YACf,MAAMC,aAAaF,IAAIG,KAAK,CAACC,GAAG,CAAC,CAACC;gBAC9B,MAAMC,QAAQD,KAAKE,UAAU,CAACD,KAAK,CAAC;gBACpC,OAAOA,QAAQA,KAAK,CAAC,EAAE,GAAG;YAC9B;YACA,MAAME,SAASP,IAAIQ,IAAI,EAAEC,OAAO,CAAC,EAAE,EAAEC,MAAMC;YAC3C,MAAMzB,aAAae,YAAYD,IAAIY,OAAO,EAAEL;QAChD;KACH;AACL;AAEA,gBAAgB;AAChB,OAAO,MAAMM,aAAa,CAAC,EAAEC,SAAS,EAAiB,GAAoB,CAAA;QACvEC,MAAM;QACNC,QAAQ;YACJ,GAAGF,WAAWE,MAAM;QACxB;QACA1B,OAAO;YACH2B,OAAO;YACP,GAAGH,WAAWxB,KAAK;QACvB;QACAE,QAAQL;QACR+B,OAAOrB;QACPJ,OAAO;QACP,GAAIqB,aAAa,CAAC,CAAC;IACvB,CAAA,EAAG;AAEH,OAAO,MAAMK,qBAAqB,CAAC,EAAEL,SAAS,EAAqB,GAAwB,CAAA;QACvFC,MAAM;QACNC,QAAQ;YACJ,GAAGF,WAAWE,MAAM;QACxB;QACA1B,OAAO;YACH2B,OAAO;YACP,GAAGH,WAAWxB,KAAK;QACvB;QACAE,QAAQL;QACR+B,OAAOrB;QACPH,QAAQ;YACJE,UAAU;YACVD,QAAQ;QACZ;QACA,GAAImB,aAAa,CAAC,CAAC;IACvB,CAAA,EAAG"}
@@ -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,14 @@
1
- import type { Config } from 'payload';
1
+ import type { Config } from "payload";
2
+ import { CjCollectionProps, CjGlobalProps } from "./cj-settings";
2
3
  interface PluginOptions {
4
+ isEnabled?: boolean;
3
5
  cjApiKey: string;
4
6
  cjEmailAddress: string;
5
7
  cjRefreshToken?: string;
8
+ isGlobal?: boolean;
9
+ collectionOverrides?: CjCollectionProps["overrides"];
10
+ globalOverrides?: CjGlobalProps["overrides"];
11
+ orderCollectionSlug?: string;
6
12
  }
7
13
  export declare const cjPlugin: (pluginOptions: PluginOptions) => (config: Config) => Config;
8
14
  export {};
package/dist/index.js CHANGED
@@ -1,36 +1,67 @@
1
- import { CjSettings } from './cj-settings';
2
- import { setCurrentAccessToken } from './sdk/access-token';
3
- import { createOrderHook } from './service/create-order.hook';
4
- const updateCollection = (collection)=>{
5
- if (collection.slug === 'orders') {
6
- return {
7
- ...collection,
8
- hooks: {
9
- ...collection.hooks,
10
- afterChange: [
11
- ...collection.hooks?.afterChange || [],
12
- createOrderHook
13
- ]
14
- }
15
- };
16
- }
17
- return collection;
18
- };
1
+ import { setTenantCredentials } from "./sdk/access-token";
2
+ import { createOrderHook } from "./service/create-order.hook";
3
+ import { CjConfigCollection, CjSettings } from "./cj-settings";
19
4
  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
5
+ const isGlobal = pluginOptions.isGlobal ?? true;
6
+ const isEnabled = pluginOptions.isEnabled ?? true;
7
+ const ordersCollection = config.collections?.find((collection)=>collection.slug === (pluginOptions.orderCollectionSlug || "orders"));
8
+ if (!ordersCollection) {
9
+ throw new Error("No orders collection found");
10
+ }
11
+ if (!ordersCollection.hooks) {
12
+ ordersCollection.hooks = {};
13
+ }
14
+ if (!ordersCollection.hooks?.afterChange?.length) {
15
+ ordersCollection.hooks.afterChange = [];
16
+ }
17
+ if (isGlobal) {
18
+ config.globals?.push(CjSettings({
19
+ overrides: pluginOptions.globalOverrides
20
+ }));
21
+ } else {
22
+ config.collections?.push(CjConfigCollection({
23
+ overrides: pluginOptions.collectionOverrides
24
+ }));
25
+ }
26
+ const productCollection = config.collections?.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
  });
26
- return {
27
- ...config,
28
- collections: updatedCollections,
29
- globals: [
30
- ...config.globals || [],
31
- CjSettings
32
- ]
32
+ if (!isEnabled) {
33
+ return config;
34
+ }
35
+ if (ordersCollection.hooks?.afterChange) {
36
+ ordersCollection.hooks.afterChange.push(createOrderHook);
37
+ }
38
+ const incomingOnInit = config.onInit;
39
+ config.onInit = async (payload)=>{
40
+ if (incomingOnInit) {
41
+ await incomingOnInit(payload);
42
+ }
43
+ const cjSettingsDocs = [];
44
+ if (isGlobal) {
45
+ setTenantCredentials("1", {
46
+ emailAddress: pluginOptions.cjEmailAddress,
47
+ password: pluginOptions.cjApiKey,
48
+ refreshToken: pluginOptions.cjRefreshToken
49
+ });
50
+ return;
51
+ } else {
52
+ const cjSettings = await payload.find({
53
+ collection: "cj-settings"
54
+ });
55
+ cjSettingsDocs.push(...cjSettings?.docs);
56
+ }
57
+ cjSettingsDocs.forEach((config)=>{
58
+ setTenantCredentials(config?.shop?.slug || "1", {
59
+ emailAddress: config.email,
60
+ password: config.apiToken
61
+ });
62
+ });
33
63
  };
64
+ return config;
34
65
  };
35
66
 
36
67
  //# sourceMappingURL=index.js.map
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 { Config, SelectField } from \"payload\";\nimport { setTenantCredentials } from \"./sdk/access-token\";\nimport { createOrderHook } from \"./service/create-order.hook\";\nimport { CjCollectionProps, CjConfigCollection, CjGlobalProps, CjSettings } from \"./cj-settings\";\n\ninterface PluginOptions {\n isEnabled?: boolean;\n cjApiKey: string;\n cjEmailAddress: string;\n cjRefreshToken?: string;\n isGlobal?: boolean;\n collectionOverrides?: CjCollectionProps[\"overrides\"];\n globalOverrides?: CjGlobalProps[\"overrides\"];\n orderCollectionSlug?: string;\n}\n\nexport const cjPlugin =\n (pluginOptions: PluginOptions) =>\n (config: Config): Config => {\n const isGlobal = pluginOptions.isGlobal ?? true;\n\n const isEnabled = pluginOptions.isEnabled ?? true;\n\n const ordersCollection = config.collections?.find(\n (collection) => collection.slug === (pluginOptions.orderCollectionSlug || \"orders\"),\n );\n\n if (!ordersCollection) {\n throw new Error(\"No orders collection found\");\n }\n\n if (!ordersCollection.hooks) {\n ordersCollection.hooks = {};\n }\n\n if (!ordersCollection.hooks?.afterChange?.length) {\n ordersCollection.hooks.afterChange = [];\n }\n\n if (isGlobal) {\n config.globals?.push(CjSettings({ overrides: pluginOptions.globalOverrides }));\n } else {\n config.collections?.push(\n CjConfigCollection({ overrides: pluginOptions.collectionOverrides }),\n );\n }\n const productCollection = config.collections?.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 if (!isEnabled) {\n return config;\n }\n if (ordersCollection.hooks?.afterChange) {\n ordersCollection.hooks.afterChange.push(createOrderHook);\n }\n\n const incomingOnInit = config.onInit;\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload);\n }\n\n const cjSettingsDocs: any = [];\n\n if (isGlobal) {\n setTenantCredentials(\"1\", {\n emailAddress: pluginOptions.cjEmailAddress,\n password: pluginOptions.cjApiKey,\n refreshToken: pluginOptions.cjRefreshToken,\n });\n return;\n } else {\n const cjSettings = await payload.find({\n collection: \"cj-settings\",\n });\n\n cjSettingsDocs.push(...cjSettings?.docs);\n }\n\n cjSettingsDocs.forEach((config: any) => {\n setTenantCredentials(config?.shop?.slug || \"1\", {\n emailAddress: config.email,\n password: config.apiToken,\n });\n });\n };\n\n return config;\n };\n"],"names":["setTenantCredentials","createOrderHook","CjConfigCollection","CjSettings","cjPlugin","pluginOptions","config","isGlobal","isEnabled","ordersCollection","collections","find","collection","slug","orderCollectionSlug","Error","hooks","afterChange","length","globals","push","overrides","globalOverrides","collectionOverrides","productCollection","sourceField","fields","field","name","options","label","value","incomingOnInit","onInit","payload","cjSettingsDocs","emailAddress","cjEmailAddress","password","cjApiKey","refreshToken","cjRefreshToken","cjSettings","docs","forEach","shop","email","apiToken"],"mappings":"AACA,SAASA,oBAAoB,QAAQ,qBAAqB;AAC1D,SAASC,eAAe,QAAQ,8BAA8B;AAC9D,SAA4BC,kBAAkB,EAAiBC,UAAU,QAAQ,gBAAgB;AAajG,OAAO,MAAMC,WACT,CAACC,gBACD,CAACC;QACG,MAAMC,WAAWF,cAAcE,QAAQ,IAAI;QAE3C,MAAMC,YAAYH,cAAcG,SAAS,IAAI;QAE7C,MAAMC,mBAAmBH,OAAOI,WAAW,EAAEC,KACzC,CAACC,aAAeA,WAAWC,IAAI,KAAMR,CAAAA,cAAcS,mBAAmB,IAAI,QAAO;QAGrF,IAAI,CAACL,kBAAkB;YACnB,MAAM,IAAIM,MAAM;QACpB;QAEA,IAAI,CAACN,iBAAiBO,KAAK,EAAE;YACzBP,iBAAiBO,KAAK,GAAG,CAAC;QAC9B;QAEA,IAAI,CAACP,iBAAiBO,KAAK,EAAEC,aAAaC,QAAQ;YAC9CT,iBAAiBO,KAAK,CAACC,WAAW,GAAG,EAAE;QAC3C;QAEA,IAAIV,UAAU;YACVD,OAAOa,OAAO,EAAEC,KAAKjB,WAAW;gBAAEkB,WAAWhB,cAAciB,eAAe;YAAC;QAC/E,OAAO;YACHhB,OAAOI,WAAW,EAAEU,KAChBlB,mBAAmB;gBAAEmB,WAAWhB,cAAckB,mBAAmB;YAAC;QAE1E;QACA,MAAMC,oBAAoBlB,OAAOI,WAAW,EAAEC,KAC1C,CAACC,aAAeA,WAAWC,IAAI,KAAK;QAGxC,MAAMY,cAAcD,mBAAmBE,QAAQf,KAC3C,CAACgB,QAAU,AAACA,MAAsBC,IAAI,KAAK;QAG/CH,YAAYI,OAAO,CAACT,IAAI,CAAC;YACrBU,OAAO;YACPC,OAAO;QACX;QAEA,IAAI,CAACvB,WAAW;YACZ,OAAOF;QACX;QACA,IAAIG,iBAAiBO,KAAK,EAAEC,aAAa;YACrCR,iBAAiBO,KAAK,CAACC,WAAW,CAACG,IAAI,CAACnB;QAC5C;QAEA,MAAM+B,iBAAiB1B,OAAO2B,MAAM;QAEpC3B,OAAO2B,MAAM,GAAG,OAAOC;YACnB,IAAIF,gBAAgB;gBAChB,MAAMA,eAAeE;YACzB;YAEA,MAAMC,iBAAsB,EAAE;YAE9B,IAAI5B,UAAU;gBACVP,qBAAqB,KAAK;oBACtBoC,cAAc/B,cAAcgC,cAAc;oBAC1CC,UAAUjC,cAAckC,QAAQ;oBAChCC,cAAcnC,cAAcoC,cAAc;gBAC9C;gBACA;YACJ,OAAO;gBACH,MAAMC,aAAa,MAAMR,QAAQvB,IAAI,CAAC;oBAClCC,YAAY;gBAChB;gBAEAuB,eAAef,IAAI,IAAIsB,YAAYC;YACvC;YAEAR,eAAeS,OAAO,CAAC,CAACtC;gBACpBN,qBAAqBM,QAAQuC,MAAMhC,QAAQ,KAAK;oBAC5CuB,cAAc9B,OAAOwC,KAAK;oBAC1BR,UAAUhC,OAAOyC,QAAQ;gBAC7B;YACJ;QACJ;QAEA,OAAOzC;IACX,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,39 @@
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');
6
- }
7
- const { emailAddress, password, refreshToken } = credentials;
8
- let accessToken = (await cjSdk.refreshAccessToken(refreshToken || '')).accessToken;
9
- if (!accessToken) {
10
- accessToken = (await cjSdk.getAccessToken(emailAddress, password)).accessToken;
11
- }
4
+ const shopId = "1";
5
+ const accessToken = await getTenantAccessToken(shopId);
12
6
  return accessToken;
13
7
  };
14
- export const setCurrentAccessToken = ({ emailAddress, password, refreshToken })=>{
15
- credentials = {
16
- emailAddress,
17
- password,
18
- refreshToken
19
- };
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`);
15
+ }
16
+ const { emailAddress, password, refreshToken } = creds;
17
+ let newAccessToken;
18
+ let newRefreshToken;
19
+ if (!refreshToken) {
20
+ const result = await cjSdk.getAccessToken(emailAddress, password);
21
+ newAccessToken = result.accessToken;
22
+ newRefreshToken = result.refreshToken;
23
+ tenantCredentialsMap.set(shopId, {
24
+ ...creds,
25
+ refreshToken: newRefreshToken
26
+ });
27
+ } else {
28
+ const result = await cjSdk.refreshAccessToken(refreshToken);
29
+ newAccessToken = result.accessToken;
30
+ newRefreshToken = result.refreshToken;
31
+ tenantCredentialsMap.set(shopId, {
32
+ ...creds,
33
+ refreshToken: newRefreshToken
34
+ });
35
+ }
36
+ return newAccessToken;
20
37
  };
21
38
 
22
39
  //# 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\n let newAccessToken: string;\n let newRefreshToken: string | undefined;\n\n if (!refreshToken) {\n const result = await cjSdk.getAccessToken(emailAddress, password);\n newAccessToken = result.accessToken;\n newRefreshToken = result.refreshToken;\n\n tenantCredentialsMap.set(shopId, {\n ...creds,\n refreshToken: newRefreshToken,\n });\n } else {\n const result = await cjSdk.refreshAccessToken(refreshToken);\n newAccessToken = result.accessToken;\n newRefreshToken = result.refreshToken;\n\n tenantCredentialsMap.set(shopId, {\n ...creds,\n refreshToken: newRefreshToken,\n });\n }\n\n return newAccessToken;\n};\n"],"names":["cjSdk","tenantCredentialsMap","Map","getCurrentAccessToken","shopId","accessToken","getTenantAccessToken","setTenantCredentials","creds","set","get","emailAddress","password","Error","refreshToken","newAccessToken","newRefreshToken","result","getAccessToken","refreshAccessToken"],"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;IAEjD,IAAIO;IACJ,IAAIC;IAEJ,IAAI,CAACF,cAAc;QACf,MAAMG,SAAS,MAAMjB,MAAMkB,cAAc,CAACP,cAAcC;QACxDG,iBAAiBE,OAAOZ,WAAW;QACnCW,kBAAkBC,OAAOH,YAAY;QAErCb,qBAAqBQ,GAAG,CAACL,QAAQ;YAC7B,GAAGI,KAAK;YACRM,cAAcE;QAClB;IACJ,OAAO;QACH,MAAMC,SAAS,MAAMjB,MAAMmB,kBAAkB,CAACL;QAC9CC,iBAAiBE,OAAOZ,WAAW;QACnCW,kBAAkBC,OAAOH,YAAY;QAErCb,qBAAqBQ,GAAG,CAACL,QAAQ;YAC7B,GAAGI,KAAK;YACRM,cAAcE;QAClB;IACJ;IAEA,OAAOD;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"}
@@ -1,4 +1,4 @@
1
1
  import type { BasePayload } from "payload";
2
2
  import type { ProductDetails } from "../sdk/products/product-types";
3
3
  export declare const fetchExchangeRates: () => Promise<any>;
4
- export declare const syncProducts: (productIds: string[], payload: BasePayload) => Promise<ProductDetails[]>;
4
+ export declare const syncProducts: (productIds: string[], payload: BasePayload, shopId?: string) => Promise<ProductDetails[]>;
@@ -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)=>({
@@ -96,7 +97,7 @@ const findProductById = async (productId)=>{
96
97
  });
97
98
  return result.data;
98
99
  };
99
- const createOrUpdateProduct = async (product, payload)=>{
100
+ const createOrUpdateProduct = async (product, payload, shopId)=>{
100
101
  const { totalDocs } = await payload.count({
101
102
  collection: "products",
102
103
  where: {
@@ -109,7 +110,8 @@ const createOrUpdateProduct = async (product, payload)=>{
109
110
  return payload.create({
110
111
  collection: "products",
111
112
  data: {
112
- ...product
113
+ ...product,
114
+ shop: shopId
113
115
  }
114
116
  });
115
117
  }
@@ -119,7 +121,7 @@ export const fetchExchangeRates = async ()=>{
119
121
  const data = await response.json();
120
122
  return data;
121
123
  };
122
- export const syncProducts = async (productIds, payload)=>{
124
+ export const syncProducts = async (productIds, payload, shopId)=>{
123
125
  const exchangeRates = await fetchExchangeRates();
124
126
  const storeSettings = await payload.findGlobal({
125
127
  slug: "store-settings"
@@ -140,7 +142,7 @@ export const syncProducts = async (productIds, payload)=>{
140
142
  const mappedProducts = products.map((product)=>{
141
143
  return mapMockProductToSchema(product, editorConfig, rate, payload);
142
144
  });
143
- await Promise.all(mappedProducts.map((product)=>createOrUpdateProduct(product, payload)));
145
+ await Promise.all(mappedProducts.map((product)=>createOrUpdateProduct(product, payload, shopId)));
144
146
  return products;
145
147
  };
146
148
 
@@ -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 shopId?: string,\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: {\n ...product,\n shop: shopId,\n } 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, shopId?: string) => {\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, shopId)),\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","shopId","totalDocs","count","where","equals","shop","fetchExchangeRates","json","syncProducts","productIds","exchangeRates","storeSettings","findGlobal","slug","rates","currency","default","config","products","push","mappedProducts","all"],"mappings":"AAGA,SAASA,oBAAoB,EAAEC,mBAAmB,QAAQ,+BAA+B;AACzF,OAAOC,aAAa,aAAa;AACjC,SAASC,KAAK,QAAQ,QAAQ;AAI9B,YAAYC,WAAW,gBAAgB;AACvC,OAAOC,QAAQC,OAAO,QAAc,OAAO;AAC3C,OAAOC,QAAQ,KAAK;AACpB,SAASC,SAAS,QAAQ,OAAO;AACjC,SAASC,QAAQ,QAAQ,SAAS;AAClC,SAASC,SAAS,QAAQ,cAAc;AACxC,SAASC,aAAa,QAAQ,MAAM;AAEpC,MAAMC,aAAaD,cAAc,YAAYE,GAAG;AAChD,MAAMC,YAAYR,QAAQM;AAE1B,MAAMG,iBAAiBP,UAAUC;AAejC,MAAMO,QAAQ,CAACC,KAAe,IAAIC,QAAQ,CAACC,UAAYC,WAAWD,SAASF;AAE3E,MAAMI,WAAW,OAAOC,KAAaC;IACjC,IAAI;QACA,MAAMC,WAAW,MAAMC,MAAMH;QAE7B,IAAI,CAACE,SAASE,EAAE,EAAE;YACd,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAEL,IAAI,EAAE,EAAEE,SAASI,UAAU,EAAE;QACpE;QAEA,MAAMC,cAAcL,SAASM,OAAO,CAACC,GAAG,CAAC;QACzC,MAAMC,gBAAgBR,SAASM,OAAO,CAACC,GAAG,CAAC;QAE3CE,QAAQC,GAAG,CAAC,iBAAiBL;QAC7BI,QAAQC,GAAG,CAAC,mBAAmBF;QAE/B,MAAMG,SAASC,OAAOC,IAAI,CAAC,MAAMb,SAASc,WAAW;QAErD,MAAM5B,UAAUa,UAAUY;QAE1BF,QAAQC,GAAG,CAAC,sBAAsBX;IACtC,EAAE,OAAOgB,OAAO;QACZN,QAAQM,KAAK,CAAC,2BAA2BA;IAC7C;AACJ;AAEA,eAAeC,qBAAqBC,GAAW,EAAEC,OAAoB;IACjE,MAAMC,eAAetC,KAAKuC,IAAI,CAAC9B,WAAW;IAE1C,IAAI;QACA,kBAAkB;QAClB,MAAMU,WAAW,MAAMC,MAAMgB;QAC7B,IAAI,CAACjB,SAASE,EAAE,EAAE,MAAM,IAAIC,MAAM,CAAC,uBAAuB,EAAEH,SAASI,UAAU,EAAE;QAEjF,+CAA+C;QAC/C,MAAMP,SAASoB,KAAKE;QAEpB,6CAA6C;QAC7C,MAAME,gBAAgB,MAAMH,QAAQI,MAAM,CAAC;YACvCC,YAAY;YACZC,MAAM;gBACFC,KAAK;YACT;YAEAC,UAAUP;QACd;QAEAV,QAAQC,GAAG,CAAC,4BAA4BW;QAExC,sCAAsC;QACtCtC,GAAG4C,MAAM,CAACR,cAAc,CAACS;YACrB,IAAIA,KAAKnB,QAAQM,KAAK,CAAC,kCAAkCa;QAC7D;QAEA,OAAO;YACHC,IAAIR,cAAcQ,EAAE;YACpBJ,KAAKJ,cAAcI,GAAG,IAAI;YAC1BK,QAAQ;YACRC,WAAWV,cAAcU,SAAS;YAClCC,WAAWX,cAAcW,SAAS;YAClC3C,KAAKgC,cAAchC,GAAG;YACtB4C,cAAcZ,cAAcY,YAAY,IAAI;YAC5ClC,UAAUsB,cAActB,QAAQ;YAChCmC,UAAUb,cAAca,QAAQ;YAChCC,UAAUd,cAAcc,QAAQ;YAChCC,OAAOf,cAAce,KAAK;YAC1BC,QAAQhB,cAAcgB,MAAM;YAC5BC,QAAQ;YACRC,QAAQ;QACZ;IACJ,EAAE,OAAOxB,OAAO;QACZN,QAAQM,KAAK,CAAC,0BAA0BA;IAC5C;AACJ;AACA,SAASyB,uBACLC,OAAuB,EACvBC,YAAiB,EACjBC,IAAY,EACZzB,OAAoB;IAEpB,OAAO;QACH0B,aAAapE,qBAAqB;YAC9BkE;YACAG,MAAMJ,QAAQG,WAAW,IAAI;YAC7BjE;QAIJ;QACAmE,QAAQ;QACRC,KAAKN,QAAQM,GAAG;QAChBC,OAAOP,QAAQQ,aAAa;QAC5BC,UAAUT,QAAQS,QAAQ,EAAEC,IAAI,CAACC,UAAa,CAAA;gBAC1CC,UAAUD,QAAQE,YAAY;gBAC9BC,SAASH,QAAQI,UAAU,EAAEC,MAAM,KAAKN,IAAI,CAACO,KAAKC,QAAW,CAAA;wBACzDC,QAAQD,UAAU,IAAI,UAAU;wBAChCE,OAAOH;oBACX,CAAA;gBACAI,OAAO,IAAIpF,QAAQ0E,QAAQW,gBAAgB,IAAI,GAAGC,GAAG,CAACrB,MAAMsB,QAAQ,GAAGC,OAAO,CAAC;gBAC/EC,KAAKf,QAAQe,GAAG;YACpB,CAAA;IACJ;AACJ;AAEA,MAAMC,kBAAkB,OAAOC;IAC3B,MAAMC,SAAS,MAAM1F,MAAM2F,iBAAiB,CAAC;QACzCxB,KAAKsB;IACT;IACA,OAAOC,OAAO9C,IAAI;AACtB;AAEA,MAAMgD,wBAAwB,OAC1B/B,SACAvB,SACAuD;IAEA,MAAM,EAAEC,SAAS,EAAE,GAAG,MAAMxD,QAAQyD,KAAK,CAAC;QACtCpD,YAAY;QACZqD,OAAO;YACH7B,KAAK;gBACD8B,QAAQpC,QAAQM,GAAG;YACvB;QACJ;IACJ;IAEA,IAAI2B,cAAc,GAAG;QACjB,OAAOxD,QAAQI,MAAM,CAAC;YAClBC,YAAY;YACZC,MAAM;gBACF,GAAGiB,OAAO;gBACVqC,MAAML;YACV;QACJ;IACJ;AACJ;AAEA,OAAO,MAAMM,qBAAqB;IAC9B,MAAM/E,WAAW,MAAMC,MAAM;IAC7B,MAAMuB,OAAO,MAAMxB,SAASgF,IAAI;IAEhC,OAAOxD;AACX,EAAE;AAEF,OAAO,MAAMyD,eAAe,OAAOC,YAAsBhE,SAAsBuD;IAC3E,MAAMU,gBAAgB,MAAMJ;IAC5B,MAAMK,gBAAgB,MAAMlE,QAAQmE,UAAU,CAAC;QAC3CC,MAAM;IACV;IACA,MAAM3C,OAAOwC,cAAcI,KAAK,CAACH,cAAcI,QAAQ,IAAI,MAAM;IAEjE,MAAM9C,eAAe,MAAMjE,oBAAoBgH,OAAO,CAAC;QACnDC,QAAQxE,QAAQwE,MAAM;IAC1B;IACA,MAAMC,WAA6B,EAAE;IACrC,KAAK,MAAMtB,aAAaa,WAAY;QAChC,MAAMzC,UAAU,MAAM2B,gBAAgBC;QACtC,IAAI,CAAC5B,SAAS;YACV;QACJ;QACAkD,SAASC,IAAI,CAACnD;QACd,MAAMjD,MAAM;IAChB;IACA,MAAMqG,iBAAiBF,SAASxC,GAAG,CAAC,CAACV;QACjC,OAAOD,uBAAuBC,SAASC,cAAcC,MAAMzB;IAC/D;IAEA,MAAMxB,QAAQoG,GAAG,CACbD,eAAe1C,GAAG,CAAC,CAACV,UAAY+B,sBAAsB/B,SAAgBvB,SAASuD;IAGnF,OAAOkB;AACX,EAAE"}
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.4",
4
4
  "description": "A blank template to get started with Payload 3.0",
5
5
  "type": "module",
6
6
  "exports": {