@brytdesigns/shopify-ajax-client 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ import * as Data from 'effect/Data';
2
+
3
+ class AjaxClientResponse extends Data.Class {
4
+ }
5
+ const make = (data) => Data.case()(data);
6
+
7
+ export { AjaxClientResponse, make };
8
+ //# sourceMappingURL=AjaxClientResponse.js.map
9
+ //# sourceMappingURL=AjaxClientResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/AjaxClientResponse.ts"],"names":[],"mappings":";;AAWO,MAAM,kBAAA,SAAwC,KAAK,KAExD,CAAA;AAAC;AAEI,MAAM,OAAO,CAClB,IAAA,KACG,IAAK,CAAA,IAAA,GAAkC,IAAI","file":"AjaxClientResponse.js","sourcesContent":["import * as Data from \"effect/Data\";\n\ninterface IAjaxClientResponse<TData = any> {\n data?: TData;\n error?: {\n status: number;\n message: string;\n description?: string;\n };\n}\n\nexport class AjaxClientResponse<TData = any> extends Data.Class<\n IAjaxClientResponse<TData>\n> {}\n\nexport const make = <TData = undefined>(\n data: Parameters<ReturnType<typeof Data.case<AjaxClientResponse<TData>>>>[0],\n) => Data.case<AjaxClientResponse<TData>>()(data);\n"]}
@@ -0,0 +1,10 @@
1
+ import { Logging } from '@brytdesigns/shopify-utils/effect';
2
+
3
+ const withNamespacedLogSpan = Logging.makeNamespacedLogSpan(
4
+ "[@brytdesigns/shopify-ajax-client]"
5
+ );
6
+ const filterLevelOrNever = Logging.filterLevelOrNever;
7
+
8
+ export { filterLevelOrNever, withNamespacedLogSpan };
9
+ //# sourceMappingURL=LoggerUtils.js.map
10
+ //# sourceMappingURL=LoggerUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/LoggerUtils.ts"],"names":[],"mappings":";;AAEO,MAAM,wBAAwB,OAAQ,CAAA,qBAAA;AAAA,EAC3C;AACF;AAEO,MAAM,qBAAqB,OAAQ,CAAA","file":"LoggerUtils.js","sourcesContent":["import { Logging } from \"@brytdesigns/shopify-utils/effect\";\n\nexport const withNamespacedLogSpan = Logging.makeNamespacedLogSpan(\n \"[@brytdesigns/shopify-ajax-client]\",\n);\n\nexport const filterLevelOrNever = Logging.filterLevelOrNever;\n"]}
@@ -0,0 +1,17 @@
1
+ import * as Data from 'effect/Data';
2
+
3
+ class CartError extends Data.TaggedError(
4
+ "@brytdesigns/ajax-client/CartError"
5
+ ) {
6
+ }
7
+ class InvalidAjaxMethodError extends Data.TaggedError(
8
+ "@brytdesigns/ajax-client/InvalidAjaxMethodError"
9
+ ) {
10
+ constructor() {
11
+ super({ message: "Invalid HTTP method | Allowed: 'get' or 'post'" });
12
+ }
13
+ }
14
+
15
+ export { CartError, InvalidAjaxMethodError };
16
+ //# sourceMappingURL=errors.js.map
17
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/errors.ts"],"names":[],"mappings":";;AAMO,MAAM,kBAAkB,IAAK,CAAA,WAAA;AAAA,EAClC;AACF,CAIG,CAAA;AAAC;AAMG,MAAM,+BAA+B,IAAK,CAAA,WAAA;AAAA,EAC/C;AACF,CAEG,CAAA;AAAA,EACD,WAAc,GAAA;AACZ,IAAM,KAAA,CAAA,EAAE,OAAS,EAAA,gDAAA,EAAkD,CAAA;AAAA;AAEvE","file":"errors.js","sourcesContent":["import * as Data from \"effect/Data\";\n\n/**\n * @internal\n *\n */\nexport class CartError extends Data.TaggedError(\n \"@brytdesigns/ajax-client/CartError\",\n)<{\n status: number;\n message: string;\n description: string;\n}> {}\n\n/**\n * @internal\n *\n */\nexport class InvalidAjaxMethodError extends Data.TaggedError(\n \"@brytdesigns/ajax-client/InvalidAjaxMethodError\",\n)<{\n message: string;\n}> {\n constructor() {\n super({ message: \"Invalid HTTP method | Allowed: 'get' or 'post'\" });\n }\n}\n"]}
@@ -0,0 +1,93 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ import * as HttpClient from '@effect/platform/HttpClient';
4
+ import * as Data from 'effect/Data';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as LogLevel from 'effect/LogLevel';
7
+ import * as Schema from 'effect/Schema';
8
+
9
+ export interface IShopifyRoutes {
10
+ readonly account_addresses_url: string;
11
+ readonly account_login_url: string;
12
+ readonly account_logout_url: string;
13
+ readonly account_recover_url: string;
14
+ readonly account_register_url: string;
15
+ readonly account_url: string;
16
+ readonly all_products_collection_url: string;
17
+ readonly product_url: string;
18
+ readonly products_url: string;
19
+ readonly cart_add_url: string;
20
+ readonly cart_change_url: string;
21
+ readonly cart_clear_url: string;
22
+ readonly cart_update_url: string;
23
+ readonly cart_url: string;
24
+ readonly collections_url: string;
25
+ readonly predictive_search_url: string;
26
+ readonly product_recommendations_url: string;
27
+ readonly root_url: string;
28
+ readonly search_url: string;
29
+ readonly storefront_login_url: string;
30
+ }
31
+ export interface IStorefrontClientConfig {
32
+ readonly accessToken: string;
33
+ readonly shopName: string;
34
+ apiVersion: string;
35
+ }
36
+ declare const Defaults: IShopifyRoutes;
37
+ declare class ShopifyRoutes extends Data.Class<IShopifyRoutes> {
38
+ constructor();
39
+ }
40
+ declare const make: () => ShopifyRoutes;
41
+ declare class StorefrontClientConfig extends Data.Class<IStorefrontClientConfig> {
42
+ constructor();
43
+ }
44
+ declare const make$1: () => StorefrontClientConfig;
45
+ declare const Input: Schema.Struct<{
46
+ sections: Schema.optional<Schema.transform<Schema.Array$<typeof Schema.String>, typeof Schema.String>>;
47
+ sections_url: Schema.optional<typeof Schema.String>;
48
+ }>;
49
+ export type UniqueKeys<T extends string> = T extends `${infer K},${infer Rest}` ? K | UniqueKeys<Rest> : T;
50
+ declare function makeResponseSchema<const T extends string>(input: T): Schema.Record$<Schema.SchemaClass<UniqueKeys<T>, UniqueKeys<T>, never>, Schema.NullOr<Schema.transformOrFail<typeof Schema.String, Schema.instanceOf<Element>, never>>>;
51
+ declare namespace StorefrontClientConfig$1 {
52
+ export { StorefrontClientConfig, make$1 as make$1 };
53
+ }
54
+ declare namespace ShopifyRoutes$1 {
55
+ export { Defaults, ShopifyRoutes, make };
56
+ }
57
+ declare namespace Window$1 {
58
+ export { ShopifyRoutes$1 as ShopifyRoutes$1, StorefrontClientConfig$1 as StorefrontClientConfig$1 };
59
+ }
60
+ declare namespace Sections {
61
+ export { Input, makeResponseSchema };
62
+ }
63
+ declare namespace Ajax {
64
+ export { Sections, Window$1 as Window$1 };
65
+ }
66
+ export interface IAjaxClientResponse<TData = any> {
67
+ data?: TData;
68
+ error?: {
69
+ status: number;
70
+ message: string;
71
+ description?: string;
72
+ };
73
+ }
74
+ declare class AjaxClientResponse<TData = any> extends Data.Class<IAjaxClientResponse<TData>> {
75
+ }
76
+ declare const BaseOutputSchema: Schema.Struct<{}>;
77
+ declare const ProductInputSchema: Schema.extend<Schema.Struct<{
78
+ sections: Schema.optional<Schema.transform<Schema.Array$<typeof Schema.String>, typeof Schema.String>>;
79
+ sections_url: Schema.optional<typeof Schema.String>;
80
+ }>, Schema.Struct<{
81
+ handle: typeof Schema.String;
82
+ }>>;
83
+ export declare const Default: import("effect/Layer").Layer<HttpClient.HttpClient, never, never>;
84
+ export type ValidAjaxRoutes = keyof Pick<Ajax.Window.ShopifyRoutes.ShopifyRoutes, "product_url" | "products_url" | "predictive_search_url" | "product_recommendations_url" | "cart_add_url" | "cart_update_url" | "cart_url" | "cart_change_url" | "cart_clear_url">;
85
+ export declare const makeFactory: <RouteName extends ValidAjaxRoutes, A extends RouteName extends "product_url" ? typeof ProductInputSchema.Type : typeof Ajax.Sections.Input.Type, I, R, B extends typeof BaseOutputSchema.Type, J, S>({ routeName, inputSchema, outputSchema, }: {
86
+ routeName: RouteName;
87
+ inputSchema: Schema.Schema<A, I, R>;
88
+ outputSchema: Schema.Schema<B, J, S>;
89
+ }) => (input?: Schema.Schema<A, I, R>["Encoded"], options?: {
90
+ headers?: Record<string, string>;
91
+ }) => Effect.Effect<AjaxClientResponse<undefined> | AjaxClientResponse<B>, Error, HttpClient.HttpClient | Exclude<R, import("effect/Scope").Scope> | Exclude<S, import("effect/Scope").Scope>>;
92
+
93
+ export {};
@@ -0,0 +1,158 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import * as Schema from 'effect/Schema';
3
+ import * as Function from 'effect/Function';
4
+ import * as HttpClient from '@effect/platform/HttpClient';
5
+ import * as HttpClientResponse from '@effect/platform/HttpClientResponse';
6
+ import * as HttpClientRequest from '@effect/platform/HttpClientRequest';
7
+ import * as BrowserHttpClient from '@effect/platform-browser/BrowserHttpClient';
8
+ import { Ajax } from '@brytdesigns/shopify-utils/effect';
9
+ import * as LoggerUtils from './LoggerUtils.js';
10
+ import { InvalidAjaxMethodError } from './errors.js';
11
+ import * as AjaxClientResponse from './AjaxClientResponse.js';
12
+
13
+ Schema.Struct({});
14
+ Schema.extend(
15
+ Ajax.Sections.Input,
16
+ Schema.Struct({
17
+ handle: Schema.String
18
+ })
19
+ );
20
+ const Default = BrowserHttpClient.layerXMLHttpRequest;
21
+ const METHOD = {
22
+ GET: "get",
23
+ POST: "post"
24
+ };
25
+ const METHODS_BY_URL = {
26
+ products_url: METHOD.GET,
27
+ product_url: METHOD.GET,
28
+ predictive_search_url: METHOD.GET,
29
+ product_recommendations_url: METHOD.GET,
30
+ cart_add_url: METHOD.POST,
31
+ cart_update_url: METHOD.POST,
32
+ cart_url: METHOD.GET,
33
+ cart_change_url: METHOD.POST,
34
+ cart_clear_url: METHOD.POST
35
+ };
36
+ const makeFactory = ({
37
+ routeName,
38
+ inputSchema,
39
+ outputSchema
40
+ }) => (input, options) => Effect.gen(function* () {
41
+ const client = yield* HttpClient.HttpClient;
42
+ const decodedInput = yield* Schema.decodeUnknown(inputSchema)(
43
+ input || {}
44
+ );
45
+ const routes = Ajax.Window.ShopifyRoutes.make();
46
+ let route;
47
+ if (routeName === "product_url" && "handle" in decodedInput) {
48
+ route = routes[routeName].replace(":handle", decodedInput.handle);
49
+ } else {
50
+ route = routes[routeName];
51
+ }
52
+ const url = `${window.location.origin}${route}`;
53
+ const method = METHODS_BY_URL[routeName];
54
+ let request;
55
+ if (method === "post") {
56
+ request = yield* HttpClientRequest.post(url, {
57
+ acceptJson: true,
58
+ headers: {
59
+ "X-SDK-Variant": "brytdesigns",
60
+ "X-SK-Variant-Source": "shopify-ajax-client",
61
+ ...options?.headers || {}
62
+ }
63
+ }).pipe(HttpClientRequest.bodyJson(decodedInput));
64
+ } else if (method === "get") {
65
+ request = HttpClientRequest.get(url, {
66
+ acceptJson: true,
67
+ headers: {
68
+ "X-SDK-Variant": "brytdesigns",
69
+ "X-SK-Variant-Source": "shopify-ajax-client",
70
+ ...options?.headers || {}
71
+ }
72
+ }).pipe(HttpClientRequest.setUrlParams(decodedInput));
73
+ } else {
74
+ return yield* Effect.fail(new InvalidAjaxMethodError());
75
+ }
76
+ const response = yield* client.execute(request);
77
+ if (response.status !== 200) {
78
+ const data = yield* response.json;
79
+ return AjaxClientResponse.make({
80
+ error: {
81
+ description: data.description,
82
+ status: data.status,
83
+ message: data.message
84
+ }
85
+ });
86
+ }
87
+ if (decodedInput.sections) {
88
+ const output2 = outputSchema.pipe(
89
+ Schema.extend(
90
+ Schema.Struct({
91
+ sections: Ajax.Sections.makeResponseSchema(decodedInput.sections)
92
+ })
93
+ )
94
+ );
95
+ const json2 = yield* Function.pipe(
96
+ response,
97
+ HttpClientResponse.schemaBodyJson(output2)
98
+ );
99
+ const clientResponse2 = AjaxClientResponse.make({
100
+ data: json2
101
+ });
102
+ yield* Effect.annotateLogsScoped({
103
+ method,
104
+ route,
105
+ input: decodedInput,
106
+ output: clientResponse2
107
+ });
108
+ return clientResponse2;
109
+ }
110
+ const output = outputSchema;
111
+ const json = yield* Function.pipe(
112
+ response,
113
+ HttpClientResponse.schemaBodyJson(output)
114
+ );
115
+ const clientResponse = AjaxClientResponse.make({
116
+ data: json
117
+ });
118
+ yield* Effect.annotateLogsScoped({
119
+ method,
120
+ route,
121
+ input: decodedInput,
122
+ output: clientResponse
123
+ });
124
+ yield* Effect.logInfo("Request");
125
+ return clientResponse;
126
+ }).pipe(
127
+ Effect.scoped,
128
+ LoggerUtils.withNamespacedLogSpan(
129
+ routeName.replace("_url", "").replace("_", ":")
130
+ ),
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
+ })
154
+ );
155
+
156
+ export { Default, makeFactory };
157
+ //# sourceMappingURL=index.js.map
158
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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 BrowserHttpClient from \"@effect/platform-browser/BrowserHttpClient\";\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 = BrowserHttpClient.layerXMLHttpRequest;\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\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-SK-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"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@brytdesigns/shopify-ajax-client",
3
+ "version": "1.0.0",
4
+ "description": "An AJAX cart that integrates with ALL shopify ajax apis",
5
+ "main": "./dist/main/index.js",
6
+ "types": "./dist/main/index.d.ts",
7
+ "module": "./dist/main/index.js",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/main/index.d.ts",
14
+ "import": "./dist/main/index.js"
15
+ },
16
+ "./effect": {
17
+ "types": "./dist/effect/index.d.ts",
18
+ "import": "./dist/effect/index.js"
19
+ }
20
+ },
21
+ "type": "module",
22
+ "keywords": [],
23
+ "author": "Bryt Designs",
24
+ "license": "ISC",
25
+ "devDependencies": {
26
+ "@effect/vitest": "^0.19.0",
27
+ "dts-bundle-generator": "^9.5.1",
28
+ "tsup": "^8.4.0",
29
+ "vitest": "^3.0.6"
30
+ },
31
+ "dependencies": {
32
+ "@effect/platform": "0.90.0",
33
+ "@effect/platform-browser": "^0.70.0",
34
+ "effect": "3.17.2",
35
+ "lz-string": "^1.5.0",
36
+ "@brytdesigns/shopify-utils": "1.2.17"
37
+ },
38
+ "scripts": {
39
+ "build": "tsup --clean",
40
+ "dev": "tsx src/index.ts",
41
+ "typecheck": "tsc --noEmit",
42
+ "test": "vitest"
43
+ }
44
+ }