@swell/apps-sdk 1.0.189 → 2.0.0-alpha.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.
Files changed (229) hide show
  1. package/README.md +146 -247
  2. package/dist/backend.d.cts +81 -0
  3. package/dist/backend.d.ts +81 -0
  4. package/dist/backend.js +152 -0
  5. package/dist/browser-refusal.d.cts +1 -0
  6. package/dist/browser-refusal.d.ts +1 -0
  7. package/dist/browser-refusal.js +2 -0
  8. package/dist/context.d.cts +21 -0
  9. package/dist/context.d.ts +21 -0
  10. package/dist/context.js +42 -0
  11. package/dist/error.d.cts +23 -0
  12. package/dist/error.d.ts +23 -0
  13. package/dist/error.js +30 -0
  14. package/dist/guard.d.cts +1 -0
  15. package/dist/guard.d.ts +1 -0
  16. package/dist/guard.js +4 -0
  17. package/dist/index.d.cts +9 -0
  18. package/dist/index.d.ts +9 -0
  19. package/dist/index.js +5 -20298
  20. package/dist/staff.d.cts +16 -0
  21. package/dist/staff.d.ts +16 -0
  22. package/dist/staff.js +33 -0
  23. package/dist/storefront.d.cts +28 -0
  24. package/dist/storefront.d.ts +28 -0
  25. package/dist/storefront.js +44 -0
  26. package/dist/version.d.cts +1 -0
  27. package/dist/version.d.ts +1 -0
  28. package/dist/version.js +2 -0
  29. package/dist/workflow.d.cts +1 -0
  30. package/dist/workflow.d.ts +1 -0
  31. package/dist/workflow.js +35 -0
  32. package/package.json +48 -63
  33. package/dist/index.cjs +0 -20546
  34. package/dist/index.cjs.map +0 -7
  35. package/dist/index.js.map +0 -7
  36. package/dist/index.mjs +0 -20403
  37. package/dist/index.mjs.map +0 -7
  38. package/dist/src/api.d.ts +0 -96
  39. package/dist/src/cache/cache.d.ts +0 -41
  40. package/dist/src/cache/cf-worker-kv-keyv-adapter.d.ts +0 -18
  41. package/dist/src/cache/constants.d.ts +0 -7
  42. package/dist/src/cache/content-cache.d.ts +0 -21
  43. package/dist/src/cache/html-cache/html-cache-backend.d.ts +0 -64
  44. package/dist/src/cache/html-cache/html-cache-factory.d.ts +0 -9
  45. package/dist/src/cache/html-cache/html-cache-kv.d.ts +0 -38
  46. package/dist/src/cache/html-cache/html-cache-worker.d.ts +0 -8
  47. package/dist/src/cache/html-cache/html-cache.d.ts +0 -120
  48. package/dist/src/cache/html-cache/index.d.ts +0 -4
  49. package/dist/src/cache/index.d.ts +0 -9
  50. package/dist/src/cache/kv-variety.d.ts +0 -10
  51. package/dist/src/cache/request-cache.d.ts +0 -4
  52. package/dist/src/cache/resource-cache.d.ts +0 -4
  53. package/dist/src/cache/theme-cache.d.ts +0 -4
  54. package/dist/src/cache/theme-file-cache.d.ts +0 -87
  55. package/dist/src/compatibility/drops/all_products.d.ts +0 -10
  56. package/dist/src/compatibility/drops/articles.d.ts +0 -10
  57. package/dist/src/compatibility/drops/blogs.d.ts +0 -10
  58. package/dist/src/compatibility/drops/collections.d.ts +0 -19
  59. package/dist/src/compatibility/drops/image-src.d.ts +0 -15
  60. package/dist/src/compatibility/drops/image.d.ts +0 -29
  61. package/dist/src/compatibility/drops/images.d.ts +0 -9
  62. package/dist/src/compatibility/drops/money.d.ts +0 -10
  63. package/dist/src/compatibility/drops/object-handles.d.ts +0 -6
  64. package/dist/src/compatibility/drops/pages.d.ts +0 -17
  65. package/dist/src/compatibility/drops/robots-rule.d.ts +0 -9
  66. package/dist/src/compatibility/drops/template.d.ts +0 -9
  67. package/dist/src/compatibility/shopify-configs.d.ts +0 -8
  68. package/dist/src/compatibility/shopify-fonts.d.ts +0 -1
  69. package/dist/src/compatibility/shopify-objects/address.d.ts +0 -7
  70. package/dist/src/compatibility/shopify-objects/article.d.ts +0 -7
  71. package/dist/src/compatibility/shopify-objects/blog.d.ts +0 -6
  72. package/dist/src/compatibility/shopify-objects/cart.d.ts +0 -6
  73. package/dist/src/compatibility/shopify-objects/collection.d.ts +0 -7
  74. package/dist/src/compatibility/shopify-objects/collections.d.ts +0 -6
  75. package/dist/src/compatibility/shopify-objects/content.d.ts +0 -12
  76. package/dist/src/compatibility/shopify-objects/currency.d.ts +0 -5
  77. package/dist/src/compatibility/shopify-objects/customer.d.ts +0 -6
  78. package/dist/src/compatibility/shopify-objects/filter.d.ts +0 -6
  79. package/dist/src/compatibility/shopify-objects/font.d.ts +0 -5
  80. package/dist/src/compatibility/shopify-objects/form.d.ts +0 -29
  81. package/dist/src/compatibility/shopify-objects/image.d.ts +0 -10
  82. package/dist/src/compatibility/shopify-objects/index.d.ts +0 -27
  83. package/dist/src/compatibility/shopify-objects/line_item.d.ts +0 -7
  84. package/dist/src/compatibility/shopify-objects/link.d.ts +0 -5
  85. package/dist/src/compatibility/shopify-objects/localization.d.ts +0 -5
  86. package/dist/src/compatibility/shopify-objects/media.d.ts +0 -9
  87. package/dist/src/compatibility/shopify-objects/money.d.ts +0 -3
  88. package/dist/src/compatibility/shopify-objects/order.d.ts +0 -11
  89. package/dist/src/compatibility/shopify-objects/page.d.ts +0 -5
  90. package/dist/src/compatibility/shopify-objects/paginate.d.ts +0 -5
  91. package/dist/src/compatibility/shopify-objects/predictive_search.d.ts +0 -5
  92. package/dist/src/compatibility/shopify-objects/product.d.ts +0 -9
  93. package/dist/src/compatibility/shopify-objects/recommendations.d.ts +0 -5
  94. package/dist/src/compatibility/shopify-objects/resource.d.ts +0 -27
  95. package/dist/src/compatibility/shopify-objects/search.d.ts +0 -5
  96. package/dist/src/compatibility/shopify-objects/shop.d.ts +0 -5
  97. package/dist/src/compatibility/shopify-objects/template.d.ts +0 -4
  98. package/dist/src/compatibility/shopify-objects/variant.d.ts +0 -6
  99. package/dist/src/compatibility/shopify.d.ts +0 -134
  100. package/dist/src/constants.d.ts +0 -598
  101. package/dist/src/content.d.ts +0 -8
  102. package/dist/src/easyblocks/config.d.ts +0 -152
  103. package/dist/src/easyblocks/index.d.ts +0 -2
  104. package/dist/src/easyblocks/utils.d.ts +0 -23
  105. package/dist/src/editor/resources.d.ts +0 -9
  106. package/dist/src/fonts.d.ts +0 -6
  107. package/dist/src/globals.d.ts +0 -7
  108. package/dist/src/index.d.ts +0 -16
  109. package/dist/src/liquid/color.d.ts +0 -33
  110. package/dist/src/liquid/drops/render.d.ts +0 -10
  111. package/dist/src/liquid/filters/asset_url.d.ts +0 -3
  112. package/dist/src/liquid/filters/brightness_difference.d.ts +0 -2
  113. package/dist/src/liquid/filters/color_brightness.d.ts +0 -2
  114. package/dist/src/liquid/filters/color_contrast.d.ts +0 -2
  115. package/dist/src/liquid/filters/color_darken.d.ts +0 -2
  116. package/dist/src/liquid/filters/color_desaturate.d.ts +0 -2
  117. package/dist/src/liquid/filters/color_difference.d.ts +0 -2
  118. package/dist/src/liquid/filters/color_extract.d.ts +0 -4
  119. package/dist/src/liquid/filters/color_lighten.d.ts +0 -2
  120. package/dist/src/liquid/filters/color_mix.d.ts +0 -2
  121. package/dist/src/liquid/filters/color_modify.d.ts +0 -3
  122. package/dist/src/liquid/filters/color_saturate.d.ts +0 -2
  123. package/dist/src/liquid/filters/color_to_hex.d.ts +0 -2
  124. package/dist/src/liquid/filters/color_to_hsl.d.ts +0 -2
  125. package/dist/src/liquid/filters/color_to_rgb.d.ts +0 -2
  126. package/dist/src/liquid/filters/date.d.ts +0 -7
  127. package/dist/src/liquid/filters/date_next_interval.d.ts +0 -3
  128. package/dist/src/liquid/filters/default_errors.d.ts +0 -3
  129. package/dist/src/liquid/filters/divided_by.d.ts +0 -2
  130. package/dist/src/liquid/filters/embedded_content.d.ts +0 -2
  131. package/dist/src/liquid/filters/escape.d.ts +0 -3
  132. package/dist/src/liquid/filters/font_face.d.ts +0 -2
  133. package/dist/src/liquid/filters/font_modify.d.ts +0 -3
  134. package/dist/src/liquid/filters/font_url.d.ts +0 -2
  135. package/dist/src/liquid/filters/format_address.d.ts +0 -6
  136. package/dist/src/liquid/filters/handleize.d.ts +0 -3
  137. package/dist/src/liquid/filters/image_tag.d.ts +0 -3
  138. package/dist/src/liquid/filters/image_url.d.ts +0 -8
  139. package/dist/src/liquid/filters/index.d.ts +0 -120
  140. package/dist/src/liquid/filters/inline_asset_content.d.ts +0 -2
  141. package/dist/src/liquid/filters/inline_editable.d.ts +0 -4
  142. package/dist/src/liquid/filters/json.d.ts +0 -3
  143. package/dist/src/liquid/filters/json_pretty.d.ts +0 -3
  144. package/dist/src/liquid/filters/locale_flag.d.ts +0 -2
  145. package/dist/src/liquid/filters/minus.d.ts +0 -2
  146. package/dist/src/liquid/filters/money.d.ts +0 -4
  147. package/dist/src/liquid/filters/money_with_currency.d.ts +0 -3
  148. package/dist/src/liquid/filters/money_without_currency.d.ts +0 -3
  149. package/dist/src/liquid/filters/money_without_trailing_zeros.d.ts +0 -3
  150. package/dist/src/liquid/filters/preload_tag.d.ts +0 -3
  151. package/dist/src/liquid/filters/script_tag.d.ts +0 -3
  152. package/dist/src/liquid/filters/shopify/asset_img_url.d.ts +0 -3
  153. package/dist/src/liquid/filters/shopify/default_pagination.d.ts +0 -3
  154. package/dist/src/liquid/filters/shopify/hex_to_rgba.d.ts +0 -2
  155. package/dist/src/liquid/filters/shopify/img_url.d.ts +0 -3
  156. package/dist/src/liquid/filters/shopify/item_count_for_variant.d.ts +0 -6
  157. package/dist/src/liquid/filters/shopify/payment_button.d.ts +0 -2
  158. package/dist/src/liquid/filters/shopify/payment_terms.d.ts +0 -2
  159. package/dist/src/liquid/filters/shopify/placeholder-svgs/index.d.ts +0 -5
  160. package/dist/src/liquid/filters/shopify/placeholder_svg_tag.d.ts +0 -3
  161. package/dist/src/liquid/filters/shopify/shopify_asset_url.d.ts +0 -3
  162. package/dist/src/liquid/filters/shopify/structured_data.d.ts +0 -3
  163. package/dist/src/liquid/filters/stylesheet_tag.d.ts +0 -3
  164. package/dist/src/liquid/filters/time_tag.d.ts +0 -2
  165. package/dist/src/liquid/filters/translate.d.ts +0 -3
  166. package/dist/src/liquid/filters/where.d.ts +0 -3
  167. package/dist/src/liquid/font.d.ts +0 -51
  168. package/dist/src/liquid/form.d.ts +0 -17
  169. package/dist/src/liquid/hash.d.ts +0 -5
  170. package/dist/src/liquid/index.d.ts +0 -52
  171. package/dist/src/liquid/operators.d.ts +0 -10
  172. package/dist/src/liquid/tags/assign.d.ts +0 -3
  173. package/dist/src/liquid/tags/case.d.ts +0 -3
  174. package/dist/src/liquid/tags/comment.d.ts +0 -3
  175. package/dist/src/liquid/tags/content_for.d.ts +0 -3
  176. package/dist/src/liquid/tags/doc.d.ts +0 -2
  177. package/dist/src/liquid/tags/for.d.ts +0 -3
  178. package/dist/src/liquid/tags/form.d.ts +0 -3
  179. package/dist/src/liquid/tags/if.d.ts +0 -4
  180. package/dist/src/liquid/tags/index.d.ts +0 -42
  181. package/dist/src/liquid/tags/inline_editable.d.ts +0 -3
  182. package/dist/src/liquid/tags/javascript.d.ts +0 -3
  183. package/dist/src/liquid/tags/layout.d.ts +0 -3
  184. package/dist/src/liquid/tags/paginate.d.ts +0 -3
  185. package/dist/src/liquid/tags/render.d.ts +0 -6
  186. package/dist/src/liquid/tags/section.d.ts +0 -3
  187. package/dist/src/liquid/tags/sections.d.ts +0 -3
  188. package/dist/src/liquid/tags/shopify/include.d.ts +0 -3
  189. package/dist/src/liquid/tags/shopify/schema.d.ts +0 -3
  190. package/dist/src/liquid/tags/style.d.ts +0 -3
  191. package/dist/src/liquid/tags/stylesheet.d.ts +0 -3
  192. package/dist/src/liquid/test-helpers.d.ts +0 -8
  193. package/dist/src/liquid/tokens/identifier-token.d.ts +0 -9
  194. package/dist/src/liquid/tokens/index.d.ts +0 -2
  195. package/dist/src/liquid/tokienizer.d.ts +0 -5
  196. package/dist/src/liquid/utils.d.ts +0 -45
  197. package/dist/src/menus.d.ts +0 -25
  198. package/dist/src/resources/account.d.ts +0 -6
  199. package/dist/src/resources/addresses.d.ts +0 -7
  200. package/dist/src/resources/blog.d.ts +0 -7
  201. package/dist/src/resources/blog_category.d.ts +0 -7
  202. package/dist/src/resources/cart.d.ts +0 -6
  203. package/dist/src/resources/categories.d.ts +0 -7
  204. package/dist/src/resources/category.d.ts +0 -7
  205. package/dist/src/resources/index.d.ts +0 -48
  206. package/dist/src/resources/order.d.ts +0 -7
  207. package/dist/src/resources/orders.d.ts +0 -7
  208. package/dist/src/resources/page.d.ts +0 -7
  209. package/dist/src/resources/predictive_search.d.ts +0 -6
  210. package/dist/src/resources/product.d.ts +0 -7
  211. package/dist/src/resources/product_helpers.d.ts +0 -21
  212. package/dist/src/resources/search.d.ts +0 -6
  213. package/dist/src/resources/subscription.d.ts +0 -7
  214. package/dist/src/resources/subscriptions.d.ts +0 -7
  215. package/dist/src/resources/swell_types.d.ts +0 -163
  216. package/dist/src/resources/variant.d.ts +0 -9
  217. package/dist/src/resources.d.ts +0 -113
  218. package/dist/src/theme/theme-loader.d.ts +0 -110
  219. package/dist/src/theme.d.ts +0 -204
  220. package/dist/src/utils/escape.d.ts +0 -1
  221. package/dist/src/utils/index.d.ts +0 -34
  222. package/dist/src/utils/kv-flavor.d.ts +0 -7
  223. package/dist/src/utils/logger.d.ts +0 -21
  224. package/dist/src/utils/md5.d.ts +0 -1
  225. package/dist/types/cloudflare.d.ts +0 -61
  226. package/dist/types/shopify.d.ts +0 -1035
  227. package/dist/types/swell.d.ts +0 -576
  228. package/types/index.d.ts +0 -4
  229. package/types/svg.d.ts +0 -4
@@ -0,0 +1,152 @@
1
+ import { parseSwellHeaders, requireString, validateUrl } from './context.js';
2
+ import { SwellError } from './error.js';
3
+ import { validateWorkflowParams } from './workflow.js';
4
+ import { USER_AGENT } from './version.js';
5
+ // Matches JSON bodies: undefined values are omitted and Dates become ISO strings.
6
+ function queryParts(query, prefix = '') {
7
+ return Object.entries(query).flatMap(([key, value]) => {
8
+ const name = prefix ? `${prefix}[${key}]` : key;
9
+ if (value === undefined)
10
+ return [];
11
+ // A bare key decodes to native null on the server; `key=null` would be the string "null".
12
+ if (value === null)
13
+ return [encodeURIComponent(name)];
14
+ if (value instanceof Date)
15
+ value = value.toISOString();
16
+ return typeof value === 'object' ? queryParts(value, name)
17
+ : [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
18
+ });
19
+ }
20
+ /** Per-request backend client. Use explicit credentials outside trusted platform ingress. */
21
+ export class SwellBackendAPI {
22
+ #baseUrl;
23
+ #authorization;
24
+ #appId;
25
+ #requestId;
26
+ get userAgent() { return USER_AGENT; }
27
+ workflows = {
28
+ /** Creates a workflow instance. Optional params must be JSON-safe and at most 128 KiB of UTF-8 JSON; invalid params reject. */
29
+ create: async (name, params) => {
30
+ const data = { workflow_name: name };
31
+ if (params !== undefined)
32
+ data.params = validateWorkflowParams(params);
33
+ return this.post('/:workflows/instances', data);
34
+ },
35
+ };
36
+ functions = {
37
+ /**
38
+ * Invokes an app's private function from server code and resolves to its response payload,
39
+ * without the envelope's status or headers.
40
+ * `appId` is the app identifier from `Swell-App-Id` (`parseSwellHeaders(headers).appId`).
41
+ * `method` (default `post`) selects the function's handler. GET data reaches the function
42
+ * as query parameters, so its values must be flat strings, numbers or booleans.
43
+ * Throws `SwellError` when the function reports a non-2xx status or an error.
44
+ * Callers authorize the operation first; no caller headers are forwarded.
45
+ */
46
+ call: async (appId, name, data, { method = 'post' } = {}) => {
47
+ requireString(appId, 'appId');
48
+ requireString(name, 'function name');
49
+ if (!['get', 'post', 'put', 'delete'].includes(method))
50
+ throw new Error(`Invalid function method: ${method}`);
51
+ if (method === 'get' && data && Object.values(data).some(value => !['string', 'number', 'boolean'].includes(typeof value))) {
52
+ throw new Error('GET function data must contain only string, number or boolean values');
53
+ }
54
+ const result = await this.put(`/:functions/${encodeURIComponent(`app.${appId}.${name}`)}`, { $call: { data: data ?? {}, method } });
55
+ if (!result || typeof result !== 'object')
56
+ throw new SwellError(`Function not found: ${name}`, { status: 404 });
57
+ const { status, error, code, response } = result;
58
+ if (error !== undefined || (typeof status === 'number' && (status < 200 || status > 299))) {
59
+ const message = typeof error === 'string' ? error : typeof response?.error === 'string' ? response.error : `Function ${name} failed`;
60
+ const failure = new SwellError(message, { status, code });
61
+ failure.body = response ?? result;
62
+ throw failure;
63
+ }
64
+ return response;
65
+ },
66
+ };
67
+ constructor(options) {
68
+ if (options.headers && ['storeId', 'apiHost', 'accessToken', 'secretKey', 'appId', 'requestId'].some(key => key in options)) {
69
+ throw new Error('headers and explicit backend credentials are mutually exclusive');
70
+ }
71
+ const config = options.headers ? parseSwellHeaders(options.headers) : options;
72
+ const secretKey = 'secretKey' in config ? config.secretKey : undefined;
73
+ requireString(config.storeId, 'storeId');
74
+ if ((config.accessToken !== undefined) === (secretKey !== undefined))
75
+ throw new Error('Provide exactly one accessToken or secretKey');
76
+ const credential = config.accessToken ?? secretKey;
77
+ requireString(credential, 'accessToken or secretKey');
78
+ this.#baseUrl = validateUrl(config.apiHost, 'apiHost');
79
+ const bytes = new TextEncoder().encode(`${config.storeId}:${credential}`);
80
+ this.#authorization = `Basic ${btoa(Array.from(bytes, byte => String.fromCharCode(byte)).join(''))}`;
81
+ this.#appId = config.appId;
82
+ this.#requestId = config.requestId;
83
+ }
84
+ async #makeRequest(method, path, data) {
85
+ // Paths stay on the configured host: '' means '/', spaces are encoded, dot segments are
86
+ // normalized by URL parsing, fragments/backslashes/control characters are rejected.
87
+ if (typeof path !== 'string' || /^[a-z][a-z\d+.-]*:/i.test(path) || path.startsWith('//') || /[\\#\x00-\x1f\x7f]/.test(path)) {
88
+ throw new Error('Backend endpoint must be a path on the configured API host');
89
+ }
90
+ const endpointUrl = path.replace(/^\//, '').replaceAll(' ', '%20');
91
+ const headers = {
92
+ Authorization: this.#authorization, 'User-Agent': this.userAgent, 'Content-Type': 'application/json',
93
+ ...(this.#requestId ? { 'Swell-Request-ID': this.#requestId } : {}),
94
+ };
95
+ const init = { method, headers, redirect: 'manual' };
96
+ let query = '';
97
+ if (data) {
98
+ try {
99
+ if (method !== 'GET')
100
+ init.body = JSON.stringify(data);
101
+ else {
102
+ const params = queryParts(data).join('&');
103
+ if (params)
104
+ query = `${path.includes('?') ? '&' : '?'}${params}`;
105
+ }
106
+ }
107
+ catch {
108
+ throw new Error(`Error serializing data: ${data}`);
109
+ }
110
+ }
111
+ const response = await fetch(`${this.#baseUrl}/${endpointUrl}${query}`, init);
112
+ const text = await response.text();
113
+ let result;
114
+ try {
115
+ result = JSON.parse(text);
116
+ }
117
+ catch {
118
+ result = text.trim();
119
+ }
120
+ if (!response.ok)
121
+ throw new SwellError(result, { status: response.status, method, endpointUrl });
122
+ if (method !== 'GET' && result?.errors)
123
+ throw new SwellError(result.errors, { status: 400, method, endpointUrl });
124
+ return result;
125
+ }
126
+ get(path, query) { return this.#makeRequest('GET', path, query); }
127
+ put(path, data) { return this.#makeRequest('PUT', path, data); }
128
+ post(path, data) { return this.#makeRequest('POST', path, data); }
129
+ delete(path, data) { return this.#makeRequest('DELETE', path, data); }
130
+ /** Reads installed-app settings; defaults to the configured app ID and rejects when neither ID is supplied. */
131
+ async settings(appId = this.#appId) {
132
+ requireString(appId, 'appId for settings()');
133
+ return this.get(`/settings/${encodeURIComponent(appId)}`);
134
+ }
135
+ /** Atomic operations returning results in operation order; only conflicts and throttling retry, and only when requested. */
136
+ async transaction(ops, options = {}) {
137
+ const cfg = { limit: 3, base: 100, max: 5000, jitter: true, ...(options.retry === true ? {} : options.retry) };
138
+ let attempt = 0;
139
+ while (true) {
140
+ try {
141
+ return await this.post('/:transaction', ops);
142
+ }
143
+ catch (error) {
144
+ if (!options.retry || !(error instanceof SwellError) || !error.isRetryable || attempt >= cfg.limit)
145
+ throw error;
146
+ const delay = Math.min(cfg.base * 2 ** attempt, cfg.max);
147
+ await new Promise(resolve => setTimeout(resolve, cfg.jitter ? delay * (0.5 + Math.random() * 0.5) : delay));
148
+ attempt++;
149
+ }
150
+ }
151
+ }
152
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ throw new Error('@swell/apps-sdk is server-only; import swell-js in browser code');
2
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { PublicConfig } from 'swell-js';
2
+ export type HeaderReader = Pick<Headers, 'get'>;
3
+ export interface SwellContext {
4
+ storeId?: string;
5
+ appId?: string;
6
+ environmentId?: string;
7
+ storefrontId?: string;
8
+ accessToken?: string;
9
+ publicKey?: string;
10
+ apiHost?: string;
11
+ adminUrl?: string;
12
+ vaultUrl?: string;
13
+ requestId?: string;
14
+ isLocalDev: boolean;
15
+ }
16
+ /** Parses trusted ingress headers; does not verify their signature. */
17
+ export declare function parseSwellHeaders(headers: HeaderReader): SwellContext;
18
+ export declare function requireString(value: unknown, field: string): asserts value is string;
19
+ export declare function validateUrl(value: unknown, field: string): string;
20
+ /** Projects only public configuration. Deliver it with Cache-Control: private, no-store. */
21
+ export declare function getStorefrontConfig(headers: HeaderReader): PublicConfig;
@@ -0,0 +1,21 @@
1
+ import type { PublicConfig } from 'swell-js';
2
+ export type HeaderReader = Pick<Headers, 'get'>;
3
+ export interface SwellContext {
4
+ storeId?: string;
5
+ appId?: string;
6
+ environmentId?: string;
7
+ storefrontId?: string;
8
+ accessToken?: string;
9
+ publicKey?: string;
10
+ apiHost?: string;
11
+ adminUrl?: string;
12
+ vaultUrl?: string;
13
+ requestId?: string;
14
+ isLocalDev: boolean;
15
+ }
16
+ /** Parses trusted ingress headers; does not verify their signature. */
17
+ export declare function parseSwellHeaders(headers: HeaderReader): SwellContext;
18
+ export declare function requireString(value: unknown, field: string): asserts value is string;
19
+ export declare function validateUrl(value: unknown, field: string): string;
20
+ /** Projects only public configuration. Deliver it with Cache-Control: private, no-store. */
21
+ export declare function getStorefrontConfig(headers: HeaderReader): PublicConfig;
@@ -0,0 +1,42 @@
1
+ /** Parses trusted ingress headers; does not verify their signature. */
2
+ export function parseSwellHeaders(headers) {
3
+ const read = (name) => headers.get(`Swell-${name}`) ?? undefined;
4
+ return {
5
+ storeId: read('Store-Id'), appId: read('App-Id'),
6
+ environmentId: read('Environment-Id'), storefrontId: read('Storefront-Id'),
7
+ accessToken: read('Access-Token'), publicKey: read('Public-Key'),
8
+ apiHost: read('API-Host'), adminUrl: read('Admin-Url'),
9
+ vaultUrl: read('Vault-Url'), requestId: read('Request-ID'),
10
+ isLocalDev: read('Local-Dev') === 'true',
11
+ };
12
+ }
13
+ export function requireString(value, field) {
14
+ if (typeof value !== 'string' || !value.trim())
15
+ throw new Error(`Missing or invalid ${field}`);
16
+ }
17
+ export function validateUrl(value, field) {
18
+ requireString(value, field);
19
+ let url;
20
+ try {
21
+ url = new URL(value);
22
+ }
23
+ catch {
24
+ throw new Error(`Invalid ${field}: expected an absolute HTTP(S) URL`);
25
+ }
26
+ if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) {
27
+ throw new Error(`Invalid ${field}: expected an HTTP(S) URL without credentials, query or fragment`);
28
+ }
29
+ return url.href.replace(/\/$/, '');
30
+ }
31
+ /** Projects only public configuration. Deliver it with Cache-Control: private, no-store. */
32
+ export function getStorefrontConfig(headers) {
33
+ const context = parseSwellHeaders(headers);
34
+ requireString(context.storeId, 'storeId');
35
+ requireString(context.publicKey, 'publicKey');
36
+ return {
37
+ storeId: context.storeId, publicKey: context.publicKey,
38
+ url: validateUrl(context.adminUrl, 'adminUrl'),
39
+ vaultUrl: context.vaultUrl === undefined ? 'https://vault.schema.io' : validateUrl(context.vaultUrl, 'vaultUrl'),
40
+ ...(context.storefrontId ? { headers: { 'Swell-Storefront-Id': context.storefrontId } } : {}),
41
+ };
42
+ }
@@ -0,0 +1,23 @@
1
+ export interface SwellErrorOptions {
2
+ status?: number;
3
+ method?: string;
4
+ endpointUrl?: string;
5
+ code?: string;
6
+ retry?: boolean;
7
+ }
8
+ /**
9
+ * Backend or function error; ordinary operations never retry automatically.
10
+ * Machine-readable contract: `status`, optional `code` and optional `body`.
11
+ * Ordinary backend errors retain structured responses in `body`; string errors have no body.
12
+ * HTTP-200 non-GET validation failures retain the `errors` field map. Function invocation
13
+ * failures retain the response payload or, if nullish, the invocation envelope.
14
+ * `message` is for humans and may change.
15
+ */
16
+ export declare class SwellError extends Error {
17
+ status: number;
18
+ body?: any;
19
+ code?: string;
20
+ retry?: boolean;
21
+ constructor(message: any, options?: SwellErrorOptions);
22
+ get isRetryable(): boolean;
23
+ }
@@ -0,0 +1,23 @@
1
+ export interface SwellErrorOptions {
2
+ status?: number;
3
+ method?: string;
4
+ endpointUrl?: string;
5
+ code?: string;
6
+ retry?: boolean;
7
+ }
8
+ /**
9
+ * Backend or function error; ordinary operations never retry automatically.
10
+ * Machine-readable contract: `status`, optional `code` and optional `body`.
11
+ * Ordinary backend errors retain structured responses in `body`; string errors have no body.
12
+ * HTTP-200 non-GET validation failures retain the `errors` field map. Function invocation
13
+ * failures retain the response payload or, if nullish, the invocation envelope.
14
+ * `message` is for humans and may change.
15
+ */
16
+ export declare class SwellError extends Error {
17
+ status: number;
18
+ body?: any;
19
+ code?: string;
20
+ retry?: boolean;
21
+ constructor(message: any, options?: SwellErrorOptions);
22
+ get isRetryable(): boolean;
23
+ }
package/dist/error.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Backend or function error; ordinary operations never retry automatically.
3
+ * Machine-readable contract: `status`, optional `code` and optional `body`.
4
+ * Ordinary backend errors retain structured responses in `body`; string errors have no body.
5
+ * HTTP-200 non-GET validation failures retain the `errors` field map. Function invocation
6
+ * failures retain the response payload or, if nullish, the invocation envelope.
7
+ * `message` is for humans and may change.
8
+ */
9
+ export class SwellError extends Error {
10
+ status;
11
+ body;
12
+ code;
13
+ retry;
14
+ constructor(message, options = {}) {
15
+ const body = typeof message === 'string' ? undefined : message;
16
+ let formatted = typeof message === 'string' ? message
17
+ : typeof body?.error?.message === 'string' ? body.error.message : JSON.stringify(message, null, 2);
18
+ if (options.method && options.endpointUrl)
19
+ formatted = `${options.method} /${options.endpointUrl}\n${formatted}`;
20
+ super(formatted);
21
+ this.name = 'SwellError';
22
+ this.status = options.status || 500;
23
+ this.body = body;
24
+ this.code = options.code || body?.error?.code;
25
+ this.retry = options.retry;
26
+ }
27
+ get isRetryable() {
28
+ return this.code === 'transaction_conflict' || this.code === 'transaction_throttled';
29
+ }
30
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/guard.js ADDED
@@ -0,0 +1,4 @@
1
+ if (typeof document !== 'undefined') {
2
+ throw new Error('@swell/apps-sdk is server-only; import swell-js in browser code');
3
+ }
4
+ export {};
@@ -0,0 +1,9 @@
1
+ import './guard.cjs';
2
+ export { parseSwellHeaders, getStorefrontConfig } from './context.cjs';
3
+ export type { HeaderReader, SwellContext } from './context.cjs';
4
+ export { SwellBackendAPI } from './backend.cjs';
5
+ export type { BackendOptions, SwellCollection, SwellData, TransactionOperation, TransactionOptions } from './backend.cjs';
6
+ export { SwellError } from './error.cjs';
7
+ export type { SwellErrorOptions } from './error.cjs';
8
+ export { requireStaff } from './staff.cjs';
9
+ export type { StaffIdentity, StaffOptions } from './staff.cjs';
@@ -0,0 +1,9 @@
1
+ import './guard.js';
2
+ export { parseSwellHeaders, getStorefrontConfig } from './context.js';
3
+ export type { HeaderReader, SwellContext } from './context.js';
4
+ export { SwellBackendAPI } from './backend.js';
5
+ export type { BackendOptions, SwellCollection, SwellData, TransactionOperation, TransactionOptions } from './backend.js';
6
+ export { SwellError } from './error.js';
7
+ export type { SwellErrorOptions } from './error.js';
8
+ export { requireStaff } from './staff.js';
9
+ export type { StaffIdentity, StaffOptions } from './staff.js';