@porulle/import-woocommerce 0.64.0 → 0.65.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/index.d.ts CHANGED
@@ -138,6 +138,7 @@ export interface WooImportOptions {
138
138
  consumerSecret?: string;
139
139
  products?: WooProduct[];
140
140
  customers?: WooCustomer[];
141
+ currency?: string;
141
142
  fetchImpl?: typeof fetch;
142
143
  mediaFetcher?: (url: string) => Promise<{
143
144
  data: ArrayBuffer;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Err, Ok } from "@porulle/core";
1
+ import { Err, Ok, toMinorUnits } from "@porulle/core";
2
2
  function slugify(value) {
3
3
  return value
4
4
  .toLowerCase()
@@ -6,13 +6,34 @@ function slugify(value) {
6
6
  .replace(/[^a-z0-9]+/g, "-")
7
7
  .replace(/^-+|-+$/g, "") || `product-${crypto.randomUUID().slice(0, 8)}`;
8
8
  }
9
- function buildWooUrl(base, path, key, secret) {
9
+ function buildWooUrl(base, path, key, secret, page = 1) {
10
10
  const url = new URL(path, base.replace(/\/$/, "/"));
11
11
  url.searchParams.set("consumer_key", key);
12
12
  url.searchParams.set("consumer_secret", secret);
13
13
  url.searchParams.set("per_page", "100");
14
+ url.searchParams.set("page", String(page));
14
15
  return url.toString();
15
16
  }
17
+ function normalizeCurrency(value) {
18
+ if (typeof value !== "string" || value.trim() === "")
19
+ return undefined;
20
+ return value.trim().toUpperCase();
21
+ }
22
+ function settingCurrency(data) {
23
+ if (Array.isArray(data)) {
24
+ for (const entry of data) {
25
+ if (typeof entry !== "object" || entry === null)
26
+ continue;
27
+ const setting = entry;
28
+ if (setting.id === "woocommerce_currency")
29
+ return normalizeCurrency(setting.value);
30
+ }
31
+ }
32
+ if (typeof data !== "object" || data === null)
33
+ return undefined;
34
+ const object = data;
35
+ return normalizeCurrency(object.woocommerce_currency);
36
+ }
16
37
  async function fetchJson(fetchImpl, url) {
17
38
  try {
18
39
  const response = await fetchImpl(url, { headers: { accept: "application/json" } });
@@ -22,7 +43,7 @@ async function fetchJson(fetchImpl, url) {
22
43
  message: `WooCommerce request failed (${response.status}) for ${url}.`,
23
44
  });
24
45
  }
25
- return Ok((await response.json()));
46
+ return Ok({ data: (await response.json()), response });
26
47
  }
27
48
  catch (error) {
28
49
  return Err({
@@ -31,6 +52,10 @@ async function fetchJson(fetchImpl, url) {
31
52
  });
32
53
  }
33
54
  }
55
+ function totalPages(response) {
56
+ const value = Number.parseInt(response.headers.get("x-wp-totalpages") ?? "", 10);
57
+ return Number.isFinite(value) && value > 0 ? value : undefined;
58
+ }
34
59
  async function loadProducts(options) {
35
60
  if (options.products)
36
61
  return Ok(options.products);
@@ -41,7 +66,17 @@ async function loadProducts(options) {
41
66
  });
42
67
  }
43
68
  const fetchImpl = options.fetchImpl ?? fetch;
44
- return fetchJson(fetchImpl, buildWooUrl(options.storeUrl, "/wp-json/wc/v3/products", options.consumerKey, options.consumerSecret));
69
+ const products = [];
70
+ for (let page = 1;; page += 1) {
71
+ const response = await fetchJson(fetchImpl, buildWooUrl(options.storeUrl, "/wp-json/wc/v3/products", options.consumerKey, options.consumerSecret, page));
72
+ if (!response.ok)
73
+ return response;
74
+ products.push(...response.value.data);
75
+ if (response.value.data.length === 0 || (totalPages(response.value.response) ?? Number.POSITIVE_INFINITY) <= page) {
76
+ break;
77
+ }
78
+ }
79
+ return Ok(products);
45
80
  }
46
81
  async function loadCustomers(options) {
47
82
  if (options.customers)
@@ -50,7 +85,26 @@ async function loadCustomers(options) {
50
85
  return Ok([]);
51
86
  }
52
87
  const fetchImpl = options.fetchImpl ?? fetch;
53
- return fetchJson(fetchImpl, buildWooUrl(options.storeUrl, "/wp-json/wc/v3/customers", options.consumerKey, options.consumerSecret));
88
+ const customers = [];
89
+ for (let page = 1;; page += 1) {
90
+ const response = await fetchJson(fetchImpl, buildWooUrl(options.storeUrl, "/wp-json/wc/v3/customers", options.consumerKey, options.consumerSecret, page));
91
+ if (!response.ok)
92
+ return response;
93
+ customers.push(...response.value.data);
94
+ if (response.value.data.length === 0 || (totalPages(response.value.response) ?? Number.POSITIVE_INFINITY) <= page) {
95
+ break;
96
+ }
97
+ }
98
+ return Ok(customers);
99
+ }
100
+ async function loadCurrency(options) {
101
+ const configured = normalizeCurrency(options.currency);
102
+ if (configured)
103
+ return configured;
104
+ if (!options.storeUrl || !options.consumerKey || !options.consumerSecret)
105
+ return undefined;
106
+ const response = await fetchJson(options.fetchImpl ?? fetch, buildWooUrl(options.storeUrl, "/wp-json/wc/v3/settings/general", options.consumerKey, options.consumerSecret));
107
+ return response.ok ? settingCurrency(response.value.data) : undefined;
54
108
  }
55
109
  function filenameFromUrl(url) {
56
110
  try {
@@ -79,6 +133,7 @@ export async function importWooCommerceCatalog(options) {
79
133
  const customers = await loadCustomers(options);
80
134
  if (!customers.ok)
81
135
  return customers;
136
+ const currency = await loadCurrency(options);
82
137
  const summary = {
83
138
  entitiesImported: 0,
84
139
  variantsImported: 0,
@@ -136,6 +191,8 @@ export async function importWooCommerceCatalog(options) {
136
191
  const variationData = product.variationsData ?? [];
137
192
  for (const variant of variationData) {
138
193
  try {
194
+ // An unknown store currency falls back to two decimals.
195
+ const price = toMinorUnits(variant.price, currency ?? "");
139
196
  const optionValueIds = (variant.attributes ?? [])
140
197
  .map((attribute) => optionValueIdByKey.get(`${attribute.name}::${attribute.option ?? ""}`))
141
198
  .filter((value) => typeof value === "string");
@@ -146,7 +203,7 @@ export async function importWooCommerceCatalog(options) {
146
203
  metadata: {
147
204
  source: "woocommerce",
148
205
  wooVariationId: variant.id,
149
- price: variant.price,
206
+ ...(price !== undefined ? { price } : {}),
150
207
  },
151
208
  });
152
209
  summary.variantsImported += 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@porulle/import-woocommerce",
3
- "version": "0.64.0",
3
+ "version": "0.65.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -11,7 +11,7 @@
11
11
  }
12
12
  },
13
13
  "dependencies": {
14
- "@porulle/core": "0.64.0"
14
+ "@porulle/core": "0.65.0"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@types/node": "^24.5.2",
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Err, Ok, type Result } from "@porulle/core";
1
+ import { Err, Ok, toMinorUnits, type Result } from "@porulle/core";
2
2
 
3
3
  export interface WooImage {
4
4
  id: number;
@@ -126,6 +126,7 @@ export interface WooImportOptions {
126
126
  consumerSecret?: string;
127
127
  products?: WooProduct[];
128
128
  customers?: WooCustomer[];
129
+ currency?: string;
129
130
  fetchImpl?: typeof fetch;
130
131
  mediaFetcher?: (url: string) => Promise<{ data: ArrayBuffer; contentType: string; filename?: string }>;
131
132
  entityType?: string;
@@ -147,15 +148,37 @@ function slugify(value: string): string {
147
148
  .replace(/^-+|-+$/g, "") || `product-${crypto.randomUUID().slice(0, 8)}`;
148
149
  }
149
150
 
150
- function buildWooUrl(base: string, path: string, key: string, secret: string): string {
151
+ function buildWooUrl(base: string, path: string, key: string, secret: string, page = 1): string {
151
152
  const url = new URL(path, base.replace(/\/$/, "/"));
152
153
  url.searchParams.set("consumer_key", key);
153
154
  url.searchParams.set("consumer_secret", secret);
154
155
  url.searchParams.set("per_page", "100");
156
+ url.searchParams.set("page", String(page));
155
157
  return url.toString();
156
158
  }
157
159
 
158
- async function fetchJson<T>(fetchImpl: typeof fetch, url: string): Promise<Result<T>> {
160
+ function normalizeCurrency(value: unknown): string | undefined {
161
+ if (typeof value !== "string" || value.trim() === "") return undefined;
162
+ return value.trim().toUpperCase();
163
+ }
164
+
165
+ function settingCurrency(data: unknown): string | undefined {
166
+ if (Array.isArray(data)) {
167
+ for (const entry of data) {
168
+ if (typeof entry !== "object" || entry === null) continue;
169
+ const setting = entry as Record<string, unknown>;
170
+ if (setting.id === "woocommerce_currency") return normalizeCurrency(setting.value);
171
+ }
172
+ }
173
+ if (typeof data !== "object" || data === null) return undefined;
174
+ const object = data as Record<string, unknown>;
175
+ return normalizeCurrency(object.woocommerce_currency);
176
+ }
177
+
178
+ async function fetchJson<T>(
179
+ fetchImpl: typeof fetch,
180
+ url: string,
181
+ ): Promise<Result<{ data: T; response: Response }>> {
159
182
  try {
160
183
  const response = await fetchImpl(url, { headers: { accept: "application/json" } });
161
184
  if (!response.ok) {
@@ -164,7 +187,7 @@ async function fetchJson<T>(fetchImpl: typeof fetch, url: string): Promise<Resul
164
187
  message: `WooCommerce request failed (${response.status}) for ${url}.`,
165
188
  });
166
189
  }
167
- return Ok((await response.json()) as T);
190
+ return Ok({ data: (await response.json()) as T, response });
168
191
  } catch (error) {
169
192
  return Err({
170
193
  code: "WOO_API_FAILED",
@@ -173,6 +196,11 @@ async function fetchJson<T>(fetchImpl: typeof fetch, url: string): Promise<Resul
173
196
  }
174
197
  }
175
198
 
199
+ function totalPages(response: Response): number | undefined {
200
+ const value = Number.parseInt(response.headers.get("x-wp-totalpages") ?? "", 10);
201
+ return Number.isFinite(value) && value > 0 ? value : undefined;
202
+ }
203
+
176
204
  async function loadProducts(options: WooImportOptions): Promise<Result<WooProduct[]>> {
177
205
  if (options.products) return Ok(options.products);
178
206
  if (!options.storeUrl || !options.consumerKey || !options.consumerSecret) {
@@ -183,10 +211,19 @@ async function loadProducts(options: WooImportOptions): Promise<Result<WooProduc
183
211
  }
184
212
 
185
213
  const fetchImpl = options.fetchImpl ?? fetch;
186
- return fetchJson<WooProduct[]>(
187
- fetchImpl,
188
- buildWooUrl(options.storeUrl, "/wp-json/wc/v3/products", options.consumerKey, options.consumerSecret),
189
- );
214
+ const products: WooProduct[] = [];
215
+ for (let page = 1; ; page += 1) {
216
+ const response = await fetchJson<WooProduct[]>(
217
+ fetchImpl,
218
+ buildWooUrl(options.storeUrl, "/wp-json/wc/v3/products", options.consumerKey, options.consumerSecret, page),
219
+ );
220
+ if (!response.ok) return response;
221
+ products.push(...response.value.data);
222
+ if (response.value.data.length === 0 || (totalPages(response.value.response) ?? Number.POSITIVE_INFINITY) <= page) {
223
+ break;
224
+ }
225
+ }
226
+ return Ok(products);
190
227
  }
191
228
 
192
229
  async function loadCustomers(options: WooImportOptions): Promise<Result<WooCustomer[]>> {
@@ -196,10 +233,30 @@ async function loadCustomers(options: WooImportOptions): Promise<Result<WooCusto
196
233
  }
197
234
 
198
235
  const fetchImpl = options.fetchImpl ?? fetch;
199
- return fetchJson<WooCustomer[]>(
200
- fetchImpl,
201
- buildWooUrl(options.storeUrl, "/wp-json/wc/v3/customers", options.consumerKey, options.consumerSecret),
236
+ const customers: WooCustomer[] = [];
237
+ for (let page = 1; ; page += 1) {
238
+ const response = await fetchJson<WooCustomer[]>(
239
+ fetchImpl,
240
+ buildWooUrl(options.storeUrl, "/wp-json/wc/v3/customers", options.consumerKey, options.consumerSecret, page),
241
+ );
242
+ if (!response.ok) return response;
243
+ customers.push(...response.value.data);
244
+ if (response.value.data.length === 0 || (totalPages(response.value.response) ?? Number.POSITIVE_INFINITY) <= page) {
245
+ break;
246
+ }
247
+ }
248
+ return Ok(customers);
249
+ }
250
+
251
+ async function loadCurrency(options: WooImportOptions): Promise<string | undefined> {
252
+ const configured = normalizeCurrency(options.currency);
253
+ if (configured) return configured;
254
+ if (!options.storeUrl || !options.consumerKey || !options.consumerSecret) return undefined;
255
+ const response = await fetchJson<unknown>(
256
+ options.fetchImpl ?? fetch,
257
+ buildWooUrl(options.storeUrl, "/wp-json/wc/v3/settings/general", options.consumerKey, options.consumerSecret),
202
258
  );
259
+ return response.ok ? settingCurrency(response.value.data) : undefined;
203
260
  }
204
261
 
205
262
  function filenameFromUrl(url: string): string {
@@ -233,6 +290,7 @@ export async function importWooCommerceCatalog(options: WooImportOptions): Promi
233
290
 
234
291
  const customers = await loadCustomers(options);
235
292
  if (!customers.ok) return customers;
293
+ const currency = await loadCurrency(options);
236
294
 
237
295
  const summary: WooImportSummary = {
238
296
  entitiesImported: 0,
@@ -298,6 +356,8 @@ export async function importWooCommerceCatalog(options: WooImportOptions): Promi
298
356
  const variationData = product.variationsData ?? [];
299
357
  for (const variant of variationData) {
300
358
  try {
359
+ // An unknown store currency falls back to two decimals.
360
+ const price = toMinorUnits(variant.price, currency ?? "");
301
361
  const optionValueIds = (variant.attributes ?? [])
302
362
  .map((attribute) => optionValueIdByKey.get(`${attribute.name}::${attribute.option ?? ""}`))
303
363
  .filter((value): value is string => typeof value === "string");
@@ -309,7 +369,7 @@ export async function importWooCommerceCatalog(options: WooImportOptions): Promi
309
369
  metadata: {
310
370
  source: "woocommerce",
311
371
  wooVariationId: variant.id,
312
- price: variant.price,
372
+ ...(price !== undefined ? { price } : {}),
313
373
  },
314
374
  });
315
375