@swell/apps-sdk 1.0.190 → 2.0.0-alpha.1

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 (235) hide show
  1. package/README.md +188 -254
  2. package/dist/backend.d.cts +81 -0
  3. package/dist/backend.d.ts +81 -0
  4. package/dist/backend.js +154 -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 +7 -0
  9. package/dist/context.d.ts +7 -0
  10. package/dist/context.js +29 -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 +11 -0
  18. package/dist/index.d.ts +11 -0
  19. package/dist/index.js +6 -20299
  20. package/dist/jwks.d.cts +1 -0
  21. package/dist/jwks.d.ts +1 -0
  22. package/dist/jwks.js +70 -0
  23. package/dist/request-context.d.cts +37 -0
  24. package/dist/request-context.d.ts +37 -0
  25. package/dist/request-context.js +99 -0
  26. package/dist/staff.d.cts +7 -0
  27. package/dist/staff.d.ts +7 -0
  28. package/dist/staff.js +7 -0
  29. package/dist/storefront.d.cts +28 -0
  30. package/dist/storefront.d.ts +28 -0
  31. package/dist/storefront.js +44 -0
  32. package/dist/version.d.cts +1 -0
  33. package/dist/version.d.ts +1 -0
  34. package/dist/version.js +2 -0
  35. package/dist/workflow.d.cts +1 -0
  36. package/dist/workflow.d.ts +1 -0
  37. package/dist/workflow.js +35 -0
  38. package/package.json +48 -63
  39. package/dist/index.cjs +0 -20547
  40. package/dist/index.cjs.map +0 -7
  41. package/dist/index.js.map +0 -7
  42. package/dist/index.mjs +0 -20404
  43. package/dist/index.mjs.map +0 -7
  44. package/dist/src/api.d.ts +0 -96
  45. package/dist/src/cache/cache.d.ts +0 -41
  46. package/dist/src/cache/cf-worker-kv-keyv-adapter.d.ts +0 -18
  47. package/dist/src/cache/constants.d.ts +0 -7
  48. package/dist/src/cache/content-cache.d.ts +0 -21
  49. package/dist/src/cache/html-cache/html-cache-backend.d.ts +0 -64
  50. package/dist/src/cache/html-cache/html-cache-factory.d.ts +0 -9
  51. package/dist/src/cache/html-cache/html-cache-kv.d.ts +0 -38
  52. package/dist/src/cache/html-cache/html-cache-worker.d.ts +0 -8
  53. package/dist/src/cache/html-cache/html-cache.d.ts +0 -120
  54. package/dist/src/cache/html-cache/index.d.ts +0 -4
  55. package/dist/src/cache/index.d.ts +0 -9
  56. package/dist/src/cache/kv-variety.d.ts +0 -10
  57. package/dist/src/cache/request-cache.d.ts +0 -4
  58. package/dist/src/cache/resource-cache.d.ts +0 -4
  59. package/dist/src/cache/theme-cache.d.ts +0 -4
  60. package/dist/src/cache/theme-file-cache.d.ts +0 -87
  61. package/dist/src/compatibility/drops/all_products.d.ts +0 -10
  62. package/dist/src/compatibility/drops/articles.d.ts +0 -10
  63. package/dist/src/compatibility/drops/blogs.d.ts +0 -10
  64. package/dist/src/compatibility/drops/collections.d.ts +0 -19
  65. package/dist/src/compatibility/drops/image-src.d.ts +0 -15
  66. package/dist/src/compatibility/drops/image.d.ts +0 -29
  67. package/dist/src/compatibility/drops/images.d.ts +0 -9
  68. package/dist/src/compatibility/drops/money.d.ts +0 -10
  69. package/dist/src/compatibility/drops/object-handles.d.ts +0 -6
  70. package/dist/src/compatibility/drops/pages.d.ts +0 -17
  71. package/dist/src/compatibility/drops/robots-rule.d.ts +0 -9
  72. package/dist/src/compatibility/drops/template.d.ts +0 -9
  73. package/dist/src/compatibility/shopify-configs.d.ts +0 -8
  74. package/dist/src/compatibility/shopify-fonts.d.ts +0 -1
  75. package/dist/src/compatibility/shopify-objects/address.d.ts +0 -7
  76. package/dist/src/compatibility/shopify-objects/article.d.ts +0 -7
  77. package/dist/src/compatibility/shopify-objects/blog.d.ts +0 -6
  78. package/dist/src/compatibility/shopify-objects/cart.d.ts +0 -6
  79. package/dist/src/compatibility/shopify-objects/collection.d.ts +0 -7
  80. package/dist/src/compatibility/shopify-objects/collections.d.ts +0 -6
  81. package/dist/src/compatibility/shopify-objects/content.d.ts +0 -12
  82. package/dist/src/compatibility/shopify-objects/currency.d.ts +0 -5
  83. package/dist/src/compatibility/shopify-objects/customer.d.ts +0 -6
  84. package/dist/src/compatibility/shopify-objects/filter.d.ts +0 -6
  85. package/dist/src/compatibility/shopify-objects/font.d.ts +0 -5
  86. package/dist/src/compatibility/shopify-objects/form.d.ts +0 -29
  87. package/dist/src/compatibility/shopify-objects/image.d.ts +0 -10
  88. package/dist/src/compatibility/shopify-objects/index.d.ts +0 -27
  89. package/dist/src/compatibility/shopify-objects/line_item.d.ts +0 -7
  90. package/dist/src/compatibility/shopify-objects/link.d.ts +0 -5
  91. package/dist/src/compatibility/shopify-objects/localization.d.ts +0 -5
  92. package/dist/src/compatibility/shopify-objects/media.d.ts +0 -9
  93. package/dist/src/compatibility/shopify-objects/money.d.ts +0 -3
  94. package/dist/src/compatibility/shopify-objects/order.d.ts +0 -11
  95. package/dist/src/compatibility/shopify-objects/page.d.ts +0 -5
  96. package/dist/src/compatibility/shopify-objects/paginate.d.ts +0 -5
  97. package/dist/src/compatibility/shopify-objects/predictive_search.d.ts +0 -5
  98. package/dist/src/compatibility/shopify-objects/product.d.ts +0 -9
  99. package/dist/src/compatibility/shopify-objects/recommendations.d.ts +0 -5
  100. package/dist/src/compatibility/shopify-objects/resource.d.ts +0 -27
  101. package/dist/src/compatibility/shopify-objects/search.d.ts +0 -5
  102. package/dist/src/compatibility/shopify-objects/shop.d.ts +0 -5
  103. package/dist/src/compatibility/shopify-objects/template.d.ts +0 -4
  104. package/dist/src/compatibility/shopify-objects/variant.d.ts +0 -6
  105. package/dist/src/compatibility/shopify.d.ts +0 -134
  106. package/dist/src/constants.d.ts +0 -598
  107. package/dist/src/content.d.ts +0 -8
  108. package/dist/src/easyblocks/config.d.ts +0 -152
  109. package/dist/src/easyblocks/index.d.ts +0 -2
  110. package/dist/src/easyblocks/utils.d.ts +0 -23
  111. package/dist/src/editor/resources.d.ts +0 -9
  112. package/dist/src/fonts.d.ts +0 -6
  113. package/dist/src/globals.d.ts +0 -7
  114. package/dist/src/index.d.ts +0 -16
  115. package/dist/src/liquid/color.d.ts +0 -33
  116. package/dist/src/liquid/drops/render.d.ts +0 -10
  117. package/dist/src/liquid/filters/asset_url.d.ts +0 -3
  118. package/dist/src/liquid/filters/brightness_difference.d.ts +0 -2
  119. package/dist/src/liquid/filters/color_brightness.d.ts +0 -2
  120. package/dist/src/liquid/filters/color_contrast.d.ts +0 -2
  121. package/dist/src/liquid/filters/color_darken.d.ts +0 -2
  122. package/dist/src/liquid/filters/color_desaturate.d.ts +0 -2
  123. package/dist/src/liquid/filters/color_difference.d.ts +0 -2
  124. package/dist/src/liquid/filters/color_extract.d.ts +0 -4
  125. package/dist/src/liquid/filters/color_lighten.d.ts +0 -2
  126. package/dist/src/liquid/filters/color_mix.d.ts +0 -2
  127. package/dist/src/liquid/filters/color_modify.d.ts +0 -3
  128. package/dist/src/liquid/filters/color_saturate.d.ts +0 -2
  129. package/dist/src/liquid/filters/color_to_hex.d.ts +0 -2
  130. package/dist/src/liquid/filters/color_to_hsl.d.ts +0 -2
  131. package/dist/src/liquid/filters/color_to_rgb.d.ts +0 -2
  132. package/dist/src/liquid/filters/date.d.ts +0 -7
  133. package/dist/src/liquid/filters/date_next_interval.d.ts +0 -3
  134. package/dist/src/liquid/filters/default_errors.d.ts +0 -3
  135. package/dist/src/liquid/filters/divided_by.d.ts +0 -2
  136. package/dist/src/liquid/filters/embedded_content.d.ts +0 -2
  137. package/dist/src/liquid/filters/escape.d.ts +0 -3
  138. package/dist/src/liquid/filters/font_face.d.ts +0 -2
  139. package/dist/src/liquid/filters/font_modify.d.ts +0 -3
  140. package/dist/src/liquid/filters/font_url.d.ts +0 -2
  141. package/dist/src/liquid/filters/format_address.d.ts +0 -6
  142. package/dist/src/liquid/filters/handleize.d.ts +0 -3
  143. package/dist/src/liquid/filters/image_tag.d.ts +0 -3
  144. package/dist/src/liquid/filters/image_url.d.ts +0 -8
  145. package/dist/src/liquid/filters/index.d.ts +0 -120
  146. package/dist/src/liquid/filters/inline_asset_content.d.ts +0 -2
  147. package/dist/src/liquid/filters/inline_editable.d.ts +0 -4
  148. package/dist/src/liquid/filters/json.d.ts +0 -3
  149. package/dist/src/liquid/filters/json_pretty.d.ts +0 -3
  150. package/dist/src/liquid/filters/locale_flag.d.ts +0 -2
  151. package/dist/src/liquid/filters/minus.d.ts +0 -2
  152. package/dist/src/liquid/filters/money.d.ts +0 -4
  153. package/dist/src/liquid/filters/money_with_currency.d.ts +0 -3
  154. package/dist/src/liquid/filters/money_without_currency.d.ts +0 -3
  155. package/dist/src/liquid/filters/money_without_trailing_zeros.d.ts +0 -3
  156. package/dist/src/liquid/filters/preload_tag.d.ts +0 -3
  157. package/dist/src/liquid/filters/script_tag.d.ts +0 -3
  158. package/dist/src/liquid/filters/shopify/asset_img_url.d.ts +0 -3
  159. package/dist/src/liquid/filters/shopify/default_pagination.d.ts +0 -3
  160. package/dist/src/liquid/filters/shopify/hex_to_rgba.d.ts +0 -2
  161. package/dist/src/liquid/filters/shopify/img_url.d.ts +0 -3
  162. package/dist/src/liquid/filters/shopify/item_count_for_variant.d.ts +0 -6
  163. package/dist/src/liquid/filters/shopify/payment_button.d.ts +0 -2
  164. package/dist/src/liquid/filters/shopify/payment_terms.d.ts +0 -2
  165. package/dist/src/liquid/filters/shopify/placeholder-svgs/index.d.ts +0 -5
  166. package/dist/src/liquid/filters/shopify/placeholder_svg_tag.d.ts +0 -3
  167. package/dist/src/liquid/filters/shopify/shopify_asset_url.d.ts +0 -3
  168. package/dist/src/liquid/filters/shopify/structured_data.d.ts +0 -3
  169. package/dist/src/liquid/filters/stylesheet_tag.d.ts +0 -3
  170. package/dist/src/liquid/filters/time_tag.d.ts +0 -2
  171. package/dist/src/liquid/filters/translate.d.ts +0 -3
  172. package/dist/src/liquid/filters/where.d.ts +0 -3
  173. package/dist/src/liquid/font.d.ts +0 -51
  174. package/dist/src/liquid/form.d.ts +0 -17
  175. package/dist/src/liquid/hash.d.ts +0 -5
  176. package/dist/src/liquid/index.d.ts +0 -52
  177. package/dist/src/liquid/operators.d.ts +0 -10
  178. package/dist/src/liquid/tags/assign.d.ts +0 -3
  179. package/dist/src/liquid/tags/case.d.ts +0 -3
  180. package/dist/src/liquid/tags/comment.d.ts +0 -3
  181. package/dist/src/liquid/tags/content_for.d.ts +0 -3
  182. package/dist/src/liquid/tags/doc.d.ts +0 -2
  183. package/dist/src/liquid/tags/for.d.ts +0 -3
  184. package/dist/src/liquid/tags/form.d.ts +0 -3
  185. package/dist/src/liquid/tags/if.d.ts +0 -4
  186. package/dist/src/liquid/tags/index.d.ts +0 -42
  187. package/dist/src/liquid/tags/inline_editable.d.ts +0 -3
  188. package/dist/src/liquid/tags/javascript.d.ts +0 -3
  189. package/dist/src/liquid/tags/layout.d.ts +0 -3
  190. package/dist/src/liquid/tags/paginate.d.ts +0 -3
  191. package/dist/src/liquid/tags/render.d.ts +0 -6
  192. package/dist/src/liquid/tags/section.d.ts +0 -3
  193. package/dist/src/liquid/tags/sections.d.ts +0 -3
  194. package/dist/src/liquid/tags/shopify/include.d.ts +0 -3
  195. package/dist/src/liquid/tags/shopify/schema.d.ts +0 -3
  196. package/dist/src/liquid/tags/style.d.ts +0 -3
  197. package/dist/src/liquid/tags/stylesheet.d.ts +0 -3
  198. package/dist/src/liquid/test-helpers.d.ts +0 -8
  199. package/dist/src/liquid/tokens/identifier-token.d.ts +0 -9
  200. package/dist/src/liquid/tokens/index.d.ts +0 -2
  201. package/dist/src/liquid/tokienizer.d.ts +0 -5
  202. package/dist/src/liquid/utils.d.ts +0 -45
  203. package/dist/src/menus.d.ts +0 -25
  204. package/dist/src/resources/account.d.ts +0 -6
  205. package/dist/src/resources/addresses.d.ts +0 -7
  206. package/dist/src/resources/blog.d.ts +0 -7
  207. package/dist/src/resources/blog_category.d.ts +0 -7
  208. package/dist/src/resources/cart.d.ts +0 -6
  209. package/dist/src/resources/categories.d.ts +0 -7
  210. package/dist/src/resources/category.d.ts +0 -7
  211. package/dist/src/resources/index.d.ts +0 -48
  212. package/dist/src/resources/order.d.ts +0 -7
  213. package/dist/src/resources/orders.d.ts +0 -7
  214. package/dist/src/resources/page.d.ts +0 -7
  215. package/dist/src/resources/predictive_search.d.ts +0 -6
  216. package/dist/src/resources/product.d.ts +0 -7
  217. package/dist/src/resources/product_helpers.d.ts +0 -21
  218. package/dist/src/resources/search.d.ts +0 -6
  219. package/dist/src/resources/subscription.d.ts +0 -7
  220. package/dist/src/resources/subscriptions.d.ts +0 -7
  221. package/dist/src/resources/swell_types.d.ts +0 -163
  222. package/dist/src/resources/variant.d.ts +0 -9
  223. package/dist/src/resources.d.ts +0 -113
  224. package/dist/src/theme/theme-loader.d.ts +0 -110
  225. package/dist/src/theme.d.ts +0 -204
  226. package/dist/src/utils/escape.d.ts +0 -1
  227. package/dist/src/utils/index.d.ts +0 -34
  228. package/dist/src/utils/kv-flavor.d.ts +0 -7
  229. package/dist/src/utils/logger.d.ts +0 -21
  230. package/dist/src/utils/md5.d.ts +0 -1
  231. package/dist/types/cloudflare.d.ts +0 -61
  232. package/dist/types/shopify.d.ts +0 -1035
  233. package/dist/types/swell.d.ts +0 -576
  234. package/types/index.d.ts +0 -4
  235. package/types/svg.d.ts +0 -4
package/README.md CHANGED
@@ -1,304 +1,238 @@
1
1
  # Swell Apps SDK
2
2
 
3
- The Swell Apps SDK is a TypeScript-based library designed to simplify the development of isomorphic Swell apps by providing streamlined API access, theme rendering capabilities, and comprehensive caching solutions.
4
-
5
- ## Features
6
-
7
- ### Core functionality
8
- - **Unified API access** - Seamless integration with both Swell Backend API and Storefront API
9
- - **Authentication handling** - Automatic scoped access token management based on app permissions
10
- - **Theme rendering** - Complete Shopify-compatible theme system with Liquid templating
11
- - **Resource management** - Deferred loading of storefront resources (products, categories, etc.)
12
- - **Caching system** - Multi-tier caching with Cloudflare KV integration
13
- - **Shopify compatibility** - Full compatibility layer for migrating Shopify themes and apps
14
-
15
- ### Theme capabilities
16
- - **Liquid templating** - Enhanced Liquid engine with Swell-specific objects and filters
17
- - **Section rendering** - Dynamic section management with schema support
18
- - **Settings resolution** - Automatic theme and section settings processing
19
- - **Layout system** - Flexible layout rendering with section groups
20
- - **Asset management** - Optimized asset loading and URL generation
21
- - **Localization** - Multi-language support with translation rendering
22
-
23
- ### Developer experience
24
- - **TypeScript support** - Full type safety with comprehensive type definitions
25
- - **Isomorphic design** - Works seamlessly in both browser and server environments
26
- - **Error handling** - Robust error management with detailed debugging information
27
- - **Performance optimized** - Built-in caching and resource optimization
28
- - **Extensible architecture** - Plugin system for custom resource types
3
+ The Swell Apps SDK is a TypeScript library for building server-side Swell apps. It
4
+ provides access to the Backend and Storefront APIs, along with helpers for app
5
+ configuration, customer sessions and staff identity.
6
+
7
+ Use it in Swell-hosted apps, Cloudflare Workers or Node.js servers. For browser
8
+ applications, use [`swell-js`](https://github.com/swellstores/swell-js).
29
9
 
30
10
  ## Installation
31
11
 
32
- ```bash
33
- npm install @swell/apps-sdk
12
+ ```sh
13
+ npm install @swell/apps-sdk@next swell-js@^5.9.1
34
14
  ```
35
15
 
36
- ## Getting started
37
-
38
- ### Basic setup
39
-
40
- ```typescript
41
- import { Swell } from '@swell/apps-sdk';
16
+ Supports Node.js 22.22.2+ and Cloudflare Workers, with no Node compatibility flags
17
+ needed in Workers. Includes ES modules, CommonJS and TypeScript declarations.
42
18
 
43
- // Initialize Swell instance in your app frontend
44
- const swell = new Swell({
45
- serverHeaders: context.request.headers, // Headers from worker environment
46
- });
47
-
48
- // Make backend API calls
49
- const products = await swell.backend.get('/products');
19
+ Version 2 replaces the 1.x theme API. Existing theme applications should remain on
20
+ 1.x until migrated to `@swell/themes-sdk`.
50
21
 
51
- // Make storefront API calls
52
- const cart = await swell.storefront.get('/cart');
53
- ```
22
+ ## Getting started
54
23
 
55
- ### Headers and app proxying
24
+ ### Request context
56
25
 
57
- When your Swell app is deployed, it runs behind Swell's proxy infrastructure. The proxy automatically injects essential headers that contain authentication tokens, store configuration, and storefront context. These headers are critical for the SDK to function properly:
26
+ Swell supplies the current store's configuration, credentials and staff identity with
27
+ each request. Verify this context once, then reuse it to create clients and check staff
28
+ access. Use the same pattern for Swell-hosted and self-hosted frontends.
58
29
 
59
- ```typescript
60
- // Headers passed from Swell's proxy contain:
61
- // - swell-store-id: The store identifier
62
- // - swell-public-key: Frontend API access key
63
- // - swell-access-token: Backend API access token (scoped to app permissions)
64
- // - swell-storefront-id: Current storefront instance
65
- // - swell-environment-id: Environment (development, staging, production)
66
- // - swell-theme-id: Active theme identifier
67
- // - swell-storefront-context: Preloaded cart/account data
30
+ ```ts
31
+ import { verifySwellContext } from '@swell/apps-sdk';
68
32
 
69
- const swell = new Swell({
70
- serverHeaders: context.request.headers, // Contains all proxy-injected headers
71
- getCookie: (name) => getCookieValue(name),
72
- setCookie: (name, value, options) => setCookieValue(name, value, options),
33
+ const context = await verifySwellContext(request.headers, {
34
+ appId: 'my-app', // Your app's configured slug.
73
35
  });
74
36
  ```
75
37
 
76
- Without these headers, the SDK cannot:
77
- - Authenticate with Swell APIs
78
- - Determine which store and storefront to operate on
79
- - Access cached resources or maintain session state
80
- - Render themes with proper configuration
81
-
82
- The `serverHeaders` parameter should always be passed the complete headers object from your app's request context to ensure full functionality.
83
-
84
- ### Theme rendering
85
-
86
- ```typescript
87
- import { Swell, SwellTheme, SwellProduct } from '@swell/apps-sdk';
88
-
89
- const swell = new Swell({
90
- serverHeaders: context.request.headers,
91
- ...options,
92
- });
93
-
94
- // Initialize theme with optional configuration
95
- const theme = new SwellTheme(swell, {
96
- forms: formConfigs,
97
- resources: customResources,
98
- globals: additionalGlobals,
99
- });
100
-
101
- // Fetch settings and set global context
102
- await theme.initGlobals('product'); // page ID
38
+ In a server component, pass `await headers()`. Keep the context and clients on the
39
+ server, scoped to the incoming request.
103
40
 
104
- // Create page data with deferred resource loading
105
- const data = {
106
- product: new SwellProduct(swell, context.params.id),
107
- };
41
+ ### Backend API calls
108
42
 
109
- // Render theme page
110
- const renderedPage = await theme.renderPage(data);
111
- ```
43
+ ```ts
44
+ import { SwellBackendAPI } from '@swell/apps-sdk';
112
45
 
113
- ## API reference
46
+ // Reuse the context resolved for this request.
47
+ const backend = new SwellBackendAPI({ context });
114
48
 
115
- ### Swell class
116
-
117
- The main entry point for SDK functionality:
118
-
119
- ```typescript
120
- class Swell {
121
- // API access
122
- backend: SwellBackendAPI;
123
- storefront: typeof SwellJS;
124
-
125
- // Configuration
126
- config: SwellAppConfig;
127
- url: URL;
128
- headers: Record<string, string>;
129
- queryParams: ParsedQs;
130
-
131
- // State
132
- isEditor: boolean;
133
- isPreview: boolean;
134
- storefrontContext: SwellData;
135
-
136
- // Methods
137
- get<T>(url: string, query?: SwellData): Promise<T>;
138
- post<T>(url: string, data: SwellData): Promise<T>;
139
- put<T>(url: string, data: SwellData): Promise<T>;
140
- delete<T>(url: string, data?: SwellData): Promise<T>;
141
- getCachedResource<T>(key: string, args: unknown[], handler: () => T, isCacheble = true): Promise<T>;
142
- }
49
+ // Fetch products from the Backend API.
50
+ const products = await backend.get('/products', { limit: 10 });
143
51
  ```
144
52
 
145
- ### SwellTheme class
146
-
147
- Handles theme rendering and management:
148
-
149
- ```typescript
150
- class SwellTheme {
151
- // Core properties
152
- swell: Swell;
153
- globals: ThemeGlobals;
154
- liquidSwell: LiquidSwell;
155
-
156
- // Methods
157
- initGlobals(pageId: string, altTemplate?: string): Promise<void>;
158
- renderPage(pageData?: SwellData, altTemplate?: string): Promise<string>;
159
- renderSection(sectionId: string, pageData?: SwellData): Promise<string>;
160
- renderLayout(layoutName?: string, data?: SwellData): Promise<string>;
161
- getSectionSchema(sectionName: string): Promise<ThemeSectionSchema>;
162
- setGlobals(globals: Partial<ThemeGlobals>): void;
163
- }
164
- ```
53
+ For an external server, read credentials from your server configuration:
165
54
 
166
- ### Resource classes
167
-
168
- Built-in storefront resource classes for deferred loading:
169
-
170
- #### Standard resources
171
- - `SwellAccount` - Customer account management
172
- - `SwellBlog` - Blog post content
173
- - `SwellBlogCategory` - Blog categorization
174
- - `SwellCart` - Shopping cart state
175
- - `SwellCategory` - Product categories
176
- - `SwellOrder` - Order information
177
- - `SwellPage` - Static pages
178
- - `SwellProduct` - Product details
179
- - `SwellVariant` - Product variants
180
-
181
- #### Primitive resources
182
- - `SwellStorefrontCollection` - Collection results with pagination
183
- - `SwellStorefrontRecord` - Individual records
184
- - `SwellStorefrontSingleton` - Unique resources (cart, account)
185
-
186
- ```typescript
187
- // Create custom resource class
188
- class MyAppCollection extends SwellStorefrontCollection {
189
- constructor(swell: Swell, query: SwellData = {}) {
190
- super(swell, 'my-app-collection', query);
191
- return this._getProxy();
192
- }
193
- }
194
-
195
- // Usage in theme data
196
- const data = {
197
- myCollection: new MyAppCollection(swell, { limit: 20 }),
198
- };
55
+ ```ts
56
+ const backend = new SwellBackendAPI({ storeId, secretKey, apiHost });
199
57
  ```
200
58
 
201
- ## Caching
59
+ ### Storefront API calls
202
60
 
203
- ### Memory caching
204
- Resources are automatically cached in memory per worker instance:
61
+ Use the Storefront API for customer-facing data and cart or account operations.
62
+ In this example, `cookies` is your framework's cookie jar. Its reads must include
63
+ pending writes and deletions.
205
64
 
206
- ```typescript
207
- // Cached resource with custom handler
208
- const cachedData = await swell.getCachedResource(
209
- 'expensive-operation',
210
- [param1, param2],
211
- async () => {
212
- return await performExpensiveOperation(param1, param2);
213
- }
214
- );
215
- ```
216
-
217
- ### Cloudflare KV caching
218
- For production scalability, enable KV caching:
65
+ ```ts
66
+ import { getStorefrontConfig } from '@swell/apps-sdk';
67
+ import { createStorefrontClient } from '@swell/apps-sdk/storefront';
219
68
 
220
- ```typescript
221
- const swell = new Swell({
222
- serverHeaders: context.request.headers,
223
- workerEnv: context.locals.runtime.env, // Contains THEME KV binding
224
- workerCtx: context.locals.runtime.ctx, // Worker context
69
+ // Build public storefront configuration from the request context.
70
+ const config = getStorefrontConfig(context);
71
+ const storefront = createStorefrontClient(config, {
72
+ cookies: {
73
+ get: name => cookies.get(name)?.value,
74
+ set: (name, value, options) => { cookies.set(name, value, options); },
75
+ },
225
76
  });
77
+
78
+ // Use the same methods available in swell-js.
79
+ const products = await storefront.products.list({ limit: 10 });
226
80
  ```
227
81
 
228
- ### Cache invalidation
229
- Caches are automatically invalidated based on:
230
- - Session cookies (for cart/account data)
231
- - Theme configuration versions
232
- - Storefront environment changes
82
+ External servers can supply `storeId`, `publicKey` and `swell-js` options such as
83
+ `url`, `locale` or `currency` directly as the config. Only the `/storefront` entry
84
+ loads the `swell-js` runtime.
233
85
 
234
- ## Shopify compatibility
86
+ ### Browser configuration
235
87
 
236
- The SDK includes comprehensive Shopify compatibility for theme migration.
88
+ Send the public config from `getStorefrontConfig` to your browser app through a
89
+ loader or endpoint with `Cache-Control: private, no-store`. Then initialize swell-js:
237
90
 
238
- ### Supported Shopify features
239
- - **Template mapping** - Direct file path compatibility
240
- - **Liquid objects** - Full object structure compatibility
241
- - **Form handling** - Compatible form endpoints and validation
242
- - **Section schemas** - Shopify section configuration format
243
- - **Settings data** - `settings_data.json` and `settings_schema.json`
91
+ ```ts
92
+ import swell from 'swell-js';
244
93
 
245
- ## Liquid templating
94
+ swell.init(config.storeId, config.publicKey, config);
95
+ ```
246
96
 
247
- Enhanced Liquid templating with Swell-specific features. See [Swell Liquid documentation](https://developers.swell.is/storefronts/swell-liquid-reference) for details.
97
+ Send only this public config to the browser; the request context contains server credentials.
248
98
 
249
- ## Performance optimization
99
+ ### Staff identity
250
100
 
251
- ### Lazy loading
252
- Resources are loaded only when accessed in templates:
101
+ Use `requireStaff` to check that a request belongs to a staff member of the current
102
+ store before applying your application's permission checks:
253
103
 
254
- ```liquid
255
- <!-- Product data is fetched only when this line executes -->
256
- {{ product.name }}
104
+ ```ts
105
+ import { requireStaff } from '@swell/apps-sdk';
257
106
 
258
- <!-- Collection is fetched only when iteration begins -->
259
- {% for item in collection.products %}
260
- {{ item.name }}
261
- {% endfor %}
107
+ const staff = requireStaff(context); // { userId, storeId }, or a 401 SwellError.
108
+ const optionalStaff = context.staff; // null for a visitor; no exception needed.
262
109
  ```
263
110
 
264
- ## Development
265
-
266
- ### Building the SDK
267
- ```bash
268
- # Install dependencies
269
- npm install
111
+ ## API reference
270
112
 
271
- # Build for production
272
- npm run build
113
+ ### Backend client
273
114
 
274
- # Watch for changes
275
- npm run watch
115
+ Pass `{ context }` for a frontend request, or explicit credentials for an external
116
+ server. Backend calls require an access token or secret key and an absolute HTTP(S)
117
+ `apiHost`. Do not mix input sources. Invalid constructor options throw immediately;
118
+ all backend methods return promises and reject on failure.
119
+
120
+ | Method | Result |
121
+ | --- | --- |
122
+ | `get(path, query?)` | Response data |
123
+ | `post(path, data?)`, `put(path, data?)`, `delete(path, data?)` | Response data |
124
+ | `settings(appId?)` | Installed-app settings; defaults to the configured app ID |
125
+ | `workflows.create(name, params?)` | Created workflow instance |
126
+ | `transaction(ops, options?)` | Operation results in input order |
127
+ | `functions.call(appId, name, data?, options?)` | Function response payload |
128
+
129
+ Response generics describe expected data without validating it. `SwellCollection<T>`
130
+ is for ordinary paginated lists; aggregations and `page: false` return other shapes.
131
+
132
+ Requests stay on the configured host; redirects are refused. Use endpoint paths,
133
+ not absolute URLs. Request IDs are forwarded when supplied. GET queries use bracket
134
+ notation, omit undefined values, encode Dates as ISO strings, and preserve native
135
+ null separately from the string `'null'`. Other methods send JSON.
136
+
137
+ **Workflows:** supplied parameters must be JSON-safe and at most 128 KiB of serialized
138
+ UTF-8 JSON. Omitted parameters are not sent. Invalid or oversized parameters reject
139
+ with `workflow_params_unserializable` or `workflow_params_too_large`.
140
+
141
+ **Transactions:** each operation contains `method`, `url` and optional `data`.
142
+ Retries are off by default. Set `retry: true` or
143
+ `retry: { limit: 3, base: 100, max: 5000, jitter: true }` to enable them. These are the
144
+ defaults: `limit` counts additional attempts, and delays are in milliseconds. Only
145
+ `transaction_conflict` and `transaction_throttled` retry. Ordinary requests and network
146
+ failures are not retried.
147
+
148
+ **Private functions:** use the app slug from `context.appId` and authorize the caller
149
+ first. `options.method` defaults to `post`; `get`, `put` and `delete` are also supported.
150
+ GET data must contain only flat string, number or boolean values. Caller headers are
151
+ not forwarded; response status and headers are not returned. Function errors and
152
+ non-2xx statuses reject with `SwellError`.
153
+
154
+ Private-app calls require platform support for app-slug lookup and fail on deployments
155
+ without it. Function execution and `req.swell` remain managed by the CLI and platform.
156
+
157
+ ### Cookies and caching
158
+
159
+ Cookie adapters exchange decoded values and own the current state. If your framework
160
+ reads only incoming cookies, track pending writes and deletions in request-local state.
161
+ The SDK keeps no cookie cache.
162
+
163
+ Native cookie names and defaults apply: path `/`, one week, `sameSite: 'lax'`.
164
+ `cookieOptions` replaces these defaults; `{}` delegates attributes to the adapter.
165
+ Per-write attributes take precedence.
166
+
167
+ Omit `cookies.set` for read-only access. Attempted writes then throw, including session
168
+ rotation during GET requests. A supplied writer may throw or skip a write; after a skip,
169
+ its reader must still report the actual state. Writer return values are ignored.
170
+ Persist cookies in writable route handlers or actions.
171
+
172
+ For API response caching, replace `storefront.request` before first use. The SDK
173
+ leaves response caching to your application.
174
+
175
+ ### Request context options
176
+
177
+ `verifySwellContext(headers, { env?, appId?, storeId?, vaultUrl? })` returns the request
178
+ context or throws if verification fails. Set `appId` and, for a single-store app,
179
+ `storeId` from trusted configuration to reject contexts intended for another app or
180
+ store. Without these options, it verifies the source but does not restrict the
181
+ destination. `vaultUrl` provides an optional vault endpoint override.
182
+
183
+ Configuration is read from `process.env`, or from `env` when supplied. Workers without
184
+ Node compatibility should pass their bindings as `env`.
185
+
186
+ | Variable | Default | Purpose |
187
+ | --- | --- | --- |
188
+ | `SWELL_VERIFY_HEADERS` | enabled | Set exactly `"false"` to skip signature verification during local development. |
189
+ | `SWELL_HEADERS_JWKS_URL` | `https://swell.store/.well-known/jwks.json` | Override the verification-key endpoint; its origin must match the token's issuer. |
190
+
191
+ For local development against a local Swell instance, put `SWELL_VERIFY_HEADERS=false`
192
+ in `.dev.vars`. Remove it or set it to `"true"` to restore verification. Token structure
193
+ and claim validation still apply, but the context is no longer authenticated: anyone
194
+ who can reach the frontend directly can supply forged context, including staff identity.
195
+ Use this bypass only for local development.
196
+
197
+ For server integrations, construct `SwellBackendAPI` with explicit credentials and
198
+ `createStorefrontClient` with explicit public configuration. These clients do not
199
+ require an HTTP request or staff identity.
200
+
201
+ ### Staff identity
202
+
203
+ `requireStaff(context)` returns `{ userId, storeId }` or throws `SwellError` with
204
+ status 401 and code `staff_required`. For optional staff access, read `context.staff`,
205
+ which is null for visitors.
206
+
207
+ Staff includes any signed-in dashboard user of the store, including partners and Swell
208
+ support. Swell's proxy handles staff authentication and write-origin checks; your
209
+ application decides what each staff member may do.
210
+
211
+ ### Errors
212
+
213
+ Import `SwellError` from the root package. Use `status` and optional `code`/`body` for
214
+ error handling; `message` is for people and may change.
215
+
216
+ - Structured backend errors retain their body; string errors have no body.
217
+ - HTTP-200 non-GET validation failures use status 400 and the `errors` field map as
218
+ `body`. Successful GET responses containing `errors` are returned as data.
219
+ - Function invocation failures retain the response payload, or the invocation envelope
220
+ when the payload is null or absent, in `body`.
221
+ - Header verification uses 401 / `invalid_swell_context` for absent, malformed, expired
222
+ or rejected tokens, and 503 / `swell_jwks_unavailable` for key-service failures.
223
+ - Backend/storefront network errors remain native. Local configuration errors may be
224
+ ordinary `Error` instances; not every failure is a `SwellError`.
276
225
 
277
- # Run tests
278
- npm test
279
- ```
226
+ ## Development
280
227
 
281
- ### Project structure
282
- ```
283
- src/
284
- ├── api.ts # Core Swell class and API handling
285
- ├── theme.ts # SwellTheme class and rendering
286
- ├── resources.ts # Storefront resource classes
287
- ├── liquid/ # Liquid templating engine
288
- ├── compatibility/ # Shopify compatibility layer
289
- ├── cache/ # Caching implementations
290
- ├── utils/ # Utility functions
291
- └── index.ts # Main exports
228
+ ```sh
229
+ npm ci
230
+ npm run verify
292
231
  ```
293
232
 
294
- ## Resources
295
-
296
- - [Swell Documentation](https://developers.swell.is/)
297
- - [Apps Development Guide](https://developers.swell.is/apps/overview)
298
- - [Proxima Example App](https://developers.swell.is/storefronts/proxima)
299
- - [Swell Liquid Reference](https://developers.swell.is/storefronts/swell-liquid-reference)
300
- - [GitHub Repository](https://github.com/swellstores/swell-apps-sdk)
233
+ `verify` builds the SDK, runs unit tests and typechecks, then checks the packed package,
234
+ browser/Worker boundaries and workerd execution.
301
235
 
302
- ## 📄 License
236
+ ## License
303
237
 
304
- See the [LICENSE](LICENSE) file for details.
238
+ [MIT](LICENSE)
@@ -0,0 +1,81 @@
1
+ import type { SwellRequestContext } from './request-context.cjs';
2
+ export type SwellData = Record<string, any>;
3
+ export type BackendOptions = {
4
+ context: SwellRequestContext;
5
+ storeId?: never;
6
+ apiHost?: never;
7
+ accessToken?: never;
8
+ secretKey?: never;
9
+ appId?: never;
10
+ requestId?: never;
11
+ } | ({
12
+ context?: never;
13
+ storeId: string;
14
+ apiHost: string;
15
+ appId?: string;
16
+ requestId?: string;
17
+ } & ({
18
+ accessToken: string;
19
+ secretKey?: never;
20
+ } | {
21
+ secretKey: string;
22
+ accessToken?: never;
23
+ }));
24
+ /** Envelope of an ordinary paginated backend list. `page: false` and aggregations return other shapes. */
25
+ export interface SwellCollection<T = SwellData> {
26
+ results: T[];
27
+ count: number;
28
+ page: number;
29
+ page_count: number;
30
+ limit: number;
31
+ pages?: Record<string, {
32
+ start: number;
33
+ end: number;
34
+ }>;
35
+ }
36
+ export interface TransactionOperation {
37
+ method: string;
38
+ url: string;
39
+ data?: any;
40
+ }
41
+ export interface TransactionOptions {
42
+ /** Opt in to retries: limit counts additional attempts (default 3); base/max are ms (100/5000); jitter defaults to true. */
43
+ retry?: true | {
44
+ limit?: number;
45
+ base?: number;
46
+ max?: number;
47
+ jitter?: boolean;
48
+ };
49
+ }
50
+ /** Backend client from a frontend request context or explicit server credentials. */
51
+ export declare class SwellBackendAPI {
52
+ #private;
53
+ protected get userAgent(): string;
54
+ readonly workflows: {
55
+ /** Creates a workflow instance. Optional params must be JSON-safe and at most 128 KiB of UTF-8 JSON; invalid params reject. */
56
+ create: (name: string, params?: unknown) => Promise<SwellData>;
57
+ };
58
+ readonly functions: {
59
+ /**
60
+ * Invokes an app's private function from server code and resolves to its response payload,
61
+ * without the envelope's status or headers.
62
+ * `appId` is the app identifier from the request context (`context.appId`).
63
+ * `method` (default `post`) selects the function's handler. GET data reaches the function
64
+ * as query parameters, so its values must be flat strings, numbers or booleans.
65
+ * Throws `SwellError` when the function reports a non-2xx status or an error.
66
+ * Callers authorize the operation first; no caller headers are forwarded.
67
+ */
68
+ call: <T = SwellData>(appId: string, name: string, data?: SwellData, { method }?: {
69
+ method?: "get" | "post" | "put" | "delete";
70
+ }) => Promise<T>;
71
+ };
72
+ constructor(options: BackendOptions);
73
+ get<T = SwellData>(path: string, query?: SwellData): Promise<T>;
74
+ put<T = SwellData>(path: string, data?: any): Promise<T>;
75
+ post<T = SwellData>(path: string, data?: any): Promise<T>;
76
+ delete<T = SwellData>(path: string, data?: any): Promise<T>;
77
+ /** Reads installed-app settings; defaults to the configured app ID and rejects when neither ID is supplied. */
78
+ settings<T = SwellData>(appId?: string | undefined): Promise<T>;
79
+ /** Atomic operations returning results in operation order; only conflicts and throttling retry, and only when requested. */
80
+ transaction(ops: TransactionOperation[], options?: TransactionOptions): Promise<any[]>;
81
+ }
@@ -0,0 +1,81 @@
1
+ import type { SwellRequestContext } from './request-context.js';
2
+ export type SwellData = Record<string, any>;
3
+ export type BackendOptions = {
4
+ context: SwellRequestContext;
5
+ storeId?: never;
6
+ apiHost?: never;
7
+ accessToken?: never;
8
+ secretKey?: never;
9
+ appId?: never;
10
+ requestId?: never;
11
+ } | ({
12
+ context?: never;
13
+ storeId: string;
14
+ apiHost: string;
15
+ appId?: string;
16
+ requestId?: string;
17
+ } & ({
18
+ accessToken: string;
19
+ secretKey?: never;
20
+ } | {
21
+ secretKey: string;
22
+ accessToken?: never;
23
+ }));
24
+ /** Envelope of an ordinary paginated backend list. `page: false` and aggregations return other shapes. */
25
+ export interface SwellCollection<T = SwellData> {
26
+ results: T[];
27
+ count: number;
28
+ page: number;
29
+ page_count: number;
30
+ limit: number;
31
+ pages?: Record<string, {
32
+ start: number;
33
+ end: number;
34
+ }>;
35
+ }
36
+ export interface TransactionOperation {
37
+ method: string;
38
+ url: string;
39
+ data?: any;
40
+ }
41
+ export interface TransactionOptions {
42
+ /** Opt in to retries: limit counts additional attempts (default 3); base/max are ms (100/5000); jitter defaults to true. */
43
+ retry?: true | {
44
+ limit?: number;
45
+ base?: number;
46
+ max?: number;
47
+ jitter?: boolean;
48
+ };
49
+ }
50
+ /** Backend client from a frontend request context or explicit server credentials. */
51
+ export declare class SwellBackendAPI {
52
+ #private;
53
+ protected get userAgent(): string;
54
+ readonly workflows: {
55
+ /** Creates a workflow instance. Optional params must be JSON-safe and at most 128 KiB of UTF-8 JSON; invalid params reject. */
56
+ create: (name: string, params?: unknown) => Promise<SwellData>;
57
+ };
58
+ readonly functions: {
59
+ /**
60
+ * Invokes an app's private function from server code and resolves to its response payload,
61
+ * without the envelope's status or headers.
62
+ * `appId` is the app identifier from the request context (`context.appId`).
63
+ * `method` (default `post`) selects the function's handler. GET data reaches the function
64
+ * as query parameters, so its values must be flat strings, numbers or booleans.
65
+ * Throws `SwellError` when the function reports a non-2xx status or an error.
66
+ * Callers authorize the operation first; no caller headers are forwarded.
67
+ */
68
+ call: <T = SwellData>(appId: string, name: string, data?: SwellData, { method }?: {
69
+ method?: "get" | "post" | "put" | "delete";
70
+ }) => Promise<T>;
71
+ };
72
+ constructor(options: BackendOptions);
73
+ get<T = SwellData>(path: string, query?: SwellData): Promise<T>;
74
+ put<T = SwellData>(path: string, data?: any): Promise<T>;
75
+ post<T = SwellData>(path: string, data?: any): Promise<T>;
76
+ delete<T = SwellData>(path: string, data?: any): Promise<T>;
77
+ /** Reads installed-app settings; defaults to the configured app ID and rejects when neither ID is supplied. */
78
+ settings<T = SwellData>(appId?: string | undefined): Promise<T>;
79
+ /** Atomic operations returning results in operation order; only conflicts and throttling retry, and only when requested. */
80
+ transaction(ops: TransactionOperation[], options?: TransactionOptions): Promise<any[]>;
81
+ }