@scryme/sdk 0.1.0 β†’ 9.64.2

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
@@ -2,10 +2,14 @@
2
2
 
3
3
  The official TypeScript SDK for the **Scryme V3 API**β€”engineered for scalability, security, and developer convenience. This SDK provides complete, type-safe coverage of all Scryme V3 services, allowing developers to seamlessly integrate their applications with the Scryme ecosystem.
4
4
 
5
+ For the complete, interactive documentation, live sandbox playgrounds, and detailed OpenAPI schemas, please visit our documentation portal:
6
+ πŸ‘‰ **[https://docs.scryme.tech](https://docs.scryme.tech)**
7
+
5
8
  ## πŸš€ Features
6
9
 
7
10
  - **End-to-End Type Safety**: Direct compilation from the core OpenAPI 3.0 specification.
8
11
  - **Axios-Based Client**: Built-in support for request/response interceptors, customizable base URLs, and timeout configurations.
12
+ - **Strictly Isolated Client & Server SDKs**: Prevents request state and session pollution in multi-tenant environments.
9
13
  - **Comprehensive API Coverage**:
10
14
  - **Auth**: Token exchange (Client Credentials Flow) & OAuth2 proxy support.
11
15
  - **Inventory**: Stock queries, multi-branch listings, batch tracking (trace, split, merge), B2B availability checks, and integrity verify/fix logic.
@@ -30,329 +34,128 @@ pnpm add @scryme/sdk
30
34
 
31
35
  ---
32
36
 
33
- ## πŸ”‘ Authentication
37
+ ## πŸ”‘ Client & Server SDK Isolation
38
+
39
+ The SDK supports distinct, fully isolated client-side and server-side setup options to prevent request state and session pollution in multi-tenant environments.
34
40
 
35
- The Scryme V3 API uses **OAuth2 Client Credentials Flow** to authorize external applications and integrations.
41
+ ### 🌐 Server-Side Setup (`@scryme/sdk/server`)
42
+ Strictly isolates requests and Axios instances. Ideal for Next.js API routes, edge functions, backend microservices, or Windmill workflows.
36
43
 
37
- ### Step 1: Exchange Credentials for an Access Token
38
- To retrieve an access token, pass your `clientId` and `clientSecret` (generated during device/app provisioning) to the token exchange endpoint:
44
+ #### Class-Based Constructor (`ScrymeServerSDK`)
45
+ Requires `clientId`, `clientSecret`, and `orgSlug` strictly to initialize correctly:
39
46
 
40
47
  ```typescript
41
- import axios from "axios";
42
- import { authExchangeToken } from "@scryme/sdk";
48
+ import { ScrymeServerSDK } from "@scryme/sdk/server";
43
49
 
44
- // Initialize the global axios configuration if needed
45
- axios.defaults.baseURL = "https://api.scryme.tech";
50
+ const scrymeServer = new ScrymeServerSDK({
51
+ baseURL: "https://api.scryme.tech",
52
+ orgSlug: "your-org-slug", // Automatic orgSlug injection on all API calls!
53
+ clientId: "your_client_id_123",
54
+ clientSecret: "your_client_secret_456",
55
+ });
46
56
 
47
- async function authenticate() {
48
- try {
49
- const response = await authExchangeToken({
50
- clientId: "your_client_id_123",
51
- clientSecret: "your_client_secret_456"
52
- });
53
-
54
- const { accessToken, expiresIn } = response.data;
55
- console.log(`Authenticated successfully! Token expires in ${expiresIn}s.`);
56
- return accessToken;
57
- } catch (error) {
58
- console.error("Authentication failed:", error);
59
- throw error;
60
- }
57
+ async function run() {
58
+ // 1. Call APIs directlyβ€”the SDK handles token retrieval, refresh, and auto-injection of orgSlug automatically!
59
+ const products = await scrymeServer.catalog.getProducts({ limit: 10 });
60
+ console.log("Server Products:", products.data);
61
61
  }
62
62
  ```
63
63
 
64
- ### Step 2: Configure Authenticated Client Calls
65
- Once you have the `accessToken`, register an Axios request interceptor to automatically attach the bearer token to all outgoing requests:
64
+ Or use the helper factory `createServerSDK`, which provides fallback defaults:
66
65
 
67
66
  ```typescript
68
- import axios from "axios";
69
-
70
- function setupAuthenticatedClient(token: string) {
71
- axios.interceptors.request.use((config) => {
72
- config.headers.Authorization = `Bearer ${token}`;
73
- return config;
74
- });
75
- }
67
+ import { createServerSDK } from "@scryme/sdk/server";
68
+
69
+ const scrymeServer = createServerSDK({
70
+ baseURL: "https://api.scryme.tech",
71
+ orgSlug: "your-org-slug",
72
+ clientId: "your_client_id_123",
73
+ clientSecret: "your_client_secret_456",
74
+ });
76
75
  ```
77
76
 
78
- ---
79
-
80
- ## πŸ› οΈ Domain Modules & Usage Examples
77
+ ### πŸ“± Client-Side Setup (`@scryme/sdk/client`)
78
+ Provides stateful and reactive state persistence (localStorage / StorageProviders) with login listeners and automatic session recoveries.
81
79
 
82
- Below are comprehensive examples showing how to interact with the key V3 modules.
83
-
84
- ### πŸ“¦ 1. V3 Inventory Management
85
- Query stock levels, trace/merge/split batches, and check availability for B2B accounts.
80
+ #### Class-Based Constructor (`ScrymeClientSDK`)
81
+ Requires `clientId`, `clientSecret`, and `orgSlug` strictly to initialize correctly:
86
82
 
87
83
  ```typescript
88
- import {
89
- inventoryGetInventory,
90
- inventoryVerifyIntegrity,
91
- inventoryMergeBatches,
92
- inventorySplitBatch
93
- } from "@scryme/sdk";
94
-
95
- const orgSlug = "scryme-hq";
96
- const locationId = "loc_nairobi_001";
97
-
98
- // 1. Get current stock levels at a specific location
99
- async function checkStock() {
100
- const response = await inventoryGetInventory(orgSlug, {
101
- locationId,
102
- limit: 50,
103
- offset: 0
104
- });
105
- console.log("Stock Inventory:", response.data);
106
- }
84
+ import { ScrymeClientSDK } from "@scryme/sdk/client";
107
85
 
108
- // 2. Verify stock integrity and run discrepancy checks
109
- async function runIntegrityCheck() {
110
- const result = await inventoryVerifyIntegrity(orgSlug);
111
- console.log("Integrity Report:", result.data);
112
- }
86
+ const scrymeClient = new ScrymeClientSDK({
87
+ orgSlug: "your-org-slug",
88
+ clientId: "your_client_id_123",
89
+ clientSecret: "your_client_secret_456",
90
+ });
113
91
 
114
- // 3. Merge multiple stock batches into a single parent batch
115
- async function consolidateBatches() {
116
- await inventoryMergeBatches(orgSlug, {
117
- // Merge parameters
118
- });
119
- }
120
- ```
121
-
122
- ### πŸ›’ 2. Orders & B2B Sales
123
- Submit quotes, verify B2B item stock availability, and convert approved quotes to orders.
92
+ // Reactively listen to auth state changes
93
+ scrymeClient.auth.onAuthStateChange((event, session) => {
94
+ console.log(`Auth Event: ${event}`, session);
95
+ });
124
96
 
125
- ```typescript
126
- import {
127
- ordersCreateOrder,
128
- ordersRequestB2BQuote,
129
- ordersConvertQuoteToOrder,
130
- ordersGetOrders
131
- } from "@scryme/sdk";
132
-
133
- // 1. Request a pricing and availability quote for B2B items
134
- async function createQuote() {
135
- const quote = await ordersRequestB2BQuote(orgSlug, {
136
- customerId: "cust_999",
137
- businessAccountId: "biz_acme_corp",
138
- locationId: "loc_nairobi_001",
139
- items: [
140
- { variantId: "var_espresso_beans_01", quantity: 15 }
141
- ],
142
- notes: "Requires delivery before Friday"
143
- });
144
- console.log("Quote Requested:", quote.data);
145
- }
146
-
147
- // 2. Convert an approved quote directly into a sales order
148
- async function approveAndOrder(quoteId: string) {
149
- const order = await ordersConvertQuoteToOrder(quoteId, orgSlug);
150
- console.log("Sales Order Created:", order.data);
97
+ async function runClient() {
98
+ // Call APIs directlyβ€”the SDK handles token retrieval, refresh, and auto-injection of orgSlug automatically!
99
+ const stock = await scrymeClient.inventory.getInventory({ limit: 5 });
100
+ console.log("Client Stock:", stock.data);
151
101
  }
152
102
  ```
153
103
 
154
- ### πŸ‘₯ 3. Customers & CRM
155
- Create and query contacts, build custom CRM records with schemas, and manage timelines.
104
+ Or use the helper factory `createClientSDK`, which provides fallback defaults:
156
105
 
157
106
  ```typescript
158
- import {
159
- customersGetCustomers,
160
- crmControllerCreateRecord,
161
- crmControllerCreateNote,
162
- crmControllerGetTimeline
163
- } from "@scryme/sdk";
164
-
165
- // 1. Fetch organization-scoped customers
166
- async function listCustomers() {
167
- const customers = await customersGetCustomers(orgSlug, { limit: 10 });
168
- console.log("Customers list:", customers.data);
169
- }
107
+ import { createClientSDK } from "@scryme/sdk/client";
170
108
 
171
- // 2. Create custom CRM fields and records
172
- async function logDealRecord() {
173
- // Create a record under the 'deal' definition
174
- const record = await crmControllerCreateRecord(orgSlug, {
175
- objectId: "def_deal_id",
176
- ownerId: "member_sales_rep_01",
177
- data: {
178
- title: "Enterprise Upgrade 2026",
179
- amount: 450000,
180
- stage: "discovery",
181
- expectedCloseDate: "2026-12-31"
182
- }
183
- });
184
-
185
- const recordId = record.data.id;
186
-
187
- // Add rich markdown notes to the deal's timeline
188
- await crmControllerCreateNote(orgSlug, {
189
- recordId,
190
- content: "# Kickoff Meeting Notes\n- Client loved the POS speed.\n- Wants M-Pesa automated routing.",
191
- timelineDate: new Date().toISOString()
192
- });
193
-
194
- // Fetch unified timelines containing all activities and notes
195
- const timeline = await crmControllerGetTimeline(recordId, orgSlug);
196
- console.log("Deal Timeline:", timeline.data);
197
- }
109
+ const scrymeClient = createClientSDK({
110
+ orgSlug: "your-org-slug",
111
+ clientId: "your_client_id_123",
112
+ clientSecret: "your_client_secret_456",
113
+ });
198
114
  ```
199
115
 
200
- ### 🎫 4. Loyalty & Marketing
201
- Track customer rewards, redeem points for discounts, and validate vouchers at Checkout.
116
+ ---
202
117
 
203
- ```typescript
204
- import {
205
- loyaltyGetCustomerStatus,
206
- loyaltyRedeemReward,
207
- loyaltyValidateVoucher
208
- } from "@scryme/sdk";
209
-
210
- // 1. Get customer points balance, tier level, and available rewards
211
- async function checkLoyalty(customerId: string) {
212
- const status = await loyaltyGetCustomerStatus(customerId, orgSlug);
213
- console.log(`Tier: ${status.data.tier}, Balance: ${status.data.points} pts`);
214
- }
118
+ ## πŸ”‘ Global / Legacy API client (`getScrymeV3API`)
215
119
 
216
- // 2. Validate voucher code and check customer eligibility
217
- async function processDiscount(code: string, customerId: string) {
218
- try {
219
- const validation = await loyaltyValidateVoucher(orgSlug, {
220
- code,
221
- customerId
222
- });
223
- console.log("Voucher Approved:", validation.data);
224
- } catch (error) {
225
- console.error("Invalid voucher code:", error);
226
- }
227
- }
228
- ```
120
+ Alternatively, if you prefer utilizing a global request client or overriding behavior manually, you can initialize the custom Orval proxy with `getScrymeV3API`. It supports optional auto-injection of `orgSlug` from environment variables (`SCRYME_ORG_SLUG`, etc.) or custom default configurations.
229
121
 
230
- ### πŸ’΅ 5. Finance, Petty Cash, & Expenses
231
- Track spending, top up petty cash drawers, and map payments to utility accounts.
122
+ ### Complete Initialization Example:
232
123
 
233
124
  ```typescript
234
- import {
235
- expenseControllerCreateExpense,
236
- pettyCashControllerCreateFund,
237
- pettyCashControllerTopUpFund,
238
- utilityAccountControllerCreateAccount
239
- } from "@scryme/sdk";
240
-
241
- // 1. Create a physical utility tracking account
242
- async function setupElectricityMeter() {
243
- const account = await utilityAccountControllerCreateAccount({
244
- name: "HQ Power - Meter A",
245
- provider: "Kenya Power",
246
- accountNumber: "22334455-01",
247
- meterNumber: "M-778899",
248
- type: "ELECTRICITY"
249
- });
250
- return account.data.id;
251
- }
252
-
253
- // 2. Record a direct corporate expense
254
- async function logExpense(utilityAccountId: string) {
255
- await expenseControllerCreateExpense({
256
- description: "HQ Monthly Electricity Bill",
257
- amount: 14500,
258
- categoryId: "cat_utilities_01",
259
- paymentMethod: "MPESA",
260
- utilityAccountId,
261
- isReimbursable: false,
262
- isBillable: false
263
- });
264
- }
265
- ```
125
+ import { getScrymeV3API } from "@scryme/sdk";
126
+ import axios from "axios";
266
127
 
267
- ### 🏒 6. Staff, Shifts, & Attendance
268
- Log clock-ins, check rosters, and manage custom permission sets and roles.
128
+ // 1. Initialize the API instance (optionally passing a custom Axios instance)
129
+ const apiBaseUrl = process.env.SCRYME_API_URL || "https://api.scryme.tech";
130
+ axios.defaults.baseURL = apiBaseUrl;
269
131
 
270
- ```typescript
271
- import {
272
- attendanceControllerCheckIn,
273
- attendanceControllerCheckOut,
274
- roleManagementControllerCreateCustomRole,
275
- membersControllerGetMembers
276
- } from "@scryme/sdk";
277
-
278
- // 1. Employee Clock-In with notes and location validation
279
- async function clockIn(memberId: string) {
280
- await attendanceControllerCheckIn(orgSlug, {
281
- locationId: "loc_nairobi_001",
282
- notes: "Starting morning shift at register 02"
283
- });
284
- }
132
+ const scryme = getScrymeV3API(axios);
285
133
 
286
- // 2. Create high-security roles with customized permissions
287
- async function setupManagerRole() {
288
- const role = await roleManagementControllerCreateCustomRole(orgSlug, {
289
- name: "Vault Auditor",
290
- description: "Access to petty cash floats and inventory adjustments",
291
- permissions: [
292
- "finance:manage-floats",
293
- "inventory:adjust"
294
- ]
295
- });
296
- console.log("Audit Role Created:", role.data);
297
- }
298
- ```
134
+ async function runFlow() {
135
+ try {
136
+ // 2. Perform Client Credentials flow to retrieve access token
137
+ const tokenResponse = await scryme.authExchangeToken({
138
+ clientId: process.env.SCRYME_CLIENT_ID || "your_id",
139
+ clientSecret: process.env.SCRYME_CLIENT_SECRET || "your_secret"
140
+ });
299
141
 
300
- ### πŸ“… 7. Services, Scheduling, & Bookings
301
- Manage appointments, track resource utilization, and deduct materials automatically upon completion.
142
+ const accessToken = tokenResponse.data.accessToken;
143
+ console.log("Successfully logged in! Token retrieved.");
302
144
 
303
- ```typescript
304
- import {
305
- servicesControllerCreateBooking,
306
- servicesControllerCompleteBooking,
307
- publicServicesControllerRequestOtp,
308
- publicServicesControllerVerifyOtp
309
- } from "@scryme/sdk";
310
-
311
- // 1. Book an appointment for a customer with specific staff/resources
312
- async function bookAppointment() {
313
- const booking = await servicesControllerCreateBooking(orgSlug, {
314
- serviceId: "srv_coffee_cupping_01",
315
- customerId: "cust_123",
316
- locationId: "loc_nairobi_001",
317
- scheduledStartTime: "2026-10-15T09:00:00Z",
318
- staffIds: ["member_barista_expert_01"],
319
- resourceIds: ["res_cupping_lab_A"],
320
- notes: "VIP tasting session"
321
- });
322
- console.log("Appointment Booked:", booking.data);
323
- }
145
+ // 3. Register the token in the Axios headers
146
+ axios.defaults.headers.common["Authorization"] = `Bearer ${accessToken}`;
324
147
 
325
- // 2. Complete a booking and auto-deduct standard raw materials
326
- async function checkoutBooking(bookingId: string) {
327
- await servicesControllerCompleteBooking(bookingId, orgSlug, {
328
- actualStartTime: "2026-10-15T09:02:00Z",
329
- actualEndTime: "2026-10-15T10:15:00Z",
330
- materials: [
331
- { variantId: "var_specialty_beans_cupping", quantity: 0.25 } // 250g beans consumed
332
- ]
333
- });
334
- console.log("Booking closed and inventory updated.");
148
+ // 4. Perform type-safe V3 operations (orgSlug is auto-injected from environment!)
149
+ const products = await scryme.catalogGetProducts({ limit: 10 });
150
+ console.log("Catalog Products:", products.data);
151
+ } catch (error) {
152
+ console.error("SDK execution failed:", error);
153
+ }
335
154
  }
336
155
  ```
337
156
 
338
- ### πŸ”— 8. Webhooks & Event Subscriptions
339
- Subscribe to system events and safely verify incoming signatures.
340
-
341
- ```typescript
342
- import { webhooksCreate } from "@scryme/sdk";
343
-
344
- // 1. Register a webhook callback to sync orders to an external ERP
345
- async function setupWebhook() {
346
- const webhook = await webhooksCreate(orgSlug, {
347
- name: "External ERP Sync",
348
- url: "https://erp.mycompany.com/webhooks/scryme",
349
- events: ["order.created", "inventory.updated"]
350
- });
351
-
352
- // Use the secret to verify signatures in your endpoint (see Best Practices below)
353
- console.log("Webhook Registered. HMAC Secret:", webhook.data.secret);
354
- }
355
- ```
157
+ For more domain examples, detailed schemas, and active playgrounds, head over to:
158
+ πŸ‘‰ **[docs.scryme.tech](https://docs.scryme.tech)**
356
159
 
357
160
  ---
358
161
 
@@ -391,7 +194,7 @@ Scryme V3 API returns standardized error structures. Always wrap your SDK calls
391
194
  import { isAxiosError } from "axios";
392
195
 
393
196
  try {
394
- await checkStock();
197
+ await scrymeClient.inventory.getInventory({ limit: 5 });
395
198
  } catch (error) {
396
199
  if (isAxiosError(error) && error.response) {
397
200
  const apiError = error.response.data;