@scayle/storefront-core 8.60.1 → 8.61.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.
@@ -40,9 +40,9 @@ export const getCheckoutToken = defineRpcHandler(async (jwtPayload = {}, context
40
40
  ...customData,
41
41
  ...orderCustomData
42
42
  }
43
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.60.1"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
43
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.61.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
44
44
  return {
45
45
  accessToken: refreshedAccessToken,
46
46
  checkoutJwt
47
47
  };
48
- });
48
+ }, { method: "POST" });
@@ -50,7 +50,7 @@ export const getOrderById = defineRpcHandler(async ({ orderId }, context) => {
50
50
  "Unknown error"
51
51
  );
52
52
  }
53
- });
53
+ }, { method: "POST" });
54
54
  export const getOrderCustomData = defineRpcHandler(async () => {
55
55
  return {};
56
- });
56
+ }, { method: "POST" });
@@ -56,7 +56,7 @@ export const updateShopUser = defineRpcHandler(async (payload, context) => {
56
56
  "Error while updating user information"
57
57
  );
58
58
  }
59
- });
59
+ }, { method: "PUT" });
60
60
  export const updatePassword = defineRpcHandler(async ({ oldPassword, newPassword }, context) => {
61
61
  const shopUser = context.user;
62
62
  const oauthEnabled = context.oauth?.apiHost && context.oauth?.clientId && context.oauth?.clientSecret;
@@ -121,4 +121,4 @@ export const updatePassword = defineRpcHandler(async ({ oldPassword, newPassword
121
121
  }
122
122
  }
123
123
  return { user: shopUser };
124
- });
124
+ }, { method: "PUT" });
@@ -5,6 +5,8 @@ const getShopUserAddresses = defineRpcHandler(
5
5
  const shopId = context.shopId;
6
6
  const client = new CustomerAPIClient(context);
7
7
  return (await client.getAddresses(shopId)).entities;
8
- }
8
+ },
9
+ // We use POST here to prevent user data to be leaking into caches.
10
+ { method: "POST" }
9
11
  );
10
12
  export { getShopUserAddresses };
@@ -6,13 +6,13 @@ export const fetchAllNavigationTrees = defineRpcHandler(async ({ params }, conte
6
6
  return await cached(navigation.getAll, {
7
7
  cacheKeyPrefix: "getAll-navigation-trees"
8
8
  })(params);
9
- });
9
+ }, { method: "GET" });
10
10
  export const fetchNavigationTreeById = defineRpcHandler(async ({ treeId, params }, context) => {
11
11
  const { sapiClient: { navigation }, cached } = context;
12
12
  return await cached(navigation.getById, {
13
13
  cacheKeyPrefix: `getById-navigation-trees-${treeId}`
14
14
  })(treeId, params);
15
- });
15
+ }, { method: "GET" });
16
16
  export const fetchNavigationTreeByName = defineRpcHandler(async ({ treeName, params }, context) => {
17
17
  const { sapiClient: { navigation }, cached } = context;
18
18
  return await cached(
@@ -34,4 +34,4 @@ export const fetchNavigationTreeByName = defineRpcHandler(async ({ treeName, par
34
34
  cacheKeyPrefix: `getByName-navigation-trees-${treeName}`
35
35
  }
36
36
  )(treeName, params);
37
- });
37
+ }, { method: "GET" });
@@ -46,7 +46,7 @@ export const getExternalIdpRedirect = defineRpcHandler(async ({ queryParams, aut
46
46
  })
47
47
  );
48
48
  return Object.fromEntries(results);
49
- });
49
+ }, { method: "GET" });
50
50
  export const handleIDPLoginCallback = defineRpcHandler(async (payload, context) => {
51
51
  if (!hasSession(context)) {
52
52
  return new ErrorResponse(
@@ -61,4 +61,4 @@ export const handleIDPLoginCallback = defineRpcHandler(async (payload, context)
61
61
  return {
62
62
  message: "success"
63
63
  };
64
- });
64
+ }, { method: "POST" });
@@ -4,6 +4,7 @@ import { MINUTE } from "../../cache/index.mjs";
4
4
  import { unwrap } from "../../utils/response.mjs";
5
5
  import { mapSAPIFetchErrorToResponse } from "../../utils/sapi.mjs";
6
6
  import { ErrorResponse } from "../../errors/index.mjs";
7
+ import { defineRpcHandler } from "../../utils/index.mjs";
7
8
  const MAX_PER_PAGE = 100;
8
9
  const sanitizeAttributesForSAPI = ({
9
10
  attributes,
@@ -32,7 +33,7 @@ export async function resolveCategoryIdFromParams(context, params) {
32
33
  }
33
34
  return { category, categoryId };
34
35
  }
35
- export const getProductById = async function getProductById2(options, context) {
36
+ export const getProductById = defineRpcHandler(async (options, context) => {
36
37
  const { sapiClient, cached, withParams } = context;
37
38
  const campaignKey = await context.callRpc?.("getCampaignKey");
38
39
  return await cached(
@@ -47,8 +48,8 @@ export const getProductById = async function getProductById2(options, context) {
47
48
  pricePromotionKey: options.pricePromotionKey,
48
49
  includeSellableForFree: options.includeSellableForFree
49
50
  });
50
- };
51
- export const getProductsByIds = async function getProductsByIds2(options, context) {
51
+ }, { method: "GET" });
52
+ export const getProductsByIds = defineRpcHandler(async (options, context) => {
52
53
  const { sapiClient, cached, withParams } = context;
53
54
  const campaignKey = await context.callRpc?.("getCampaignKey");
54
55
  return await cached(
@@ -62,8 +63,8 @@ export const getProductsByIds = async function getProductsByIds2(options, contex
62
63
  campaignKey,
63
64
  pricePromotionKey: options.pricePromotionKey
64
65
  });
65
- };
66
- export const getProductsByReferenceKeys = async function getProductsByReferenceKeys2(options, context) {
66
+ }, { method: "GET" });
67
+ export const getProductsByReferenceKeys = defineRpcHandler(async (options, context) => {
67
68
  const { sapiClient, cached, withParams } = context;
68
69
  const campaignKey = await context.callRpc?.("getCampaignKey");
69
70
  return await cached(
@@ -77,63 +78,66 @@ export const getProductsByReferenceKeys = async function getProductsByReferenceK
77
78
  campaignKey,
78
79
  pricePromotionKey: options.pricePromotionKey
79
80
  });
80
- };
81
- export const getProductsCount = async function getProductsCount2(params, context) {
82
- const {
83
- includedFilters,
84
- where = void 0,
85
- includeSoldOut = false,
86
- includeSellableForFree = false,
87
- orFiltersOperator = void 0
88
- } = params;
89
- const { cached, sapiClient } = context;
90
- const campaignKey = await context.callRpc?.("getCampaignKey");
91
- const { categoryId } = await resolveCategoryIdFromParams(context, params);
92
- const { attributes, whitelistAttributes, ...filter } = where || {};
93
- const response = await getSanitizedAttributes(
94
- context,
95
- categoryId,
96
- attributes || [],
97
- includedFilters,
98
- includeSoldOut,
99
- includeSellableForFree,
100
- orFiltersOperator
101
- );
102
- if (response instanceof ErrorResponse) {
103
- return response;
104
- }
105
- const sanitizedAttributes = response;
106
- const productCount = await cached(sapiClient.products.query, {
107
- ttl: 15 * MINUTE,
108
- cacheKeyPrefix: "products-query"
109
- })({
110
- where: {
111
- ...filter,
81
+ }, { method: "GET" });
82
+ export const getProductsCount = defineRpcHandler(
83
+ async (params, context) => {
84
+ const {
85
+ includedFilters,
86
+ where = void 0,
87
+ includeSoldOut = false,
88
+ includeSellableForFree = false,
89
+ orFiltersOperator = void 0
90
+ } = params;
91
+ const { cached, sapiClient } = context;
92
+ const campaignKey = await context.callRpc?.("getCampaignKey");
93
+ const { categoryId } = await resolveCategoryIdFromParams(context, params);
94
+ const { attributes, whitelistAttributes, ...filter } = where || {};
95
+ const response = await getSanitizedAttributes(
96
+ context,
112
97
  categoryId,
113
- attributes: [
114
- ...sanitizedAttributes,
115
- ...whitelistAttributes || []
116
- ]
117
- },
118
- pagination: {
119
- perPage: 1
120
- },
121
- campaignKey,
122
- includeSellableForFree,
123
- includeSoldOut,
124
- orFiltersOperator
125
- });
126
- return {
127
- count: productCount?.pagination.total
128
- };
129
- };
130
- export const fetchAllFiltersForCategory = async function fetchAllFiltersForCategory2({
98
+ attributes || [],
99
+ includedFilters,
100
+ includeSoldOut,
101
+ includeSellableForFree,
102
+ orFiltersOperator
103
+ );
104
+ if (response instanceof ErrorResponse) {
105
+ return response;
106
+ }
107
+ const sanitizedAttributes = response;
108
+ const productCount = await cached(sapiClient.products.query, {
109
+ ttl: 15 * MINUTE,
110
+ cacheKeyPrefix: "products-query"
111
+ })({
112
+ where: {
113
+ ...filter,
114
+ categoryId,
115
+ attributes: [
116
+ ...sanitizedAttributes,
117
+ ...whitelistAttributes || []
118
+ ]
119
+ },
120
+ pagination: {
121
+ perPage: 1
122
+ },
123
+ campaignKey,
124
+ includeSellableForFree,
125
+ includeSoldOut,
126
+ orFiltersOperator
127
+ });
128
+ return {
129
+ count: productCount?.pagination.total
130
+ };
131
+ },
132
+ { method: "GET" }
133
+ );
134
+ export const fetchAllFiltersForCategory = defineRpcHandler(async ({
131
135
  includedFilters = [],
132
136
  category,
133
137
  includeSoldOut,
134
138
  includeSellableForFree,
135
139
  orFiltersOperator
136
- }, context) {
140
+ }, context) => {
137
141
  const { cached, sapiClient } = context;
138
142
  const campaignKey = await context.callRpc?.("getCampaignKey");
139
143
  const fetchAndMapFiltersToSlugs = async () => {
@@ -152,7 +156,7 @@ export const fetchAllFiltersForCategory = async function fetchAllFiltersForCateg
152
156
  // cached for 4 hours
153
157
  cacheKey: `filters-for-category-${category.id}`
154
158
  })();
155
- };
159
+ }, { method: "GET" });
156
160
  async function getSanitizedAttributes(context, categoryId, attributes, includedFilters, includeSoldOut, includeSellableForFree, orFiltersOperator) {
157
161
  const response = await fetchAllFiltersForCategory(
158
162
  {
@@ -174,7 +178,7 @@ async function getSanitizedAttributes(context, categoryId, attributes, includedF
174
178
  includedFilters
175
179
  });
176
180
  }
177
- export const getFilters = async function getFilters2(params, context) {
181
+ export const getFilters = defineRpcHandler(async (params, context) => {
178
182
  const {
179
183
  includedFilters,
180
184
  where = void 0,
@@ -245,8 +249,8 @@ export const getFilters = async function getFilters2(params, context) {
245
249
  filters,
246
250
  unfilteredCount: productCount?.pagination.total
247
251
  };
248
- };
249
- export const getProductsByCategory = async function getProductsByCategory2(params, context) {
252
+ }, { method: "GET" });
253
+ export const getProductsByCategory = defineRpcHandler(async (params, context) => {
250
254
  const {
251
255
  includedFilters,
252
256
  cache,
@@ -321,4 +325,4 @@ export const getProductsByCategory = async function getProductsByCategory2(param
321
325
  ...pagination
322
326
  }
323
327
  };
324
- };
328
+ }, { method: "GET" });
@@ -18,7 +18,7 @@ export const getPromotions = defineRpcHandler(async (params = {}, context) => {
18
18
  ...params,
19
19
  pagination: setPaginationDefault(params.pagination)
20
20
  });
21
- });
21
+ }, { method: "GET" });
22
22
  export const getCurrentPromotions = defineRpcHandler(async (params = {}, context) => {
23
23
  const { sapiClient, cached } = context;
24
24
  const now = /* @__PURE__ */ new Date();
@@ -31,7 +31,7 @@ export const getCurrentPromotions = defineRpcHandler(async (params = {}, context
31
31
  activeAt,
32
32
  pagination: setPaginationDefault(params.pagination)
33
33
  });
34
- });
34
+ }, { method: "GET" });
35
35
  export const getPromotionsByIds = defineRpcHandler(async (ids, context) => {
36
36
  const { sapiClient, cached } = context;
37
37
  return await cached(
@@ -40,4 +40,4 @@ export const getPromotionsByIds = defineRpcHandler(async (ids, context) => {
40
40
  cacheKeyPrefix: "getByIds-promotions"
41
41
  }
42
42
  )(ids);
43
- });
43
+ }, { method: "GET" });
@@ -9,7 +9,7 @@ export const getSearchSuggestions = defineRpcHandler(async ({ term, with: _with,
9
9
  with: _with ?? withParams?.searchV2
10
10
  }
11
11
  );
12
- });
12
+ }, { method: "GET" });
13
13
  export const resolveSearch = defineRpcHandler(async ({ term, with: _with, categoryId }, context) => {
14
14
  const { cached, sapiClient, withParams } = context;
15
15
  const resolvedEntity = await cached(sapiClient.searchv2.resolve, {
@@ -22,4 +22,4 @@ export const resolveSearch = defineRpcHandler(async ({ term, with: _with, catego
22
22
  return null;
23
23
  }
24
24
  return resolvedEntity;
25
- });
25
+ }, { method: "GET" });
@@ -99,7 +99,7 @@ export const oauthLogin = defineRpcHandler(async (login, context) => {
99
99
  "Login failed"
100
100
  );
101
101
  }
102
- });
102
+ }, { method: "POST" });
103
103
  export const oauthRegister = defineRpcHandler(async (register, context) => {
104
104
  if (!hasSession(context)) {
105
105
  return new ErrorResponse(
@@ -132,7 +132,7 @@ export const oauthRegister = defineRpcHandler(async (register, context) => {
132
132
  "Register failed"
133
133
  );
134
134
  }
135
- });
135
+ }, { method: "POST" });
136
136
  export const oauthGuestLogin = defineRpcHandler(async (guest, context) => {
137
137
  if (!hasSession(context)) {
138
138
  return new ErrorResponse(
@@ -164,7 +164,7 @@ export const oauthGuestLogin = defineRpcHandler(async (guest, context) => {
164
164
  "Guest login failed"
165
165
  );
166
166
  }
167
- });
167
+ }, { method: "POST" });
168
168
  export const refreshAccessToken = defineRpcHandler(async (context) => {
169
169
  if (!hasSession(context)) {
170
170
  return new ErrorResponse(
@@ -212,7 +212,7 @@ export const refreshAccessToken = defineRpcHandler(async (context) => {
212
212
  }
213
213
  return { success: false };
214
214
  }
215
- });
215
+ }, { method: "POST" });
216
216
  export const oauthRevokeToken = defineRpcHandler(async (context) => {
217
217
  if (!hasSession(context)) {
218
218
  return new ErrorResponse(
@@ -251,7 +251,7 @@ export const oauthRevokeToken = defineRpcHandler(async (context) => {
251
251
  }
252
252
  return { result: false };
253
253
  }
254
- });
254
+ }, { method: "POST" });
255
255
  export const oauthForgetPassword = defineRpcHandler(async ({ email }, context) => {
256
256
  if (!hasSession(context)) {
257
257
  return new ErrorResponse(
@@ -294,7 +294,7 @@ export const oauthForgetPassword = defineRpcHandler(async ({ email }, context) =
294
294
  }
295
295
  return { success: false };
296
296
  }
297
- });
297
+ }, { method: "POST" });
298
298
  export const updatePasswordByHash = defineRpcHandler(async (passwordHash, context) => {
299
299
  if (!hasSession(context)) {
300
300
  return new ErrorResponse(
@@ -331,4 +331,4 @@ export const updatePasswordByHash = defineRpcHandler(async (passwordHash, contex
331
331
  );
332
332
  }
333
333
  return new Response(null, { status: HttpStatusCode.NO_CONTENT });
334
- });
334
+ }, { method: "POST" });
@@ -8,5 +8,5 @@ const getShopConfiguration = defineRpcHandler(async (context) => {
8
8
  cacheKeyPrefix: "get-shopConfigurations"
9
9
  }
10
10
  )();
11
- });
11
+ }, { method: "GET" });
12
12
  export { getShopConfiguration };
@@ -17,7 +17,9 @@ const getUser = defineRpcHandler(
17
17
  return {
18
18
  user
19
19
  };
20
- }
20
+ },
21
+ // We use POST here to prevent user data to be leaking into caches.
22
+ { method: "POST" }
21
23
  );
22
24
  const fetchUser = defineRpcHandler(async ({ accessToken }, context) => {
23
25
  const { shopId } = context;
@@ -35,7 +37,7 @@ const fetchUser = defineRpcHandler(async ({ accessToken }, context) => {
35
37
  ({ shopId: shopId2 }) => shopId2 === context.shopId
36
38
  );
37
39
  return user;
38
- });
40
+ }, { method: "POST" });
39
41
  const refreshUser = defineRpcHandler(async (context) => {
40
42
  if (!hasSession(context)) {
41
43
  return new ErrorResponse(
@@ -59,7 +61,7 @@ const refreshUser = defineRpcHandler(async (context) => {
59
61
  await context.destroySession();
60
62
  return { user: void 0 };
61
63
  }
62
- });
64
+ }, { method: "POST" });
63
65
  const getAccessToken = defineRpcHandler(async ({ forceTokenRefresh = false } = { forceTokenRefresh: false }, context) => {
64
66
  if (!hasSession(context)) {
65
67
  return new ErrorResponse(
@@ -107,5 +109,5 @@ const getAccessToken = defineRpcHandler(async ({ forceTokenRefresh = false } = {
107
109
  }
108
110
  }
109
111
  return context.accessToken;
110
- });
112
+ }, { method: "POST" });
111
113
  export { getUser, fetchUser, refreshUser, getAccessToken };
@@ -16,4 +16,4 @@ export const getVariantById = defineRpcHandler(async ({ ids, include = defaultWi
16
16
  ids,
17
17
  include ? { with: resolvedWith, campaignKey, pricePromotionKey } : void 0
18
18
  );
19
- });
19
+ }, { method: "GET" });
@@ -33,7 +33,8 @@ export const getWishlist = defineRpcHandler(
33
33
  pricePromotionKey: pricePromotionKey ?? ""
34
34
  }
35
35
  );
36
- }
36
+ },
37
+ { method: "POST" }
37
38
  );
38
39
  export const addItemToWishlist = defineRpcHandler(async (options, context) => {
39
40
  if (!hasSession(context)) {
@@ -46,7 +47,10 @@ export const addItemToWishlist = defineRpcHandler(async (options, context) => {
46
47
  const { sapiClient, wishlistKey } = context;
47
48
  const campaignKey = await context.callRpc?.("getCampaignKey");
48
49
  const { productId, variantId } = options;
49
- const { pricePromotionKey, ...resolvedWith } = getWithParams(options, context);
50
+ const { pricePromotionKey, ...resolvedWith } = getWithParams(
51
+ options,
52
+ context
53
+ );
50
54
  if (!productId && !variantId) {
51
55
  return new ErrorResponse(
52
56
  HttpStatusCode.BAD_REQUEST,
@@ -70,7 +74,7 @@ export const addItemToWishlist = defineRpcHandler(async (options, context) => {
70
74
  context.log.error("Adding to wishlist failed", result.wishlist);
71
75
  return new Response(JSON.stringify({ kind, type }), { status: code });
72
76
  }
73
- });
77
+ }, { method: "PUT" });
74
78
  export const removeItemFromWishlist = defineRpcHandler(async (options, context) => {
75
79
  if (!hasSession(context)) {
76
80
  return new ErrorResponse(
@@ -81,7 +85,10 @@ export const removeItemFromWishlist = defineRpcHandler(async (options, context)
81
85
  }
82
86
  const { sapiClient, wishlistKey } = context;
83
87
  const campaignKey = await context.callRpc?.("getCampaignKey");
84
- const { pricePromotionKey, ...resolvedWith } = getWithParams(options, context);
88
+ const { pricePromotionKey, ...resolvedWith } = getWithParams(
89
+ options,
90
+ context
91
+ );
85
92
  return await mapSAPIFetchErrorToResponse(sapiClient.wishlist.deleteItem)(
86
93
  wishlistKey,
87
94
  options.itemKey,
@@ -91,7 +98,7 @@ export const removeItemFromWishlist = defineRpcHandler(async (options, context)
91
98
  pricePromotionKey: pricePromotionKey ?? ""
92
99
  }
93
100
  );
94
- });
101
+ }, { method: "DELETE" });
95
102
  export const clearWishlist = defineRpcHandler(
96
103
  async (context) => {
97
104
  const wishlistResponse = await getWishlist({}, context);
@@ -105,5 +112,6 @@ export const clearWishlist = defineRpcHandler(
105
112
  })
106
113
  );
107
114
  return await getWishlist({}, context);
108
- }
115
+ },
116
+ { method: "DELETE" }
109
117
  );
@@ -1,24 +1,37 @@
1
1
  import type { RpcContext } from './context';
2
+ /**
3
+ * Discriminator attached to RPC handlers indicating whether they accept a
4
+ * parameters argument or only the RPC context.
5
+ */
6
+ export type RpcType = 'NoParam' | 'WithParam';
7
+ /**
8
+ * HTTP method an RPC handler is exposed under.
9
+ * `GET` is reserved for safe, idempotent, read-only calls (enables CDN/browser caching).
10
+ * `POST` is the default for every other call and for legacy handlers.
11
+ */
12
+ export type RpcHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
2
13
  /**
3
14
  * Type for an RPC handler that accepts parameters.
4
15
  *
5
- * @note In the upcoming major release `rpcType` property will be mandatory.
16
+ * @note In the upcoming major release the `rpcType` and `httpMethod` properties will be mandatory.
6
17
  *
7
18
  * @template Params The type of the parameters object.
8
19
  * @template ResponseType The type of the response.
9
20
  */
10
21
  export type ParamRpcHandler<Params extends Record<string, any>, ResponseType> = ((params: Params, context: RpcContext) => Promise<(ResponseType extends undefined ? void : ResponseType) | Response> | ResponseType | Response) & {
11
22
  rpcType?: 'WithParam';
23
+ httpMethod?: RpcHttpMethod;
12
24
  };
13
25
  /**
14
26
  * Type for an RPC handler that does not accept parameters.
15
27
  *
16
- * @note In the upcoming major release `rpcType` property will be mandatory.
28
+ * @note In the upcoming major release the `rpcType` and `httpMethod` properties will be mandatory.
17
29
  *
18
30
  * @template ResponseType The type of the response.
19
31
  */
20
32
  export type NoParamRpcHandler<ResponseType> = ((context: RpcContext) => Promise<ResponseType | Response> | ResponseType | Response) & {
21
33
  rpcType?: 'NoParam';
34
+ httpMethod?: RpcHttpMethod;
22
35
  };
23
36
  /**
24
37
  * Generic RPC handler type. Handles both cases with and without parameters.
@@ -35,10 +35,15 @@ export const hmac = async (value, secret, algorithm = "SHA-256") => {
35
35
  };
36
36
  function base64ToBytes(base64) {
37
37
  const binString = atob(base64);
38
- return Uint8Array.from(binString, (m) => m.codePointAt(0));
38
+ return Uint8Array.from(
39
+ binString,
40
+ (m) => m.codePointAt(0)
41
+ );
39
42
  }
40
43
  function bytesToBase64(bytes) {
41
- const binString = Array.from(bytes, (x) => String.fromCodePoint(x)).join("");
44
+ const binString = Array.from(bytes, (x) => String.fromCodePoint(x)).join(
45
+ ""
46
+ );
42
47
  return btoa(binString);
43
48
  }
44
49
  export const encodeBase64 = (string) => {
@@ -5,5 +5,6 @@ export * from './basket';
5
5
  export * from './campaign';
6
6
  export { unwrap } from './response';
7
7
  export { generateBasketKey, generateWishlistKey } from './keys';
8
- export { defineRpcHandler } from './rpc';
8
+ export { defineRpcHandler, DEFAULT_RPC_HTTP_METHOD } from './rpc';
9
+ export type { DefineRpcHandlerOptions } from './rpc';
9
10
  export { sha256 } from './hash';
@@ -5,5 +5,5 @@ export * from "./basket.mjs";
5
5
  export * from "./campaign.mjs";
6
6
  export { unwrap } from "./response.mjs";
7
7
  export { generateBasketKey, generateWishlistKey } from "./keys.mjs";
8
- export { defineRpcHandler } from "./rpc.mjs";
8
+ export { defineRpcHandler, DEFAULT_RPC_HTTP_METHOD } from "./rpc.mjs";
9
9
  export { sha256 } from "./hash.mjs";
@@ -1,27 +1,44 @@
1
1
  import type { RpcMethods, RpcMethodName } from '..';
2
- import type { RpcContext, RpcHandler } from '../types';
3
- type RpcType = 'NoParam' | 'WithParam';
2
+ import type { RpcContext, RpcHandler, RpcHttpMethod, RpcType } from '../types';
3
+ /**
4
+ * Options accepted by {@link defineRpcHandler}.
5
+ */
6
+ export interface DefineRpcHandlerOptions {
7
+ /**
8
+ * HTTP method the RPC endpoint will be exposed under.
9
+ * Defaults to `'POST'`. Use `'GET'` for read-only, cacheable endpoints;
10
+ * `'PUT'` / `'DELETE'` for RESTful update/delete semantics.
11
+ */
12
+ method?: RpcHttpMethod;
13
+ }
14
+ /**
15
+ * Default HTTP method for RPC handlers when not explicitly specified.
16
+ */
17
+ export declare const DEFAULT_RPC_HTTP_METHOD: RpcHttpMethod;
4
18
  /**
5
19
  * Defines an RPC method handler.
6
20
  *
7
21
  * @param handler - The RPC handler function.
22
+ * @param options - Optional handler options (e.g. HTTP method).
8
23
  * @returns The handler itself, with correct types enforced and internal properties set.
9
24
  */
10
- export declare function defineRpcHandler<Params extends Record<string, any> | undefined, Result>(handler: (params: Params, context: RpcContext) => Result | Response | Promise<Result | Response>): RpcHandler<Params, Result>;
25
+ export declare function defineRpcHandler<Params extends Record<string, any> | undefined, Result>(handler: (params: Params, context: RpcContext) => Result | Response | Promise<Result | Response>, options?: DefineRpcHandlerOptions): RpcHandler<Params, Result>;
11
26
  /**
12
27
  * Defines an RPC method handler.
13
28
  *
14
29
  * @param handler - The RPC handler function.
30
+ * @param options - Optional handler options (e.g. HTTP method).
15
31
  * @returns The handler itself, with correct types enforced and internal properties set.
16
32
  */
17
- export declare function defineRpcHandler<Result>(handler: (context: RpcContext) => Result | Response | Promise<Result | Response>): RpcHandler<Result>;
33
+ export declare function defineRpcHandler<Result>(handler: (context: RpcContext) => Result | Response | Promise<Result | Response>, options?: DefineRpcHandlerOptions): RpcHandler<Result>;
18
34
  /**
19
35
  * Defines an RPC method handler.
20
36
  *
21
37
  * @param handler The RPC handler function.
38
+ * @param options Optional handler options (e.g. HTTP method).
22
39
  * @returns The handler itself, with correct types enforced and internal properties set.
23
40
  */
24
- export declare function defineRpcHandler<T extends RpcMethods[RpcMethodName]>(handler: T): T & {
41
+ export declare function defineRpcHandler<T extends RpcMethods[RpcMethodName]>(handler: T, options?: DefineRpcHandlerOptions): T & {
25
42
  rpcType: RpcType;
43
+ httpMethod: RpcHttpMethod;
26
44
  };
27
- export {};
@@ -1,5 +1,6 @@
1
- export function defineRpcHandler(handler) {
1
+ export const DEFAULT_RPC_HTTP_METHOD = "POST";
2
+ export function defineRpcHandler(handler, options) {
2
3
  const rpcType = handler.length === 1 ? "NoParam" : "WithParam";
3
- const handlerWithType = Object.assign(handler, { rpcType });
4
- return handlerWithType;
4
+ const httpMethod = options?.method ?? DEFAULT_RPC_HTTP_METHOD;
5
+ return Object.assign(handler, { rpcType, httpMethod });
5
6
  }