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 +126 -25
- package/dist/index.cjs +51 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -12
- package/dist/index.d.ts +4 -12
- package/dist/index.js +51 -41
- package/dist/index.js.map +1 -1
- package/dist/types.d.cts +55 -45
- package/dist/types.d.ts +55 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
# arky-sdk
|
|
2
2
|
|
|
3
|
-
Official TypeScript SDK for Arky
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
##
|
|
249
|
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
-
|
|
254
|
-
-
|
|
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?.
|
|
159
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
|
187
|
-
|
|
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
|
|
195
|
-
return apiConfig.httpClient.
|
|
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.
|
|
1502
|
+
var SDK_VERSION = "0.3.28";
|
|
1493
1503
|
var SUPPORTED_FRAMEWORKS = [
|
|
1494
1504
|
"astro",
|
|
1495
1505
|
"react",
|