@decocms/apps-wake 8.1.0-next.0 → 8.1.0-next.2
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 +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/storefront.d.ts +14 -0
- package/dist/storefront.d.ts.map +1 -0
- package/dist/storefront.js +14 -0
- package/dist/storefront.js.map +1 -0
- package/dist/storefrontTypes.d.ts +7 -0
- package/dist/storefrontTypes.d.ts.map +1 -0
- package/dist/storefrontTypes.js +2 -0
- package/dist/storefrontTypes.js.map +1 -0
- package/dist/utils/client.d.ts +12 -0
- package/dist/utils/client.d.ts.map +1 -0
- package/dist/utils/client.js +2 -0
- package/dist/utils/client.js.map +1 -0
- package/dist/utils/gql.d.ts +16 -0
- package/dist/utils/gql.d.ts.map +1 -0
- package/dist/utils/gql.js +16 -0
- package/dist/utils/gql.js.map +1 -0
- package/dist/utils/graphql/queries.d.ts +117 -0
- package/dist/utils/graphql/queries.d.ts.map +1 -0
- package/dist/utils/graphql/queries.js +1323 -0
- package/dist/utils/graphql/queries.js.map +1 -0
- package/dist/utils/graphql/storefront.graphql.gen.d.ts +10344 -0
- package/dist/utils/graphql/storefront.graphql.gen.d.ts.map +1 -0
- package/dist/utils/graphql/storefront.graphql.gen.js +9 -0
- package/dist/utils/graphql/storefront.graphql.gen.js.map +1 -0
- package/dist/utils/graphqlOperationName.d.ts +36 -0
- package/dist/utils/graphqlOperationName.d.ts.map +1 -0
- package/dist/utils/graphqlOperationName.js +59 -0
- package/dist/utils/graphqlOperationName.js.map +1 -0
- package/dist/wakeClient.d.ts +54 -0
- package/dist/wakeClient.d.ts.map +1 -0
- package/dist/wakeClient.js +85 -0
- package/dist/wakeClient.js.map +1 -0
- package/package.json +26 -37
- package/src/index.ts +3 -63
- package/src/storefront.ts +1 -1
- package/src/storefrontTypes.ts +1 -1
- package/src/utils/gql.ts +1 -2
- package/src/utils/graphql/queries.ts +1 -1
- package/src/wakeClient.ts +3 -3
- package/src/__tests__/wakeClient.test.ts +0 -136
- package/src/actions/cart/addCoupon.ts +0 -43
- package/src/actions/cart/addItem.ts +0 -10
- package/src/actions/cart/addItems.ts +0 -50
- package/src/actions/cart/addKit.ts +0 -53
- package/src/actions/cart/partnerAssociate.ts +0 -48
- package/src/actions/cart/partnerDisassociate.ts +0 -43
- package/src/actions/cart/removeCoupon.ts +0 -39
- package/src/actions/cart/removeKit.ts +0 -56
- package/src/actions/cart/updateItemQuantity.ts +0 -69
- package/src/actions/newsletter/register.ts +0 -32
- package/src/actions/notifyme.ts +0 -28
- package/src/actions/review/create.ts +0 -30
- package/src/actions/shippingSimulation.ts +0 -60
- package/src/actions/submmitForm.ts +0 -25
- package/src/actions/wishlist/addProduct.ts +0 -43
- package/src/actions/wishlist/removeProduct.ts +0 -45
- package/src/client.ts +0 -123
- package/src/commerceLoaders.ts +0 -137
- package/src/handlers/sitemap.ts +0 -61
- package/src/loaders/cart.ts +0 -46
- package/src/loaders/partners.ts +0 -58
- package/src/loaders/productDetailsPage.ts +0 -174
- package/src/loaders/productList.ts +0 -262
- package/src/loaders/productListingPage.ts +0 -333
- package/src/loaders/proxy.ts +0 -79
- package/src/loaders/recommendations.ts +0 -84
- package/src/loaders/shop.ts +0 -37
- package/src/loaders/suggestion.ts +0 -67
- package/src/loaders/user.ts +0 -48
- package/src/loaders/wishlist.ts +0 -40
- package/src/manifest.gen.ts +0 -69
- package/src/mod.ts +0 -88
- package/src/registry.ts +0 -9
- package/src/utils/authError.ts +0 -107
- package/src/utils/authenticate.ts +0 -42
- package/src/utils/capitalize.ts +0 -9
- package/src/utils/cart.ts +0 -33
- package/src/utils/cookies.ts +0 -82
- package/src/utils/getVariations.ts +0 -47
- package/src/utils/graphql.ts +0 -72
- package/src/utils/httpError.ts +0 -15
- package/src/utils/instrumentedFetch.ts +0 -46
- package/src/utils/operationRouter.ts +0 -51
- package/src/utils/parseHeaders.ts +0 -19
- package/src/utils/partner.ts +0 -34
- package/src/utils/requestCtx.ts +0 -41
- package/src/utils/transform.ts +0 -460
- package/src/utils/types.ts +0 -6
- package/src/utils/user.ts +0 -9
- package/tsconfig.json +0 -7
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// deno-fmt-ignore-file
|
|
2
|
+
// deno-lint-ignore-file no-explicit-any ban-types ban-unused-ignore
|
|
3
|
+
//
|
|
4
|
+
// DO NOT EDIT. This file is generated by deco.
|
|
5
|
+
// This file SHOULD be checked into source version control.
|
|
6
|
+
// To generate this file: deno task start
|
|
7
|
+
//
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=storefront.graphql.gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront.graphql.gen.js","sourceRoot":"","sources":["../../../src/utils/graphql/storefront.graphql.gen.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,oEAAoE;AACpE,EAAE;AACF,+CAA+C;AAC/C,2DAA2D;AAC3D,yCAAyC;AACzC,EAAE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a semantic operation name from a GraphQL document.
|
|
3
|
+
*
|
|
4
|
+
* Used at the Shopify GraphQL client layer to stamp `init.operation`
|
|
5
|
+
* on the outbound fetch. The framework then suffixes the integration
|
|
6
|
+
* name (`shopify.<operation>`) onto the span and uses the same string
|
|
7
|
+
* as the `fetch.operation` attribute + histogram label.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order:
|
|
10
|
+
*
|
|
11
|
+
* 1. An explicit `operationName` argument (e.g. when the client
|
|
12
|
+
* received one alongside a multi-operation document) wins.
|
|
13
|
+
* 2. If the document has exactly one named operation, that name
|
|
14
|
+
* is used.
|
|
15
|
+
* 3. If the document has zero or many anonymous operations, we
|
|
16
|
+
* return `undefined` so the caller can fall back (typically to
|
|
17
|
+
* the URL-derived `storefront.graphql` / `admin.graphql`).
|
|
18
|
+
*
|
|
19
|
+
* The parser is deliberately a small regex pass, not a full GraphQL
|
|
20
|
+
* tokenizer:
|
|
21
|
+
*
|
|
22
|
+
* - GraphQL operation definitions live at the top level of the
|
|
23
|
+
* document, never nested inside other operations, fragments, or
|
|
24
|
+
* selection sets, so positional context isn't required to find
|
|
25
|
+
* them — only to not match the literal words `query` /
|
|
26
|
+
* `mutation` / `subscription` inside string values.
|
|
27
|
+
* - We strip block strings (`""" … """`), string literals
|
|
28
|
+
* (`"…"`), and `# …` comments before matching, which is enough
|
|
29
|
+
* to make false-positive matches inside comments / docs vanish.
|
|
30
|
+
*
|
|
31
|
+
* If a Shopify operation is ever sufficiently mis-named to break
|
|
32
|
+
* this (unlikely, since the storefront SDK names them deliberately),
|
|
33
|
+
* the caller can always set `init.operation` explicitly.
|
|
34
|
+
*/
|
|
35
|
+
export declare function extractGraphqlOperationName(document: string, explicit?: string): string | undefined;
|
|
36
|
+
//# sourceMappingURL=graphqlOperationName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphqlOperationName.d.ts","sourceRoot":"","sources":["../../src/utils/graphqlOperationName.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAUH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAoBpB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a semantic operation name from a GraphQL document.
|
|
3
|
+
*
|
|
4
|
+
* Used at the Shopify GraphQL client layer to stamp `init.operation`
|
|
5
|
+
* on the outbound fetch. The framework then suffixes the integration
|
|
6
|
+
* name (`shopify.<operation>`) onto the span and uses the same string
|
|
7
|
+
* as the `fetch.operation` attribute + histogram label.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order:
|
|
10
|
+
*
|
|
11
|
+
* 1. An explicit `operationName` argument (e.g. when the client
|
|
12
|
+
* received one alongside a multi-operation document) wins.
|
|
13
|
+
* 2. If the document has exactly one named operation, that name
|
|
14
|
+
* is used.
|
|
15
|
+
* 3. If the document has zero or many anonymous operations, we
|
|
16
|
+
* return `undefined` so the caller can fall back (typically to
|
|
17
|
+
* the URL-derived `storefront.graphql` / `admin.graphql`).
|
|
18
|
+
*
|
|
19
|
+
* The parser is deliberately a small regex pass, not a full GraphQL
|
|
20
|
+
* tokenizer:
|
|
21
|
+
*
|
|
22
|
+
* - GraphQL operation definitions live at the top level of the
|
|
23
|
+
* document, never nested inside other operations, fragments, or
|
|
24
|
+
* selection sets, so positional context isn't required to find
|
|
25
|
+
* them — only to not match the literal words `query` /
|
|
26
|
+
* `mutation` / `subscription` inside string values.
|
|
27
|
+
* - We strip block strings (`""" … """`), string literals
|
|
28
|
+
* (`"…"`), and `# …` comments before matching, which is enough
|
|
29
|
+
* to make false-positive matches inside comments / docs vanish.
|
|
30
|
+
*
|
|
31
|
+
* If a Shopify operation is ever sufficiently mis-named to break
|
|
32
|
+
* this (unlikely, since the storefront SDK names them deliberately),
|
|
33
|
+
* the caller can always set `init.operation` explicitly.
|
|
34
|
+
*/
|
|
35
|
+
const OPERATION_RE = /\b(?:query|mutation|subscription)\s+([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
36
|
+
const stripCommentsAndStrings = (doc) => doc
|
|
37
|
+
.replace(/"""[\s\S]*?"""/g, '""')
|
|
38
|
+
.replace(/"(?:\\.|[^"\\])*"/g, '""')
|
|
39
|
+
.replace(/#[^\n]*/g, "");
|
|
40
|
+
export function extractGraphqlOperationName(document, explicit) {
|
|
41
|
+
if (explicit)
|
|
42
|
+
return explicit;
|
|
43
|
+
if (!document)
|
|
44
|
+
return undefined;
|
|
45
|
+
const stripped = stripCommentsAndStrings(document);
|
|
46
|
+
const names = [];
|
|
47
|
+
OPERATION_RE.lastIndex = 0;
|
|
48
|
+
for (let match = OPERATION_RE.exec(stripped); match !== null; match = OPERATION_RE.exec(stripped)) {
|
|
49
|
+
const [, name] = match;
|
|
50
|
+
if (name)
|
|
51
|
+
names.push(name);
|
|
52
|
+
if (names.length > 1)
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (names.length === 1)
|
|
56
|
+
return names[0];
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=graphqlOperationName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphqlOperationName.js","sourceRoot":"","sources":["../../src/utils/graphqlOperationName.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,YAAY,GAAG,+DAA+D,CAAC;AAErF,MAAM,uBAAuB,GAAG,CAAC,GAAW,EAAU,EAAE,CACtD,GAAG;KACA,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC;KAChC,OAAO,CAAC,oBAAoB,EAAE,IAAI,CAAC;KACnC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAE7B,MAAM,UAAU,2BAA2B,CACzC,QAAgB,EAChB,QAAiB;IAEjB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhC,MAAM,QAAQ,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,YAAY,CAAC,SAAS,GAAG,CAAC,CAAC;IAC3B,KACE,IAAI,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EACvC,KAAK,KAAK,IAAI,EACd,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EACnC,CAAC;QACD,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;QACvB,IAAI,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM;IAC9B,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Wake client: a thin, typed client for Wake's Storefront GraphQL API and
|
|
3
|
+
* the one checkout REST call a storefront needs, over the framework's
|
|
4
|
+
* instrumented fetch (provider "wake"). See /next/upstream-clients.
|
|
5
|
+
*
|
|
6
|
+
* Configuration comes in as arguments; the site reads its environment where
|
|
7
|
+
* it creates the client. Converters, hooks, cart/session flows, caching and
|
|
8
|
+
* proxying belong to the site (platform templates), not here.
|
|
9
|
+
*/
|
|
10
|
+
import { createInstrumentedFetch } from "@decocms/blocks/fetch";
|
|
11
|
+
import type { UserAuthenticate } from "./utils/client.ts";
|
|
12
|
+
import { type QueryDefinition } from "./utils/gql.ts";
|
|
13
|
+
export interface WakeClientConfig {
|
|
14
|
+
/** Wake Storefront API token, sent as `TCS-Access-Token`. */
|
|
15
|
+
storefrontToken: string;
|
|
16
|
+
/** Storefront GraphQL endpoint; defaults to Wake's multi-tenant endpoint. */
|
|
17
|
+
storefrontEndpoint?: string;
|
|
18
|
+
/** Checkout origin, e.g. `https://checkout.example.com`. Required by `getLogin`. */
|
|
19
|
+
checkoutUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface WakeClientOptions {
|
|
22
|
+
/** The fetch underneath, e.g. a fake in tests. Defaults to `globalThis.fetch`. */
|
|
23
|
+
fetch?: Parameters<typeof createInstrumentedFetch>[0]["fetch"];
|
|
24
|
+
}
|
|
25
|
+
/** Thrown on a non-2xx response or a GraphQL `errors` payload. Never carries bodies or tokens. */
|
|
26
|
+
export declare class WakeError extends Error {
|
|
27
|
+
readonly operation: string;
|
|
28
|
+
readonly status: number;
|
|
29
|
+
/** How many GraphQL errors the response carried (0 for an HTTP failure). */
|
|
30
|
+
readonly graphqlErrors: number;
|
|
31
|
+
constructor(operation: string, status: number,
|
|
32
|
+
/** How many GraphQL errors the response carried (0 for an HTTP failure). */
|
|
33
|
+
graphqlErrors?: number);
|
|
34
|
+
}
|
|
35
|
+
export type WakeClient = ReturnType<typeof createWakeClient>;
|
|
36
|
+
export declare function createWakeClient(config: WakeClientConfig, options?: WakeClientOptions): {
|
|
37
|
+
/**
|
|
38
|
+
* Run a Storefront GraphQL operation (see `@decocms/apps-wake/storefront`).
|
|
39
|
+
* The operation label is the document's operation name. `headers` adds
|
|
40
|
+
* per-call headers, such as `X-Forwarded-For` or a customer access token;
|
|
41
|
+
* they never override the token or the content type.
|
|
42
|
+
*/
|
|
43
|
+
graphql<TData, TVariables = Record<string, unknown>>(document: string | QueryDefinition, variables?: TVariables, init?: {
|
|
44
|
+
headers?: Record<string, string>;
|
|
45
|
+
}): Promise<TData>;
|
|
46
|
+
/**
|
|
47
|
+
* `GET /api/Login/Get` on the checkout: exchanges the shopper's checkout
|
|
48
|
+
* cookies (the `fbits-login` cookie) for their account, or `null` when
|
|
49
|
+
* they aren't signed in (401, 403 or 404). Any other failure, such as
|
|
50
|
+
* a 429, throws a `WakeError`.
|
|
51
|
+
*/
|
|
52
|
+
getLogin(cookie: string): Promise<UserAuthenticate | null>;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=wakeClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeClient.d.ts","sourceRoot":"","sources":["../src/wakeClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKlE,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;CAChE;AAED,kGAAkG;AAClG,qBAAa,SAAU,SAAQ,KAAK;IAEhC,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,aAAa;IAJxB,YACW,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM;IACvB,4EAA4E;IACnE,aAAa,SAAI,EAQ3B;CACF;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,GAAE,iBAAsB;IAMtF;;;;;OAKG;IACG,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAC7C,MAAM,GAAG,eAAe,cACtB,UAAU,SAChB;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACzC,OAAO,CAAC,KAAK,CAAC;IAmBjB;;;;;OAKG;IACG,QAAQ,SAAS,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;EAanE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Wake client: a thin, typed client for Wake's Storefront GraphQL API and
|
|
3
|
+
* the one checkout REST call a storefront needs, over the framework's
|
|
4
|
+
* instrumented fetch (provider "wake"). See /next/upstream-clients.
|
|
5
|
+
*
|
|
6
|
+
* Configuration comes in as arguments; the site reads its environment where
|
|
7
|
+
* it creates the client. Converters, hooks, cart/session flows, caching and
|
|
8
|
+
* proxying belong to the site (platform templates), not here.
|
|
9
|
+
*/
|
|
10
|
+
import { createInstrumentedFetch } from "@decocms/blocks/fetch";
|
|
11
|
+
import { buildQuery } from "./utils/gql.js";
|
|
12
|
+
import { extractGraphqlOperationName } from "./utils/graphqlOperationName.js";
|
|
13
|
+
const WAKE_STOREFRONT_ENDPOINT = "https://storefront-api.fbits.net/graphql";
|
|
14
|
+
/** Thrown on a non-2xx response or a GraphQL `errors` payload. Never carries bodies or tokens. */
|
|
15
|
+
export class WakeError extends Error {
|
|
16
|
+
operation;
|
|
17
|
+
status;
|
|
18
|
+
graphqlErrors;
|
|
19
|
+
constructor(operation, status,
|
|
20
|
+
/** How many GraphQL errors the response carried (0 for an HTTP failure). */
|
|
21
|
+
graphqlErrors = 0) {
|
|
22
|
+
super(graphqlErrors > 0
|
|
23
|
+
? `wake ${operation} returned ${graphqlErrors} GraphQL error(s)`
|
|
24
|
+
: `wake ${operation} failed with HTTP ${status}`);
|
|
25
|
+
this.operation = operation;
|
|
26
|
+
this.status = status;
|
|
27
|
+
this.graphqlErrors = graphqlErrors;
|
|
28
|
+
this.name = "WakeError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function createWakeClient(config, options = {}) {
|
|
32
|
+
const request = createInstrumentedFetch({ provider: "wake", fetch: options.fetch });
|
|
33
|
+
const endpoint = config.storefrontEndpoint || WAKE_STOREFRONT_ENDPOINT;
|
|
34
|
+
const checkoutUrl = config.checkoutUrl;
|
|
35
|
+
return {
|
|
36
|
+
/**
|
|
37
|
+
* Run a Storefront GraphQL operation (see `@decocms/apps-wake/storefront`).
|
|
38
|
+
* The operation label is the document's operation name. `headers` adds
|
|
39
|
+
* per-call headers, such as `X-Forwarded-For` or a customer access token;
|
|
40
|
+
* they never override the token or the content type.
|
|
41
|
+
*/
|
|
42
|
+
async graphql(document, variables, init = {}) {
|
|
43
|
+
const query = typeof document === "string" ? document : buildQuery(document);
|
|
44
|
+
const operation = extractGraphqlOperationName(query) ?? "graphql";
|
|
45
|
+
const headers = new Headers(init.headers);
|
|
46
|
+
headers.set("content-type", "application/json");
|
|
47
|
+
headers.set("tcs-access-token", config.storefrontToken);
|
|
48
|
+
const response = await request(endpoint, {
|
|
49
|
+
operation,
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers,
|
|
52
|
+
body: JSON.stringify({ query, variables }),
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok)
|
|
55
|
+
throw new WakeError(operation, response.status);
|
|
56
|
+
const body = (await response.json());
|
|
57
|
+
if (body.errors?.length)
|
|
58
|
+
throw new WakeError(operation, response.status, body.errors.length);
|
|
59
|
+
if (body.data === undefined)
|
|
60
|
+
throw new WakeError(operation, response.status);
|
|
61
|
+
return body.data;
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* `GET /api/Login/Get` on the checkout: exchanges the shopper's checkout
|
|
65
|
+
* cookies (the `fbits-login` cookie) for their account, or `null` when
|
|
66
|
+
* they aren't signed in (401, 403 or 404). Any other failure, such as
|
|
67
|
+
* a 429, throws a `WakeError`.
|
|
68
|
+
*/
|
|
69
|
+
async getLogin(cookie) {
|
|
70
|
+
if (!checkoutUrl)
|
|
71
|
+
throw new Error("wake getLogin: set checkoutUrl");
|
|
72
|
+
const response = await request(new URL("/api/Login/Get", checkoutUrl), {
|
|
73
|
+
operation: "getLogin",
|
|
74
|
+
headers: { cookie },
|
|
75
|
+
});
|
|
76
|
+
if (response.status === 401 || response.status === 403 || response.status === 404) {
|
|
77
|
+
return null; // not signed in
|
|
78
|
+
}
|
|
79
|
+
if (!response.ok)
|
|
80
|
+
throw new WakeError("getLogin", response.status);
|
|
81
|
+
return (await response.json());
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=wakeClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeClient.js","sourceRoot":"","sources":["../src/wakeClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAwB,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,MAAM,wBAAwB,GAAG,0CAA0C,CAAC;AAgB5E,kGAAkG;AAClG,MAAM,OAAO,SAAU,SAAQ,KAAK;IAEvB,SAAS;IACT,MAAM;IAEN,aAAa;IAJxB,YACW,SAAiB,EACjB,MAAc;IACvB,4EAA4E;IACnE,aAAa,GAAG,CAAC;QAE1B,KAAK,CACH,aAAa,GAAG,CAAC;YACf,CAAC,CAAC,QAAQ,SAAS,aAAa,aAAa,mBAAmB;YAChE,CAAC,CAAC,QAAQ,SAAS,qBAAqB,MAAM,EAAE,CACnD,CAAC;yBATO,SAAS;sBACT,MAAM;6BAEN,aAAa;QAOtB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAID,MAAM,UAAU,gBAAgB,CAAC,MAAwB,EAAE,OAAO,GAAsB,EAAE;IACxF,MAAM,OAAO,GAAG,uBAAuB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACpF,MAAM,QAAQ,GAAG,MAAM,CAAC,kBAAkB,IAAI,wBAAwB,CAAC;IACvE,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IAEvC,OAAO;QACL;;;;;WAKG;QACH,KAAK,CAAC,OAAO,CACX,QAAkC,EAClC,SAAsB,EACtB,IAAI,GAAyC,EAAE;YAE/C,MAAM,KAAK,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC7E,MAAM,SAAS,GAAG,2BAA2B,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;YAClE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE;gBACvC,SAAS;gBACT,MAAM,EAAE,MAAM;gBACd,OAAO;gBACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;aAC3C,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClE,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyC,CAAC;YAC7E,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM;gBAAE,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7F,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;gBAAE,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;QAED;;;;;WAKG;QACH,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,IAAI,CAAC,WAAW;gBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,GAAG,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE;gBACrE,SAAS,EAAE,UAAU;gBACrB,OAAO,EAAE,EAAE,MAAM,EAAE;aACpB,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAClF,OAAO,IAAI,CAAC,CAAC,gBAAgB;YAC/B,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnE,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA4B,CAAC;QAC5D,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,57 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/apps-wake",
|
|
3
|
-
"version": "8.1.0-next.
|
|
3
|
+
"version": "8.1.0-next.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Thin Wake Commerce Storefront API client for Deco sites",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/decocms/blocks.git",
|
|
9
9
|
"directory": "packages/apps-wake"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
|
+
"dist",
|
|
12
13
|
"src",
|
|
13
|
-
"
|
|
14
|
+
"!src/**/*.test.ts",
|
|
15
|
+
"!src/**/__tests__"
|
|
14
16
|
],
|
|
15
|
-
"main": "./
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
16
19
|
"exports": {
|
|
17
|
-
".":
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"./
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"./
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"./utils/*": "./src/utils/*.ts",
|
|
33
|
-
"./registry": "./src/registry.ts"
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"source": "./src/index.ts",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./storefront": {
|
|
26
|
+
"types": "./dist/storefront.d.ts",
|
|
27
|
+
"source": "./src/storefront.ts",
|
|
28
|
+
"default": "./dist/storefront.js"
|
|
29
|
+
},
|
|
30
|
+
"./storefront/types": {
|
|
31
|
+
"types": "./dist/storefrontTypes.d.ts",
|
|
32
|
+
"source": "./src/storefrontTypes.ts",
|
|
33
|
+
"default": "./dist/storefrontTypes.js"
|
|
34
|
+
}
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
|
-
"build": "tsc",
|
|
37
|
+
"build": "node ../../scripts/tsc.mjs --clean dist -p tsconfig.build.json",
|
|
38
|
+
"prepack": "npm run build",
|
|
37
39
|
"test": "vitest run --root ../.. packages/apps-wake/",
|
|
38
|
-
"typecheck": "tsc
|
|
39
|
-
"lint:unused": "knip"
|
|
40
|
+
"typecheck": "node ../../scripts/tsc.mjs -p tsconfig.json"
|
|
40
41
|
},
|
|
41
42
|
"dependencies": {
|
|
42
|
-
"@decocms/blocks": "8.1.0-next.
|
|
43
|
-
"@decocms/apps-commerce": "8.1.0-next.0",
|
|
44
|
-
"@decocms/tanstack": "8.1.0-next.0"
|
|
45
|
-
},
|
|
46
|
-
"peerDependencies": {
|
|
47
|
-
"react": "^19.0.0",
|
|
48
|
-
"react-dom": "^19.0.0"
|
|
49
|
-
},
|
|
50
|
-
"devDependencies": {
|
|
51
|
-
"@types/react": "^19.0.0",
|
|
52
|
-
"@types/react-dom": "^19.0.0",
|
|
53
|
-
"knip": "^5.86.0",
|
|
54
|
-
"typescript": "^5.9.0"
|
|
43
|
+
"@decocms/blocks": "8.1.0-next.2"
|
|
55
44
|
},
|
|
56
45
|
"publishConfig": {
|
|
57
46
|
"registry": "https://registry.npmjs.org",
|
package/src/index.ts
CHANGED
|
@@ -1,71 +1,11 @@
|
|
|
1
|
-
//
|
|
1
|
+
// The thin Wake client (see /next/upstream-clients). Operations are in
|
|
2
2
|
// `@decocms/apps-wake/storefront`, their types in `.../storefront/types`.
|
|
3
3
|
|
|
4
|
-
export type { UserAuthenticate } from "./utils/client";
|
|
4
|
+
export type { UserAuthenticate } from "./utils/client.ts";
|
|
5
5
|
export {
|
|
6
6
|
createWakeClient,
|
|
7
7
|
type WakeClient,
|
|
8
8
|
type WakeClientConfig,
|
|
9
9
|
type WakeClientOptions,
|
|
10
10
|
WakeError,
|
|
11
|
-
} from "./wakeClient";
|
|
12
|
-
|
|
13
|
-
// v7 (kept for v7 consumers until the v7 modules are dropped)
|
|
14
|
-
// App contract
|
|
15
|
-
|
|
16
|
-
// Cart actions
|
|
17
|
-
export { default as addItem } from "./actions/cart/addItem";
|
|
18
|
-
export { type CartItem, default as addItems } from "./actions/cart/addItems";
|
|
19
|
-
export { default as updateItemQuantity } from "./actions/cart/updateItemQuantity";
|
|
20
|
-
// Client & Config
|
|
21
|
-
export type { WakeConfig } from "./client";
|
|
22
|
-
export {
|
|
23
|
-
configureWake,
|
|
24
|
-
getBaseUrl,
|
|
25
|
-
getCheckoutUrl,
|
|
26
|
-
getWakeClient,
|
|
27
|
-
getWakeConfig,
|
|
28
|
-
initWakeFromBlocks,
|
|
29
|
-
setWakeFetch,
|
|
30
|
-
} from "./client";
|
|
31
|
-
// Commerce loaders factory (cached, CMS-registerable map)
|
|
32
|
-
export {
|
|
33
|
-
type CommerceLoaderFn,
|
|
34
|
-
createWakeCommerceLoaders,
|
|
35
|
-
type WakeCommerceLoadersOptions,
|
|
36
|
-
} from "./commerceLoaders";
|
|
37
|
-
// Cart / user / wishlist
|
|
38
|
-
export { default as cartLoader } from "./loaders/cart";
|
|
39
|
-
// Shop / partners
|
|
40
|
-
export { default as partnersLoader } from "./loaders/partners";
|
|
41
|
-
// Product loaders
|
|
42
|
-
export { default as productDetailsPageLoader } from "./loaders/productDetailsPage";
|
|
43
|
-
export { default as productListLoader } from "./loaders/productList";
|
|
44
|
-
export { default as productListingPageLoader } from "./loaders/productListingPage";
|
|
45
|
-
export type { WakeProxyRoute } from "./loaders/proxy";
|
|
46
|
-
export { default as proxyLoader } from "./loaders/proxy";
|
|
47
|
-
export { default as recommendationsLoader } from "./loaders/recommendations";
|
|
48
|
-
export { default as shopLoader } from "./loaders/shop";
|
|
49
|
-
export { default as suggestionLoader } from "./loaders/suggestion";
|
|
50
|
-
export { default as userLoader } from "./loaders/user";
|
|
51
|
-
export { default as wishlistLoader } from "./loaders/wishlist";
|
|
52
|
-
export { configure, type Props, type WakeState } from "./mod";
|
|
53
|
-
// Registry
|
|
54
|
-
export { WAKE_REGISTRY_ENTRY } from "./registry";
|
|
55
|
-
|
|
56
|
-
// Cookie utils
|
|
57
|
-
export { getCartCookie, setCartCookie, setClientCookie } from "./utils/cart";
|
|
58
|
-
export { getCookies, setCookie } from "./utils/cookies";
|
|
59
|
-
// GraphQL client + fetch instrumentation
|
|
60
|
-
export { extractGraphqlOperationName } from "./utils/graphqlOperationName";
|
|
61
|
-
export { type CreateWakeFetchOptions, createWakeFetch } from "./utils/instrumentedFetch";
|
|
62
|
-
export { wakeOperationRouter } from "./utils/operationRouter";
|
|
63
|
-
export { getPartnerCookie } from "./utils/partner";
|
|
64
|
-
// Transform helpers
|
|
65
|
-
export {
|
|
66
|
-
parseSlug,
|
|
67
|
-
toBreadcrumbList,
|
|
68
|
-
toFilters,
|
|
69
|
-
toProduct,
|
|
70
|
-
} from "./utils/transform";
|
|
71
|
-
export { getUserCookie } from "./utils/user";
|
|
11
|
+
} from "./wakeClient.ts";
|
package/src/storefront.ts
CHANGED
package/src/storefrontTypes.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* Storefront GraphQL schema, one `<Operation>Query`/`<Operation>Mutation` and
|
|
4
4
|
* `...Variables` pair per operation in `@decocms/apps-wake/storefront`.
|
|
5
5
|
*/
|
|
6
|
-
export type * from "./utils/graphql/storefront.graphql.gen";
|
|
6
|
+
export type * from "./utils/graphql/storefront.graphql.gen.ts";
|
package/src/utils/gql.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GraphQL document helpers
|
|
3
|
-
* the v7 GraphQL client (`./graphql.ts`). Pure: no I/O, no framework imports.
|
|
2
|
+
* GraphQL document helpers used by the client (`../wakeClient.ts`). Pure: no I/O, no framework imports.
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
/**
|
package/src/wakeClient.ts
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* proxying belong to the site (platform templates), not here.
|
|
9
9
|
*/
|
|
10
10
|
import { createInstrumentedFetch } from "@decocms/blocks/fetch";
|
|
11
|
-
import type { UserAuthenticate } from "./utils/client";
|
|
12
|
-
import { buildQuery, type QueryDefinition } from "./utils/gql";
|
|
13
|
-
import { extractGraphqlOperationName } from "./utils/graphqlOperationName";
|
|
11
|
+
import type { UserAuthenticate } from "./utils/client.ts";
|
|
12
|
+
import { buildQuery, type QueryDefinition } from "./utils/gql.ts";
|
|
13
|
+
import { extractGraphqlOperationName } from "./utils/graphqlOperationName.ts";
|
|
14
14
|
|
|
15
15
|
const WAKE_STOREFRONT_ENDPOINT = "https://storefront-api.fbits.net/graphql";
|
|
16
16
|
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
// @vitest-environment node
|
|
2
|
-
/**
|
|
3
|
-
* The v8 Wake client (/next/upstream-clients): every request goes through the
|
|
4
|
-
* instrumented fetch as provider "wake", named by its operation, and errors
|
|
5
|
-
* never carry bodies or tokens.
|
|
6
|
-
*/
|
|
7
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
-
|
|
9
|
-
const instrumented = vi.hoisted(() => ({
|
|
10
|
-
providers: [] as string[],
|
|
11
|
-
operations: [] as (string | undefined)[],
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
vi.mock("@decocms/blocks/fetch", async (importOriginal) => {
|
|
15
|
-
const real = await importOriginal<typeof import("@decocms/blocks/fetch")>();
|
|
16
|
-
return {
|
|
17
|
-
createInstrumentedFetch: (options: Parameters<typeof real.createInstrumentedFetch>[0]) => {
|
|
18
|
-
instrumented.providers.push(options.provider);
|
|
19
|
-
const request = real.createInstrumentedFetch(options);
|
|
20
|
-
return (input: string | URL | Request, init?: RequestInit & { operation?: string }) => {
|
|
21
|
-
instrumented.operations.push(init?.operation);
|
|
22
|
-
return request(input, init);
|
|
23
|
-
};
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
import { GetProduct } from "../storefront";
|
|
29
|
-
import { createWakeClient, WakeError } from "../wakeClient";
|
|
30
|
-
|
|
31
|
-
/** The error a call rejects with (fails the test if it resolves). */
|
|
32
|
-
const failure = (call: Promise<unknown>): Promise<Error> =>
|
|
33
|
-
call.then(
|
|
34
|
-
() => {
|
|
35
|
-
throw new Error("expected the call to fail");
|
|
36
|
-
},
|
|
37
|
-
(error: Error) => error,
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
function upstream(body: unknown, status = 200) {
|
|
41
|
-
return vi.fn(
|
|
42
|
-
async (_input: string | URL | Request, _init?: RequestInit) =>
|
|
43
|
-
new Response(JSON.stringify(body), { status }),
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
beforeEach(() => {
|
|
48
|
-
instrumented.providers.length = 0;
|
|
49
|
-
instrumented.operations.length = 0;
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("createWakeClient", () => {
|
|
53
|
-
it("runs a storefront operation through the instrumented fetch, labeled by its name", async () => {
|
|
54
|
-
const fetch = upstream({ data: { product: { productId: 1 } } });
|
|
55
|
-
const wake = createWakeClient({ storefrontToken: "tok" }, { fetch });
|
|
56
|
-
|
|
57
|
-
const data = await wake.graphql<{ product: { productId: number } }>(
|
|
58
|
-
GetProduct,
|
|
59
|
-
{ productId: 1 },
|
|
60
|
-
{
|
|
61
|
-
headers: {
|
|
62
|
-
"x-forwarded-for": "203.0.113.7",
|
|
63
|
-
"TCS-Access-Token": "spoofed",
|
|
64
|
-
"Content-Type": "text/plain",
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
expect(data).toEqual({ product: { productId: 1 } });
|
|
70
|
-
expect(instrumented.providers).toEqual(["wake"]);
|
|
71
|
-
expect(instrumented.operations).toEqual(["GetProduct"]);
|
|
72
|
-
const [url, init] = fetch.mock.calls[0]!;
|
|
73
|
-
expect(String(url)).toBe("https://storefront-api.fbits.net/graphql");
|
|
74
|
-
const headers = new Headers(init?.headers);
|
|
75
|
-
// Per-call headers can't override the token or the content type, whatever their case.
|
|
76
|
-
expect(headers.get("tcs-access-token")).toBe("tok");
|
|
77
|
-
expect(headers.get("content-type")).toBe("application/json");
|
|
78
|
-
expect(headers.get("x-forwarded-for")).toBe("203.0.113.7");
|
|
79
|
-
const body = JSON.parse(String(init?.body));
|
|
80
|
-
expect(body.variables).toEqual({ productId: 1 });
|
|
81
|
-
expect(body.query).toContain("fragment"); // fragments are sent with the document
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("throws a WakeError without the body on HTTP and GraphQL failures", async () => {
|
|
85
|
-
const failing = createWakeClient(
|
|
86
|
-
{ storefrontToken: "tok" },
|
|
87
|
-
{ fetch: upstream({ secret: "x" }, 502) },
|
|
88
|
-
);
|
|
89
|
-
const httpError = await failure(failing.graphql("query Shop { shop { name } }"));
|
|
90
|
-
expect(httpError).toBeInstanceOf(WakeError);
|
|
91
|
-
expect(httpError.message).toBe("wake Shop failed with HTTP 502");
|
|
92
|
-
|
|
93
|
-
const erroring = createWakeClient(
|
|
94
|
-
{ storefrontToken: "tok" },
|
|
95
|
-
{ fetch: upstream({ errors: [{ message: "customer jane@example.com not found" }] }) },
|
|
96
|
-
);
|
|
97
|
-
const gqlError = await failure(erroring.graphql("query Shop { shop { name } }"));
|
|
98
|
-
expect(gqlError.message).toBe("wake Shop returned 1 GraphQL error(s)");
|
|
99
|
-
expect(gqlError.message).not.toContain("jane");
|
|
100
|
-
expect(gqlError.message).not.toContain("tok");
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("reads the signed-in shopper from the checkout, or null when signed out", async () => {
|
|
104
|
-
const fetch = upstream({ CustomerAccessToken: "cat", Email: "a@example.com" });
|
|
105
|
-
const wake = createWakeClient(
|
|
106
|
-
{ storefrontToken: "tok", checkoutUrl: "https://checkout.example.com" },
|
|
107
|
-
{ fetch },
|
|
108
|
-
);
|
|
109
|
-
expect(await wake.getLogin("fbits-login=abc")).toMatchObject({ CustomerAccessToken: "cat" });
|
|
110
|
-
const [url, init] = fetch.mock.calls[0]!;
|
|
111
|
-
expect(String(url)).toBe("https://checkout.example.com/api/Login/Get");
|
|
112
|
-
expect(new Headers(init?.headers).get("cookie")).toBe("fbits-login=abc");
|
|
113
|
-
expect(instrumented.operations).toEqual(["getLogin"]);
|
|
114
|
-
|
|
115
|
-
const signedOut = createWakeClient(
|
|
116
|
-
{ storefrontToken: "tok", checkoutUrl: "https://checkout.example.com" },
|
|
117
|
-
{ fetch: upstream({}, 401) },
|
|
118
|
-
);
|
|
119
|
-
expect(await signedOut.getLogin("")).toBeNull();
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("throws on a rate limit instead of reporting the shopper as signed out", async () => {
|
|
123
|
-
const limited = createWakeClient(
|
|
124
|
-
{ storefrontToken: "tok", checkoutUrl: "https://checkout.example.com" },
|
|
125
|
-
{ fetch: upstream({}, 429) },
|
|
126
|
-
);
|
|
127
|
-
const error = await failure(limited.getLogin("fbits-login=abc"));
|
|
128
|
-
expect(error).toBeInstanceOf(WakeError);
|
|
129
|
-
expect(error.message).toBe("wake getLogin failed with HTTP 429");
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("requires checkoutUrl for getLogin", async () => {
|
|
133
|
-
const wake = createWakeClient({ storefrontToken: "tok" }, { fetch: upstream({}) });
|
|
134
|
-
await expect(wake.getLogin("")).rejects.toThrow(/set checkoutUrl/);
|
|
135
|
-
});
|
|
136
|
-
});
|