otapi-client 1.0.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.
@@ -0,0 +1,160 @@
1
+ interface OTClientConfig {
2
+ language?: string;
3
+ secret?: string;
4
+ baseUrl?: string;
5
+ debug?: boolean;
6
+ }
7
+ interface OTApiResponse<T = unknown> {
8
+ ErrorCode: string;
9
+ ErrorDescription?: string;
10
+ Result?: T;
11
+ }
12
+ interface AuthenticateParams {
13
+ sessionId?: string;
14
+ userLogin: string;
15
+ userPassword: string;
16
+ rememberMe?: boolean;
17
+ }
18
+ interface AuthenticateInstanceOperatorParams {
19
+ userLogin: string;
20
+ userPassword: string;
21
+ }
22
+ interface AuthenticateAsUserParams {
23
+ sessionId: string;
24
+ userLogin: string;
25
+ }
26
+ interface RegisterUserParams {
27
+ sessionId?: string;
28
+ userParameters: string;
29
+ }
30
+ type ItemBlockList = "DeliveryCosts" | "Promotions" | "Vendor" | "RootPath" | "ProviderReviews" | "MostPopularVendorItems16" | "RecommendedItems" | "Description" | "OriginalDescription";
31
+ interface BatchGetItemFullInfoParams {
32
+ sessionId?: string;
33
+ itemId: string;
34
+ itemParameters?: string;
35
+ blockList?: ItemBlockList[];
36
+ }
37
+ type SearchBlockList = "SubCategories" | "SearchProperties" | "RootPath" | "Vendor" | "Brand" | "Category" | "HintCategories" | "AvailableSearchMethods";
38
+ interface SearchConfigurator {
39
+ Pid: string;
40
+ Vid: string;
41
+ }
42
+ interface SearchFeature {
43
+ Name: string;
44
+ value: boolean;
45
+ }
46
+ interface SearchItemsParameters {
47
+ Provider?: string;
48
+ SearchMethod?: string;
49
+ CategoryId?: string;
50
+ VendorName?: string;
51
+ VendorId?: string;
52
+ VendorAreaId?: string;
53
+ ItemTitle?: string;
54
+ LanguageOfQuery?: string;
55
+ MinPrice?: number;
56
+ MaxPrice?: number;
57
+ EnableDirectSearch?: boolean;
58
+ CurrencyCode?: string;
59
+ MinVolume?: number;
60
+ MaxVolume?: number;
61
+ MinVendorRating?: number;
62
+ MaxVendorRating?: number;
63
+ BrandId?: string;
64
+ Configurators?: SearchConfigurator[];
65
+ OrderBy?: string;
66
+ OutputMode?: string;
67
+ CategoryMode?: string;
68
+ IsTmall?: boolean;
69
+ StuffStatus?: string;
70
+ Features?: SearchFeature[];
71
+ UseOptimalFrameSize?: boolean;
72
+ MinFirstLot?: number;
73
+ MaxFirstLot?: number;
74
+ MinUpdatedTime?: string;
75
+ MaxUpdatedTime?: string;
76
+ MinCreatedTime?: string;
77
+ MaxCreatedTime?: string;
78
+ Module?: string;
79
+ ImageUrl?: string;
80
+ ImageFileId?: string;
81
+ ImageItemId?: string;
82
+ }
83
+ interface OrderItem {
84
+ Id: string;
85
+ ConfigurationId?: string;
86
+ Quantity: number;
87
+ Weight?: number;
88
+ Comment?: string;
89
+ PromotionId?: string;
90
+ PriceType?: string;
91
+ }
92
+ interface OrderAddData {
93
+ DeliveryModeId?: string;
94
+ Comment?: string;
95
+ UserProfileId?: string;
96
+ Items: OrderItem[];
97
+ }
98
+ interface UserProfileCreateData {
99
+ FirstName?: string;
100
+ LastName?: string;
101
+ MiddleName?: string;
102
+ CountryCode?: string;
103
+ Region?: string;
104
+ City?: string;
105
+ CityCode?: string;
106
+ Address?: string;
107
+ Phone?: string;
108
+ PostalCode?: string;
109
+ ExternalDeliveryId?: string;
110
+ PickupPointCode?: string;
111
+ PassportNumber?: string;
112
+ ResetPassportIssueDate?: boolean;
113
+ PassportIssueDate?: string;
114
+ RegistrationAddress?: string;
115
+ INN?: string;
116
+ EnableValidation?: boolean;
117
+ }
118
+ interface CreateUserProfileParams {
119
+ sessionId: string;
120
+ createData: UserProfileCreateData;
121
+ }
122
+ interface AddOrderParams {
123
+ sessionId?: string;
124
+ xmlAddData: OrderAddData;
125
+ }
126
+ interface BatchSearchItemsFrameParams {
127
+ sessionId?: string;
128
+ xmlParameters: SearchItemsParameters;
129
+ framePosition: number;
130
+ frameSize: number;
131
+ blockList?: SearchBlockList[];
132
+ }
133
+
134
+ declare class OTClient {
135
+ private readonly instanceKey;
136
+ private readonly language;
137
+ private readonly secret?;
138
+ private readonly baseUrl;
139
+ private readonly debug;
140
+ constructor(instanceKey: string, config?: OTClientConfig);
141
+ private sign;
142
+ private request;
143
+ GetAnonymousSession(): Promise<OTApiResponse>;
144
+ Authenticate(params: AuthenticateParams): Promise<OTApiResponse>;
145
+ AuthenticateInstanceOperator(params: AuthenticateInstanceOperatorParams): Promise<OTApiResponse>;
146
+ AuthenticateAsUser(params: AuthenticateAsUserParams): Promise<OTApiResponse>;
147
+ RegisterUser(params: RegisterUserParams): Promise<OTApiResponse>;
148
+ BatchGetItemFullInfo(params: BatchGetItemFullInfoParams): Promise<OTApiResponse>;
149
+ BatchSearchItemsFrame(params: BatchSearchItemsFrameParams): Promise<OTApiResponse>;
150
+ CreateUserProfile(params: CreateUserProfileParams): Promise<OTApiResponse>;
151
+ AddOrder(params: AddOrderParams): Promise<OTApiResponse>;
152
+ GetRootCategoryInfoList(): Promise<OTApiResponse>;
153
+ GetBrandInfoList(): Promise<OTApiResponse>;
154
+ }
155
+ declare class OTApiError extends Error {
156
+ code: string;
157
+ constructor(code: string, description?: string);
158
+ }
159
+
160
+ export { type AddOrderParams, type AuthenticateAsUserParams, type AuthenticateInstanceOperatorParams, type AuthenticateParams, type BatchGetItemFullInfoParams, type BatchSearchItemsFrameParams, type CreateUserProfileParams, type ItemBlockList, OTApiError, type OTApiResponse, OTClient, type OTClientConfig, type OrderAddData, type OrderItem, type RegisterUserParams, type SearchBlockList, type SearchConfigurator, type SearchFeature, type SearchItemsParameters, type UserProfileCreateData };
@@ -0,0 +1,160 @@
1
+ interface OTClientConfig {
2
+ language?: string;
3
+ secret?: string;
4
+ baseUrl?: string;
5
+ debug?: boolean;
6
+ }
7
+ interface OTApiResponse<T = unknown> {
8
+ ErrorCode: string;
9
+ ErrorDescription?: string;
10
+ Result?: T;
11
+ }
12
+ interface AuthenticateParams {
13
+ sessionId?: string;
14
+ userLogin: string;
15
+ userPassword: string;
16
+ rememberMe?: boolean;
17
+ }
18
+ interface AuthenticateInstanceOperatorParams {
19
+ userLogin: string;
20
+ userPassword: string;
21
+ }
22
+ interface AuthenticateAsUserParams {
23
+ sessionId: string;
24
+ userLogin: string;
25
+ }
26
+ interface RegisterUserParams {
27
+ sessionId?: string;
28
+ userParameters: string;
29
+ }
30
+ type ItemBlockList = "DeliveryCosts" | "Promotions" | "Vendor" | "RootPath" | "ProviderReviews" | "MostPopularVendorItems16" | "RecommendedItems" | "Description" | "OriginalDescription";
31
+ interface BatchGetItemFullInfoParams {
32
+ sessionId?: string;
33
+ itemId: string;
34
+ itemParameters?: string;
35
+ blockList?: ItemBlockList[];
36
+ }
37
+ type SearchBlockList = "SubCategories" | "SearchProperties" | "RootPath" | "Vendor" | "Brand" | "Category" | "HintCategories" | "AvailableSearchMethods";
38
+ interface SearchConfigurator {
39
+ Pid: string;
40
+ Vid: string;
41
+ }
42
+ interface SearchFeature {
43
+ Name: string;
44
+ value: boolean;
45
+ }
46
+ interface SearchItemsParameters {
47
+ Provider?: string;
48
+ SearchMethod?: string;
49
+ CategoryId?: string;
50
+ VendorName?: string;
51
+ VendorId?: string;
52
+ VendorAreaId?: string;
53
+ ItemTitle?: string;
54
+ LanguageOfQuery?: string;
55
+ MinPrice?: number;
56
+ MaxPrice?: number;
57
+ EnableDirectSearch?: boolean;
58
+ CurrencyCode?: string;
59
+ MinVolume?: number;
60
+ MaxVolume?: number;
61
+ MinVendorRating?: number;
62
+ MaxVendorRating?: number;
63
+ BrandId?: string;
64
+ Configurators?: SearchConfigurator[];
65
+ OrderBy?: string;
66
+ OutputMode?: string;
67
+ CategoryMode?: string;
68
+ IsTmall?: boolean;
69
+ StuffStatus?: string;
70
+ Features?: SearchFeature[];
71
+ UseOptimalFrameSize?: boolean;
72
+ MinFirstLot?: number;
73
+ MaxFirstLot?: number;
74
+ MinUpdatedTime?: string;
75
+ MaxUpdatedTime?: string;
76
+ MinCreatedTime?: string;
77
+ MaxCreatedTime?: string;
78
+ Module?: string;
79
+ ImageUrl?: string;
80
+ ImageFileId?: string;
81
+ ImageItemId?: string;
82
+ }
83
+ interface OrderItem {
84
+ Id: string;
85
+ ConfigurationId?: string;
86
+ Quantity: number;
87
+ Weight?: number;
88
+ Comment?: string;
89
+ PromotionId?: string;
90
+ PriceType?: string;
91
+ }
92
+ interface OrderAddData {
93
+ DeliveryModeId?: string;
94
+ Comment?: string;
95
+ UserProfileId?: string;
96
+ Items: OrderItem[];
97
+ }
98
+ interface UserProfileCreateData {
99
+ FirstName?: string;
100
+ LastName?: string;
101
+ MiddleName?: string;
102
+ CountryCode?: string;
103
+ Region?: string;
104
+ City?: string;
105
+ CityCode?: string;
106
+ Address?: string;
107
+ Phone?: string;
108
+ PostalCode?: string;
109
+ ExternalDeliveryId?: string;
110
+ PickupPointCode?: string;
111
+ PassportNumber?: string;
112
+ ResetPassportIssueDate?: boolean;
113
+ PassportIssueDate?: string;
114
+ RegistrationAddress?: string;
115
+ INN?: string;
116
+ EnableValidation?: boolean;
117
+ }
118
+ interface CreateUserProfileParams {
119
+ sessionId: string;
120
+ createData: UserProfileCreateData;
121
+ }
122
+ interface AddOrderParams {
123
+ sessionId?: string;
124
+ xmlAddData: OrderAddData;
125
+ }
126
+ interface BatchSearchItemsFrameParams {
127
+ sessionId?: string;
128
+ xmlParameters: SearchItemsParameters;
129
+ framePosition: number;
130
+ frameSize: number;
131
+ blockList?: SearchBlockList[];
132
+ }
133
+
134
+ declare class OTClient {
135
+ private readonly instanceKey;
136
+ private readonly language;
137
+ private readonly secret?;
138
+ private readonly baseUrl;
139
+ private readonly debug;
140
+ constructor(instanceKey: string, config?: OTClientConfig);
141
+ private sign;
142
+ private request;
143
+ GetAnonymousSession(): Promise<OTApiResponse>;
144
+ Authenticate(params: AuthenticateParams): Promise<OTApiResponse>;
145
+ AuthenticateInstanceOperator(params: AuthenticateInstanceOperatorParams): Promise<OTApiResponse>;
146
+ AuthenticateAsUser(params: AuthenticateAsUserParams): Promise<OTApiResponse>;
147
+ RegisterUser(params: RegisterUserParams): Promise<OTApiResponse>;
148
+ BatchGetItemFullInfo(params: BatchGetItemFullInfoParams): Promise<OTApiResponse>;
149
+ BatchSearchItemsFrame(params: BatchSearchItemsFrameParams): Promise<OTApiResponse>;
150
+ CreateUserProfile(params: CreateUserProfileParams): Promise<OTApiResponse>;
151
+ AddOrder(params: AddOrderParams): Promise<OTApiResponse>;
152
+ GetRootCategoryInfoList(): Promise<OTApiResponse>;
153
+ GetBrandInfoList(): Promise<OTApiResponse>;
154
+ }
155
+ declare class OTApiError extends Error {
156
+ code: string;
157
+ constructor(code: string, description?: string);
158
+ }
159
+
160
+ export { type AddOrderParams, type AuthenticateAsUserParams, type AuthenticateInstanceOperatorParams, type AuthenticateParams, type BatchGetItemFullInfoParams, type BatchSearchItemsFrameParams, type CreateUserProfileParams, type ItemBlockList, OTApiError, type OTApiResponse, OTClient, type OTClientConfig, type OrderAddData, type OrderItem, type RegisterUserParams, type SearchBlockList, type SearchConfigurator, type SearchFeature, type SearchItemsParameters, type UserProfileCreateData };
package/dist/index.js ADDED
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ OTApiError: () => OTApiError,
24
+ OTClient: () => OTClient
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/client.ts
29
+ var import_crypto = require("crypto");
30
+ function buildSearchXml(params) {
31
+ let xml = "<SearchItemsParameters>";
32
+ for (const [key, value] of Object.entries(params)) {
33
+ if (value === void 0) continue;
34
+ if (key === "Configurators" && Array.isArray(value)) {
35
+ xml += "<Configurators>";
36
+ for (const c of value) {
37
+ xml += `<Configurator Pid="${c.Pid}" Vid="${c.Vid}" />`;
38
+ }
39
+ xml += "</Configurators>";
40
+ } else if (key === "Features" && Array.isArray(value)) {
41
+ xml += "<Features>";
42
+ for (const f of value) {
43
+ xml += `<Feature Name="${f.Name}">${f.value}</Feature>`;
44
+ }
45
+ xml += "</Features>";
46
+ } else {
47
+ xml += `<${key}>${value}</${key}>`;
48
+ }
49
+ }
50
+ xml += "</SearchItemsParameters>";
51
+ return xml;
52
+ }
53
+ function buildSimpleXml(rootTag, data) {
54
+ let xml = `<${rootTag}>`;
55
+ for (const [key, value] of Object.entries(data)) {
56
+ if (value !== void 0) xml += `<${key}>${value}</${key}>`;
57
+ }
58
+ xml += `</${rootTag}>`;
59
+ return xml;
60
+ }
61
+ function buildOrderXml(data) {
62
+ let xml = "<OrderAddData>";
63
+ if (data.DeliveryModeId) xml += `<DeliveryModeId>${data.DeliveryModeId}</DeliveryModeId>`;
64
+ if (data.Comment) xml += `<Comment>${data.Comment}</Comment>`;
65
+ if (data.UserProfileId) xml += `<UserProfileId>${data.UserProfileId}</UserProfileId>`;
66
+ xml += "<Items>";
67
+ for (const item of data.Items) {
68
+ xml += "<Item>";
69
+ xml += `<Id>${item.Id}</Id>`;
70
+ if (item.ConfigurationId) xml += `<ConfigurationId>${item.ConfigurationId}</ConfigurationId>`;
71
+ xml += `<Quantity>${item.Quantity}</Quantity>`;
72
+ if (item.Weight !== void 0) xml += `<Weight>${item.Weight}</Weight>`;
73
+ if (item.Comment) xml += `<Comment>${item.Comment}</Comment>`;
74
+ if (item.PromotionId) xml += `<PromotionId>${item.PromotionId}</PromotionId>`;
75
+ if (item.PriceType) xml += `<PriceType>${item.PriceType}</PriceType>`;
76
+ xml += "</Item>";
77
+ }
78
+ xml += "</Items>";
79
+ xml += "</OrderAddData>";
80
+ return xml;
81
+ }
82
+ var OTClient = class {
83
+ constructor(instanceKey, config = {}) {
84
+ this.instanceKey = instanceKey;
85
+ this.language = config.language ?? "en";
86
+ this.secret = config.secret;
87
+ this.baseUrl = config.baseUrl ?? "https://otapi.net/service-json";
88
+ this.debug = config.debug ?? false;
89
+ }
90
+ sign(methodName, params) {
91
+ const now = /* @__PURE__ */ new Date();
92
+ const timestamp = now.getUTCFullYear().toString() + String(now.getUTCMonth() + 1).padStart(2, "0") + String(now.getUTCDate()).padStart(2, "0") + String(now.getUTCHours()).padStart(2, "0") + String(now.getUTCMinutes()).padStart(2, "0") + String(now.getUTCSeconds()).padStart(2, "0");
93
+ const allParams = { ...params, timestamp };
94
+ const sortedValues = Object.keys(allParams).sort().map((key) => allParams[key]).join("");
95
+ const raw = methodName + sortedValues + this.secret;
96
+ const signature = (0, import_crypto.createHash)("sha256").update(raw).digest("hex");
97
+ return { signature, timestamp };
98
+ }
99
+ async request(method, extraParams = {}) {
100
+ const params = {
101
+ instanceKey: this.instanceKey,
102
+ language: this.language,
103
+ ...extraParams
104
+ };
105
+ if (this.secret) {
106
+ const { signature, timestamp } = this.sign(method, params);
107
+ params.signature = signature;
108
+ params.timestamp = timestamp;
109
+ }
110
+ const url = `${this.baseUrl}/${method}`;
111
+ const body = new URLSearchParams(params);
112
+ const response = await fetch(url, {
113
+ method: "POST",
114
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
115
+ body
116
+ });
117
+ if (!response.ok) {
118
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
119
+ }
120
+ const data = await response.json();
121
+ if (this.debug) {
122
+ console.log(`[OTClient] ${method} ->`, JSON.stringify(data, null, 2));
123
+ }
124
+ if (data.ErrorCode !== "Ok") {
125
+ throw new OTApiError(data.ErrorCode, data.ErrorDescription);
126
+ }
127
+ return data;
128
+ }
129
+ async GetAnonymousSession() {
130
+ return this.request("GetAnonymousSession");
131
+ }
132
+ async Authenticate(params) {
133
+ const extra = {
134
+ userLogin: params.userLogin,
135
+ userPassword: params.userPassword
136
+ };
137
+ if (params.sessionId) extra.sessionId = params.sessionId;
138
+ if (params.rememberMe !== void 0)
139
+ extra.rememberMe = String(params.rememberMe);
140
+ return this.request("Authenticate", extra);
141
+ }
142
+ async AuthenticateInstanceOperator(params) {
143
+ return this.request("AuthenticateInstanceOperator", {
144
+ userLogin: params.userLogin,
145
+ userPassword: params.userPassword
146
+ });
147
+ }
148
+ async AuthenticateAsUser(params) {
149
+ return this.request("AuthenticateAsUser", {
150
+ sessionId: params.sessionId,
151
+ userLogin: params.userLogin
152
+ });
153
+ }
154
+ async RegisterUser(params) {
155
+ const extra = {
156
+ userParameters: params.userParameters
157
+ };
158
+ if (params.sessionId) extra.sessionId = params.sessionId;
159
+ return this.request("RegisterUser", extra);
160
+ }
161
+ async BatchGetItemFullInfo(params) {
162
+ const extra = {
163
+ itemId: params.itemId
164
+ };
165
+ if (params.sessionId) extra.sessionId = params.sessionId;
166
+ if (params.itemParameters) extra.itemParameters = params.itemParameters;
167
+ if (params.blockList) extra.blockList = params.blockList.join(",");
168
+ return this.request("BatchGetItemFullInfo", extra);
169
+ }
170
+ async BatchSearchItemsFrame(params) {
171
+ const extra = {
172
+ xmlParameters: buildSearchXml(params.xmlParameters),
173
+ framePosition: String(params.framePosition),
174
+ frameSize: String(params.frameSize)
175
+ };
176
+ if (params.sessionId) extra.sessionId = params.sessionId;
177
+ if (params.blockList) extra.blockList = params.blockList.join(",");
178
+ return this.request("BatchSearchItemsFrame", extra);
179
+ }
180
+ async CreateUserProfile(params) {
181
+ return this.request("CreateUserProfile", {
182
+ sessionId: params.sessionId,
183
+ createData: buildSimpleXml("UserProfileCreateData", params.createData)
184
+ });
185
+ }
186
+ async AddOrder(params) {
187
+ const extra = {
188
+ xmlAddData: buildOrderXml(params.xmlAddData)
189
+ };
190
+ if (params.sessionId) extra.sessionId = params.sessionId;
191
+ return this.request("AddOrder", extra);
192
+ }
193
+ async GetRootCategoryInfoList() {
194
+ return this.request("GetRootCategoryInfoList");
195
+ }
196
+ async GetBrandInfoList() {
197
+ return this.request("GetBrandInfoList");
198
+ }
199
+ };
200
+ var OTApiError = class extends Error {
201
+ constructor(code, description) {
202
+ super(description ?? `OTApi error: ${code}`);
203
+ this.name = "OTApiError";
204
+ this.code = code;
205
+ }
206
+ };
207
+ // Annotate the CommonJS export names for ESM import in node:
208
+ 0 && (module.exports = {
209
+ OTApiError,
210
+ OTClient
211
+ });
212
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["export { OTClient } from \"./client\";\nexport { OTApiError } from \"./client\";\nexport type {\n OTClientConfig,\n OTApiResponse,\n AuthenticateParams,\n AuthenticateInstanceOperatorParams,\n AuthenticateAsUserParams,\n RegisterUserParams,\n BatchGetItemFullInfoParams,\n ItemBlockList,\n BatchSearchItemsFrameParams,\n SearchBlockList,\n SearchItemsParameters,\n SearchConfigurator,\n SearchFeature,\n AddOrderParams,\n OrderAddData,\n OrderItem,\n CreateUserProfileParams,\n UserProfileCreateData,\n} from \"./types\";\n","import { createHash } from \"crypto\";\nimport type {\n OTClientConfig,\n OTApiResponse,\n AuthenticateParams,\n AuthenticateInstanceOperatorParams,\n AuthenticateAsUserParams,\n RegisterUserParams,\n BatchGetItemFullInfoParams,\n BatchSearchItemsFrameParams,\n SearchItemsParameters,\n AddOrderParams,\n OrderAddData,\n CreateUserProfileParams,\n UserProfileCreateData,\n} from \"./types\";\n\nfunction buildSearchXml(params: SearchItemsParameters): string {\n let xml = \"<SearchItemsParameters>\";\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n\n if (key === \"Configurators\" && Array.isArray(value)) {\n xml += \"<Configurators>\";\n for (const c of value) {\n xml += `<Configurator Pid=\"${c.Pid}\" Vid=\"${c.Vid}\" />`;\n }\n xml += \"</Configurators>\";\n } else if (key === \"Features\" && Array.isArray(value)) {\n xml += \"<Features>\";\n for (const f of value) {\n xml += `<Feature Name=\"${f.Name}\">${f.value}</Feature>`;\n }\n xml += \"</Features>\";\n } else {\n xml += `<${key}>${value}</${key}>`;\n }\n }\n\n xml += \"</SearchItemsParameters>\";\n return xml;\n}\n\nfunction buildSimpleXml(rootTag: string, data: Record<string, unknown>): string {\n let xml = `<${rootTag}>`;\n for (const [key, value] of Object.entries(data)) {\n if (value !== undefined) xml += `<${key}>${value}</${key}>`;\n }\n xml += `</${rootTag}>`;\n return xml;\n}\n\nfunction buildOrderXml(data: OrderAddData): string {\n let xml = \"<OrderAddData>\";\n if (data.DeliveryModeId) xml += `<DeliveryModeId>${data.DeliveryModeId}</DeliveryModeId>`;\n if (data.Comment) xml += `<Comment>${data.Comment}</Comment>`;\n if (data.UserProfileId) xml += `<UserProfileId>${data.UserProfileId}</UserProfileId>`;\n xml += \"<Items>\";\n for (const item of data.Items) {\n xml += \"<Item>\";\n xml += `<Id>${item.Id}</Id>`;\n if (item.ConfigurationId) xml += `<ConfigurationId>${item.ConfigurationId}</ConfigurationId>`;\n xml += `<Quantity>${item.Quantity}</Quantity>`;\n if (item.Weight !== undefined) xml += `<Weight>${item.Weight}</Weight>`;\n if (item.Comment) xml += `<Comment>${item.Comment}</Comment>`;\n if (item.PromotionId) xml += `<PromotionId>${item.PromotionId}</PromotionId>`;\n if (item.PriceType) xml += `<PriceType>${item.PriceType}</PriceType>`;\n xml += \"</Item>\";\n }\n xml += \"</Items>\";\n xml += \"</OrderAddData>\";\n return xml;\n}\n\nexport class OTClient {\n private readonly instanceKey: string;\n private readonly language: string;\n private readonly secret?: string;\n private readonly baseUrl: string;\n private readonly debug: boolean;\n\n constructor(instanceKey: string, config: OTClientConfig = {}) {\n this.instanceKey = instanceKey;\n this.language = config.language ?? \"en\";\n this.secret = config.secret;\n this.baseUrl = config.baseUrl ?? \"https://otapi.net/service-json\";\n this.debug = config.debug ?? false;\n }\n\n private sign(\n methodName: string,\n params: Record<string, string>\n ): { signature: string; timestamp: string } {\n const now = new Date();\n const timestamp =\n now.getUTCFullYear().toString() +\n String(now.getUTCMonth() + 1).padStart(2, \"0\") +\n String(now.getUTCDate()).padStart(2, \"0\") +\n String(now.getUTCHours()).padStart(2, \"0\") +\n String(now.getUTCMinutes()).padStart(2, \"0\") +\n String(now.getUTCSeconds()).padStart(2, \"0\");\n\n const allParams: Record<string, string> = { ...params, timestamp };\n const sortedValues = Object.keys(allParams)\n .sort()\n .map((key) => allParams[key])\n .join(\"\");\n\n const raw = methodName + sortedValues + this.secret;\n const signature = createHash(\"sha256\").update(raw).digest(\"hex\");\n\n return { signature, timestamp };\n }\n\n private async request<T = unknown>(\n method: string,\n extraParams: Record<string, string> = {}\n ): Promise<OTApiResponse<T>> {\n const params: Record<string, string> = {\n instanceKey: this.instanceKey,\n language: this.language,\n ...extraParams,\n };\n\n if (this.secret) {\n const { signature, timestamp } = this.sign(method, params);\n params.signature = signature;\n params.timestamp = timestamp;\n }\n\n const url = `${this.baseUrl}/${method}`;\n const body = new URLSearchParams(params);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const data: OTApiResponse<T> = await response.json();\n\n if (this.debug) {\n console.log(`[OTClient] ${method} ->`, JSON.stringify(data, null, 2));\n }\n\n if (data.ErrorCode !== \"Ok\") {\n throw new OTApiError(data.ErrorCode, data.ErrorDescription);\n }\n\n return data;\n }\n\n async GetAnonymousSession(): Promise<OTApiResponse> {\n return this.request(\"GetAnonymousSession\");\n }\n\n async Authenticate(params: AuthenticateParams): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n userLogin: params.userLogin,\n userPassword: params.userPassword,\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n if (params.rememberMe !== undefined)\n extra.rememberMe = String(params.rememberMe);\n return this.request(\"Authenticate\", extra);\n }\n\n async AuthenticateInstanceOperator(\n params: AuthenticateInstanceOperatorParams\n ): Promise<OTApiResponse> {\n return this.request(\"AuthenticateInstanceOperator\", {\n userLogin: params.userLogin,\n userPassword: params.userPassword,\n });\n }\n\n async AuthenticateAsUser(\n params: AuthenticateAsUserParams\n ): Promise<OTApiResponse> {\n return this.request(\"AuthenticateAsUser\", {\n sessionId: params.sessionId,\n userLogin: params.userLogin,\n });\n }\n\n async RegisterUser(params: RegisterUserParams): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n userParameters: params.userParameters,\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n return this.request(\"RegisterUser\", extra);\n }\n\n async BatchGetItemFullInfo(\n params: BatchGetItemFullInfoParams\n ): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n itemId: params.itemId,\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n if (params.itemParameters) extra.itemParameters = params.itemParameters;\n if (params.blockList) extra.blockList = params.blockList.join(\",\");\n return this.request(\"BatchGetItemFullInfo\", extra);\n }\n\n async BatchSearchItemsFrame(\n params: BatchSearchItemsFrameParams\n ): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n xmlParameters: buildSearchXml(params.xmlParameters),\n framePosition: String(params.framePosition),\n frameSize: String(params.frameSize),\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n if (params.blockList) extra.blockList = params.blockList.join(\",\");\n return this.request(\"BatchSearchItemsFrame\", extra);\n }\n\n async CreateUserProfile(params: CreateUserProfileParams): Promise<OTApiResponse> {\n return this.request(\"CreateUserProfile\", {\n sessionId: params.sessionId,\n createData: buildSimpleXml(\"UserProfileCreateData\", params.createData as unknown as Record<string, unknown>),\n });\n }\n\n async AddOrder(params: AddOrderParams): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n xmlAddData: buildOrderXml(params.xmlAddData),\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n return this.request(\"AddOrder\", extra);\n }\n\n async GetRootCategoryInfoList(): Promise<OTApiResponse> {\n return this.request(\"GetRootCategoryInfoList\");\n }\n\n async GetBrandInfoList(): Promise<OTApiResponse> {\n return this.request(\"GetBrandInfoList\");\n }\n}\n\nexport class OTApiError extends Error {\n code: string;\n\n constructor(code: string, description?: string) {\n super(description ?? `OTApi error: ${code}`);\n this.name = \"OTApiError\";\n this.code = code;\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,184 @@
1
+ // src/client.ts
2
+ import { createHash } from "crypto";
3
+ function buildSearchXml(params) {
4
+ let xml = "<SearchItemsParameters>";
5
+ for (const [key, value] of Object.entries(params)) {
6
+ if (value === void 0) continue;
7
+ if (key === "Configurators" && Array.isArray(value)) {
8
+ xml += "<Configurators>";
9
+ for (const c of value) {
10
+ xml += `<Configurator Pid="${c.Pid}" Vid="${c.Vid}" />`;
11
+ }
12
+ xml += "</Configurators>";
13
+ } else if (key === "Features" && Array.isArray(value)) {
14
+ xml += "<Features>";
15
+ for (const f of value) {
16
+ xml += `<Feature Name="${f.Name}">${f.value}</Feature>`;
17
+ }
18
+ xml += "</Features>";
19
+ } else {
20
+ xml += `<${key}>${value}</${key}>`;
21
+ }
22
+ }
23
+ xml += "</SearchItemsParameters>";
24
+ return xml;
25
+ }
26
+ function buildSimpleXml(rootTag, data) {
27
+ let xml = `<${rootTag}>`;
28
+ for (const [key, value] of Object.entries(data)) {
29
+ if (value !== void 0) xml += `<${key}>${value}</${key}>`;
30
+ }
31
+ xml += `</${rootTag}>`;
32
+ return xml;
33
+ }
34
+ function buildOrderXml(data) {
35
+ let xml = "<OrderAddData>";
36
+ if (data.DeliveryModeId) xml += `<DeliveryModeId>${data.DeliveryModeId}</DeliveryModeId>`;
37
+ if (data.Comment) xml += `<Comment>${data.Comment}</Comment>`;
38
+ if (data.UserProfileId) xml += `<UserProfileId>${data.UserProfileId}</UserProfileId>`;
39
+ xml += "<Items>";
40
+ for (const item of data.Items) {
41
+ xml += "<Item>";
42
+ xml += `<Id>${item.Id}</Id>`;
43
+ if (item.ConfigurationId) xml += `<ConfigurationId>${item.ConfigurationId}</ConfigurationId>`;
44
+ xml += `<Quantity>${item.Quantity}</Quantity>`;
45
+ if (item.Weight !== void 0) xml += `<Weight>${item.Weight}</Weight>`;
46
+ if (item.Comment) xml += `<Comment>${item.Comment}</Comment>`;
47
+ if (item.PromotionId) xml += `<PromotionId>${item.PromotionId}</PromotionId>`;
48
+ if (item.PriceType) xml += `<PriceType>${item.PriceType}</PriceType>`;
49
+ xml += "</Item>";
50
+ }
51
+ xml += "</Items>";
52
+ xml += "</OrderAddData>";
53
+ return xml;
54
+ }
55
+ var OTClient = class {
56
+ constructor(instanceKey, config = {}) {
57
+ this.instanceKey = instanceKey;
58
+ this.language = config.language ?? "en";
59
+ this.secret = config.secret;
60
+ this.baseUrl = config.baseUrl ?? "https://otapi.net/service-json";
61
+ this.debug = config.debug ?? false;
62
+ }
63
+ sign(methodName, params) {
64
+ const now = /* @__PURE__ */ new Date();
65
+ const timestamp = now.getUTCFullYear().toString() + String(now.getUTCMonth() + 1).padStart(2, "0") + String(now.getUTCDate()).padStart(2, "0") + String(now.getUTCHours()).padStart(2, "0") + String(now.getUTCMinutes()).padStart(2, "0") + String(now.getUTCSeconds()).padStart(2, "0");
66
+ const allParams = { ...params, timestamp };
67
+ const sortedValues = Object.keys(allParams).sort().map((key) => allParams[key]).join("");
68
+ const raw = methodName + sortedValues + this.secret;
69
+ const signature = createHash("sha256").update(raw).digest("hex");
70
+ return { signature, timestamp };
71
+ }
72
+ async request(method, extraParams = {}) {
73
+ const params = {
74
+ instanceKey: this.instanceKey,
75
+ language: this.language,
76
+ ...extraParams
77
+ };
78
+ if (this.secret) {
79
+ const { signature, timestamp } = this.sign(method, params);
80
+ params.signature = signature;
81
+ params.timestamp = timestamp;
82
+ }
83
+ const url = `${this.baseUrl}/${method}`;
84
+ const body = new URLSearchParams(params);
85
+ const response = await fetch(url, {
86
+ method: "POST",
87
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
88
+ body
89
+ });
90
+ if (!response.ok) {
91
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
92
+ }
93
+ const data = await response.json();
94
+ if (this.debug) {
95
+ console.log(`[OTClient] ${method} ->`, JSON.stringify(data, null, 2));
96
+ }
97
+ if (data.ErrorCode !== "Ok") {
98
+ throw new OTApiError(data.ErrorCode, data.ErrorDescription);
99
+ }
100
+ return data;
101
+ }
102
+ async GetAnonymousSession() {
103
+ return this.request("GetAnonymousSession");
104
+ }
105
+ async Authenticate(params) {
106
+ const extra = {
107
+ userLogin: params.userLogin,
108
+ userPassword: params.userPassword
109
+ };
110
+ if (params.sessionId) extra.sessionId = params.sessionId;
111
+ if (params.rememberMe !== void 0)
112
+ extra.rememberMe = String(params.rememberMe);
113
+ return this.request("Authenticate", extra);
114
+ }
115
+ async AuthenticateInstanceOperator(params) {
116
+ return this.request("AuthenticateInstanceOperator", {
117
+ userLogin: params.userLogin,
118
+ userPassword: params.userPassword
119
+ });
120
+ }
121
+ async AuthenticateAsUser(params) {
122
+ return this.request("AuthenticateAsUser", {
123
+ sessionId: params.sessionId,
124
+ userLogin: params.userLogin
125
+ });
126
+ }
127
+ async RegisterUser(params) {
128
+ const extra = {
129
+ userParameters: params.userParameters
130
+ };
131
+ if (params.sessionId) extra.sessionId = params.sessionId;
132
+ return this.request("RegisterUser", extra);
133
+ }
134
+ async BatchGetItemFullInfo(params) {
135
+ const extra = {
136
+ itemId: params.itemId
137
+ };
138
+ if (params.sessionId) extra.sessionId = params.sessionId;
139
+ if (params.itemParameters) extra.itemParameters = params.itemParameters;
140
+ if (params.blockList) extra.blockList = params.blockList.join(",");
141
+ return this.request("BatchGetItemFullInfo", extra);
142
+ }
143
+ async BatchSearchItemsFrame(params) {
144
+ const extra = {
145
+ xmlParameters: buildSearchXml(params.xmlParameters),
146
+ framePosition: String(params.framePosition),
147
+ frameSize: String(params.frameSize)
148
+ };
149
+ if (params.sessionId) extra.sessionId = params.sessionId;
150
+ if (params.blockList) extra.blockList = params.blockList.join(",");
151
+ return this.request("BatchSearchItemsFrame", extra);
152
+ }
153
+ async CreateUserProfile(params) {
154
+ return this.request("CreateUserProfile", {
155
+ sessionId: params.sessionId,
156
+ createData: buildSimpleXml("UserProfileCreateData", params.createData)
157
+ });
158
+ }
159
+ async AddOrder(params) {
160
+ const extra = {
161
+ xmlAddData: buildOrderXml(params.xmlAddData)
162
+ };
163
+ if (params.sessionId) extra.sessionId = params.sessionId;
164
+ return this.request("AddOrder", extra);
165
+ }
166
+ async GetRootCategoryInfoList() {
167
+ return this.request("GetRootCategoryInfoList");
168
+ }
169
+ async GetBrandInfoList() {
170
+ return this.request("GetBrandInfoList");
171
+ }
172
+ };
173
+ var OTApiError = class extends Error {
174
+ constructor(code, description) {
175
+ super(description ?? `OTApi error: ${code}`);
176
+ this.name = "OTApiError";
177
+ this.code = code;
178
+ }
179
+ };
180
+ export {
181
+ OTApiError,
182
+ OTClient
183
+ };
184
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { createHash } from \"crypto\";\nimport type {\n OTClientConfig,\n OTApiResponse,\n AuthenticateParams,\n AuthenticateInstanceOperatorParams,\n AuthenticateAsUserParams,\n RegisterUserParams,\n BatchGetItemFullInfoParams,\n BatchSearchItemsFrameParams,\n SearchItemsParameters,\n AddOrderParams,\n OrderAddData,\n CreateUserProfileParams,\n UserProfileCreateData,\n} from \"./types\";\n\nfunction buildSearchXml(params: SearchItemsParameters): string {\n let xml = \"<SearchItemsParameters>\";\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n\n if (key === \"Configurators\" && Array.isArray(value)) {\n xml += \"<Configurators>\";\n for (const c of value) {\n xml += `<Configurator Pid=\"${c.Pid}\" Vid=\"${c.Vid}\" />`;\n }\n xml += \"</Configurators>\";\n } else if (key === \"Features\" && Array.isArray(value)) {\n xml += \"<Features>\";\n for (const f of value) {\n xml += `<Feature Name=\"${f.Name}\">${f.value}</Feature>`;\n }\n xml += \"</Features>\";\n } else {\n xml += `<${key}>${value}</${key}>`;\n }\n }\n\n xml += \"</SearchItemsParameters>\";\n return xml;\n}\n\nfunction buildSimpleXml(rootTag: string, data: Record<string, unknown>): string {\n let xml = `<${rootTag}>`;\n for (const [key, value] of Object.entries(data)) {\n if (value !== undefined) xml += `<${key}>${value}</${key}>`;\n }\n xml += `</${rootTag}>`;\n return xml;\n}\n\nfunction buildOrderXml(data: OrderAddData): string {\n let xml = \"<OrderAddData>\";\n if (data.DeliveryModeId) xml += `<DeliveryModeId>${data.DeliveryModeId}</DeliveryModeId>`;\n if (data.Comment) xml += `<Comment>${data.Comment}</Comment>`;\n if (data.UserProfileId) xml += `<UserProfileId>${data.UserProfileId}</UserProfileId>`;\n xml += \"<Items>\";\n for (const item of data.Items) {\n xml += \"<Item>\";\n xml += `<Id>${item.Id}</Id>`;\n if (item.ConfigurationId) xml += `<ConfigurationId>${item.ConfigurationId}</ConfigurationId>`;\n xml += `<Quantity>${item.Quantity}</Quantity>`;\n if (item.Weight !== undefined) xml += `<Weight>${item.Weight}</Weight>`;\n if (item.Comment) xml += `<Comment>${item.Comment}</Comment>`;\n if (item.PromotionId) xml += `<PromotionId>${item.PromotionId}</PromotionId>`;\n if (item.PriceType) xml += `<PriceType>${item.PriceType}</PriceType>`;\n xml += \"</Item>\";\n }\n xml += \"</Items>\";\n xml += \"</OrderAddData>\";\n return xml;\n}\n\nexport class OTClient {\n private readonly instanceKey: string;\n private readonly language: string;\n private readonly secret?: string;\n private readonly baseUrl: string;\n private readonly debug: boolean;\n\n constructor(instanceKey: string, config: OTClientConfig = {}) {\n this.instanceKey = instanceKey;\n this.language = config.language ?? \"en\";\n this.secret = config.secret;\n this.baseUrl = config.baseUrl ?? \"https://otapi.net/service-json\";\n this.debug = config.debug ?? false;\n }\n\n private sign(\n methodName: string,\n params: Record<string, string>\n ): { signature: string; timestamp: string } {\n const now = new Date();\n const timestamp =\n now.getUTCFullYear().toString() +\n String(now.getUTCMonth() + 1).padStart(2, \"0\") +\n String(now.getUTCDate()).padStart(2, \"0\") +\n String(now.getUTCHours()).padStart(2, \"0\") +\n String(now.getUTCMinutes()).padStart(2, \"0\") +\n String(now.getUTCSeconds()).padStart(2, \"0\");\n\n const allParams: Record<string, string> = { ...params, timestamp };\n const sortedValues = Object.keys(allParams)\n .sort()\n .map((key) => allParams[key])\n .join(\"\");\n\n const raw = methodName + sortedValues + this.secret;\n const signature = createHash(\"sha256\").update(raw).digest(\"hex\");\n\n return { signature, timestamp };\n }\n\n private async request<T = unknown>(\n method: string,\n extraParams: Record<string, string> = {}\n ): Promise<OTApiResponse<T>> {\n const params: Record<string, string> = {\n instanceKey: this.instanceKey,\n language: this.language,\n ...extraParams,\n };\n\n if (this.secret) {\n const { signature, timestamp } = this.sign(method, params);\n params.signature = signature;\n params.timestamp = timestamp;\n }\n\n const url = `${this.baseUrl}/${method}`;\n const body = new URLSearchParams(params);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const data: OTApiResponse<T> = await response.json();\n\n if (this.debug) {\n console.log(`[OTClient] ${method} ->`, JSON.stringify(data, null, 2));\n }\n\n if (data.ErrorCode !== \"Ok\") {\n throw new OTApiError(data.ErrorCode, data.ErrorDescription);\n }\n\n return data;\n }\n\n async GetAnonymousSession(): Promise<OTApiResponse> {\n return this.request(\"GetAnonymousSession\");\n }\n\n async Authenticate(params: AuthenticateParams): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n userLogin: params.userLogin,\n userPassword: params.userPassword,\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n if (params.rememberMe !== undefined)\n extra.rememberMe = String(params.rememberMe);\n return this.request(\"Authenticate\", extra);\n }\n\n async AuthenticateInstanceOperator(\n params: AuthenticateInstanceOperatorParams\n ): Promise<OTApiResponse> {\n return this.request(\"AuthenticateInstanceOperator\", {\n userLogin: params.userLogin,\n userPassword: params.userPassword,\n });\n }\n\n async AuthenticateAsUser(\n params: AuthenticateAsUserParams\n ): Promise<OTApiResponse> {\n return this.request(\"AuthenticateAsUser\", {\n sessionId: params.sessionId,\n userLogin: params.userLogin,\n });\n }\n\n async RegisterUser(params: RegisterUserParams): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n userParameters: params.userParameters,\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n return this.request(\"RegisterUser\", extra);\n }\n\n async BatchGetItemFullInfo(\n params: BatchGetItemFullInfoParams\n ): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n itemId: params.itemId,\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n if (params.itemParameters) extra.itemParameters = params.itemParameters;\n if (params.blockList) extra.blockList = params.blockList.join(\",\");\n return this.request(\"BatchGetItemFullInfo\", extra);\n }\n\n async BatchSearchItemsFrame(\n params: BatchSearchItemsFrameParams\n ): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n xmlParameters: buildSearchXml(params.xmlParameters),\n framePosition: String(params.framePosition),\n frameSize: String(params.frameSize),\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n if (params.blockList) extra.blockList = params.blockList.join(\",\");\n return this.request(\"BatchSearchItemsFrame\", extra);\n }\n\n async CreateUserProfile(params: CreateUserProfileParams): Promise<OTApiResponse> {\n return this.request(\"CreateUserProfile\", {\n sessionId: params.sessionId,\n createData: buildSimpleXml(\"UserProfileCreateData\", params.createData as unknown as Record<string, unknown>),\n });\n }\n\n async AddOrder(params: AddOrderParams): Promise<OTApiResponse> {\n const extra: Record<string, string> = {\n xmlAddData: buildOrderXml(params.xmlAddData),\n };\n if (params.sessionId) extra.sessionId = params.sessionId;\n return this.request(\"AddOrder\", extra);\n }\n\n async GetRootCategoryInfoList(): Promise<OTApiResponse> {\n return this.request(\"GetRootCategoryInfoList\");\n }\n\n async GetBrandInfoList(): Promise<OTApiResponse> {\n return this.request(\"GetBrandInfoList\");\n }\n}\n\nexport class OTApiError extends Error {\n code: string;\n\n constructor(code: string, description?: string) {\n super(description ?? `OTApi error: ${code}`);\n this.name = \"OTApiError\";\n this.code = code;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "otapi-client",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript client for OTApi e-commerce REST API",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch"
21
+ },
22
+ "keywords": [
23
+ "otapi",
24
+ "ecommerce",
25
+ "api-client"
26
+ ],
27
+ "author": "",
28
+ "license": "ISC",
29
+ "devDependencies": {
30
+ "@types/node": "^25.5.0",
31
+ "tsup": "^8.5.1",
32
+ "tsx": "^4.21.0",
33
+ "typescript": "~5.7.0"
34
+ }
35
+ }