@shopnex/cj-plugin 1.0.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cj-settings.d.ts +17 -5
- package/dist/cj-settings.js +95 -81
- package/dist/cj-settings.js.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.js +8 -24
- package/dist/index.js.map +1 -1
- package/dist/sdk/access-token.d.ts +1 -1
- package/dist/sdk/access-token.js +11 -11
- package/dist/sdk/access-token.js.map +1 -1
- package/dist/{auth.js → sdk/auth.js} +11 -12
- package/dist/sdk/auth.js.map +1 -0
- package/dist/sdk/cj-sdk.d.ts +16 -4
- package/dist/sdk/cj-sdk.js +36 -4
- package/dist/sdk/cj-sdk.js.map +1 -1
- package/dist/sdk/products/products.d.ts +1 -0
- package/dist/sdk/products/products.js +1 -2
- package/dist/sdk/products/products.js.map +1 -1
- package/dist/service/access-token.d.ts +2 -0
- package/dist/service/access-token.js +53 -0
- package/dist/service/access-token.js.map +1 -0
- package/dist/service/create-order.hook.js +5 -2
- package/dist/service/create-order.hook.js.map +1 -1
- package/dist/service/sync-products.d.ts +7 -2
- package/dist/service/sync-products.js +85 -103
- package/dist/service/sync-products.js.map +1 -1
- package/package.json +4 -2
- package/dist/auth.js.map +0 -1
- /package/dist/{auth.d.ts → sdk/auth.d.ts} +0 -0
package/dist/cj-settings.d.ts
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
-
import type { CollectionConfig
|
1
|
+
import type { CollectionConfig } from "payload";
|
2
2
|
export type CjCollectionProps = {
|
3
3
|
overrides?: Partial<CollectionConfig>;
|
4
4
|
};
|
5
|
-
export type
|
6
|
-
|
5
|
+
export type CjData = {
|
6
|
+
id: string;
|
7
|
+
emailAddress?: string;
|
8
|
+
apiToken?: string;
|
9
|
+
refreshToken?: string;
|
10
|
+
refreshTokenExpiry?: string | Date;
|
11
|
+
accessToken?: string;
|
12
|
+
accessTokenExpiry?: string | Date;
|
13
|
+
pod?: {
|
14
|
+
id: string;
|
15
|
+
relationTo: "media";
|
16
|
+
};
|
17
|
+
items: {
|
18
|
+
productUrl: string;
|
19
|
+
}[];
|
7
20
|
};
|
8
|
-
export declare const
|
9
|
-
export declare const CjConfigCollection: ({ overrides }: CjCollectionProps) => CollectionConfig;
|
21
|
+
export declare const CjConfigCollection: ({ overrides, }: CjCollectionProps) => CollectionConfig;
|
package/dist/cj-settings.js
CHANGED
@@ -1,83 +1,5 @@
|
|
1
1
|
import { syncProducts } from "./service/sync-products";
|
2
|
-
|
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"
|
39
|
-
},
|
40
|
-
fields: [
|
41
|
-
{
|
42
|
-
name: "productUrl",
|
43
|
-
type: "text"
|
44
|
-
}
|
45
|
-
],
|
46
|
-
label: "Products",
|
47
|
-
labels: {
|
48
|
-
plural: "Product URLs",
|
49
|
-
singular: "Product URL"
|
50
|
-
}
|
51
|
-
}
|
52
|
-
];
|
53
|
-
// Shared hooks definition
|
54
|
-
const sharedHooks = {
|
55
|
-
beforeChange: [
|
56
|
-
async ({ data, req })=>{
|
57
|
-
const productIds = data.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
|
-
]
|
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
|
-
});
|
2
|
+
import { encryptedField } from "@shopnex/utils";
|
81
3
|
export const CjConfigCollection = ({ overrides })=>({
|
82
4
|
slug: "cj-settings",
|
83
5
|
access: {
|
@@ -85,10 +7,102 @@ export const CjConfigCollection = ({ overrides })=>({
|
|
85
7
|
},
|
86
8
|
admin: {
|
87
9
|
group: "Plugins",
|
10
|
+
useAsTitle: "emailAddress",
|
88
11
|
...overrides?.admin
|
89
12
|
},
|
90
|
-
fields:
|
91
|
-
|
13
|
+
fields: [
|
14
|
+
{
|
15
|
+
label: "Credentials",
|
16
|
+
type: "collapsible",
|
17
|
+
fields: [
|
18
|
+
{
|
19
|
+
type: "row",
|
20
|
+
fields: [
|
21
|
+
{
|
22
|
+
name: "emailAddress",
|
23
|
+
type: "text"
|
24
|
+
},
|
25
|
+
encryptedField({
|
26
|
+
name: "apiToken",
|
27
|
+
type: "text"
|
28
|
+
})
|
29
|
+
]
|
30
|
+
},
|
31
|
+
{
|
32
|
+
type: "row",
|
33
|
+
fields: [
|
34
|
+
encryptedField({
|
35
|
+
name: "refreshToken",
|
36
|
+
type: "text"
|
37
|
+
}),
|
38
|
+
{
|
39
|
+
name: "refreshTokenExpiry",
|
40
|
+
type: "date"
|
41
|
+
}
|
42
|
+
]
|
43
|
+
},
|
44
|
+
{
|
45
|
+
type: "row",
|
46
|
+
fields: [
|
47
|
+
encryptedField({
|
48
|
+
name: "accessToken",
|
49
|
+
type: "text"
|
50
|
+
}),
|
51
|
+
{
|
52
|
+
name: "accessTokenExpiry",
|
53
|
+
type: "date"
|
54
|
+
}
|
55
|
+
]
|
56
|
+
}
|
57
|
+
]
|
58
|
+
},
|
59
|
+
{
|
60
|
+
label: "Logo Area POD",
|
61
|
+
name: "pod",
|
62
|
+
type: "upload",
|
63
|
+
relationTo: "media"
|
64
|
+
},
|
65
|
+
{
|
66
|
+
name: "items",
|
67
|
+
type: "array",
|
68
|
+
admin: {
|
69
|
+
description: "A list of product URLs to sync with CJ Dropshipping"
|
70
|
+
},
|
71
|
+
fields: [
|
72
|
+
{
|
73
|
+
name: "productUrl",
|
74
|
+
type: "text"
|
75
|
+
}
|
76
|
+
],
|
77
|
+
label: "Products",
|
78
|
+
labels: {
|
79
|
+
plural: "Product URLs",
|
80
|
+
singular: "Product URL"
|
81
|
+
}
|
82
|
+
}
|
83
|
+
],
|
84
|
+
hooks: {
|
85
|
+
beforeChange: [
|
86
|
+
async ({ data, req })=>{
|
87
|
+
const productIds = data.items?.map((item)=>{
|
88
|
+
const match = item.productUrl.match(/(?<=-p-)([0-9A-Fa-f-]+)(?=\.html)/);
|
89
|
+
return match ? match[0] : null;
|
90
|
+
});
|
91
|
+
if (!productIds) {
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
const shopId = req.user?.shops?.[0]?.shop?.id;
|
95
|
+
if (productIds.length > 0) {
|
96
|
+
await syncProducts({
|
97
|
+
productIds,
|
98
|
+
payload: req.payload,
|
99
|
+
shopId,
|
100
|
+
data
|
101
|
+
});
|
102
|
+
}
|
103
|
+
}
|
104
|
+
]
|
105
|
+
},
|
92
106
|
labels: {
|
93
107
|
singular: "CJ Dropshipping",
|
94
108
|
plural: "CJ Configs"
|
package/dist/cj-settings.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/cj-settings.ts"],"sourcesContent":["import type {
|
1
|
+
{"version":3,"sources":["../src/cj-settings.ts"],"sourcesContent":["import type {\n CollectionBeforeChangeHook,\n CollectionConfig,\n Field,\n GlobalConfig,\n} from \"payload\";\nimport { syncProducts } from \"./service/sync-products\";\nimport { encryptedField } from \"@shopnex/utils\";\n\n// Collection Config\nexport type CjCollectionProps = {\n overrides?: Partial<CollectionConfig>;\n};\n\nexport type CjData = {\n id: string;\n emailAddress?: string;\n apiToken?: string;\n refreshToken?: string;\n refreshTokenExpiry?: string | Date;\n accessToken?: string;\n accessTokenExpiry?: string | Date;\n pod?: {\n id: string;\n relationTo: \"media\";\n };\n items: {\n productUrl: string;\n }[];\n};\n\nexport const CjConfigCollection = ({\n overrides,\n}: CjCollectionProps): CollectionConfig => ({\n slug: \"cj-settings\",\n access: {\n ...overrides?.access,\n },\n admin: {\n group: \"Plugins\",\n useAsTitle: \"emailAddress\",\n ...overrides?.admin,\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 encryptedField({\n name: \"apiToken\",\n type: \"text\",\n }),\n ],\n },\n {\n type: \"row\",\n fields: [\n encryptedField({\n name: \"refreshToken\",\n type: \"text\",\n }),\n {\n name: \"refreshTokenExpiry\",\n type: \"date\",\n },\n ],\n },\n {\n type: \"row\",\n fields: [\n encryptedField({\n name: \"accessToken\",\n type: \"text\",\n }),\n {\n name: \"accessTokenExpiry\",\n type: \"date\",\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:\n \"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 async ({ data, req }) => {\n const productIds = data.items?.map((item: any) => {\n const match = item.productUrl.match(\n /(?<=-p-)([0-9A-Fa-f-]+)(?=\\.html)/\n );\n return match ? match[0] : null;\n });\n if (!productIds) {\n return;\n }\n const shopId = (req.user?.shops as any)?.[0]?.shop?.id;\n if (productIds.length > 0) {\n await syncProducts({\n productIds,\n payload: req.payload,\n shopId,\n data,\n });\n }\n },\n ] as CollectionBeforeChangeHook<CjData>[],\n },\n labels: {\n singular: \"CJ Dropshipping\",\n plural: \"CJ Configs\",\n },\n ...(overrides || {}),\n});\n"],"names":["syncProducts","encryptedField","CjConfigCollection","overrides","slug","access","admin","group","useAsTitle","fields","label","type","name","relationTo","description","labels","plural","singular","hooks","beforeChange","data","req","productIds","items","map","item","match","productUrl","shopId","user","shops","shop","id","length","payload"],"mappings":"AAMA,SAASA,YAAY,QAAQ,0BAA0B;AACvD,SAASC,cAAc,QAAQ,iBAAiB;AAwBhD,OAAO,MAAMC,qBAAqB,CAAC,EAC/BC,SAAS,EACO,GAAwB,CAAA;QACxCC,MAAM;QACNC,QAAQ;YACJ,GAAGF,WAAWE,MAAM;QACxB;QACAC,OAAO;YACHC,OAAO;YACPC,YAAY;YACZ,GAAGL,WAAWG,KAAK;QACvB;QACAG,QAAQ;YACJ;gBACIC,OAAO;gBACPC,MAAM;gBACNF,QAAQ;oBACJ;wBACIE,MAAM;wBACNF,QAAQ;4BACJ;gCACIG,MAAM;gCACND,MAAM;4BACV;4BACAV,eAAe;gCACXW,MAAM;gCACND,MAAM;4BACV;yBACH;oBACL;oBACA;wBACIA,MAAM;wBACNF,QAAQ;4BACJR,eAAe;gCACXW,MAAM;gCACND,MAAM;4BACV;4BACA;gCACIC,MAAM;gCACND,MAAM;4BACV;yBACH;oBACL;oBACA;wBACIA,MAAM;wBACNF,QAAQ;4BACJR,eAAe;gCACXW,MAAM;gCACND,MAAM;4BACV;4BACA;gCACIC,MAAM;gCACND,MAAM;4BACV;yBACH;oBACL;iBACH;YACL;YACA;gBACID,OAAO;gBACPE,MAAM;gBACND,MAAM;gBACNE,YAAY;YAChB;YACA;gBACID,MAAM;gBACND,MAAM;gBACNL,OAAO;oBACHQ,aACI;gBACR;gBACAL,QAAQ;oBACJ;wBACIG,MAAM;wBACND,MAAM;oBACV;iBACH;gBACDD,OAAO;gBACPK,QAAQ;oBACJC,QAAQ;oBACRC,UAAU;gBACd;YACJ;SACH;QACDC,OAAO;YACHC,cAAc;gBACV,OAAO,EAAEC,IAAI,EAAEC,GAAG,EAAE;oBAChB,MAAMC,aAAaF,KAAKG,KAAK,EAAEC,IAAI,CAACC;wBAChC,MAAMC,QAAQD,KAAKE,UAAU,CAACD,KAAK,CAC/B;wBAEJ,OAAOA,QAAQA,KAAK,CAAC,EAAE,GAAG;oBAC9B;oBACA,IAAI,CAACJ,YAAY;wBACb;oBACJ;oBACA,MAAMM,SAAUP,IAAIQ,IAAI,EAAEC,OAAe,CAAC,EAAE,EAAEC,MAAMC;oBACpD,IAAIV,WAAWW,MAAM,GAAG,GAAG;wBACvB,MAAMjC,aAAa;4BACfsB;4BACAY,SAASb,IAAIa,OAAO;4BACpBN;4BACAR;wBACJ;oBACJ;gBACJ;aACH;QACL;QACAL,QAAQ;YACJE,UAAU;YACVD,QAAQ;QACZ;QACA,GAAIb,aAAa,CAAC,CAAC;IACvB,CAAA,EAAG"}
|
package/dist/index.d.ts
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
import type { Config } from "payload";
|
2
|
-
import { CjCollectionProps
|
2
|
+
import { CjCollectionProps } from "./cj-settings";
|
3
3
|
interface PluginOptions {
|
4
4
|
isEnabled?: boolean;
|
5
5
|
cjApiKey: string;
|
6
6
|
cjEmailAddress: string;
|
7
7
|
cjRefreshToken?: string;
|
8
|
-
isGlobal?: boolean;
|
9
8
|
collectionOverrides?: CjCollectionProps["overrides"];
|
10
|
-
globalOverrides?: CjGlobalProps["overrides"];
|
11
9
|
orderCollectionSlug?: string;
|
12
10
|
}
|
13
11
|
export declare const cjPlugin: (pluginOptions: PluginOptions) => (config: Config) => Config;
|
package/dist/index.js
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
import { setTenantCredentials } from "./sdk/access-token";
|
2
2
|
import { createOrderHook } from "./service/create-order.hook";
|
3
|
-
import { CjConfigCollection
|
3
|
+
import { CjConfigCollection } from "./cj-settings";
|
4
4
|
export const cjPlugin = (pluginOptions)=>(config)=>{
|
5
|
-
const isGlobal = pluginOptions.isGlobal ?? true;
|
6
5
|
const isEnabled = pluginOptions.isEnabled ?? true;
|
7
6
|
const ordersCollection = config.collections?.find((collection)=>collection.slug === (pluginOptions.orderCollectionSlug || "orders"));
|
8
7
|
if (!ordersCollection) {
|
@@ -14,15 +13,9 @@ export const cjPlugin = (pluginOptions)=>(config)=>{
|
|
14
13
|
if (!ordersCollection.hooks?.afterChange?.length) {
|
15
14
|
ordersCollection.hooks.afterChange = [];
|
16
15
|
}
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
}));
|
21
|
-
} else {
|
22
|
-
config.collections?.push(CjConfigCollection({
|
23
|
-
overrides: pluginOptions.collectionOverrides
|
24
|
-
}));
|
25
|
-
}
|
16
|
+
config.collections?.push(CjConfigCollection({
|
17
|
+
overrides: pluginOptions.collectionOverrides
|
18
|
+
}));
|
26
19
|
const productCollection = config.collections?.find((collection)=>collection.slug === "products");
|
27
20
|
const sourceField = productCollection?.fields?.find((field)=>field.name === "source");
|
28
21
|
sourceField.options.push({
|
@@ -41,19 +34,10 @@ export const cjPlugin = (pluginOptions)=>(config)=>{
|
|
41
34
|
await incomingOnInit(payload);
|
42
35
|
}
|
43
36
|
const cjSettingsDocs = [];
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
}
|
37
|
+
const cjSettings = await payload.find({
|
38
|
+
collection: "cj-settings"
|
39
|
+
});
|
40
|
+
cjSettingsDocs.push(...cjSettings?.docs);
|
57
41
|
cjSettingsDocs.forEach((config)=>{
|
58
42
|
setTenantCredentials(config?.shop?.slug || "1", {
|
59
43
|
emailAddress: config.email || process.env.CJ_EMAIL_ADDRESS,
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
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
|
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 } from \"./cj-settings\";\n\ninterface PluginOptions {\n isEnabled?: boolean;\n cjApiKey: string;\n cjEmailAddress: string;\n cjRefreshToken?: string;\n collectionOverrides?: CjCollectionProps[\"overrides\"];\n orderCollectionSlug?: string;\n}\n\nexport const cjPlugin =\n (pluginOptions: PluginOptions) =>\n (config: Config): Config => {\n const isEnabled = pluginOptions.isEnabled ?? true;\n\n const ordersCollection = config.collections?.find(\n (collection) =>\n collection.slug ===\n (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 config.collections?.push(\n CjConfigCollection({ overrides: pluginOptions.collectionOverrides })\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 const cjSettings = await payload.find({\n collection: \"cj-settings\" as any,\n });\n\n cjSettingsDocs.push(...cjSettings?.docs);\n\n cjSettingsDocs.forEach((config: any) => {\n setTenantCredentials(config?.shop?.slug || \"1\", {\n emailAddress: config.email || process.env.CJ_EMAIL_ADDRESS,\n password: config.apiToken || process.env.CJ_PASSWORD,\n });\n });\n };\n\n return config;\n };\n"],"names":["setTenantCredentials","createOrderHook","CjConfigCollection","cjPlugin","pluginOptions","config","isEnabled","ordersCollection","collections","find","collection","slug","orderCollectionSlug","Error","hooks","afterChange","length","push","overrides","collectionOverrides","productCollection","sourceField","fields","field","name","options","label","value","incomingOnInit","onInit","payload","cjSettingsDocs","cjSettings","docs","forEach","shop","emailAddress","email","process","env","CJ_EMAIL_ADDRESS","password","apiToken","CJ_PASSWORD"],"mappings":"AACA,SAASA,oBAAoB,QAAQ,qBAAqB;AAC1D,SAASC,eAAe,QAAQ,8BAA8B;AAC9D,SAA4BC,kBAAkB,QAAQ,gBAAgB;AAWtE,OAAO,MAAMC,WACT,CAACC,gBACD,CAACC;QACG,MAAMC,YAAYF,cAAcE,SAAS,IAAI;QAE7C,MAAMC,mBAAmBF,OAAOG,WAAW,EAAEC,KACzC,CAACC,aACGA,WAAWC,IAAI,KACdP,CAAAA,cAAcQ,mBAAmB,IAAI,QAAO;QAGrD,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;QACAV,OAAOG,WAAW,EAAES,KAChBf,mBAAmB;YAAEgB,WAAWd,cAAce,mBAAmB;QAAC;QAEtE,MAAMC,oBAAoBf,OAAOG,WAAW,EAAEC,KAC1C,CAACC,aAAeA,WAAWC,IAAI,KAAK;QAGxC,MAAMU,cAAcD,mBAAmBE,QAAQb,KAC3C,CAACc,QAAU,AAACA,MAAsBC,IAAI,KAAK;QAG/CH,YAAYI,OAAO,CAACR,IAAI,CAAC;YACrBS,OAAO;YACPC,OAAO;QACX;QAEA,IAAI,CAACrB,WAAW;YACZ,OAAOD;QACX;QACA,IAAIE,iBAAiBO,KAAK,EAAEC,aAAa;YACrCR,iBAAiBO,KAAK,CAACC,WAAW,CAACE,IAAI,CAAChB;QAC5C;QAEA,MAAM2B,iBAAiBvB,OAAOwB,MAAM;QAEpCxB,OAAOwB,MAAM,GAAG,OAAOC;YACnB,IAAIF,gBAAgB;gBAChB,MAAMA,eAAeE;YACzB;YAEA,MAAMC,iBAAsB,EAAE;YAE9B,MAAMC,aAAa,MAAMF,QAAQrB,IAAI,CAAC;gBAClCC,YAAY;YAChB;YAEAqB,eAAed,IAAI,IAAIe,YAAYC;YAEnCF,eAAeG,OAAO,CAAC,CAAC7B;gBACpBL,qBAAqBK,QAAQ8B,MAAMxB,QAAQ,KAAK;oBAC5CyB,cAAc/B,OAAOgC,KAAK,IAAIC,QAAQC,GAAG,CAACC,gBAAgB;oBAC1DC,UAAUpC,OAAOqC,QAAQ,IAAIJ,QAAQC,GAAG,CAACI,WAAW;gBACxD;YACJ;QACJ;QAEA,OAAOtC;IACX,EAAE"}
|
@@ -5,6 +5,6 @@ type Credentials = {
|
|
5
5
|
accessToken?: string;
|
6
6
|
};
|
7
7
|
export declare const getCurrentAccessToken: () => Promise<string>;
|
8
|
-
export declare const setTenantCredentials: (shopId: string,
|
8
|
+
export declare const setTenantCredentials: (shopId: string, credentials: Credentials) => void;
|
9
9
|
export declare const getTenantAccessToken: (shopId: string) => Promise<string>;
|
10
10
|
export {};
|
package/dist/sdk/access-token.js
CHANGED
@@ -1,39 +1,39 @@
|
|
1
|
-
import
|
1
|
+
import { getAccessToken, refreshAccessToken } from "./auth";
|
2
2
|
const tenantCredentialsMap = new Map();
|
3
3
|
export const getCurrentAccessToken = async ()=>{
|
4
4
|
const shopId = "1";
|
5
5
|
const accessToken = await getTenantAccessToken(shopId);
|
6
6
|
return accessToken;
|
7
7
|
};
|
8
|
-
export const setTenantCredentials = (shopId,
|
9
|
-
tenantCredentialsMap.set(shopId,
|
8
|
+
export const setTenantCredentials = (shopId, credentials)=>{
|
9
|
+
tenantCredentialsMap.set(shopId, credentials);
|
10
10
|
};
|
11
11
|
export const getTenantAccessToken = async (shopId)=>{
|
12
|
-
const
|
12
|
+
const credentials = tenantCredentialsMap.get(shopId) || {
|
13
13
|
emailAddress: process.env.CJ_EMAIL_ADDRESS || "",
|
14
14
|
password: process.env.CJ_PASSWORD || "",
|
15
15
|
refreshToken: process.env.CJ_REFRESH_TOKEN || ""
|
16
16
|
};
|
17
|
-
if (
|
18
|
-
return
|
17
|
+
if (credentials.accessToken) {
|
18
|
+
return credentials.accessToken;
|
19
19
|
}
|
20
|
-
if (!
|
20
|
+
if (!credentials?.emailAddress || !credentials?.password) {
|
21
21
|
throw new Error(`Credentials for tenant ${shopId} are missing or incomplete`);
|
22
22
|
}
|
23
|
-
const { emailAddress, password, refreshToken } =
|
23
|
+
const { emailAddress, password, refreshToken } = credentials;
|
24
24
|
let newAccessToken;
|
25
25
|
let newRefreshToken;
|
26
26
|
if (!refreshToken) {
|
27
|
-
const result = await
|
27
|
+
const result = await getAccessToken(emailAddress, password);
|
28
28
|
newAccessToken = result.accessToken;
|
29
29
|
newRefreshToken = result.refreshToken;
|
30
30
|
} else {
|
31
|
-
const result = await
|
31
|
+
const result = await refreshAccessToken(refreshToken);
|
32
32
|
newAccessToken = result.accessToken;
|
33
33
|
newRefreshToken = result.refreshToken;
|
34
34
|
}
|
35
35
|
tenantCredentialsMap.set(shopId, {
|
36
|
-
...
|
36
|
+
...credentials,
|
37
37
|
accessToken: newAccessToken,
|
38
38
|
refreshToken: newRefreshToken
|
39
39
|
});
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/sdk/access-token.ts"],"sourcesContent":["import
|
1
|
+
{"version":3,"sources":["../../src/sdk/access-token.ts"],"sourcesContent":["import { getAccessToken, refreshAccessToken } from \"./auth\";\n\ntype Credentials = {\n emailAddress: string;\n password: string;\n refreshToken?: string;\n accessToken?: 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 = (\n shopId: string,\n credentials: Credentials\n) => {\n tenantCredentialsMap.set(shopId, credentials);\n};\n\nexport const getTenantAccessToken = async (shopId: string) => {\n const credentials = tenantCredentialsMap.get(shopId) || {\n emailAddress: process.env.CJ_EMAIL_ADDRESS || \"\",\n password: process.env.CJ_PASSWORD || \"\",\n refreshToken: process.env.CJ_REFRESH_TOKEN || \"\",\n };\n\n if (credentials.accessToken) {\n return credentials.accessToken;\n }\n\n if (!credentials?.emailAddress || !credentials?.password) {\n throw new Error(\n `Credentials for tenant ${shopId} are missing or incomplete`\n );\n }\n\n const { emailAddress, password, refreshToken } = credentials;\n\n let newAccessToken: string;\n let newRefreshToken: string | undefined;\n\n if (!refreshToken) {\n const result = await getAccessToken(emailAddress, password);\n newAccessToken = result.accessToken;\n newRefreshToken = result.refreshToken;\n } else {\n const result = await refreshAccessToken(refreshToken);\n newAccessToken = result.accessToken;\n newRefreshToken = result.refreshToken;\n }\n\n tenantCredentialsMap.set(shopId, {\n ...credentials,\n accessToken: newAccessToken,\n refreshToken: newRefreshToken,\n });\n\n return newAccessToken;\n};\n"],"names":["getAccessToken","refreshAccessToken","tenantCredentialsMap","Map","getCurrentAccessToken","shopId","accessToken","getTenantAccessToken","setTenantCredentials","credentials","set","get","emailAddress","process","env","CJ_EMAIL_ADDRESS","password","CJ_PASSWORD","refreshToken","CJ_REFRESH_TOKEN","Error","newAccessToken","newRefreshToken","result"],"mappings":"AAAA,SAASA,cAAc,EAAEC,kBAAkB,QAAQ,SAAS;AAS5D,MAAMC,uBAAuB,IAAIC;AAEjC,OAAO,MAAMC,wBAAwB;IACjC,MAAMC,SAAS;IACf,MAAMC,cAAc,MAAMC,qBAAqBF;IAC/C,OAAOC;AACX,EAAE;AAEF,OAAO,MAAME,uBAAuB,CAChCH,QACAI;IAEAP,qBAAqBQ,GAAG,CAACL,QAAQI;AACrC,EAAE;AAEF,OAAO,MAAMF,uBAAuB,OAAOF;IACvC,MAAMI,cAAcP,qBAAqBS,GAAG,CAACN,WAAW;QACpDO,cAAcC,QAAQC,GAAG,CAACC,gBAAgB,IAAI;QAC9CC,UAAUH,QAAQC,GAAG,CAACG,WAAW,IAAI;QACrCC,cAAcL,QAAQC,GAAG,CAACK,gBAAgB,IAAI;IAClD;IAEA,IAAIV,YAAYH,WAAW,EAAE;QACzB,OAAOG,YAAYH,WAAW;IAClC;IAEA,IAAI,CAACG,aAAaG,gBAAgB,CAACH,aAAaO,UAAU;QACtD,MAAM,IAAII,MACN,CAAC,uBAAuB,EAAEf,OAAO,0BAA0B,CAAC;IAEpE;IAEA,MAAM,EAAEO,YAAY,EAAEI,QAAQ,EAAEE,YAAY,EAAE,GAAGT;IAEjD,IAAIY;IACJ,IAAIC;IAEJ,IAAI,CAACJ,cAAc;QACf,MAAMK,SAAS,MAAMvB,eAAeY,cAAcI;QAClDK,iBAAiBE,OAAOjB,WAAW;QACnCgB,kBAAkBC,OAAOL,YAAY;IACzC,OAAO;QACH,MAAMK,SAAS,MAAMtB,mBAAmBiB;QACxCG,iBAAiBE,OAAOjB,WAAW;QACnCgB,kBAAkBC,OAAOL,YAAY;IACzC;IAEAhB,qBAAqBQ,GAAG,CAACL,QAAQ;QAC7B,GAAGI,WAAW;QACdH,aAAae;QACbH,cAAcI;IAClB;IAEA,OAAOD;AACX,EAAE"}
|
@@ -1,45 +1,44 @@
|
|
1
|
-
import { cjApiClient } from
|
1
|
+
import { cjApiClient } from "../api-client";
|
2
2
|
export async function getAccessToken(email, password) {
|
3
3
|
try {
|
4
|
-
const response = await cjApiClient.post(
|
4
|
+
const response = await cjApiClient.post("authentication/getAccessToken", {
|
5
5
|
email,
|
6
6
|
password
|
7
7
|
});
|
8
8
|
if (!response.data.data?.accessToken) {
|
9
|
-
throw new Error(
|
9
|
+
throw new Error("Failed to fetch access token");
|
10
10
|
}
|
11
11
|
// TODO: add logger
|
12
12
|
// console.log('Access Token:', response.data.data?.accessToken)
|
13
13
|
return response.data.data;
|
14
14
|
} catch (error) {
|
15
|
-
console.error(
|
16
|
-
throw error // Rethrow for caller to handle
|
17
|
-
;
|
15
|
+
console.error("Error fetching access token:", error);
|
16
|
+
throw error; // Rethrow for caller to handle
|
18
17
|
}
|
19
18
|
}
|
20
19
|
export async function refreshAccessToken(refreshToken) {
|
21
20
|
try {
|
22
|
-
const response = await cjApiClient.post(
|
21
|
+
const response = await cjApiClient.post("authentication/refreshAccessToken", {
|
23
22
|
refreshToken
|
24
23
|
});
|
25
24
|
// TODO: add logger
|
26
25
|
// console.info('New Access Token:', response.data.data.accessToken)
|
27
26
|
return response.data.data;
|
28
27
|
} catch (error) {
|
29
|
-
console.error(
|
28
|
+
console.error("Error refreshing access token:", error);
|
30
29
|
throw error;
|
31
30
|
}
|
32
31
|
}
|
33
32
|
export async function logout(accessToken) {
|
34
33
|
try {
|
35
|
-
await cjApiClient.post(
|
34
|
+
await cjApiClient.post("authentication/logout", {}, {
|
36
35
|
headers: {
|
37
|
-
|
36
|
+
"CJ-Access-Token": accessToken
|
38
37
|
}
|
39
38
|
});
|
40
|
-
console.log(
|
39
|
+
console.log("Successfully logged out");
|
41
40
|
} catch (error) {
|
42
|
-
console.error(
|
41
|
+
console.error("Logout failed:", error);
|
43
42
|
throw error;
|
44
43
|
}
|
45
44
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../src/sdk/auth.ts"],"sourcesContent":["import type { AccessTokenResponse } from \"../types\";\n\nimport { cjApiClient } from \"../api-client\";\n\ninterface RefreshTokenResponse {\n code: number;\n data: {\n accessToken: string;\n accessTokenExpiryDate: string;\n createDate: string;\n refreshToken: string;\n refreshTokenExpiryDate: string;\n };\n message: string;\n requestId: string;\n result: boolean;\n}\n\ninterface LogoutResponse {\n code: number;\n data: boolean;\n message: string;\n requestId: string;\n result: boolean;\n}\n\nexport async function getAccessToken(email: string, password: string) {\n try {\n const response = await cjApiClient.post<AccessTokenResponse>(\n \"authentication/getAccessToken\",\n {\n email,\n password,\n }\n );\n\n if (!response.data.data?.accessToken) {\n throw new Error(\"Failed to fetch access token\");\n }\n // TODO: add logger\n // console.log('Access Token:', response.data.data?.accessToken)\n return response.data.data;\n } catch (error) {\n console.error(\"Error fetching access token:\", error);\n throw error; // Rethrow for caller to handle\n }\n}\n\nexport async function refreshAccessToken(refreshToken: string) {\n try {\n const response = await cjApiClient.post<RefreshTokenResponse>(\n \"authentication/refreshAccessToken\",\n {\n refreshToken,\n }\n );\n\n // TODO: add logger\n // console.info('New Access Token:', response.data.data.accessToken)\n return response.data.data;\n } catch (error) {\n console.error(\"Error refreshing access token:\", error);\n throw error;\n }\n}\n\nexport async function logout(accessToken: string) {\n try {\n await cjApiClient.post<LogoutResponse>(\n \"authentication/logout\",\n {},\n {\n headers: { \"CJ-Access-Token\": accessToken },\n }\n );\n\n console.log(\"Successfully logged out\");\n } catch (error) {\n console.error(\"Logout failed:\", error);\n throw error;\n }\n}\n"],"names":["cjApiClient","getAccessToken","email","password","response","post","data","accessToken","Error","error","console","refreshAccessToken","refreshToken","logout","headers","log"],"mappings":"AAEA,SAASA,WAAW,QAAQ,gBAAgB;AAwB5C,OAAO,eAAeC,eAAeC,KAAa,EAAEC,QAAgB;IAChE,IAAI;QACA,MAAMC,WAAW,MAAMJ,YAAYK,IAAI,CACnC,iCACA;YACIH;YACAC;QACJ;QAGJ,IAAI,CAACC,SAASE,IAAI,CAACA,IAAI,EAAEC,aAAa;YAClC,MAAM,IAAIC,MAAM;QACpB;QACA,mBAAmB;QACnB,gEAAgE;QAChE,OAAOJ,SAASE,IAAI,CAACA,IAAI;IAC7B,EAAE,OAAOG,OAAO;QACZC,QAAQD,KAAK,CAAC,gCAAgCA;QAC9C,MAAMA,OAAO,+BAA+B;IAChD;AACJ;AAEA,OAAO,eAAeE,mBAAmBC,YAAoB;IACzD,IAAI;QACA,MAAMR,WAAW,MAAMJ,YAAYK,IAAI,CACnC,qCACA;YACIO;QACJ;QAGJ,mBAAmB;QACnB,oEAAoE;QACpE,OAAOR,SAASE,IAAI,CAACA,IAAI;IAC7B,EAAE,OAAOG,OAAO;QACZC,QAAQD,KAAK,CAAC,kCAAkCA;QAChD,MAAMA;IACV;AACJ;AAEA,OAAO,eAAeI,OAAON,WAAmB;IAC5C,IAAI;QACA,MAAMP,YAAYK,IAAI,CAClB,yBACA,CAAC,GACD;YACIS,SAAS;gBAAE,mBAAmBP;YAAY;QAC9C;QAGJG,QAAQK,GAAG,CAAC;IAChB,EAAE,OAAON,OAAO;QACZC,QAAQD,KAAK,CAAC,kBAAkBA;QAChC,MAAMA;IACV;AACJ"}
|
package/dist/sdk/cj-sdk.d.ts
CHANGED
@@ -1,4 +1,16 @@
|
|
1
|
-
export
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
export declare function cjSdk({ accessToken }: {
|
2
|
+
accessToken: string;
|
3
|
+
}): {
|
4
|
+
orders: {
|
5
|
+
confirmOrder: (params: any) => Promise<import("../error-types").APIResponse<string>>;
|
6
|
+
createOrder: (params: any) => Promise<import("../error-types").APIResponse<import("./orders/order-types").CreateOrderResponse>>;
|
7
|
+
deleteOrder: (params: any) => Promise<import("../error-types").APIResponse<{
|
8
|
+
data: string;
|
9
|
+
}>>;
|
10
|
+
listOrders: (params: any) => Promise<import("../error-types").APIResponse<import("./orders/order-types").ListOrderResponse>>;
|
11
|
+
queryOrder: (params: any) => Promise<import("../error-types").APIResponse<import("./orders/order-types").QueryOrderResponse>>;
|
12
|
+
};
|
13
|
+
products: {
|
14
|
+
getProductDetails: (params: any) => Promise<import("../error-types").APIResponse<import("./products/product-types").ProductDetails>>;
|
15
|
+
};
|
16
|
+
};
|
package/dist/sdk/cj-sdk.js
CHANGED
@@ -1,6 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
export {
|
4
|
-
|
1
|
+
import { confirmOrder, createOrder, deleteOrder, listOrders, queryOrder } from "./orders/orders";
|
2
|
+
import { getProductDetails } from "./products/products";
|
3
|
+
export function cjSdk({ accessToken }) {
|
4
|
+
return {
|
5
|
+
orders: {
|
6
|
+
confirmOrder: (params)=>confirmOrder({
|
7
|
+
...params,
|
8
|
+
accessToken
|
9
|
+
}),
|
10
|
+
createOrder: (params)=>createOrder({
|
11
|
+
...params,
|
12
|
+
accessToken
|
13
|
+
}),
|
14
|
+
deleteOrder: (params)=>deleteOrder({
|
15
|
+
...params,
|
16
|
+
accessToken
|
17
|
+
}),
|
18
|
+
listOrders: (params)=>listOrders({
|
19
|
+
...params,
|
20
|
+
accessToken
|
21
|
+
}),
|
22
|
+
queryOrder: (params)=>queryOrder({
|
23
|
+
...params,
|
24
|
+
accessToken
|
25
|
+
})
|
26
|
+
},
|
27
|
+
products: {
|
28
|
+
// getProductCategory: (params) =>
|
29
|
+
// getProductCategory({ ...params, accessToken }),
|
30
|
+
getProductDetails: (params)=>getProductDetails({
|
31
|
+
...params,
|
32
|
+
accessToken
|
33
|
+
})
|
34
|
+
}
|
35
|
+
};
|
36
|
+
}
|
5
37
|
|
6
38
|
//# sourceMappingURL=cj-sdk.js.map
|
package/dist/sdk/cj-sdk.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/sdk/cj-sdk.ts"],"sourcesContent":["
|
1
|
+
{"version":3,"sources":["../../src/sdk/cj-sdk.ts"],"sourcesContent":["import {\n confirmOrder,\n createOrder,\n deleteOrder,\n listOrders,\n queryOrder,\n} from \"./orders/orders\";\nimport {\n getProductCategory,\n getProductDetails,\n getProductList,\n} from \"./products/products\";\nimport { getSettings } from \"./settings/settings-api\";\n\nexport function cjSdk({ accessToken }: { accessToken: string }) {\n return {\n orders: {\n confirmOrder: (params: any) =>\n confirmOrder({ ...params, accessToken }),\n createOrder: (params: any) =>\n createOrder({ ...params, accessToken }),\n deleteOrder: (params: any) =>\n deleteOrder({ ...params, accessToken }),\n listOrders: (params: any) => listOrders({ ...params, accessToken }),\n queryOrder: (params: any) => queryOrder({ ...params, accessToken }),\n },\n products: {\n // getProductCategory: (params) =>\n // getProductCategory({ ...params, accessToken }),\n getProductDetails: (params: any) =>\n getProductDetails({ ...params, accessToken }),\n // getProductList: (params) =>\n // getProductList({ ...params, accessToken }),\n },\n // settings: {\n // getSettings: () => getSettings({ accessToken }),\n // },\n };\n}\n"],"names":["confirmOrder","createOrder","deleteOrder","listOrders","queryOrder","getProductDetails","cjSdk","accessToken","orders","params","products"],"mappings":"AAAA,SACIA,YAAY,EACZC,WAAW,EACXC,WAAW,EACXC,UAAU,EACVC,UAAU,QACP,kBAAkB;AACzB,SAEIC,iBAAiB,QAEd,sBAAsB;AAG7B,OAAO,SAASC,MAAM,EAAEC,WAAW,EAA2B;IAC1D,OAAO;QACHC,QAAQ;YACJR,cAAc,CAACS,SACXT,aAAa;oBAAE,GAAGS,MAAM;oBAAEF;gBAAY;YAC1CN,aAAa,CAACQ,SACVR,YAAY;oBAAE,GAAGQ,MAAM;oBAAEF;gBAAY;YACzCL,aAAa,CAACO,SACVP,YAAY;oBAAE,GAAGO,MAAM;oBAAEF;gBAAY;YACzCJ,YAAY,CAACM,SAAgBN,WAAW;oBAAE,GAAGM,MAAM;oBAAEF;gBAAY;YACjEH,YAAY,CAACK,SAAgBL,WAAW;oBAAE,GAAGK,MAAM;oBAAEF;gBAAY;QACrE;QACAG,UAAU;YACN,kCAAkC;YAClC,sDAAsD;YACtDL,mBAAmB,CAACI,SAChBJ,kBAAkB;oBAAE,GAAGI,MAAM;oBAAEF;gBAAY;QAGnD;IAIJ;AACJ"}
|
@@ -3,6 +3,7 @@ import type { CategoryFirstLevel, Product, ProductDetails } from "./product-type
|
|
3
3
|
export declare function getProductCategory(accessToken: string, params: any): Promise<APIResponse<CategoryFirstLevel[]>>;
|
4
4
|
export declare function getProductList(params?: Record<string, any>): Promise<APIResponse<Product[]>>;
|
5
5
|
export declare function getProductDetails(queryParams: {
|
6
|
+
accessToken: string;
|
6
7
|
pid?: string;
|
7
8
|
productSku?: string;
|
8
9
|
variantSku?: string;
|
@@ -63,14 +63,13 @@ export async function getProductList(params = {}) {
|
|
63
63
|
}
|
64
64
|
}
|
65
65
|
export async function getProductDetails(queryParams) {
|
66
|
-
const { pid, productSku, variantSku } = queryParams;
|
66
|
+
const { pid, productSku, variantSku, accessToken } = queryParams;
|
67
67
|
if (!pid && !productSku && !variantSku) {
|
68
68
|
return {
|
69
69
|
error: "One of pid, productSku, or variantSku must be provided."
|
70
70
|
};
|
71
71
|
}
|
72
72
|
try {
|
73
|
-
const accessToken = await getCurrentAccessToken();
|
74
73
|
const response = await cjApiClient.get("https://developers.cjdropshipping.com/api2.0/v1/product/query", {
|
75
74
|
headers: {
|
76
75
|
"CJ-Access-Token": accessToken
|
@@ -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
|
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>(\n \"/product/getCategory\",\n {\n headers: { \"CJ-Access-Token\": accessToken },\n params,\n }\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(\n `Error fetching categories [${error.code}]: ${error.message}`\n );\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(\n `Error fetching product list [${error.code}]: ${error.message}`\n );\n return { error: error.message || \"Failed to fetch product list\" };\n }\n}\n\nexport async function getProductDetails(queryParams: {\n accessToken: string;\n pid?: string;\n productSku?: string;\n variantSku?: string;\n}): Promise<APIResponse<ProductDetails>> {\n const { pid, productSku, variantSku, accessToken } = 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 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:\n response.data.message || \"Failed to fetch product details\",\n };\n }\n\n return { data: response.data.data };\n } catch (error: any) {\n console.error(\n `Error fetching product details [${error.code}]: ${error.message}`\n );\n throw new Error(error.message);\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","Error"],"mappings":"AASA,SAASA,WAAW,QAAQ,mBAAmB;AAC/C,SAASC,qBAAqB,QAAQ,kBAAkB;AAExD,OAAO,eAAeC,mBAClBC,WAAmB,EACnBC,MAAW;IAEX,IAAI;QACA,MAAMC,WAAW,MAAML,YAAYM,GAAG,CAClC,wBACA;YACIC,SAAS;gBAAE,mBAAmBJ;YAAY;YAC1CC;QACJ;QAGJ,MAAMI,OAAOH,SAASG,IAAI,CAACA,IAAI;QAC/B,IAAI,CAACA,MAAM;YACP,OAAO;gBAAEC,OAAO;YAAsB;QAC1C;QAEA,OAAO;YAAED;QAAK;IAClB,EAAE,OAAOC,OAAY;QACjBC,QAAQD,KAAK,CACT,CAAC,2BAA2B,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAEjE,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAA6B;IAClE;AACJ;AAEA,OAAO,eAAeC,eAClBT,SAA8B,CAAC,CAAC;IAEhC,MAAMU,gBAAgB;QAClBC,SAAS;QACTC,UAAU;IACd;IACA,MAAMC,QAAQ;QAAE,GAAGH,aAAa;QAAE,GAAGV,MAAM;IAAC;IAE5C,IAAI;QACA,MAAMD,cAAc,MAAMF;QAC1B,MAAMI,WAAW,MAAML,YAAYM,GAAG,CAClC,gEACA;YACIC,SAAS;gBACL,mBAAmBJ;YACvB;YACAC,QAAQa;QACZ;QAGJ,MAAMT,OAAOH,SAASG,IAAI;QAE1B,IAAI,CAACA,KAAKU,MAAM,EAAE;YACd,OAAO;gBAAET,OAAOD,KAAKI,OAAO,IAAI;YAA+B;QACnE;QAEA,IAAI,CAACJ,KAAKA,IAAI,EAAEW,MAAM;YAClB,OAAO;gBAAEV,OAAO;YAAoB;QACxC;QAEA,OAAO;YAAED,MAAMA,KAAKA,IAAI,CAACW,IAAI;QAAC;IAClC,EAAE,OAAOV,OAAY;QACjBC,QAAQD,KAAK,CACT,CAAC,6BAA6B,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAEnE,OAAO;YAAEH,OAAOA,MAAMG,OAAO,IAAI;QAA+B;IACpE;AACJ;AAEA,OAAO,eAAeQ,kBAAkBC,WAKvC;IACG,MAAM,EAAEC,GAAG,EAAEC,UAAU,EAAEC,UAAU,EAAErB,WAAW,EAAE,GAAGkB;IACrD,IAAI,CAACC,OAAO,CAACC,cAAc,CAACC,YAAY;QACpC,OAAO;YACHf,OAAO;QACX;IACJ;IAEA,IAAI;QACA,MAAMJ,WAAW,MAAML,YAAYM,GAAG,CAKnC,iEAAiE;YAChEC,SAAS;gBACL,mBAAmBJ;YACvB;YACAC,QAAQiB;QACZ;QAEA,IAAI,CAAChB,SAASG,IAAI,CAACU,MAAM,EAAE;YACvB,OAAO;gBACHT,OACIJ,SAASG,IAAI,CAACI,OAAO,IAAI;YACjC;QACJ;QAEA,OAAO;YAAEJ,MAAMH,SAASG,IAAI,CAACA,IAAI;QAAC;IACtC,EAAE,OAAOC,OAAY;QACjBC,QAAQD,KAAK,CACT,CAAC,gCAAgC,EAAEA,MAAME,IAAI,CAAC,GAAG,EAAEF,MAAMG,OAAO,EAAE;QAEtE,MAAM,IAAIa,MAAMhB,MAAMG,OAAO;IACjC;AACJ"}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import { getAccessToken, refreshAccessToken } from "../sdk/auth";
|
2
|
+
const ONE_HOUR_MS = 60 * 60 * 1000;
|
3
|
+
const ONE_DAY_MS = 24 * ONE_HOUR_MS;
|
4
|
+
const TOKEN_EXPIRY = {
|
5
|
+
ACCESS: 15 * ONE_DAY_MS,
|
6
|
+
REFRESH: 180 * ONE_DAY_MS
|
7
|
+
};
|
8
|
+
const isTokenExpiring = async (expiryDate)=>{
|
9
|
+
const now = new Date();
|
10
|
+
const oneHourFromNow = new Date(now.getTime() + ONE_HOUR_MS);
|
11
|
+
const expiryDateTime = new Date(expiryDate);
|
12
|
+
return expiryDateTime.getTime() < oneHourFromNow.getTime();
|
13
|
+
};
|
14
|
+
const updateTokenData = (data, tokenResponse)=>{
|
15
|
+
const now = new Date().getTime();
|
16
|
+
data.accessToken = tokenResponse.accessToken;
|
17
|
+
data.refreshToken = tokenResponse.refreshToken;
|
18
|
+
data.accessTokenExpiry = new Date(now + TOKEN_EXPIRY.ACCESS);
|
19
|
+
data.refreshTokenExpiry = new Date(now + TOKEN_EXPIRY.REFRESH);
|
20
|
+
};
|
21
|
+
const validateCredentials = (apiToken, email)=>{
|
22
|
+
if (!apiToken || !email) {
|
23
|
+
throw new Error("Missing API token or email address");
|
24
|
+
}
|
25
|
+
};
|
26
|
+
const handleRefreshToken = async (data, refreshToken)=>{
|
27
|
+
const refreshedTokens = await refreshAccessToken(refreshToken);
|
28
|
+
updateTokenData(data, refreshedTokens);
|
29
|
+
return refreshedTokens.accessToken;
|
30
|
+
};
|
31
|
+
const getNewTokens = async (data, email, apiToken)=>{
|
32
|
+
const newTokens = await getAccessToken(email, apiToken);
|
33
|
+
updateTokenData(data, newTokens);
|
34
|
+
return newTokens.accessToken;
|
35
|
+
};
|
36
|
+
export const retrieveAccessToken = async (data)=>{
|
37
|
+
const apiToken = data.apiToken || process.env.CJ_API_TOKEN;
|
38
|
+
const email = data.emailAddress || process.env.CJ_EMAIL_ADDRESS;
|
39
|
+
validateCredentials(apiToken, email);
|
40
|
+
const { accessToken, accessTokenExpiry, refreshToken, refreshTokenExpiry } = data;
|
41
|
+
// Check if current access token is valid
|
42
|
+
if (accessToken && accessTokenExpiry && !await isTokenExpiring(accessTokenExpiry)) {
|
43
|
+
return accessToken;
|
44
|
+
}
|
45
|
+
// Try refresh token if available
|
46
|
+
if (refreshToken && refreshTokenExpiry && !await isTokenExpiring(refreshTokenExpiry)) {
|
47
|
+
return handleRefreshToken(data, refreshToken);
|
48
|
+
}
|
49
|
+
// Get new tokens if everything is expired or missing
|
50
|
+
return getNewTokens(data, email, apiToken);
|
51
|
+
};
|
52
|
+
|
53
|
+
//# sourceMappingURL=access-token.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../src/service/access-token.ts"],"sourcesContent":["import { CjData } from \"../cj-settings\";\nimport { getAccessToken, refreshAccessToken } from \"../sdk/auth\";\n\ninterface TokenResponse {\n accessToken: string;\n refreshToken: string;\n}\n\nconst ONE_HOUR_MS = 60 * 60 * 1000;\nconst ONE_DAY_MS = 24 * ONE_HOUR_MS;\nconst TOKEN_EXPIRY = {\n ACCESS: 15 * ONE_DAY_MS, // 15 days\n REFRESH: 180 * ONE_DAY_MS, // 180 days\n};\n\nconst isTokenExpiring = async (expiryDate: string | Date): Promise<boolean> => {\n const now = new Date();\n const oneHourFromNow = new Date(now.getTime() + ONE_HOUR_MS);\n const expiryDateTime = new Date(expiryDate);\n return expiryDateTime.getTime() < oneHourFromNow.getTime();\n};\n\nconst updateTokenData = (\n data: Partial<CjData>,\n tokenResponse: TokenResponse\n): void => {\n const now = new Date().getTime();\n\n data.accessToken = tokenResponse.accessToken;\n data.refreshToken = tokenResponse.refreshToken;\n data.accessTokenExpiry = new Date(now + TOKEN_EXPIRY.ACCESS);\n data.refreshTokenExpiry = new Date(now + TOKEN_EXPIRY.REFRESH);\n};\n\nconst validateCredentials = (\n apiToken: string | undefined,\n email: string | undefined\n): void => {\n if (!apiToken || !email) {\n throw new Error(\"Missing API token or email address\");\n }\n};\n\nconst handleRefreshToken = async (\n data: Partial<CjData>,\n refreshToken: string\n): Promise<string> => {\n const refreshedTokens = await refreshAccessToken(refreshToken);\n updateTokenData(data, refreshedTokens);\n return refreshedTokens.accessToken;\n};\n\nconst getNewTokens = async (\n data: Partial<CjData>,\n email: string,\n apiToken: string\n): Promise<string> => {\n const newTokens = await getAccessToken(email, apiToken);\n updateTokenData(data, newTokens);\n return newTokens.accessToken;\n};\n\nexport const retrieveAccessToken = async (\n data: Partial<CjData>\n): Promise<string> => {\n const apiToken = data.apiToken || process.env.CJ_API_TOKEN;\n const email = data.emailAddress || process.env.CJ_EMAIL_ADDRESS;\n\n validateCredentials(apiToken, email);\n\n const { accessToken, accessTokenExpiry, refreshToken, refreshTokenExpiry } =\n data;\n\n // Check if current access token is valid\n if (\n accessToken &&\n accessTokenExpiry &&\n !(await isTokenExpiring(accessTokenExpiry))\n ) {\n return accessToken;\n }\n\n // Try refresh token if available\n if (\n refreshToken &&\n refreshTokenExpiry &&\n !(await isTokenExpiring(refreshTokenExpiry))\n ) {\n return handleRefreshToken(data, refreshToken);\n }\n\n // Get new tokens if everything is expired or missing\n return getNewTokens(data, email!, apiToken!);\n};\n"],"names":["getAccessToken","refreshAccessToken","ONE_HOUR_MS","ONE_DAY_MS","TOKEN_EXPIRY","ACCESS","REFRESH","isTokenExpiring","expiryDate","now","Date","oneHourFromNow","getTime","expiryDateTime","updateTokenData","data","tokenResponse","accessToken","refreshToken","accessTokenExpiry","refreshTokenExpiry","validateCredentials","apiToken","email","Error","handleRefreshToken","refreshedTokens","getNewTokens","newTokens","retrieveAccessToken","process","env","CJ_API_TOKEN","emailAddress","CJ_EMAIL_ADDRESS"],"mappings":"AACA,SAASA,cAAc,EAAEC,kBAAkB,QAAQ,cAAc;AAOjE,MAAMC,cAAc,KAAK,KAAK;AAC9B,MAAMC,aAAa,KAAKD;AACxB,MAAME,eAAe;IACjBC,QAAQ,KAAKF;IACbG,SAAS,MAAMH;AACnB;AAEA,MAAMI,kBAAkB,OAAOC;IAC3B,MAAMC,MAAM,IAAIC;IAChB,MAAMC,iBAAiB,IAAID,KAAKD,IAAIG,OAAO,KAAKV;IAChD,MAAMW,iBAAiB,IAAIH,KAAKF;IAChC,OAAOK,eAAeD,OAAO,KAAKD,eAAeC,OAAO;AAC5D;AAEA,MAAME,kBAAkB,CACpBC,MACAC;IAEA,MAAMP,MAAM,IAAIC,OAAOE,OAAO;IAE9BG,KAAKE,WAAW,GAAGD,cAAcC,WAAW;IAC5CF,KAAKG,YAAY,GAAGF,cAAcE,YAAY;IAC9CH,KAAKI,iBAAiB,GAAG,IAAIT,KAAKD,MAAML,aAAaC,MAAM;IAC3DU,KAAKK,kBAAkB,GAAG,IAAIV,KAAKD,MAAML,aAAaE,OAAO;AACjE;AAEA,MAAMe,sBAAsB,CACxBC,UACAC;IAEA,IAAI,CAACD,YAAY,CAACC,OAAO;QACrB,MAAM,IAAIC,MAAM;IACpB;AACJ;AAEA,MAAMC,qBAAqB,OACvBV,MACAG;IAEA,MAAMQ,kBAAkB,MAAMzB,mBAAmBiB;IACjDJ,gBAAgBC,MAAMW;IACtB,OAAOA,gBAAgBT,WAAW;AACtC;AAEA,MAAMU,eAAe,OACjBZ,MACAQ,OACAD;IAEA,MAAMM,YAAY,MAAM5B,eAAeuB,OAAOD;IAC9CR,gBAAgBC,MAAMa;IACtB,OAAOA,UAAUX,WAAW;AAChC;AAEA,OAAO,MAAMY,sBAAsB,OAC/Bd;IAEA,MAAMO,WAAWP,KAAKO,QAAQ,IAAIQ,QAAQC,GAAG,CAACC,YAAY;IAC1D,MAAMT,QAAQR,KAAKkB,YAAY,IAAIH,QAAQC,GAAG,CAACG,gBAAgB;IAE/Db,oBAAoBC,UAAUC;IAE9B,MAAM,EAAEN,WAAW,EAAEE,iBAAiB,EAAED,YAAY,EAAEE,kBAAkB,EAAE,GACtEL;IAEJ,yCAAyC;IACzC,IACIE,eACAE,qBACA,CAAE,MAAMZ,gBAAgBY,oBAC1B;QACE,OAAOF;IACX;IAEA,iCAAiC;IACjC,IACIC,gBACAE,sBACA,CAAE,MAAMb,gBAAgBa,qBAC1B;QACE,OAAOK,mBAAmBV,MAAMG;IACpC;IAEA,qDAAqD;IACrD,OAAOS,aAAaZ,MAAMQ,OAAQD;AACtC,EAAE"}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import { cjSdk } from "../sdk/cj-sdk";
|
2
2
|
export const createOrderHook = async ({ doc, req })=>{
|
3
3
|
if (doc.orderStatus !== "processing") {
|
4
4
|
return;
|
@@ -23,7 +23,10 @@ export const createOrderHook = async ({ doc, req })=>{
|
|
23
23
|
layer: []
|
24
24
|
}
|
25
25
|
] : [];
|
26
|
-
const
|
26
|
+
const sdk = cjSdk({
|
27
|
+
accessToken: cjConfig?.accessToken
|
28
|
+
});
|
29
|
+
const result = await sdk.orders.createOrder({
|
27
30
|
consigneeID: doc.billingAddress?.name || "",
|
28
31
|
email: doc.billingAddress?.email || "",
|
29
32
|
fromCountryCode: "CN",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/service/create-order.hook.ts"],"sourcesContent":["import type { BasePayload, CollectionAfterChangeHook, Document } from \"payload\";\
|
1
|
+
{"version":3,"sources":["../../src/service/create-order.hook.ts"],"sourcesContent":["import type { BasePayload, CollectionAfterChangeHook, Document } from \"payload\";\nimport { 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 ({\n doc,\n req,\n}) => {\n if (doc.orderStatus !== \"processing\") {\n return;\n }\n const payload: BasePayload = req.payload;\n const cjSettings = await payload.find({\n collection: \"cj-settings\" as any,\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 sdk = cjSdk({ accessToken: cjConfig?.accessToken });\n const result = await sdk.orders.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\" as any,\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","sdk","accessToken","result","orders","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":"AACA,SAASA,KAAK,QAAQ,gBAAgB;AAatC,OAAO,MAAMC,kBAAqD,OAAO,EACrEC,GAAG,EACHC,GAAG,EACN;IACG,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,MAAMtB,MAAM;QAAEuB,aAAaV,UAAUU;IAAY;IACvD,MAAMC,SAAS,MAAMF,IAAIG,MAAM,CAACC,WAAW,CAAC;QACxCC,aAAazB,IAAI0B,cAAc,EAAEC,QAAQ;QACzCC,OAAO5B,IAAI0B,cAAc,EAAEE,SAAS;QACpCC,iBAAiB;QACjBC,aAAa9B,IAAI+B,eAAe,EAAEC,SAASC,SAAS;QACpDC,UAAU;QACVC,cAAc;QACdC,aAAapC,IAAIqC,OAAO;QACxBC,SAAS;QACTC,UAAUvC,IAAIwC,KAAK,CAACC,GAAG,CAAC,CAACC,OAAU,CAAA;gBAC/BC,UAAUD,KAAKC,QAAQ;gBACvBC,KAAKF,KAAKG,OAAO,CAACC,SAAS;YAC/B,CAAA;QACAjC;QACAkC,QAAQ;QACRhB,iBAAiB/B,IAAI+B,eAAe,EAAEC,SAASgB,SAAS;QACxDC,kBAAkBjD,IAAI+B,eAAe,EAAEC,SAASC,SAAS;QACzDiB,cAAclD,IAAI+B,eAAe,EAAEC,SAASmB,QAAQ;QACpDC,iBAAiBpD,IAAI+B,eAAe,EAAEC,SAASqB,WAAW;QAC1DC,qBAAqBtD,IAAI+B,eAAe,EAAEC,SAASqB,WAAW;QAC9DE,gBAAgBvD,IAAI+B,eAAe,EAAEC,SAASmB,QAAQ;QACtDK,sBAAsBxD,IAAI+B,eAAe,EAAEJ,QAAQ;QACnD8B,eAAezD,IAAI+B,eAAe,EAAE2B,SAAS;QAC7CC,kBAAkB3D,IAAI+B,eAAe,EAAEC,SAAS4B,SAAS;QACzDC,aAAa7D,IAAI+B,eAAe,EAAEC,SAAS8B,eAAe;QAC1DC,OAAO;IACX;IAEA,MAAMC,cAAc,MAAM7D,QAAQ8D,MAAM,CAAC;QACrC3D,YAAY;QACZ4D,MAAM;YACFhE,aAAa;QACjB;QACAK,OAAO;YACH4D,IAAI;gBACA1D,QAAQT,IAAIqC,OAAO;YACvB;QACJ;IACJ;IAEA,OAAO;QACH+B,UAAU9C;QACV0C;IACJ;AACJ,EAAE"}
|
@@ -1,4 +1,9 @@
|
|
1
1
|
import type { BasePayload } from "payload";
|
2
2
|
import type { ProductDetails } from "../sdk/products/product-types";
|
3
|
-
|
4
|
-
export declare const syncProducts: (productIds
|
3
|
+
import { CjData } from "../cj-settings";
|
4
|
+
export declare const syncProducts: ({ productIds, payload, shopId, data, }: {
|
5
|
+
productIds: string[];
|
6
|
+
payload: BasePayload;
|
7
|
+
shopId?: string;
|
8
|
+
data: Partial<CjData>;
|
9
|
+
}) => Promise<ProductDetails[]>;
|
@@ -1,103 +1,90 @@
|
|
1
1
|
import { convertHTMLToLexical, editorConfigFactory } from "@payloadcms/richtext-lexical";
|
2
2
|
import decimal from "decimal.js";
|
3
3
|
import { JSDOM } from "jsdom";
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import fs from "fs";
|
7
|
-
import { promisify } from "util";
|
8
|
-
import { pipeline } from "stream";
|
9
|
-
import { writeFile } from "fs/promises";
|
10
|
-
import { fileURLToPath } from "url";
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
12
|
-
const __dirname = dirname(__filename);
|
13
|
-
const streamPipeline = promisify(pipeline);
|
4
|
+
import { cjSdk } from "../sdk/cj-sdk";
|
5
|
+
import { retrieveAccessToken } from "./access-token";
|
14
6
|
const delay = (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
|
15
|
-
const
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}
|
31
|
-
};
|
32
|
-
async function uploadImageToPayload(src, payload) {
|
33
|
-
const tempFilePath = path.join(__dirname, "temp-image.jpg");
|
34
|
-
try {
|
35
|
-
// Fetch the image
|
36
|
-
const response = await fetch(src);
|
37
|
-
if (!response.ok) throw new Error(`Failed to fetch image: ${response.statusText}`);
|
38
|
-
// Stream the response body to a temporary file
|
39
|
-
await download(src, tempFilePath);
|
40
|
-
// Upload the image using Payload's Local API
|
41
|
-
const uploadedImage = await payload.create({
|
7
|
+
const upsertImage = async ({ payload, imageUrl, filename, alt, shopId })=>{
|
8
|
+
const imageData = await payload.find({
|
9
|
+
collection: "media",
|
10
|
+
where: {
|
11
|
+
filename: {
|
12
|
+
equals: filename
|
13
|
+
},
|
14
|
+
shop: {
|
15
|
+
equals: shopId
|
16
|
+
}
|
17
|
+
},
|
18
|
+
limit: 1
|
19
|
+
});
|
20
|
+
if (imageData.totalDocs === 0) {
|
21
|
+
return payload.create({
|
42
22
|
collection: "media",
|
43
23
|
data: {
|
44
|
-
alt
|
45
|
-
|
46
|
-
|
24
|
+
alt,
|
25
|
+
filename,
|
26
|
+
thumbnailURL: imageUrl,
|
27
|
+
url: imageUrl,
|
28
|
+
shop: shopId
|
29
|
+
}
|
47
30
|
});
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
31
|
+
}
|
32
|
+
return imageData.docs[0];
|
33
|
+
};
|
34
|
+
async function mapMockProductToSchema({ product, payload, shopId }) {
|
35
|
+
const variants = [];
|
36
|
+
for (const variant of product.variants || []){
|
37
|
+
const filename = variant?.variantImage?.split("/").pop();
|
38
|
+
if (!filename || !variant.variantImage) {
|
39
|
+
continue;
|
40
|
+
}
|
41
|
+
const alt = filename.split(".")[0];
|
42
|
+
const imageUrl = variant.variantImage;
|
43
|
+
const imageData = await upsertImage({
|
44
|
+
payload,
|
45
|
+
imageUrl,
|
46
|
+
filename,
|
47
|
+
alt,
|
48
|
+
shopId
|
49
|
+
});
|
50
|
+
const imageId = imageData.id;
|
51
|
+
variants.push({
|
52
|
+
gallery: [
|
53
|
+
imageId
|
54
|
+
],
|
55
|
+
options: variant.variantKey?.split("-").map((key, index)=>({
|
56
|
+
option: index === 0 ? "Color" : "Size",
|
57
|
+
value: key
|
58
|
+
})),
|
59
|
+
price: Number(new decimal(variant.variantSellPrice || 0).toNumber().toFixed(2)),
|
60
|
+
vid: variant.vid
|
52
61
|
});
|
53
|
-
return {
|
54
|
-
id: uploadedImage.id,
|
55
|
-
alt: uploadedImage.alt || "",
|
56
|
-
prefix: "media",
|
57
|
-
updatedAt: uploadedImage.updatedAt,
|
58
|
-
createdAt: uploadedImage.createdAt,
|
59
|
-
url: uploadedImage.url,
|
60
|
-
thumbnailURL: uploadedImage.thumbnailURL || null,
|
61
|
-
filename: uploadedImage.filename,
|
62
|
-
mimeType: uploadedImage.mimeType,
|
63
|
-
filesize: uploadedImage.filesize,
|
64
|
-
width: uploadedImage.width,
|
65
|
-
height: uploadedImage.height,
|
66
|
-
focalX: 50,
|
67
|
-
focalY: 50
|
68
|
-
};
|
69
|
-
} catch (error) {
|
70
|
-
console.error("Error uploading image:", error);
|
71
62
|
}
|
72
|
-
|
73
|
-
function mapMockProductToSchema(product, editorConfig, rate, payload) {
|
63
|
+
const cleanHtml = product.description?.replace(/<img[^>]*>/g, "");
|
74
64
|
return {
|
75
65
|
description: convertHTMLToLexical({
|
76
|
-
editorConfig
|
77
|
-
|
66
|
+
editorConfig: await editorConfigFactory.default({
|
67
|
+
config: payload.config
|
68
|
+
}),
|
69
|
+
html: cleanHtml || "<p></p>",
|
78
70
|
JSDOM
|
79
71
|
}),
|
80
72
|
source: "cj",
|
81
73
|
pid: product.pid,
|
82
74
|
title: product.productNameEn,
|
83
|
-
variants
|
84
|
-
imageUrl: variant.variantImage,
|
85
|
-
options: variant.variantKey?.split("-").map((key, index)=>({
|
86
|
-
option: index === 0 ? "Color" : "Size",
|
87
|
-
value: key
|
88
|
-
})),
|
89
|
-
price: new decimal(variant.variantSellPrice || 0).mul(rate).toNumber().toFixed(2),
|
90
|
-
vid: variant.vid
|
91
|
-
}))
|
75
|
+
variants
|
92
76
|
};
|
93
77
|
}
|
94
|
-
const findProductById = async (productId)=>{
|
95
|
-
const
|
78
|
+
const findProductById = async (productId, accessToken)=>{
|
79
|
+
const sdk = cjSdk({
|
80
|
+
accessToken
|
81
|
+
});
|
82
|
+
const result = await sdk.products.getProductDetails({
|
96
83
|
pid: productId
|
97
84
|
});
|
98
85
|
return result.data;
|
99
86
|
};
|
100
|
-
const createOrUpdateProduct = async (product, payload, shopId)=>{
|
87
|
+
const createOrUpdateProduct = async ({ product, payload, shopId })=>{
|
101
88
|
const { totalDocs } = await payload.count({
|
102
89
|
collection: "products",
|
103
90
|
where: {
|
@@ -116,34 +103,29 @@ const createOrUpdateProduct = async (product, payload, shopId)=>{
|
|
116
103
|
});
|
117
104
|
}
|
118
105
|
};
|
119
|
-
export const
|
120
|
-
const
|
121
|
-
const
|
122
|
-
return data;
|
123
|
-
};
|
124
|
-
export const syncProducts = async (productIds, payload, shopId)=>{
|
125
|
-
const exchangeRates = await fetchExchangeRates();
|
126
|
-
const storeSettings = await payload.findGlobal({
|
127
|
-
slug: "store-settings"
|
128
|
-
});
|
129
|
-
const rate = exchangeRates.rates[storeSettings.currency || "USD"];
|
130
|
-
const editorConfig = await editorConfigFactory.default({
|
131
|
-
config: payload.config
|
132
|
-
});
|
133
|
-
const products = [];
|
106
|
+
export const syncProducts = async ({ productIds, payload, shopId, data })=>{
|
107
|
+
const accessToken = await retrieveAccessToken(data);
|
108
|
+
const fetchedProducts = [];
|
134
109
|
for (const productId of productIds){
|
135
|
-
const product = await findProductById(productId);
|
136
|
-
if (
|
137
|
-
|
110
|
+
const product = await findProductById(productId, accessToken);
|
111
|
+
if (product) {
|
112
|
+
fetchedProducts.push(product);
|
138
113
|
}
|
139
|
-
|
140
|
-
await delay(1010);
|
114
|
+
await delay(1010); // throttle CJ API requests
|
141
115
|
}
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
116
|
+
// Wait for all async mapping to resolve
|
117
|
+
const mappedProducts = await Promise.all(fetchedProducts.map((product)=>mapMockProductToSchema({
|
118
|
+
product,
|
119
|
+
payload,
|
120
|
+
shopId
|
121
|
+
})));
|
122
|
+
// Create or update each mapped product
|
123
|
+
await Promise.all(mappedProducts.map((product)=>createOrUpdateProduct({
|
124
|
+
product,
|
125
|
+
payload,
|
126
|
+
shopId
|
127
|
+
})));
|
128
|
+
return fetchedProducts;
|
147
129
|
};
|
148
130
|
|
149
131
|
//# sourceMappingURL=sync-products.js.map
|
@@ -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 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":"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"}
|
1
|
+
{"version":3,"sources":["../../src/service/sync-products.ts"],"sourcesContent":["import type {\n DefaultNodeTypes,\n TypedEditorState,\n} from \"@payloadcms/richtext-lexical\";\nimport type { BasePayload } from \"payload\";\n\nimport {\n convertHTMLToLexical,\n editorConfigFactory,\n} from \"@payloadcms/richtext-lexical\";\nimport decimal from \"decimal.js\";\nimport { JSDOM } from \"jsdom\";\n\nimport type { ProductDetails } from \"../sdk/products/product-types\";\n\nimport { cjSdk } from \"../sdk/cj-sdk\";\nimport { CjData } from \"../cj-settings\";\nimport { retrieveAccessToken } from \"./access-token\";\n\ninterface Product {\n description: TypedEditorState<DefaultNodeTypes>;\n pid: string;\n title: string;\n source: \"manual\" | \"cj\";\n variants?: Array<{\n gallery?: (string | number)[];\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 upsertImage = async ({\n payload,\n imageUrl,\n filename,\n alt,\n shopId,\n}: {\n payload: BasePayload;\n imageUrl: string;\n filename: string;\n alt: string;\n shopId?: string;\n}) => {\n const imageData = await payload.find({\n collection: \"media\",\n where: {\n filename: {\n equals: filename,\n },\n shop: {\n equals: shopId,\n },\n },\n limit: 1,\n });\n if (imageData.totalDocs === 0) {\n return payload.create({\n collection: \"media\",\n data: {\n alt,\n filename,\n thumbnailURL: imageUrl,\n url: imageUrl,\n shop: shopId,\n },\n });\n }\n return imageData.docs[0];\n};\n\nasync function mapMockProductToSchema({\n product,\n payload,\n shopId,\n}: {\n product: ProductDetails;\n payload: BasePayload;\n shopId?: string;\n}) {\n const variants: Product[\"variants\"] = [];\n\n for (const variant of product.variants || []) {\n const filename = variant?.variantImage?.split(\"/\").pop();\n if (!filename || !variant.variantImage) {\n continue;\n }\n const alt = filename.split(\".\")[0];\n const imageUrl = variant.variantImage;\n const imageData = await upsertImage({\n payload,\n imageUrl,\n filename,\n alt,\n shopId,\n });\n\n const imageId = imageData.id;\n\n variants.push({\n gallery: [imageId],\n options: variant.variantKey?.split(\"-\").map((key, index) => ({\n option: index === 0 ? \"Color\" : \"Size\",\n value: key,\n })),\n price: Number(\n new decimal(variant.variantSellPrice || 0).toNumber().toFixed(2)\n ),\n vid: variant.vid,\n });\n }\n\n const cleanHtml = product.description?.replace(/<img[^>]*>/g, \"\");\n\n return {\n description: convertHTMLToLexical({\n editorConfig: await editorConfigFactory.default({\n config: payload.config, // Your Payload Config\n }),\n html: cleanHtml || \"<p></p>\",\n JSDOM, // Pass in the JSDOM import; it's not bundled to keep package size small\n }),\n source: \"cj\" as any,\n pid: product.pid,\n title: product.productNameEn,\n variants,\n };\n}\n\nconst findProductById = async (productId: string, accessToken: string) => {\n const sdk = cjSdk({ accessToken });\n const result = await sdk.products.getProductDetails({\n pid: productId,\n });\n\n return result.data;\n};\n\nconst createOrUpdateProduct = async ({\n product,\n payload,\n shopId,\n}: {\n product: Omit<Product, \"createdAt\" | \"id\" | \"updatedAt\">;\n payload: BasePayload;\n shopId?: string;\n}) => {\n const { totalDocs } = await payload.count({\n collection: \"products\" as any,\n where: {\n pid: {\n equals: product.pid,\n },\n },\n });\n\n if (totalDocs === 0) {\n return payload.create({\n collection: \"products\" as any,\n data: {\n ...product,\n shop: shopId,\n } as any,\n });\n }\n};\n\nexport const syncProducts = async ({\n productIds,\n payload,\n shopId,\n data,\n}: {\n productIds: string[];\n payload: BasePayload;\n shopId?: string;\n data: Partial<CjData>;\n}) => {\n const accessToken = await retrieveAccessToken(data);\n\n const fetchedProducts: ProductDetails[] = [];\n\n for (const productId of productIds) {\n const product = await findProductById(productId, accessToken);\n if (product) {\n fetchedProducts.push(product);\n }\n await delay(1010); // throttle CJ API requests\n }\n\n // Wait for all async mapping to resolve\n const mappedProducts: Product[] = await Promise.all(\n fetchedProducts.map((product) =>\n mapMockProductToSchema({ product, payload, shopId })\n )\n );\n\n // Create or update each mapped product\n await Promise.all(\n mappedProducts.map((product) =>\n createOrUpdateProduct({ product, payload, shopId })\n )\n );\n\n return fetchedProducts;\n};\n"],"names":["convertHTMLToLexical","editorConfigFactory","decimal","JSDOM","cjSdk","retrieveAccessToken","delay","ms","Promise","resolve","setTimeout","upsertImage","payload","imageUrl","filename","alt","shopId","imageData","find","collection","where","equals","shop","limit","totalDocs","create","data","thumbnailURL","url","docs","mapMockProductToSchema","product","variants","variant","variantImage","split","pop","imageId","id","push","gallery","options","variantKey","map","key","index","option","value","price","Number","variantSellPrice","toNumber","toFixed","vid","cleanHtml","description","replace","editorConfig","default","config","html","source","pid","title","productNameEn","findProductById","productId","accessToken","sdk","result","products","getProductDetails","createOrUpdateProduct","count","syncProducts","productIds","fetchedProducts","mappedProducts","all"],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@shopnex/cj-plugin",
|
3
|
-
"version": "1.0
|
3
|
+
"version": "1.2.0",
|
4
4
|
"description": "A blank template to get started with Payload 3.0",
|
5
5
|
"type": "module",
|
6
6
|
"exports": {
|
@@ -30,8 +30,10 @@
|
|
30
30
|
"@lexical/headless": "0.28.0",
|
31
31
|
"@lexical/html": "0.28.0",
|
32
32
|
"axios": "^1.8.3",
|
33
|
+
"decimal.js": "^10.5.0",
|
33
34
|
"jsdom": "^26.0.0",
|
34
|
-
"lexical": "0.28.0"
|
35
|
+
"lexical": "0.28.0",
|
36
|
+
"@shopnex/utils": "1.0.4"
|
35
37
|
},
|
36
38
|
"devDependencies": {
|
37
39
|
"@types/jsdom": "^21.1.7"
|
package/dist/auth.js.map
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"sources":["../src/auth.ts"],"sourcesContent":["import type { AccessTokenResponse } from './types'\n\nimport { cjApiClient } from './api-client'\n\ninterface RefreshTokenResponse {\n code: number\n data: {\n accessToken: string\n accessTokenExpiryDate: string\n createDate: string\n refreshToken: string\n refreshTokenExpiryDate: string\n }\n message: string\n requestId: string\n result: boolean\n}\n\ninterface LogoutResponse {\n code: number\n data: boolean\n message: string\n requestId: string\n result: boolean\n}\n\nexport async function getAccessToken(email: string, password: string) {\n try {\n const response = await cjApiClient.post<AccessTokenResponse>('authentication/getAccessToken', {\n email,\n password,\n })\n\n if (!response.data.data?.accessToken) {\n throw new Error('Failed to fetch access token')\n }\n // TODO: add logger\n // console.log('Access Token:', response.data.data?.accessToken)\n return response.data.data\n } catch (error) {\n console.error('Error fetching access token:', error)\n throw error // Rethrow for caller to handle\n }\n}\n\nexport async function refreshAccessToken(refreshToken: string) {\n try {\n const response = await cjApiClient.post<RefreshTokenResponse>(\n 'authentication/refreshAccessToken',\n {\n refreshToken,\n },\n )\n\n // TODO: add logger\n // console.info('New Access Token:', response.data.data.accessToken)\n return response.data.data\n } catch (error) {\n console.error('Error refreshing access token:', error)\n throw error\n }\n}\n\nexport async function logout(accessToken: string) {\n try {\n await cjApiClient.post<LogoutResponse>(\n 'authentication/logout',\n {},\n {\n headers: { 'CJ-Access-Token': accessToken },\n },\n )\n\n console.log('Successfully logged out')\n } catch (error) {\n console.error('Logout failed:', error)\n throw error\n }\n}\n"],"names":["cjApiClient","getAccessToken","email","password","response","post","data","accessToken","Error","error","console","refreshAccessToken","refreshToken","logout","headers","log"],"mappings":"AAEA,SAASA,WAAW,QAAQ,eAAc;AAwB1C,OAAO,eAAeC,eAAeC,KAAa,EAAEC,QAAgB;IAClE,IAAI;QACF,MAAMC,WAAW,MAAMJ,YAAYK,IAAI,CAAsB,iCAAiC;YAC5FH;YACAC;QACF;QAEA,IAAI,CAACC,SAASE,IAAI,CAACA,IAAI,EAAEC,aAAa;YACpC,MAAM,IAAIC,MAAM;QAClB;QACA,mBAAmB;QACnB,gEAAgE;QAChE,OAAOJ,SAASE,IAAI,CAACA,IAAI;IAC3B,EAAE,OAAOG,OAAO;QACdC,QAAQD,KAAK,CAAC,gCAAgCA;QAC9C,MAAMA,MAAM,+BAA+B;;IAC7C;AACF;AAEA,OAAO,eAAeE,mBAAmBC,YAAoB;IAC3D,IAAI;QACF,MAAMR,WAAW,MAAMJ,YAAYK,IAAI,CACrC,qCACA;YACEO;QACF;QAGF,mBAAmB;QACnB,oEAAoE;QACpE,OAAOR,SAASE,IAAI,CAACA,IAAI;IAC3B,EAAE,OAAOG,OAAO;QACdC,QAAQD,KAAK,CAAC,kCAAkCA;QAChD,MAAMA;IACR;AACF;AAEA,OAAO,eAAeI,OAAON,WAAmB;IAC9C,IAAI;QACF,MAAMP,YAAYK,IAAI,CACpB,yBACA,CAAC,GACD;YACES,SAAS;gBAAE,mBAAmBP;YAAY;QAC5C;QAGFG,QAAQK,GAAG,CAAC;IACd,EAAE,OAAON,OAAO;QACdC,QAAQD,KAAK,CAAC,kBAAkBA;QAChC,MAAMA;IACR;AACF"}
|
File without changes
|