@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.
Files changed (94) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +4 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/storefront.d.ts +14 -0
  6. package/dist/storefront.d.ts.map +1 -0
  7. package/dist/storefront.js +14 -0
  8. package/dist/storefront.js.map +1 -0
  9. package/dist/storefrontTypes.d.ts +7 -0
  10. package/dist/storefrontTypes.d.ts.map +1 -0
  11. package/dist/storefrontTypes.js +2 -0
  12. package/dist/storefrontTypes.js.map +1 -0
  13. package/dist/utils/client.d.ts +12 -0
  14. package/dist/utils/client.d.ts.map +1 -0
  15. package/dist/utils/client.js +2 -0
  16. package/dist/utils/client.js.map +1 -0
  17. package/dist/utils/gql.d.ts +16 -0
  18. package/dist/utils/gql.d.ts.map +1 -0
  19. package/dist/utils/gql.js +16 -0
  20. package/dist/utils/gql.js.map +1 -0
  21. package/dist/utils/graphql/queries.d.ts +117 -0
  22. package/dist/utils/graphql/queries.d.ts.map +1 -0
  23. package/dist/utils/graphql/queries.js +1323 -0
  24. package/dist/utils/graphql/queries.js.map +1 -0
  25. package/dist/utils/graphql/storefront.graphql.gen.d.ts +10344 -0
  26. package/dist/utils/graphql/storefront.graphql.gen.d.ts.map +1 -0
  27. package/dist/utils/graphql/storefront.graphql.gen.js +9 -0
  28. package/dist/utils/graphql/storefront.graphql.gen.js.map +1 -0
  29. package/dist/utils/graphqlOperationName.d.ts +36 -0
  30. package/dist/utils/graphqlOperationName.d.ts.map +1 -0
  31. package/dist/utils/graphqlOperationName.js +59 -0
  32. package/dist/utils/graphqlOperationName.js.map +1 -0
  33. package/dist/wakeClient.d.ts +54 -0
  34. package/dist/wakeClient.d.ts.map +1 -0
  35. package/dist/wakeClient.js +85 -0
  36. package/dist/wakeClient.js.map +1 -0
  37. package/package.json +26 -37
  38. package/src/index.ts +3 -63
  39. package/src/storefront.ts +1 -1
  40. package/src/storefrontTypes.ts +1 -1
  41. package/src/utils/gql.ts +1 -2
  42. package/src/utils/graphql/queries.ts +1 -1
  43. package/src/wakeClient.ts +3 -3
  44. package/src/__tests__/wakeClient.test.ts +0 -136
  45. package/src/actions/cart/addCoupon.ts +0 -43
  46. package/src/actions/cart/addItem.ts +0 -10
  47. package/src/actions/cart/addItems.ts +0 -50
  48. package/src/actions/cart/addKit.ts +0 -53
  49. package/src/actions/cart/partnerAssociate.ts +0 -48
  50. package/src/actions/cart/partnerDisassociate.ts +0 -43
  51. package/src/actions/cart/removeCoupon.ts +0 -39
  52. package/src/actions/cart/removeKit.ts +0 -56
  53. package/src/actions/cart/updateItemQuantity.ts +0 -69
  54. package/src/actions/newsletter/register.ts +0 -32
  55. package/src/actions/notifyme.ts +0 -28
  56. package/src/actions/review/create.ts +0 -30
  57. package/src/actions/shippingSimulation.ts +0 -60
  58. package/src/actions/submmitForm.ts +0 -25
  59. package/src/actions/wishlist/addProduct.ts +0 -43
  60. package/src/actions/wishlist/removeProduct.ts +0 -45
  61. package/src/client.ts +0 -123
  62. package/src/commerceLoaders.ts +0 -137
  63. package/src/handlers/sitemap.ts +0 -61
  64. package/src/loaders/cart.ts +0 -46
  65. package/src/loaders/partners.ts +0 -58
  66. package/src/loaders/productDetailsPage.ts +0 -174
  67. package/src/loaders/productList.ts +0 -262
  68. package/src/loaders/productListingPage.ts +0 -333
  69. package/src/loaders/proxy.ts +0 -79
  70. package/src/loaders/recommendations.ts +0 -84
  71. package/src/loaders/shop.ts +0 -37
  72. package/src/loaders/suggestion.ts +0 -67
  73. package/src/loaders/user.ts +0 -48
  74. package/src/loaders/wishlist.ts +0 -40
  75. package/src/manifest.gen.ts +0 -69
  76. package/src/mod.ts +0 -88
  77. package/src/registry.ts +0 -9
  78. package/src/utils/authError.ts +0 -107
  79. package/src/utils/authenticate.ts +0 -42
  80. package/src/utils/capitalize.ts +0 -9
  81. package/src/utils/cart.ts +0 -33
  82. package/src/utils/cookies.ts +0 -82
  83. package/src/utils/getVariations.ts +0 -47
  84. package/src/utils/graphql.ts +0 -72
  85. package/src/utils/httpError.ts +0 -15
  86. package/src/utils/instrumentedFetch.ts +0 -46
  87. package/src/utils/operationRouter.ts +0 -51
  88. package/src/utils/parseHeaders.ts +0 -19
  89. package/src/utils/partner.ts +0 -34
  90. package/src/utils/requestCtx.ts +0 -41
  91. package/src/utils/transform.ts +0 -460
  92. package/src/utils/types.ts +0 -6
  93. package/src/utils/user.ts +0 -9
  94. 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":"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"}
package/package.json CHANGED
@@ -1,57 +1,46 @@
1
1
  {
2
2
  "name": "@decocms/apps-wake",
3
- "version": "8.1.0-next.0",
3
+ "version": "8.1.0-next.2",
4
4
  "type": "module",
5
- "description": "Deco commerce app: Wake Commerce integration",
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
- "tsconfig.json"
14
+ "!src/**/*.test.ts",
15
+ "!src/**/__tests__"
14
16
  ],
15
- "main": "./src/index.ts",
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
16
19
  "exports": {
17
- ".": "./src/index.ts",
18
- "./mod": "./src/mod.ts",
19
- "./client": "./src/client.ts",
20
- "./storefront": "./src/storefront.ts",
21
- "./storefront/types": "./src/storefrontTypes.ts",
22
- "./commerceLoaders": "./src/commerceLoaders.ts",
23
- "./loaders/*": "./src/loaders/*.ts",
24
- "./actions/*": "./src/actions/*.ts",
25
- "./actions/cart/*": "./src/actions/cart/*.ts",
26
- "./actions/newsletter/*": "./src/actions/newsletter/*.ts",
27
- "./actions/review/*": "./src/actions/review/*.ts",
28
- "./actions/wishlist/*": "./src/actions/wishlist/*.ts",
29
- "./handlers/*": "./src/handlers/*.ts",
30
- "./hooks": "./src/hooks/index.ts",
31
- "./hooks/*": "./src/hooks/*.ts",
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 --noEmit",
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.0",
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
- // v8: the thin Wake client (see /next/upstream-clients). Operations are in
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
@@ -10,4 +10,4 @@
10
10
  * const data = await wake.graphql<GetProductQuery, GetProductQueryVariables>(GetProduct, { productId: 1 });
11
11
  * ```
12
12
  */
13
- export * from "./utils/graphql/queries";
13
+ export * from "./utils/graphql/queries.ts";
@@ -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 shared by the v8 client (`../wakeClient.ts`) and
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
  /**
@@ -1,4 +1,4 @@
1
- import { gql } from "../gql";
1
+ import { gql } from "../gql.ts";
2
2
 
3
3
  const Checkout = gql`
4
4
  fragment Checkout on Checkout {
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
- });