react-shopwave-connect 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -5
- package/dist/core/index.cjs +630 -510
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +109 -5
- package/dist/core/index.d.ts +109 -5
- package/dist/core/index.js +623 -511
- package/dist/core/index.js.map +1 -1
- package/dist/hooks/index.cjs +287 -188
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +40 -1
- package/dist/hooks/index.d.ts +40 -1
- package/dist/hooks/index.js +286 -189
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +716 -567
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -5
- package/dist/index.d.ts +129 -5
- package/dist/index.js +707 -568
- package/dist/index.js.map +1 -1
- package/dist/next/index.cjs +87 -45
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +65 -7
- package/dist/next/index.d.ts +65 -7
- package/dist/next/index.js +86 -46
- package/dist/next/index.js.map +1 -1
- package/dist/server/index.cjs +84 -45
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +67 -8
- package/dist/server/index.d.ts +67 -8
- package/dist/server/index.js +83 -46
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.d.cts
CHANGED
|
@@ -176,8 +176,9 @@ declare class ShopwaveAuthError extends Error {
|
|
|
176
176
|
//#region src/core/entities.d.ts
|
|
177
177
|
/**
|
|
178
178
|
* How each Shopwave entity is addressed, shared by the client functions below
|
|
179
|
-
* and the server route handlers in `react-shopwave-connect/
|
|
180
|
-
*
|
|
179
|
+
* and the server route handlers in `react-shopwave-connect/server` (wrapped with
|
|
180
|
+
* the session by `react-shopwave-connect/next`), so the two halves of the
|
|
181
|
+
* contract can't drift apart.
|
|
181
182
|
*/
|
|
182
183
|
interface EntityDefinition {
|
|
183
184
|
/** App route segment: `/api/<route>` and `/api/<route>/<id>`. */
|
|
@@ -241,7 +242,7 @@ declare const SHOPWAVE_ENTITIES: Readonly<Record<EntityKind, EntityDefinition>>;
|
|
|
241
242
|
*
|
|
242
243
|
* Like `SHOPWAVE_ENTITIES`, this table is shared by the client functions
|
|
243
244
|
* (`fetchMerchant`, `fetchUser`, `uploadImage`, …) and the server route
|
|
244
|
-
* handlers in `react-shopwave-connect/
|
|
245
|
+
* handlers in `react-shopwave-connect/server`, so the two halves of the contract
|
|
245
246
|
* can't drift apart. These aren't in `SHOPWAVE_ENTITIES` because they aren't
|
|
246
247
|
* keyed collections: `GET /merchant` answers `{ merchant: {…} }`, not a map by id.
|
|
247
248
|
*/
|
|
@@ -274,19 +275,67 @@ declare const SHOPWAVE_RESOURCES: Readonly<Record<ResourceKind, ResourceDefiniti
|
|
|
274
275
|
type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applicationLogo" | "applicationImages";
|
|
275
276
|
/** `UploadKind` → the API's `contentType` value. */
|
|
276
277
|
declare const UPLOAD_KINDS: Readonly<Record<UploadKind, string>>;
|
|
278
|
+
/**
|
|
279
|
+
* The role an image plays, sent to Shopwave as the uploader's `prefix` header.
|
|
280
|
+
* The uploader names the file `<prefix>_<hash>.<ext>`, so the role travels with
|
|
281
|
+
* the file wherever a record stores it (a product's `images`). Live, merchant
|
|
282
|
+
* 5644, 4 Nov 2026: all four values answered 201.
|
|
283
|
+
* - `product`: a product gallery image;
|
|
284
|
+
* - `product_thumbnail`: the product's lead image, shown in lists;
|
|
285
|
+
* - `variant` / `variant_thumbnail`: a variant's own image and its lead image
|
|
286
|
+
* (used by the Connect integrations).
|
|
287
|
+
*
|
|
288
|
+
* Values are the ones Connect's `uploadFileToShopwave` sends.
|
|
289
|
+
*/
|
|
290
|
+
type UploadPrefix = "product" | "product_thumbnail" | "variant" | "variant_thumbnail";
|
|
291
|
+
/** Every `UploadPrefix`, longest first so a name check never takes `product` for `product_thumbnail`. */
|
|
292
|
+
declare const UPLOAD_PREFIXES: ReadonlyArray<UploadPrefix>;
|
|
277
293
|
/** How uploads are addressed (app route and Shopwave uploader). */
|
|
278
294
|
declare const SHOPWAVE_UPLOAD: Readonly<{
|
|
279
|
-
/** App route: `POST /api/<route>` (multipart `file` + `kind`). */
|
|
295
|
+
/** App route: `POST /api/<route>` (multipart `file` + `kind`, optional `prefix`). */
|
|
280
296
|
route: "upload";
|
|
281
297
|
/** Shopwave path: `PUT {apiUrl}/uploader` (multipart `file`). */
|
|
282
298
|
upstream: "uploader";
|
|
283
299
|
/** Header that carries the upload kind upstream. */
|
|
284
300
|
kindHeader: "contentType";
|
|
301
|
+
/** Header that carries the image role upstream (see `UploadPrefix`). */
|
|
302
|
+
prefixHeader: "prefix";
|
|
285
303
|
/** Multipart field name for the file, on both sides. */
|
|
286
304
|
fileField: "file";
|
|
287
305
|
/** Multipart field name for the kind in the app request. */
|
|
288
306
|
kindField: "kind";
|
|
307
|
+
/** Multipart field name for the image role in the app request. */
|
|
308
|
+
prefixField: "prefix";
|
|
289
309
|
}>;
|
|
310
|
+
/**
|
|
311
|
+
* Read-only lists that aren't records: the merchant's distinct tags.
|
|
312
|
+
*
|
|
313
|
+
* Like `SHOPWAVE_RESOURCES`, shared by the client functions
|
|
314
|
+
* (`fetchProductTags`, `fetchProductInstanceTags`) and the server route
|
|
315
|
+
* handlers (`shopwave.lookup(kind)`), so the two halves can't drift apart.
|
|
316
|
+
*
|
|
317
|
+
* - productTags: `GET /product/tags` → `{ tags: string[] }`, every distinct tag
|
|
318
|
+
* on the merchant's products. No parameters. The API reference says
|
|
319
|
+
* "internal SKU tags are excluded", but the live API includes system tags
|
|
320
|
+
* written by imports and syncs (`PID-133`, `VID-137`, `#Hash:…`, `upc-…`;
|
|
321
|
+
* test merchant 5644, 29 Oct 2026). Apps that offer the list as suggestions
|
|
322
|
+
* filter those themselves. Tags of deleted products drop out of the list.
|
|
323
|
+
* - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
|
|
324
|
+
* the same for price instances (channels such as "Eat In", "Takeout").
|
|
325
|
+
*
|
|
326
|
+
* The app route for instance tags is `products/instance-tags`, one segment
|
|
327
|
+
* under `products`, so it sits beside `products/[id]` without nesting deeper.
|
|
328
|
+
*/
|
|
329
|
+
interface LookupDefinition {
|
|
330
|
+
/** App route: `/api/<route>`. */
|
|
331
|
+
route: string;
|
|
332
|
+
/** Key of the list in the response (`{ tags: [...] }`). */
|
|
333
|
+
key: string;
|
|
334
|
+
/** Shopwave API path. */
|
|
335
|
+
upstream: string;
|
|
336
|
+
}
|
|
337
|
+
type LookupKind = "productTags" | "productInstanceTags";
|
|
338
|
+
declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
|
|
290
339
|
//#endregion
|
|
291
340
|
//#region src/server/api.d.ts
|
|
292
341
|
/**
|
|
@@ -415,9 +464,11 @@ interface UploadOptions {
|
|
|
415
464
|
}
|
|
416
465
|
interface UploadHandlers {
|
|
417
466
|
/**
|
|
418
|
-
* Multipart `file` + `kind` (see `UploadKind`)
|
|
419
|
-
*
|
|
420
|
-
*
|
|
467
|
+
* Multipart `file` + `kind` (see `UploadKind`), and optionally `prefix`
|
|
468
|
+
* (see `UploadPrefix`) → `PUT {apiUrl}/uploader` with the `contentType` and
|
|
469
|
+
* `prefix` headers. Answers with Shopwave's reply (201 `{ fileName, path, api }`);
|
|
470
|
+
* 400 for a missing file or an unknown kind or prefix, 413 when too large,
|
|
471
|
+
* 415 for other types.
|
|
421
472
|
*/
|
|
422
473
|
POST: RouteHandler;
|
|
423
474
|
}
|
|
@@ -434,6 +485,14 @@ interface ShopwaveApiHandlers {
|
|
|
434
485
|
passthrough(path: string): {
|
|
435
486
|
GET: RouteHandler;
|
|
436
487
|
};
|
|
488
|
+
/**
|
|
489
|
+
* Handler for a read-only list (see `SHOPWAVE_LOOKUPS`), e.g.
|
|
490
|
+
* `app/api/products/tags/route.ts`: `export const { GET } = shopwave.lookup("productTags")`.
|
|
491
|
+
* Takes no parameters, so the caller's `extras` aren't forwarded.
|
|
492
|
+
*/
|
|
493
|
+
lookup(kind: LookupKind): {
|
|
494
|
+
GET: RouteHandler;
|
|
495
|
+
};
|
|
437
496
|
/** Handlers for a singleton resource: `app/api/merchant/route.ts`, `app/api/user/route.ts`. */
|
|
438
497
|
resource(kind: ResourceKind): ResourceHandlers;
|
|
439
498
|
/** Handler for `app/api/upload/route.ts`. */
|
|
@@ -445,5 +504,5 @@ interface ShopwaveApiHandlers {
|
|
|
445
504
|
declare function shopwaveDateTime(date?: Date): string;
|
|
446
505
|
declare function createShopwaveApiHandlers(config: ShopwaveApiConfig): ShopwaveApiHandlers;
|
|
447
506
|
//#endregion
|
|
448
|
-
export { BLOCKED_EXTRAS, type CollectionHandlers, type DeletableEntityKind, type EntityDefinition, type EntityKind, type ForwardInit, type ItemHandlers, RequestBodyError, type ResourceDefinition, type ResourceHandlers, type ResourceKind, type RouteContext, type RouteHandler, SHOPWAVE_ENTITIES, SHOPWAVE_RESOURCES, SHOPWAVE_TOKEN_EXPIRED_ERROR_ID, SHOPWAVE_UPLOAD, type ShopwaveApiConfig, type ShopwaveApiHandlers, ShopwaveAuthError, type ShopwaveAuthErrorCode, type ShopwaveOAuthClient, type ShopwaveOAuthConfig, type ShopwaveToken, type ShopwaveTokenResponse, UPLOAD_KINDS, type UploadHandlers, type UploadKind, type UploadOptions, type WritableEntityKind, assertOAuthConfig, authorizationHeader, createShopwaveApiHandlers, createShopwaveOAuth, createState, isExpiredTokenResponse, isTokenExpired, normalizeStoredToken, normalizeWriteBody, parseExtras, readRequestToken, safeEqual, sanitizeReturnTo, shopwaveDateTime, tokenFromResponse };
|
|
507
|
+
export { BLOCKED_EXTRAS, type CollectionHandlers, type DeletableEntityKind, type EntityDefinition, type EntityKind, type ForwardInit, type ItemHandlers, type LookupDefinition, type LookupKind, RequestBodyError, type ResourceDefinition, type ResourceHandlers, type ResourceKind, type RouteContext, type RouteHandler, SHOPWAVE_ENTITIES, SHOPWAVE_LOOKUPS, SHOPWAVE_RESOURCES, SHOPWAVE_TOKEN_EXPIRED_ERROR_ID, SHOPWAVE_UPLOAD, type ShopwaveApiConfig, type ShopwaveApiHandlers, ShopwaveAuthError, type ShopwaveAuthErrorCode, type ShopwaveOAuthClient, type ShopwaveOAuthConfig, type ShopwaveToken, type ShopwaveTokenResponse, UPLOAD_KINDS, UPLOAD_PREFIXES, type UploadHandlers, type UploadKind, type UploadOptions, type UploadPrefix, type WritableEntityKind, assertOAuthConfig, authorizationHeader, createShopwaveApiHandlers, createShopwaveOAuth, createState, isExpiredTokenResponse, isTokenExpired, normalizeStoredToken, normalizeWriteBody, parseExtras, readRequestToken, safeEqual, sanitizeReturnTo, shopwaveDateTime, tokenFromResponse };
|
|
449
508
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/server/index.d.ts
CHANGED
|
@@ -176,8 +176,9 @@ declare class ShopwaveAuthError extends Error {
|
|
|
176
176
|
//#region src/core/entities.d.ts
|
|
177
177
|
/**
|
|
178
178
|
* How each Shopwave entity is addressed, shared by the client functions below
|
|
179
|
-
* and the server route handlers in `react-shopwave-connect/
|
|
180
|
-
*
|
|
179
|
+
* and the server route handlers in `react-shopwave-connect/server` (wrapped with
|
|
180
|
+
* the session by `react-shopwave-connect/next`), so the two halves of the
|
|
181
|
+
* contract can't drift apart.
|
|
181
182
|
*/
|
|
182
183
|
interface EntityDefinition {
|
|
183
184
|
/** App route segment: `/api/<route>` and `/api/<route>/<id>`. */
|
|
@@ -241,7 +242,7 @@ declare const SHOPWAVE_ENTITIES: Readonly<Record<EntityKind, EntityDefinition>>;
|
|
|
241
242
|
*
|
|
242
243
|
* Like `SHOPWAVE_ENTITIES`, this table is shared by the client functions
|
|
243
244
|
* (`fetchMerchant`, `fetchUser`, `uploadImage`, …) and the server route
|
|
244
|
-
* handlers in `react-shopwave-connect/
|
|
245
|
+
* handlers in `react-shopwave-connect/server`, so the two halves of the contract
|
|
245
246
|
* can't drift apart. These aren't in `SHOPWAVE_ENTITIES` because they aren't
|
|
246
247
|
* keyed collections: `GET /merchant` answers `{ merchant: {…} }`, not a map by id.
|
|
247
248
|
*/
|
|
@@ -274,19 +275,67 @@ declare const SHOPWAVE_RESOURCES: Readonly<Record<ResourceKind, ResourceDefiniti
|
|
|
274
275
|
type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applicationLogo" | "applicationImages";
|
|
275
276
|
/** `UploadKind` → the API's `contentType` value. */
|
|
276
277
|
declare const UPLOAD_KINDS: Readonly<Record<UploadKind, string>>;
|
|
278
|
+
/**
|
|
279
|
+
* The role an image plays, sent to Shopwave as the uploader's `prefix` header.
|
|
280
|
+
* The uploader names the file `<prefix>_<hash>.<ext>`, so the role travels with
|
|
281
|
+
* the file wherever a record stores it (a product's `images`). Live, merchant
|
|
282
|
+
* 5644, 4 Nov 2026: all four values answered 201.
|
|
283
|
+
* - `product`: a product gallery image;
|
|
284
|
+
* - `product_thumbnail`: the product's lead image, shown in lists;
|
|
285
|
+
* - `variant` / `variant_thumbnail`: a variant's own image and its lead image
|
|
286
|
+
* (used by the Connect integrations).
|
|
287
|
+
*
|
|
288
|
+
* Values are the ones Connect's `uploadFileToShopwave` sends.
|
|
289
|
+
*/
|
|
290
|
+
type UploadPrefix = "product" | "product_thumbnail" | "variant" | "variant_thumbnail";
|
|
291
|
+
/** Every `UploadPrefix`, longest first so a name check never takes `product` for `product_thumbnail`. */
|
|
292
|
+
declare const UPLOAD_PREFIXES: ReadonlyArray<UploadPrefix>;
|
|
277
293
|
/** How uploads are addressed (app route and Shopwave uploader). */
|
|
278
294
|
declare const SHOPWAVE_UPLOAD: Readonly<{
|
|
279
|
-
/** App route: `POST /api/<route>` (multipart `file` + `kind`). */
|
|
295
|
+
/** App route: `POST /api/<route>` (multipart `file` + `kind`, optional `prefix`). */
|
|
280
296
|
route: "upload";
|
|
281
297
|
/** Shopwave path: `PUT {apiUrl}/uploader` (multipart `file`). */
|
|
282
298
|
upstream: "uploader";
|
|
283
299
|
/** Header that carries the upload kind upstream. */
|
|
284
300
|
kindHeader: "contentType";
|
|
301
|
+
/** Header that carries the image role upstream (see `UploadPrefix`). */
|
|
302
|
+
prefixHeader: "prefix";
|
|
285
303
|
/** Multipart field name for the file, on both sides. */
|
|
286
304
|
fileField: "file";
|
|
287
305
|
/** Multipart field name for the kind in the app request. */
|
|
288
306
|
kindField: "kind";
|
|
307
|
+
/** Multipart field name for the image role in the app request. */
|
|
308
|
+
prefixField: "prefix";
|
|
289
309
|
}>;
|
|
310
|
+
/**
|
|
311
|
+
* Read-only lists that aren't records: the merchant's distinct tags.
|
|
312
|
+
*
|
|
313
|
+
* Like `SHOPWAVE_RESOURCES`, shared by the client functions
|
|
314
|
+
* (`fetchProductTags`, `fetchProductInstanceTags`) and the server route
|
|
315
|
+
* handlers (`shopwave.lookup(kind)`), so the two halves can't drift apart.
|
|
316
|
+
*
|
|
317
|
+
* - productTags: `GET /product/tags` → `{ tags: string[] }`, every distinct tag
|
|
318
|
+
* on the merchant's products. No parameters. The API reference says
|
|
319
|
+
* "internal SKU tags are excluded", but the live API includes system tags
|
|
320
|
+
* written by imports and syncs (`PID-133`, `VID-137`, `#Hash:…`, `upc-…`;
|
|
321
|
+
* test merchant 5644, 29 Oct 2026). Apps that offer the list as suggestions
|
|
322
|
+
* filter those themselves. Tags of deleted products drop out of the list.
|
|
323
|
+
* - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
|
|
324
|
+
* the same for price instances (channels such as "Eat In", "Takeout").
|
|
325
|
+
*
|
|
326
|
+
* The app route for instance tags is `products/instance-tags`, one segment
|
|
327
|
+
* under `products`, so it sits beside `products/[id]` without nesting deeper.
|
|
328
|
+
*/
|
|
329
|
+
interface LookupDefinition {
|
|
330
|
+
/** App route: `/api/<route>`. */
|
|
331
|
+
route: string;
|
|
332
|
+
/** Key of the list in the response (`{ tags: [...] }`). */
|
|
333
|
+
key: string;
|
|
334
|
+
/** Shopwave API path. */
|
|
335
|
+
upstream: string;
|
|
336
|
+
}
|
|
337
|
+
type LookupKind = "productTags" | "productInstanceTags";
|
|
338
|
+
declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
|
|
290
339
|
//#endregion
|
|
291
340
|
//#region src/server/api.d.ts
|
|
292
341
|
/**
|
|
@@ -415,9 +464,11 @@ interface UploadOptions {
|
|
|
415
464
|
}
|
|
416
465
|
interface UploadHandlers {
|
|
417
466
|
/**
|
|
418
|
-
* Multipart `file` + `kind` (see `UploadKind`)
|
|
419
|
-
*
|
|
420
|
-
*
|
|
467
|
+
* Multipart `file` + `kind` (see `UploadKind`), and optionally `prefix`
|
|
468
|
+
* (see `UploadPrefix`) → `PUT {apiUrl}/uploader` with the `contentType` and
|
|
469
|
+
* `prefix` headers. Answers with Shopwave's reply (201 `{ fileName, path, api }`);
|
|
470
|
+
* 400 for a missing file or an unknown kind or prefix, 413 when too large,
|
|
471
|
+
* 415 for other types.
|
|
421
472
|
*/
|
|
422
473
|
POST: RouteHandler;
|
|
423
474
|
}
|
|
@@ -434,6 +485,14 @@ interface ShopwaveApiHandlers {
|
|
|
434
485
|
passthrough(path: string): {
|
|
435
486
|
GET: RouteHandler;
|
|
436
487
|
};
|
|
488
|
+
/**
|
|
489
|
+
* Handler for a read-only list (see `SHOPWAVE_LOOKUPS`), e.g.
|
|
490
|
+
* `app/api/products/tags/route.ts`: `export const { GET } = shopwave.lookup("productTags")`.
|
|
491
|
+
* Takes no parameters, so the caller's `extras` aren't forwarded.
|
|
492
|
+
*/
|
|
493
|
+
lookup(kind: LookupKind): {
|
|
494
|
+
GET: RouteHandler;
|
|
495
|
+
};
|
|
437
496
|
/** Handlers for a singleton resource: `app/api/merchant/route.ts`, `app/api/user/route.ts`. */
|
|
438
497
|
resource(kind: ResourceKind): ResourceHandlers;
|
|
439
498
|
/** Handler for `app/api/upload/route.ts`. */
|
|
@@ -445,5 +504,5 @@ interface ShopwaveApiHandlers {
|
|
|
445
504
|
declare function shopwaveDateTime(date?: Date): string;
|
|
446
505
|
declare function createShopwaveApiHandlers(config: ShopwaveApiConfig): ShopwaveApiHandlers;
|
|
447
506
|
//#endregion
|
|
448
|
-
export { BLOCKED_EXTRAS, type CollectionHandlers, type DeletableEntityKind, type EntityDefinition, type EntityKind, type ForwardInit, type ItemHandlers, RequestBodyError, type ResourceDefinition, type ResourceHandlers, type ResourceKind, type RouteContext, type RouteHandler, SHOPWAVE_ENTITIES, SHOPWAVE_RESOURCES, SHOPWAVE_TOKEN_EXPIRED_ERROR_ID, SHOPWAVE_UPLOAD, type ShopwaveApiConfig, type ShopwaveApiHandlers, ShopwaveAuthError, type ShopwaveAuthErrorCode, type ShopwaveOAuthClient, type ShopwaveOAuthConfig, type ShopwaveToken, type ShopwaveTokenResponse, UPLOAD_KINDS, type UploadHandlers, type UploadKind, type UploadOptions, type WritableEntityKind, assertOAuthConfig, authorizationHeader, createShopwaveApiHandlers, createShopwaveOAuth, createState, isExpiredTokenResponse, isTokenExpired, normalizeStoredToken, normalizeWriteBody, parseExtras, readRequestToken, safeEqual, sanitizeReturnTo, shopwaveDateTime, tokenFromResponse };
|
|
507
|
+
export { BLOCKED_EXTRAS, type CollectionHandlers, type DeletableEntityKind, type EntityDefinition, type EntityKind, type ForwardInit, type ItemHandlers, type LookupDefinition, type LookupKind, RequestBodyError, type ResourceDefinition, type ResourceHandlers, type ResourceKind, type RouteContext, type RouteHandler, SHOPWAVE_ENTITIES, SHOPWAVE_LOOKUPS, SHOPWAVE_RESOURCES, SHOPWAVE_TOKEN_EXPIRED_ERROR_ID, SHOPWAVE_UPLOAD, type ShopwaveApiConfig, type ShopwaveApiHandlers, ShopwaveAuthError, type ShopwaveAuthErrorCode, type ShopwaveOAuthClient, type ShopwaveOAuthConfig, type ShopwaveToken, type ShopwaveTokenResponse, UPLOAD_KINDS, UPLOAD_PREFIXES, type UploadHandlers, type UploadKind, type UploadOptions, type UploadPrefix, type WritableEntityKind, assertOAuthConfig, authorizationHeader, createShopwaveApiHandlers, createShopwaveOAuth, createState, isExpiredTokenResponse, isTokenExpired, normalizeStoredToken, normalizeWriteBody, parseExtras, readRequestToken, safeEqual, sanitizeReturnTo, shopwaveDateTime, tokenFromResponse };
|
|
449
508
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/server/index.js
CHANGED
|
@@ -244,6 +244,74 @@ function safeEqual(a, b) {
|
|
|
244
244
|
return diff === 0;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/core/resources.ts
|
|
249
|
+
/**
|
|
250
|
+
* - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
|
|
251
|
+
* updates it (without an `id` the API would create a second merchant, so the
|
|
252
|
+
* route requires one).
|
|
253
|
+
* - user: `GET /user` (read-only here; the API's `POST /user` invites users and
|
|
254
|
+
* needs the admin scope).
|
|
255
|
+
*/
|
|
256
|
+
const SHOPWAVE_RESOURCES = Object.freeze({
|
|
257
|
+
merchant: {
|
|
258
|
+
route: "merchant",
|
|
259
|
+
key: "merchant",
|
|
260
|
+
upstream: "merchant",
|
|
261
|
+
writable: true
|
|
262
|
+
},
|
|
263
|
+
user: {
|
|
264
|
+
route: "user",
|
|
265
|
+
key: "user",
|
|
266
|
+
upstream: "user",
|
|
267
|
+
writable: false
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
/** `UploadKind` → the API's `contentType` value. */
|
|
271
|
+
const UPLOAD_KINDS = Object.freeze({
|
|
272
|
+
merchant: "merchant",
|
|
273
|
+
merchantFeature: "merchantFeature",
|
|
274
|
+
product: "product",
|
|
275
|
+
user: "user",
|
|
276
|
+
applicationLogo: "applicaionLogo",
|
|
277
|
+
applicationImages: "applicaionImages"
|
|
278
|
+
});
|
|
279
|
+
/** Every `UploadPrefix`, longest first so a name check never takes `product` for `product_thumbnail`. */
|
|
280
|
+
const UPLOAD_PREFIXES = Object.freeze([
|
|
281
|
+
"product_thumbnail",
|
|
282
|
+
"variant_thumbnail",
|
|
283
|
+
"product",
|
|
284
|
+
"variant"
|
|
285
|
+
]);
|
|
286
|
+
/** How uploads are addressed (app route and Shopwave uploader). */
|
|
287
|
+
const SHOPWAVE_UPLOAD = Object.freeze({
|
|
288
|
+
route: "upload",
|
|
289
|
+
upstream: "uploader",
|
|
290
|
+
kindHeader: "contentType",
|
|
291
|
+
prefixHeader: "prefix",
|
|
292
|
+
fileField: "file",
|
|
293
|
+
kindField: "kind",
|
|
294
|
+
prefixField: "prefix"
|
|
295
|
+
});
|
|
296
|
+
function isUploadKind(value) {
|
|
297
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
|
|
298
|
+
}
|
|
299
|
+
function isUploadPrefix(value) {
|
|
300
|
+
return typeof value === "string" && UPLOAD_PREFIXES.includes(value);
|
|
301
|
+
}
|
|
302
|
+
const SHOPWAVE_LOOKUPS = Object.freeze({
|
|
303
|
+
productTags: {
|
|
304
|
+
route: "products/tags",
|
|
305
|
+
key: "tags",
|
|
306
|
+
upstream: "product/tags"
|
|
307
|
+
},
|
|
308
|
+
productInstanceTags: {
|
|
309
|
+
route: "products/instance-tags",
|
|
310
|
+
key: "tags",
|
|
311
|
+
upstream: "product/instance/tags"
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
247
315
|
//#endregion
|
|
248
316
|
//#region src/core/entities.ts
|
|
249
317
|
/**
|
|
@@ -320,50 +388,6 @@ const SHOPWAVE_ENTITIES = Object.freeze({
|
|
|
320
388
|
}
|
|
321
389
|
});
|
|
322
390
|
|
|
323
|
-
//#endregion
|
|
324
|
-
//#region src/core/resources.ts
|
|
325
|
-
/**
|
|
326
|
-
* - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
|
|
327
|
-
* updates it (without an `id` the API would create a second merchant, so the
|
|
328
|
-
* route requires one).
|
|
329
|
-
* - user: `GET /user` (read-only here; the API's `POST /user` invites users and
|
|
330
|
-
* needs the admin scope).
|
|
331
|
-
*/
|
|
332
|
-
const SHOPWAVE_RESOURCES = Object.freeze({
|
|
333
|
-
merchant: {
|
|
334
|
-
route: "merchant",
|
|
335
|
-
key: "merchant",
|
|
336
|
-
upstream: "merchant",
|
|
337
|
-
writable: true
|
|
338
|
-
},
|
|
339
|
-
user: {
|
|
340
|
-
route: "user",
|
|
341
|
-
key: "user",
|
|
342
|
-
upstream: "user",
|
|
343
|
-
writable: false
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
/** `UploadKind` → the API's `contentType` value. */
|
|
347
|
-
const UPLOAD_KINDS = Object.freeze({
|
|
348
|
-
merchant: "merchant",
|
|
349
|
-
merchantFeature: "merchantFeature",
|
|
350
|
-
product: "product",
|
|
351
|
-
user: "user",
|
|
352
|
-
applicationLogo: "applicaionLogo",
|
|
353
|
-
applicationImages: "applicaionImages"
|
|
354
|
-
});
|
|
355
|
-
/** How uploads are addressed (app route and Shopwave uploader). */
|
|
356
|
-
const SHOPWAVE_UPLOAD = Object.freeze({
|
|
357
|
-
route: "upload",
|
|
358
|
-
upstream: "uploader",
|
|
359
|
-
kindHeader: "contentType",
|
|
360
|
-
fileField: "file",
|
|
361
|
-
kindField: "kind"
|
|
362
|
-
});
|
|
363
|
-
function isUploadKind(value) {
|
|
364
|
-
return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
391
|
//#endregion
|
|
368
392
|
//#region src/server/api.ts
|
|
369
393
|
/**
|
|
@@ -692,6 +716,8 @@ function createShopwaveApiHandlers(config) {
|
|
|
692
716
|
if (!file || typeof file === "string" || file.size === 0) return jsonError(400, "invalid_body", `Missing "${SHOPWAVE_UPLOAD.fileField}"`);
|
|
693
717
|
const kind = form.get(SHOPWAVE_UPLOAD.kindField);
|
|
694
718
|
if (!isUploadKind(kind)) return jsonError(400, "invalid_body", `"${SHOPWAVE_UPLOAD.kindField}" must be one of ${Object.keys(UPLOAD_KINDS).join(", ")}`);
|
|
719
|
+
const prefix = form.get(SHOPWAVE_UPLOAD.prefixField);
|
|
720
|
+
if (prefix !== null && !isUploadPrefix(prefix)) return jsonError(400, "invalid_body", `"${SHOPWAVE_UPLOAD.prefixField}" must be one of ${UPLOAD_PREFIXES.join(", ")}`);
|
|
695
721
|
if (file.size > maxBytes) return jsonError(413, "too_large", `The file is larger than ${maxBytes} bytes`);
|
|
696
722
|
if (!acceptsType(file.type || "", accept)) return jsonError(415, "unsupported_type", `Files of type "${file.type || "unknown"}" aren't accepted`);
|
|
697
723
|
const upstreamForm = new FormData();
|
|
@@ -699,7 +725,10 @@ function createShopwaveApiHandlers(config) {
|
|
|
699
725
|
return forward(request, {
|
|
700
726
|
method: "PUT",
|
|
701
727
|
path: SHOPWAVE_UPLOAD.upstream,
|
|
702
|
-
headers: {
|
|
728
|
+
headers: {
|
|
729
|
+
[SHOPWAVE_UPLOAD.kindHeader]: UPLOAD_KINDS[kind],
|
|
730
|
+
...prefix !== null ? { [SHOPWAVE_UPLOAD.prefixHeader]: prefix } : {}
|
|
731
|
+
},
|
|
703
732
|
formData: upstreamForm,
|
|
704
733
|
forwardExtras: false
|
|
705
734
|
});
|
|
@@ -804,6 +833,14 @@ function createShopwaveApiHandlers(config) {
|
|
|
804
833
|
passthrough(path) {
|
|
805
834
|
return { GET: (request) => forward(request, { path }) };
|
|
806
835
|
},
|
|
836
|
+
lookup(kind) {
|
|
837
|
+
const def = SHOPWAVE_LOOKUPS[kind];
|
|
838
|
+
if (!def) throw new Error(`Unknown Shopwave lookup "${kind}"`);
|
|
839
|
+
return { GET: (request) => forward(request, {
|
|
840
|
+
path: def.upstream,
|
|
841
|
+
forwardExtras: false
|
|
842
|
+
}) };
|
|
843
|
+
},
|
|
807
844
|
resource(kind) {
|
|
808
845
|
const def = resourceDef(kind);
|
|
809
846
|
const save = (request) => writeResource(request, def);
|
|
@@ -820,5 +857,5 @@ function createShopwaveApiHandlers(config) {
|
|
|
820
857
|
}
|
|
821
858
|
|
|
822
859
|
//#endregion
|
|
823
|
-
export { BLOCKED_EXTRAS, RequestBodyError, SHOPWAVE_ENTITIES, SHOPWAVE_RESOURCES, SHOPWAVE_TOKEN_EXPIRED_ERROR_ID, SHOPWAVE_UPLOAD, ShopwaveAuthError, UPLOAD_KINDS, assertOAuthConfig, authorizationHeader, createShopwaveApiHandlers, createShopwaveOAuth, createState, isExpiredTokenResponse, isTokenExpired, normalizeStoredToken, normalizeWriteBody, parseExtras, readRequestToken, safeEqual, sanitizeReturnTo, shopwaveDateTime, tokenFromResponse };
|
|
860
|
+
export { BLOCKED_EXTRAS, RequestBodyError, SHOPWAVE_ENTITIES, SHOPWAVE_LOOKUPS, SHOPWAVE_RESOURCES, SHOPWAVE_TOKEN_EXPIRED_ERROR_ID, SHOPWAVE_UPLOAD, ShopwaveAuthError, UPLOAD_KINDS, UPLOAD_PREFIXES, assertOAuthConfig, authorizationHeader, createShopwaveApiHandlers, createShopwaveOAuth, createState, isExpiredTokenResponse, isTokenExpired, normalizeStoredToken, normalizeWriteBody, parseExtras, readRequestToken, safeEqual, sanitizeReturnTo, shopwaveDateTime, tokenFromResponse };
|
|
824
861
|
//# sourceMappingURL=index.js.map
|