arky-sdk 0.3.26 → 0.3.28

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
  }
@@ -174,25 +209,18 @@ var createUserApi = (apiConfig) => {
174
209
  return {
175
210
  // ===== USER PROFILE =====
176
211
  async updateUser(params, options) {
177
- const payload = {
178
- name: params.name,
179
- phoneNumbers: params.phoneNumbers || [],
180
- phoneNumber: params.phoneNumber || null,
181
- addresses: params.addresses || [],
182
- ...params.apiTokens !== void 0 && { apiTokens: params.apiTokens }
183
- };
184
- return apiConfig.httpClient.put("/v1/users/update", payload, options);
212
+ const payload = {};
213
+ if (params.name !== void 0) payload.name = params.name;
214
+ if (params.phoneNumbers !== void 0) payload.phoneNumbers = params.phoneNumbers;
215
+ if (params.addresses !== void 0) payload.addresses = params.addresses;
216
+ if (params.apiTokens !== void 0) payload.apiTokens = params.apiTokens;
217
+ return apiConfig.httpClient.put("/v1/users", payload, options);
185
218
  },
186
- async updateProfilePhone(params, options) {
187
- const payload = {
188
- phoneNumbers: [],
189
- phoneNumber: params.phoneNumber,
190
- addresses: []
191
- };
192
- return apiConfig.httpClient.put("/v1/users/update", payload, options);
219
+ async addPhoneNumber(params, options) {
220
+ return apiConfig.httpClient.post("/v1/users/phone-number", params, options);
193
221
  },
194
- async verifyPhoneCode(params, options) {
195
- return apiConfig.httpClient.put("/v1/users/confirm/phone-number", params, options);
222
+ async phoneNumberConfirm(params, options) {
223
+ return apiConfig.httpClient.post("/v1/users/phone-number/confirm", params, options);
196
224
  },
197
225
  async getMe(params, options) {
198
226
  return apiConfig.httpClient.get("/v1/users/me", options);
@@ -424,18 +452,6 @@ var createRoleApi = (apiConfig) => {
424
452
  // src/api/notification.ts
425
453
  var createNotificationApi = (apiConfig) => {
426
454
  return {
427
- async getNotifications(params, options) {
428
- return apiConfig.httpClient.get(`/v1/notifications`, {
429
- ...options,
430
- params: {
431
- limit: params.limit,
432
- previous_id: params.previous_id
433
- }
434
- });
435
- },
436
- async updateNotifications(params, options) {
437
- return apiConfig.httpClient.put(`/v1/notifications`, { seen: true }, options);
438
- },
439
455
  async trackEmailOpen(params, options) {
440
456
  return apiConfig.httpClient.get(
441
457
  `/v1/notifications/track/email/${params.trackingPixelId}`,
@@ -497,12 +513,6 @@ var createAnalyticsApi = (apiConfig) => {
497
513
  ...options,
498
514
  params
499
515
  });
500
- },
501
- async getAnalyticsHealth(params, options) {
502
- return apiConfig.httpClient.get(`/v1/analytics/${apiConfig.businessId}/health`, options);
503
- },
504
- async setupAnalytics(params, options) {
505
- return apiConfig.httpClient.post(`/v1/analytics/admin/setup`, params, options);
506
516
  }
507
517
  };
508
518
  };
@@ -1489,7 +1499,7 @@ async function injectSvgIntoElement(mediaObject, targetElement, className) {
1489
1499
  }
1490
1500
 
1491
1501
  // src/index.ts
1492
- var SDK_VERSION = "0.3.25";
1502
+ var SDK_VERSION = "0.3.28";
1493
1503
  var SUPPORTED_FRAMEWORKS = [
1494
1504
  "astro",
1495
1505
  "react",