@brytdesigns/shopify-ajax-client 1.0.6 → 1.0.8

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.
@@ -18,6 +18,50 @@ Schema.extend(
18
18
  })
19
19
  );
20
20
  const Default = FetchHttpClient.layer;
21
+ const formatCause = (cause) => {
22
+ if (cause == null) return void 0;
23
+ if (cause instanceof Error) {
24
+ const nested = formatCause(cause.cause);
25
+ const base = `${cause.name}: ${cause.message}`;
26
+ return nested ? `${base} -> ${nested}` : base;
27
+ }
28
+ if (typeof cause === "object") {
29
+ try {
30
+ return JSON.stringify(cause);
31
+ } catch {
32
+ return String(cause);
33
+ }
34
+ }
35
+ return String(cause);
36
+ };
37
+ const toError = (error) => {
38
+ if (error._tag === "RequestError" || error._tag === "ResponseError") {
39
+ const detail = formatCause(error.cause);
40
+ const message2 = detail ? `${error.message}: ${detail}` : error.message;
41
+ return Object.assign(new Error(message2, { cause: error.cause }), {
42
+ _tag: error._tag,
43
+ reason: error.reason
44
+ });
45
+ }
46
+ if (error._tag === "ParseError" || error._tag === "@brytdesigns/ajax-client/InvalidAjaxMethodError") {
47
+ return new Error(error.message, { cause: error.cause });
48
+ }
49
+ if (error._tag === "HttpBodyError") {
50
+ const reason = error.reason;
51
+ if (reason._tag === "JsonError") {
52
+ return new Error("Failed to serialize JSON request body", {
53
+ cause: reason
54
+ });
55
+ }
56
+ if (reason._tag === "SchemaError") {
57
+ return new Error(reason.error.message, {
58
+ cause: reason.error.cause
59
+ });
60
+ }
61
+ }
62
+ const message = formatCause(error) ?? error?.message ?? error?.toString?.() ?? String(error);
63
+ return new Error(message, { cause: error });
64
+ };
21
65
  const METHOD = {
22
66
  GET: "get",
23
67
  POST: "post"
@@ -128,29 +172,13 @@ const makeFactory = ({
128
172
  LoggerUtils.withNamespacedLogSpan(
129
173
  routeName.replace("_url", "").replace("_", ":")
130
174
  ),
131
- Effect.catchAll((error) => {
132
- if (error._tag === "ParseError" || error._tag === "RequestError" || error._tag === "ResponseError" || error._tag === "@brytdesigns/ajax-client/InvalidAjaxMethodError") {
133
- return Effect.fail(
134
- new Error(error.message, {
135
- cause: error.cause
136
- })
137
- );
138
- }
139
- if (error._tag === "HttpBodyError") {
140
- const reason = error.reason;
141
- if (reason._tag === "JsonError") {
142
- return Effect.fail(new Error("Failed to parse JSON response"));
143
- }
144
- if (reason._tag === "SchemaError") {
145
- return Effect.fail(
146
- new Error(reason.error.message, {
147
- cause: reason.error.cause
148
- })
149
- );
150
- }
151
- }
152
- return Effect.fail(new Error(error.toString()));
153
- })
175
+ // Log the full failure cause (including defects and the underlying
176
+ // `cause` chain) before we flatten it. This is gated by the consumer's
177
+ // minimum log level, so it only surfaces when `debug` is enabled.
178
+ Effect.tapErrorCause(
179
+ (cause) => Effect.logError("Ajax request failed", cause)
180
+ ),
181
+ Effect.catchAll((error) => Effect.fail(toError(error)))
154
182
  );
155
183
 
156
184
  export { Default, makeFactory };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"names":["output","json","clientResponse"],"mappings":"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","file":"index.js","sourcesContent":["import * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport * as Function from \"effect/Function\";\nimport * as HttpClient from \"@effect/platform/HttpClient\";\nimport * as HttpClientResponse from \"@effect/platform/HttpClientResponse\";\nimport * as HttpClientRequest from \"@effect/platform/HttpClientRequest\";\nimport * as FetchHttpClient from \"@effect/platform/FetchHttpClient\";\n\nimport { Ajax } from \"@brytdesigns/shopify-utils/effect\";\n\nimport * as LoggerUtils from \"./LoggerUtils.js\";\nimport { type CartError, InvalidAjaxMethodError } from \"./errors.js\";\nimport * as AjaxClientResponse from \"./AjaxClientResponse.js\";\n\nconst BaseOutputSchema = Schema.Struct({});\nconst ProductInputSchema = Schema.extend(\n Ajax.Sections.Input,\n Schema.Struct({\n handle: Schema.String,\n })\n);\n\nexport const Default = FetchHttpClient.layer;\n\nconst METHOD = {\n GET: \"get\",\n POST: \"post\",\n};\n\nconst METHODS_BY_URL = {\n products_url: METHOD.GET,\n product_url: METHOD.GET,\n predictive_search_url: METHOD.GET,\n product_recommendations_url: METHOD.GET,\n cart_add_url: METHOD.POST,\n cart_update_url: METHOD.POST,\n cart_url: METHOD.GET,\n cart_change_url: METHOD.POST,\n cart_clear_url: METHOD.POST,\n};\n\ntype ValidAjaxRoutes = keyof Pick<\n Ajax.Window.ShopifyRoutes.ShopifyRoutes,\n | \"product_url\"\n | \"products_url\"\n | \"predictive_search_url\"\n | \"product_recommendations_url\"\n | \"cart_add_url\"\n | \"cart_update_url\"\n | \"cart_url\"\n | \"cart_change_url\"\n | \"cart_clear_url\"\n>;\n\n/**\n * A factory function that creates an Effect to make AJAX requests to Shopify routes.\n *\n * @template RouteName - The type of Shopify route to make the request to.\n * @template A - The type of input data for the request.\n * @template I - The type of input data after decoding.\n * @template R - The type of input data after decoding, but with additional information.\n * @template B - The type of output data expected from the request.\n * @template J - The type of output data after decoding.\n * @template S - The type of output data after decoding, but with additional information.\n *\n * @param {object} params - The parameters for creating the factory function.\n * @param {RouteName} params.routeName - The name of the Shopify route to make the request to.\n * @param {Schema<A, I, R>} params.inputSchema - The schema for validating and decoding the input data.\n * @param {Schema<B, J, S>} params.outputSchema - The schema for validating and decoding the output data.\n *\n * - A function that takes input data and options, and returns an Effect to make the AJAX request.\n */\nexport const makeFactory =\n <\n RouteName extends ValidAjaxRoutes,\n A extends RouteName extends \"product_url\"\n ? typeof ProductInputSchema.Type\n : typeof Ajax.Sections.Input.Type,\n I,\n R,\n B extends typeof BaseOutputSchema.Type,\n J,\n S,\n >({\n routeName,\n inputSchema,\n outputSchema,\n }: {\n routeName: RouteName;\n inputSchema: Schema.Schema<A, I, R>;\n outputSchema: Schema.Schema<B, J, S>;\n }) =>\n (\n input?: Schema.Schema<A, I, R>[\"Encoded\"],\n options?: { headers?: Record<string, string> }\n ) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient;\n const decodedInput = yield* Schema.decodeUnknown(inputSchema)(\n input || {}\n );\n const routes = Ajax.Window.ShopifyRoutes.make();\n\n let route: string;\n\n if (routeName === \"product_url\" && \"handle\" in decodedInput) {\n route = routes[routeName].replace(\":handle\", decodedInput.handle);\n } else {\n route = routes[routeName];\n }\n\n const url = `${window.location.origin}${route}`;\n const method = METHODS_BY_URL[routeName];\n\n let request: HttpClientRequest.HttpClientRequest;\n\n if (method === \"post\") {\n request = yield* HttpClientRequest.post(url, {\n acceptJson: true,\n headers: {\n \"X-SDK-Variant\": \"brytdesigns\",\n \"X-SDK-Variant-Source\": \"shopify-ajax-client\",\n ...(options?.headers || {}),\n },\n }).pipe(HttpClientRequest.bodyJson(decodedInput));\n } else if (method === \"get\") {\n request = HttpClientRequest.get(url, {\n acceptJson: true,\n headers: {\n \"X-SDK-Variant\": \"brytdesigns\",\n \"X-SK-Variant-Source\": \"shopify-ajax-client\",\n ...(options?.headers || {}),\n },\n }).pipe(HttpClientRequest.setUrlParams(decodedInput));\n } else {\n return yield* Effect.fail(new InvalidAjaxMethodError());\n }\n\n const response = yield* client.execute(request);\n\n if (response.status !== 200) {\n const data = (yield* response.json) as CartError;\n return AjaxClientResponse.make({\n error: {\n description: data.description,\n status: data.status,\n message: data.message,\n },\n });\n }\n\n if (decodedInput.sections) {\n const output = outputSchema.pipe(\n Schema.extend(\n Schema.Struct({\n sections: Ajax.Sections.makeResponseSchema(decodedInput.sections),\n })\n )\n );\n\n const json = yield* Function.pipe(\n response,\n HttpClientResponse.schemaBodyJson(output)\n );\n\n const clientResponse = AjaxClientResponse.make({\n data: json,\n });\n\n yield* Effect.annotateLogsScoped({\n method,\n route,\n input: decodedInput,\n output: clientResponse,\n });\n\n return clientResponse;\n }\n\n const output = outputSchema;\n\n const json = yield* Function.pipe(\n response,\n HttpClientResponse.schemaBodyJson(output)\n );\n\n const clientResponse = AjaxClientResponse.make({\n data: json,\n });\n\n yield* Effect.annotateLogsScoped({\n method,\n route,\n input: decodedInput,\n output: clientResponse,\n });\n\n yield* Effect.logInfo(\"Request\");\n\n return clientResponse;\n }).pipe(\n Effect.scoped,\n LoggerUtils.withNamespacedLogSpan(\n routeName.replace(\"_url\", \"\").replace(\"_\", \":\")\n ),\n Effect.catchAll((error) => {\n if (\n error._tag === \"ParseError\" ||\n error._tag === \"RequestError\" ||\n error._tag === \"ResponseError\" ||\n error._tag === \"@brytdesigns/ajax-client/InvalidAjaxMethodError\"\n ) {\n return Effect.fail(\n new Error(error.message, {\n cause: error.cause,\n })\n );\n }\n if (error._tag === \"HttpBodyError\") {\n const reason = error.reason;\n if (reason._tag === \"JsonError\") {\n return Effect.fail(new Error(\"Failed to parse JSON response\"));\n }\n if (reason._tag === \"SchemaError\") {\n return Effect.fail(\n new Error(reason.error.message, {\n cause: reason.error.cause,\n })\n );\n }\n }\n return Effect.fail(new Error(error.toString()));\n })\n );\n"]}
1
+ {"version":3,"sources":["../../src/index.ts"],"names":["message","output","json","clientResponse"],"mappings":"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","file":"index.js","sourcesContent":["import * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport * as Function from \"effect/Function\";\nimport * as HttpClient from \"@effect/platform/HttpClient\";\nimport * as HttpClientResponse from \"@effect/platform/HttpClientResponse\";\nimport * as HttpClientRequest from \"@effect/platform/HttpClientRequest\";\nimport * as FetchHttpClient from \"@effect/platform/FetchHttpClient\";\n\nimport { Ajax } from \"@brytdesigns/shopify-utils/effect\";\n\nimport * as LoggerUtils from \"./LoggerUtils.js\";\nimport { type CartError, InvalidAjaxMethodError } from \"./errors.js\";\nimport * as AjaxClientResponse from \"./AjaxClientResponse.js\";\n\nconst BaseOutputSchema = Schema.Struct({});\nconst ProductInputSchema = Schema.extend(\n Ajax.Sections.Input,\n Schema.Struct({\n handle: Schema.String,\n })\n);\n\nexport const Default = FetchHttpClient.layer;\n\n/**\n * Recursively renders an unknown `cause` (typically the value thrown by an\n * overridden `window.fetch`) into a human readable string, walking the\n * `Error.cause` chain so the underlying reason is never lost.\n */\nconst formatCause = (cause: unknown): string | undefined => {\n if (cause == null) return undefined;\n if (cause instanceof Error) {\n const nested = formatCause(cause.cause);\n const base = `${cause.name}: ${cause.message}`;\n return nested ? `${base} -> ${nested}` : base;\n }\n if (typeof cause === \"object\") {\n try {\n return JSON.stringify(cause);\n } catch {\n return String(cause);\n }\n }\n return String(cause);\n};\n\n/**\n * Normalizes the tagged errors produced inside the request effect into a plain\n * `Error` with a descriptive message. The underlying `cause` is always\n * preserved (and folded into the message) so failures such as a rejecting\n * external `fetch` override report WHY they failed instead of just\n * \"Transport error\".\n */\nconst toError = (error: any): Error => {\n // HttpClientError — RequestError (\"Transport\"/\"Encode\"/\"InvalidUrl\") and\n // ResponseError (\"Decode\"/\"StatusCode\"/...). The actionable detail lives on\n // `error.cause`, which Effect's own `message` getter does not include.\n if (error._tag === \"RequestError\" || error._tag === \"ResponseError\") {\n const detail = formatCause(error.cause);\n const message = detail ? `${error.message}: ${detail}` : error.message;\n return Object.assign(new Error(message, { cause: error.cause }), {\n _tag: error._tag,\n reason: error.reason,\n });\n }\n\n if (\n error._tag === \"ParseError\" ||\n error._tag === \"@brytdesigns/ajax-client/InvalidAjaxMethodError\"\n ) {\n return new Error(error.message, { cause: error.cause });\n }\n\n if (error._tag === \"HttpBodyError\") {\n const reason = error.reason;\n if (reason._tag === \"JsonError\") {\n return new Error(\"Failed to serialize JSON request body\", {\n cause: reason,\n });\n }\n if (reason._tag === \"SchemaError\") {\n return new Error(reason.error.message, {\n cause: reason.error.cause,\n });\n }\n }\n\n const message =\n formatCause(error) ?? error?.message ?? error?.toString?.() ?? String(error);\n return new Error(message, { cause: error });\n};\n\nconst METHOD = {\n GET: \"get\",\n POST: \"post\",\n};\n\nconst METHODS_BY_URL = {\n products_url: METHOD.GET,\n product_url: METHOD.GET,\n predictive_search_url: METHOD.GET,\n product_recommendations_url: METHOD.GET,\n cart_add_url: METHOD.POST,\n cart_update_url: METHOD.POST,\n cart_url: METHOD.GET,\n cart_change_url: METHOD.POST,\n cart_clear_url: METHOD.POST,\n};\n\ntype ValidAjaxRoutes = keyof Pick<\n Ajax.Window.ShopifyRoutes.ShopifyRoutes,\n | \"product_url\"\n | \"products_url\"\n | \"predictive_search_url\"\n | \"product_recommendations_url\"\n | \"cart_add_url\"\n | \"cart_update_url\"\n | \"cart_url\"\n | \"cart_change_url\"\n | \"cart_clear_url\"\n>;\n\n/**\n * A factory function that creates an Effect to make AJAX requests to Shopify routes.\n *\n * @template RouteName - The type of Shopify route to make the request to.\n * @template A - The type of input data for the request.\n * @template I - The type of input data after decoding.\n * @template R - The type of input data after decoding, but with additional information.\n * @template B - The type of output data expected from the request.\n * @template J - The type of output data after decoding.\n * @template S - The type of output data after decoding, but with additional information.\n *\n * @param {object} params - The parameters for creating the factory function.\n * @param {RouteName} params.routeName - The name of the Shopify route to make the request to.\n * @param {Schema<A, I, R>} params.inputSchema - The schema for validating and decoding the input data.\n * @param {Schema<B, J, S>} params.outputSchema - The schema for validating and decoding the output data.\n *\n * - A function that takes input data and options, and returns an Effect to make the AJAX request.\n */\nexport const makeFactory =\n <\n RouteName extends ValidAjaxRoutes,\n A extends RouteName extends \"product_url\"\n ? typeof ProductInputSchema.Type\n : typeof Ajax.Sections.Input.Type,\n I,\n R,\n B extends typeof BaseOutputSchema.Type,\n J,\n S,\n >({\n routeName,\n inputSchema,\n outputSchema,\n }: {\n routeName: RouteName;\n inputSchema: Schema.Schema<A, I, R>;\n outputSchema: Schema.Schema<B, J, S>;\n }) =>\n (\n input?: Schema.Schema<A, I, R>[\"Encoded\"],\n options?: { headers?: Record<string, string> }\n ) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient;\n const decodedInput = yield* Schema.decodeUnknown(inputSchema)(\n input || {}\n );\n const routes = Ajax.Window.ShopifyRoutes.make();\n\n let route: string;\n\n if (routeName === \"product_url\" && \"handle\" in decodedInput) {\n route = routes[routeName].replace(\":handle\", decodedInput.handle);\n } else {\n route = routes[routeName];\n }\n\n const url = `${window.location.origin}${route}`;\n const method = METHODS_BY_URL[routeName];\n\n let request: HttpClientRequest.HttpClientRequest;\n\n if (method === \"post\") {\n request = yield* HttpClientRequest.post(url, {\n acceptJson: true,\n headers: {\n \"X-SDK-Variant\": \"brytdesigns\",\n \"X-SDK-Variant-Source\": \"shopify-ajax-client\",\n ...(options?.headers || {}),\n },\n }).pipe(HttpClientRequest.bodyJson(decodedInput));\n } else if (method === \"get\") {\n request = HttpClientRequest.get(url, {\n acceptJson: true,\n headers: {\n \"X-SDK-Variant\": \"brytdesigns\",\n \"X-SK-Variant-Source\": \"shopify-ajax-client\",\n ...(options?.headers || {}),\n },\n }).pipe(HttpClientRequest.setUrlParams(decodedInput));\n } else {\n return yield* Effect.fail(new InvalidAjaxMethodError());\n }\n\n const response = yield* client.execute(request);\n\n if (response.status !== 200) {\n const data = (yield* response.json) as CartError;\n return AjaxClientResponse.make({\n error: {\n description: data.description,\n status: data.status,\n message: data.message,\n },\n });\n }\n\n if (decodedInput.sections) {\n const output = outputSchema.pipe(\n Schema.extend(\n Schema.Struct({\n sections: Ajax.Sections.makeResponseSchema(decodedInput.sections),\n })\n )\n );\n\n const json = yield* Function.pipe(\n response,\n HttpClientResponse.schemaBodyJson(output)\n );\n\n const clientResponse = AjaxClientResponse.make({\n data: json,\n });\n\n yield* Effect.annotateLogsScoped({\n method,\n route,\n input: decodedInput,\n output: clientResponse,\n });\n\n return clientResponse;\n }\n\n const output = outputSchema;\n\n const json = yield* Function.pipe(\n response,\n HttpClientResponse.schemaBodyJson(output)\n );\n\n const clientResponse = AjaxClientResponse.make({\n data: json,\n });\n\n yield* Effect.annotateLogsScoped({\n method,\n route,\n input: decodedInput,\n output: clientResponse,\n });\n\n yield* Effect.logInfo(\"Request\");\n\n return clientResponse;\n }).pipe(\n Effect.scoped,\n LoggerUtils.withNamespacedLogSpan(\n routeName.replace(\"_url\", \"\").replace(\"_\", \":\")\n ),\n // Log the full failure cause (including defects and the underlying\n // `cause` chain) before we flatten it. This is gated by the consumer's\n // minimum log level, so it only surfaces when `debug` is enabled.\n Effect.tapErrorCause((cause) =>\n Effect.logError(\"Ajax request failed\", cause)\n ),\n Effect.catchAll((error) => Effect.fail(toError(error)))\n );\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brytdesigns/shopify-ajax-client",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "An AJAX cart that integrates with ALL shopify ajax apis",
5
5
  "main": "./dist/main/index.js",
6
6
  "types": "./dist/main/index.d.ts",
@@ -29,10 +29,10 @@
29
29
  "vitest": "^3.0.6"
30
30
  },
31
31
  "dependencies": {
32
- "@effect/platform": "0.93.8",
33
- "effect": "3.19.12",
32
+ "@effect/platform": "0.94.1",
33
+ "effect": "3.19.14",
34
34
  "lz-string": "^1.5.0",
35
- "@brytdesigns/shopify-utils": "1.2.21"
35
+ "@brytdesigns/shopify-utils": "1.2.22"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsup --clean",