arky-sdk 0.3.27 → 0.3.29

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.
package/README.md CHANGED
@@ -1,6 +1,29 @@
1
1
  # arky-sdk
2
2
 
3
- Official TypeScript SDK for Arky - All-in-one business platform
3
+ Official TypeScript SDK for [Arky](https://arky.io) Build online businesses with headless CMS, e-commerce, and booking systems.
4
+
5
+ ## What is Arky?
6
+
7
+ Arky is an **all-in-one platform** that gives you everything you need to run an online business:
8
+
9
+ - 📝 **Headless CMS** - Manage content with flexible blocks, multilingual support, and AI-powered content generation
10
+ - 🛒 **E-commerce** - Sell products with multi-currency pricing, inventory, orders, and Stripe payments
11
+ - 📅 **Booking System** - Manage services, providers, and reservations with availability calendars
12
+ - 📧 **Newsletters** - Send newsletters to subscribers with built-in email delivery
13
+ - 👥 **User Management** - Authentication, roles, permissions, and user profiles
14
+ - 📊 **Analytics** - Track business metrics and performance
15
+ - 💳 **Payments** - Integrated Stripe checkout and promo codes
16
+
17
+ **Build any online business:** SaaS products, e-commerce stores, booking platforms, content sites, newsletters, or multi-tenant marketplaces.
18
+
19
+ ## Why Use This SDK?
20
+
21
+ Instead of manually calling REST APIs, use this TypeScript SDK to:
22
+
23
+ ✅ **Type-safe** - Full TypeScript support with IntelliSense
24
+ ✅ **Auto-authentication** - Handles tokens, refresh, and guest sessions automatically
25
+ ✅ **Utility helpers** - Extract block values, format prices, slugify text, validate phones
26
+ ✅ **Framework-agnostic** - Works in React, Vue, Svelte, Node.js, or any JS environment
4
27
 
5
28
  ## Installation
6
29
 
@@ -10,13 +33,14 @@ npm install arky-sdk
10
33
 
11
34
  ## Quick Start
12
35
 
36
+ ### 1. Install & Initialize
37
+
13
38
  ```typescript
14
39
  import { createArkySDK } from 'arky-sdk'
15
40
 
16
41
  const arky = createArkySDK({
17
42
  baseUrl: 'https://api.arky.io',
18
43
  businessId: 'your-business-id',
19
- storageUrl: 'https://storage.arky.io',
20
44
  market: 'us',
21
45
  getToken: () => ({
22
46
  accessToken: localStorage.getItem('accessToken') || '',
@@ -32,12 +56,100 @@ const arky = createArkySDK({
32
56
  localStorage.removeItem('accessToken');
33
57
  localStorage.removeItem('refreshToken');
34
58
  },
35
- isAuthenticated: () => !!localStorage.getItem('accessToken'),
36
59
  })
60
+ ```
61
+
62
+ ### 2. Browse Products
63
+
64
+ ```typescript
65
+ // List products (like on arky.io/products)
66
+ const { items: products } = await arky.eshop.getProducts({
67
+ limit: 20
68
+ });
69
+
70
+ // Get product details (like arky.io/products/guitar)
71
+ const product = await arky.eshop.getProduct({ id: 'prod_123' });
72
+
73
+ // Get price for user's market
74
+ const price = arky.utils.getMarketPrice(product.variants[0].prices, 'US');
75
+ console.log(`${arky.utils.formatMinor(price.amount, price.currency)}`); // "$29.99"
76
+ ```
77
+
78
+ ### 3. Shop & Checkout
79
+
80
+ ```typescript
81
+ // Add to cart and checkout (like arky.io/cart)
82
+ const order = await arky.eshop.checkout({
83
+ items: [{
84
+ productId: 'prod_123',
85
+ variantId: 'var_456',
86
+ quantity: 2
87
+ }],
88
+ paymentMethod: 'CREDIT_CARD',
89
+ shippingMethodId: 'standard',
90
+ blocks: [ // Customer info
91
+ { key: 'email', values: ['customer@example.com'] },
92
+ { key: 'shipping_address', values: ['123 Main St'] }
93
+ ]
94
+ });
95
+ ```
37
96
 
38
- // Now use the SDK
39
- const collections = await arky.cms.getCollections({});
40
- const products = await arky.eshop.getProducts({});
97
+ ### 4. Book Services
98
+
99
+ ```typescript
100
+ // Browse services (like arky.io/services)
101
+ const { items: services } = await arky.reservation.getServices({});
102
+
103
+ // Check available time slots
104
+ const slots = await arky.reservation.getAvailableSlots({
105
+ serviceId: 'service_haircut',
106
+ from: Date.now(),
107
+ to: Date.now() + 86400000 // Next 24 hours
108
+ });
109
+
110
+ // Book a reservation
111
+ const reservation = await arky.reservation.checkout({
112
+ parts: [{
113
+ serviceId: 'service_haircut',
114
+ startTime: slots[0].startTime,
115
+ providerId: 'provider_jane'
116
+ }],
117
+ paymentMethod: 'CREDIT_CARD',
118
+ blocks: [ // Customer contact info
119
+ { key: 'name', values: ['John Doe'] },
120
+ { key: 'phone', values: ['+1234567890'] }
121
+ ]
122
+ });
123
+ ```
124
+
125
+ ### 5. Subscribe to Newsletter
126
+
127
+ ```typescript
128
+ // Subscribe to updates (like arky.io/newsletters)
129
+ await arky.cms.subscribeToCollection({
130
+ collectionId: 'newsletter_weekly',
131
+ email: 'user@example.com',
132
+ planId: 'plan_free'
133
+ });
134
+ ```
135
+
136
+ ### 6. Read Content
137
+
138
+ ```typescript
139
+ // Fetch blog posts or content
140
+ const { items: posts } = await arky.cms.getCollectionEntries({
141
+ collectionId: 'blog',
142
+ limit: 10
143
+ });
144
+
145
+ // Extract content from blocks
146
+ const title = arky.utils.getBlockTextValue(
147
+ posts[0].blocks.find(b => b.key === 'title'),
148
+ 'en'
149
+ );
150
+ const imageUrl = arky.utils.getImageUrl(
151
+ posts[0].blocks.find(b => b.key === 'featured_image')
152
+ );
41
153
  ```
42
154
 
43
155
  ## API Methods
@@ -245,25 +357,14 @@ const svg = await arky.utils.getSvgContentForAstro(mediaBlock)
245
357
  await arky.utils.injectSvgIntoElement(mediaBlock, element, 'custom-class')
246
358
  ```
247
359
 
248
- ## Features
249
-
250
- - 🚀 **TypeScript-first** - Full type safety and IntelliSense
251
- - 📦 **Tree-shakeable** - Import only what you need
252
- - **Lightweight** - Minimal bundle size (~120KB)
253
- - 🔄 **Auto-refresh** - Automatic token refresh
254
- - 🎯 **Framework-agnostic** - Works with any JavaScript framework
255
-
256
- ## Modules
257
-
258
- - **CMS** - Headless content management, newsletters, AI blocks
259
- - **E-shop** - E-commerce, products, orders, checkout
260
- - **Reservations** - Booking system, services, providers
261
- - **Business** - Multi-tenant business management
262
- - **User** - Authentication, profiles, roles
263
- - **Media** - File upload, image management
264
- - **Notifications** - Push, email, SMS
265
- - **Analytics** - Business metrics and insights
266
- - **Payment** - Stripe integration, quotes
360
+ ## What Can You Build?
361
+
362
+ - 🏪 **E-commerce stores** - Product catalogs, shopping carts, checkout
363
+ - 📰 **Content websites** - Blogs, documentation, marketing sites
364
+ - 📅 **Booking platforms** - Appointment scheduling, service bookings
365
+ - 📬 **Newsletter platforms** - Subscriber management, email campaigns
366
+ - 🏢 **SaaS products** - Multi-tenant apps with user auth and billing
367
+ - 🛍️ **Marketplaces** - Multi-vendor platforms with payments
267
368
 
268
369
  ## Configuration Options
269
370
 
package/dist/index.cjs CHANGED
@@ -104,6 +104,7 @@ function createHttpClient(cfg) {
104
104
  const fullUrl = `${cfg.baseUrl}${finalPath}`;
105
105
  let res;
106
106
  let data;
107
+ const startedAt = Date.now();
107
108
  try {
108
109
  res = await fetch(fullUrl, fetchOpts);
109
110
  } catch (error) {
@@ -111,6 +112,12 @@ function createHttpClient(cfg) {
111
112
  err.name = "NetworkError";
112
113
  err.method = method;
113
114
  err.url = fullUrl;
115
+ if (options?.onError && method !== "GET") {
116
+ Promise.resolve(
117
+ options.onError({ error: err, method, url: fullUrl, aborted: false })
118
+ ).catch(() => {
119
+ });
120
+ }
114
121
  throw err;
115
122
  }
116
123
  if (res.status === 401 && !options?.["_retried"]) {
@@ -137,14 +144,17 @@ function createHttpClient(cfg) {
137
144
  err.method = method;
138
145
  err.url = fullUrl;
139
146
  err.status = res.status;
147
+ if (options?.onError && method !== "GET") {
148
+ Promise.resolve(
149
+ options.onError({ error: err, method, url: fullUrl, status: res.status })
150
+ ).catch(() => {
151
+ });
152
+ }
140
153
  throw err;
141
154
  }
142
155
  if (!res.ok) {
143
156
  const serverErr = data;
144
157
  const reqErr = convertServerErrorToRequestError(serverErr);
145
- if (options?.errorMessage && cfg.notify) {
146
- cfg.notify({ message: options.errorMessage, type: "error" });
147
- }
148
158
  const err = new Error(serverErr.message || "Request failed");
149
159
  err.name = "ApiError";
150
160
  err.statusCode = serverErr.statusCode || res.status;
@@ -153,10 +163,35 @@ function createHttpClient(cfg) {
153
163
  err.url = fullUrl;
154
164
  const requestId = res.headers.get("x-request-id") || res.headers.get("request-id");
155
165
  if (requestId) err.requestId = requestId;
166
+ if (options?.onError && method !== "GET") {
167
+ Promise.resolve(
168
+ options.onError({
169
+ error: err,
170
+ method,
171
+ url: fullUrl,
172
+ status: res.status,
173
+ response: serverErr,
174
+ requestId: requestId || null,
175
+ durationMs: Date.now() - startedAt
176
+ })
177
+ ).catch(() => {
178
+ });
179
+ }
156
180
  throw err;
157
181
  }
158
- if (options?.successMessage && cfg.notify) {
159
- cfg.notify({ message: options.successMessage, type: "success" });
182
+ if (options?.onSuccess && method !== "GET") {
183
+ const requestId = res.headers.get("x-request-id") || res.headers.get("request-id");
184
+ Promise.resolve(
185
+ options.onSuccess({
186
+ data,
187
+ method,
188
+ url: fullUrl,
189
+ status: res.status,
190
+ requestId: requestId || null,
191
+ durationMs: Date.now() - startedAt
192
+ })
193
+ ).catch(() => {
194
+ });
160
195
  }
161
196
  return data;
162
197
  }
@@ -417,18 +452,6 @@ var createRoleApi = (apiConfig) => {
417
452
  // src/api/notification.ts
418
453
  var createNotificationApi = (apiConfig) => {
419
454
  return {
420
- async getNotifications(params, options) {
421
- return apiConfig.httpClient.get(`/v1/notifications`, {
422
- ...options,
423
- params: {
424
- limit: params.limit,
425
- previous_id: params.previous_id
426
- }
427
- });
428
- },
429
- async updateNotifications(params, options) {
430
- return apiConfig.httpClient.put(`/v1/notifications`, { seen: true }, options);
431
- },
432
455
  async trackEmailOpen(params, options) {
433
456
  return apiConfig.httpClient.get(
434
457
  `/v1/notifications/track/email/${params.trackingPixelId}`,
@@ -490,12 +513,6 @@ var createAnalyticsApi = (apiConfig) => {
490
513
  ...options,
491
514
  params
492
515
  });
493
- },
494
- async getAnalyticsHealth(params, options) {
495
- return apiConfig.httpClient.get(`/v1/analytics/${apiConfig.businessId}/health`, options);
496
- },
497
- async setupAnalytics(params, options) {
498
- return apiConfig.httpClient.post(`/v1/analytics/admin/setup`, params, options);
499
516
  }
500
517
  };
501
518
  };
@@ -1123,16 +1140,6 @@ var getImageUrl = (imageBlock, isBlock = true, storageUrl = "https://storage.ark
1123
1140
  }
1124
1141
  return null;
1125
1142
  };
1126
- function getGalleryThumbnail(gallery) {
1127
- if (!gallery?.length) return null;
1128
- const item = gallery.find((g) => g.settings.isThumbnail) || gallery[0];
1129
- const res = item.media.resolutions.thumbnail || item.media.resolutions.original;
1130
- return res?.url || null;
1131
- }
1132
- function thumbnailUrl(service, storageUrl = "") {
1133
- const path = getGalleryThumbnail(service.gallery);
1134
- return path ? `${storageUrl}/${path}` : null;
1135
- }
1136
1143
 
1137
1144
  // src/utils/currency.ts
1138
1145
  function getCurrencySymbol(currency) {
@@ -1482,7 +1489,7 @@ async function injectSvgIntoElement(mediaObject, targetElement, className) {
1482
1489
  }
1483
1490
 
1484
1491
  // src/index.ts
1485
- var SDK_VERSION = "0.3.25";
1492
+ var SDK_VERSION = "0.3.28";
1486
1493
  var SUPPORTED_FRAMEWORKS = [
1487
1494
  "astro",
1488
1495
  "react",
@@ -1533,8 +1540,6 @@ function createArkySDK(config) {
1533
1540
  utils: {
1534
1541
  // Block utilities
1535
1542
  getImageUrl: (imageBlock, isBlock = true) => getImageUrl(imageBlock, isBlock, storageUrl),
1536
- thumbnailUrl: (service) => thumbnailUrl(service, storageUrl),
1537
- getGalleryThumbnail,
1538
1543
  getBlockValue,
1539
1544
  getBlockValues,
1540
1545
  getBlockLabel,