@inkress/admin-sdk 1.0.0

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 ADDED
@@ -0,0 +1,455 @@
1
+ # @inkress/admin-sdk
2
+
3
+ Official Inkress Commerce API SDK for JavaScript/TypeScript applications.
4
+
5
+ [![npm version](https://badge.fury.io/js/@inkress%2Fadmin-sdk.svg)](https://badge.fury.io/js/@inkress%2Fadmin-sdk)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## Features
10
+
11
+ - 🚀 **Modern TypeScript SDK** - Built with TypeScript for excellent developer experience
12
+ - 🔒 **Secure Authentication** - JWT-based authentication with automatic token management
13
+ - 🌐 **Public Endpoints** - Access public merchant information without authentication
14
+ - 📦 **Comprehensive API Coverage** - Full coverage of Inkress Commerce API endpoints
15
+ - 🛠️ **Easy Integration** - Simple setup and intuitive API design
16
+ - 🔄 **Automatic Retries** - Built-in retry logic for resilient applications
17
+ - 📱 **Cross-Platform** - Works in Node.js, browsers, and React Native
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install @inkress/admin-sdk
23
+ ```
24
+
25
+ ```bash
26
+ yarn add @inkress/admin-sdk
27
+ ```
28
+
29
+ ```bash
30
+ pnpm add @inkress/admin-sdk
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ### Basic Setup
36
+
37
+ ```typescript
38
+ import { InkressSDK } from '@inkress/admin-sdk';
39
+
40
+ const inkress = new InkressSDK({
41
+ bearerToken: 'your-jwt-token', // Can be an empty string for public endpoints
42
+ clientId: 'm-merchant-username', // Required for merchant-specific endpoints
43
+ endpoint: 'https://api.inkress.com', // Optional, defaults to production
44
+ });
45
+ ```
46
+
47
+ ### Public Endpoints (No Authentication Required)
48
+
49
+ ```typescript
50
+ // Get public merchant information
51
+ const merchant = await inkress.public.getMerchant({
52
+ username: 'merchant-username'
53
+ });
54
+
55
+ // Get merchant products
56
+ const products = await inkress.public.getMerchantProducts('merchant-username', {
57
+ limit: 20,
58
+ search: 'laptop'
59
+ });
60
+
61
+ // Get merchant fees
62
+ const fees = await inkress.public.getMerchantFees('merchant-username', {
63
+ currency: 'JMD',
64
+ total: 1000
65
+ });
66
+ ```
67
+
68
+ ### Authenticated Operations
69
+
70
+ ```typescript
71
+ // List categories
72
+ const categories = await inkress.categories.list({ kind: 1 });
73
+
74
+ // Create a new category
75
+ const category = await inkress.categories.create({
76
+ name: 'Electronics',
77
+ description: 'Electronic devices and accessories',
78
+ kind: 1
79
+ });
80
+
81
+ // List products
82
+ const products = await inkress.products.list({
83
+ limit: 50,
84
+ category_id: 1
85
+ });
86
+
87
+ // Create an order
88
+ const order = await inkress.orders.create({
89
+ currency_code: 'USD',
90
+ customer: {
91
+ email: 'customer@example.com',
92
+ first_name: 'John',
93
+ last_name: 'Doe'
94
+ },
95
+ total: 29.99,
96
+ reference_id: 'order-123'
97
+ });
98
+ ```
99
+
100
+ ## Configuration Options
101
+
102
+ | Option | Type | Required | Default | Description |
103
+ |--------|------|----------|---------|-------------|
104
+ | `bearerToken` | `string` | Yes | - | JWT token for API authentication |
105
+ | `clientId` | `string` | No | - | Client ID for merchant-specific requests (format: `m-{username}`) |
106
+ | `endpoint` | `string` | No | `https://api.inkress.com` | API endpoint URL |
107
+ | `apiVersion` | `string` | No | `v1` | API version to use |
108
+ | `timeout` | `number` | No | `30000` | Request timeout in milliseconds |
109
+ | `retries` | `number` | No | `3` | Number of retry attempts for failed requests |
110
+ | `headers` | `Record<string, string>` | No | `{}` | Custom headers to include with requests |
111
+
112
+ ## API Resources
113
+
114
+ ### Public Resource (No Authentication)
115
+
116
+ Access public merchant information without authentication:
117
+
118
+ ```typescript
119
+ // Get merchant by username or domain
120
+ await inkress.public.getMerchant({ username: 'merchant-name' });
121
+ await inkress.public.getMerchant({ 'domain.cname': 'store.example.com' });
122
+
123
+ // Get merchant products with filtering
124
+ await inkress.public.getMerchantProducts('merchant-name', {
125
+ search: 'laptop',
126
+ category: 'electronics',
127
+ limit: 20
128
+ });
129
+
130
+ // Get merchant fees
131
+ await inkress.public.getMerchantFees('merchant-name');
132
+ ```
133
+
134
+ ### Merchants Resource
135
+
136
+ ```typescript
137
+ // List merchants
138
+ await inkress.merchants.list();
139
+
140
+ // Get merchant details
141
+ await inkress.merchants.get(merchantId);
142
+
143
+ // Update merchant
144
+ await inkress.merchants.update(merchantId, { name: 'New Name' });
145
+ ```
146
+
147
+ ### Products Resource
148
+
149
+ ```typescript
150
+ // List products with pagination and filtering
151
+ await inkress.products.list({
152
+ page: 1,
153
+ per_page: 50,
154
+ category_id: 1,
155
+ search: 'laptop'
156
+ });
157
+
158
+ // Get product details
159
+ await inkress.products.get(productId);
160
+
161
+ // Create a new product
162
+ await inkress.products.create({
163
+ name: 'Gaming Laptop',
164
+ description: 'High-performance gaming laptop',
165
+ price: 1299.99,
166
+ category_id: 1
167
+ });
168
+
169
+ // Update product
170
+ await inkress.products.update(productId, { price: 1199.99 });
171
+
172
+ // Delete product
173
+ await inkress.products.delete(productId);
174
+ ```
175
+
176
+ ### Categories Resource
177
+
178
+ ```typescript
179
+ // List categories
180
+ await inkress.categories.list({ kind: 1 });
181
+
182
+ // Get category details
183
+ await inkress.categories.get(categoryId);
184
+
185
+ // Create category
186
+ await inkress.categories.create({
187
+ name: 'Electronics',
188
+ description: 'Electronic devices',
189
+ kind: 1
190
+ });
191
+
192
+ // Update category
193
+ await inkress.categories.update(categoryId, { name: 'Updated Name' });
194
+
195
+ // Delete category
196
+ await inkress.categories.delete(categoryId);
197
+ ```
198
+
199
+ ### Orders Resource
200
+
201
+ ```typescript
202
+ // Create an order
203
+ await inkress.orders.create({
204
+ currency_code: 'USD',
205
+ customer: {
206
+ email: 'customer@example.com',
207
+ first_name: 'John',
208
+ last_name: 'Doe'
209
+ },
210
+ total: 99.99,
211
+ reference_id: 'order-123',
212
+ kind: 'online'
213
+ });
214
+
215
+ // Get order details
216
+ await inkress.orders.get(orderId);
217
+
218
+ // Update order status
219
+ await inkress.orders.update(orderId, { status: 2 });
220
+
221
+ // Get order status (public endpoint)
222
+ await inkress.orders.getStatus(orderId);
223
+
224
+ // List orders
225
+ await inkress.orders.list();
226
+ ```
227
+
228
+ ### Users Resource
229
+
230
+ ```typescript
231
+ // List users
232
+ await inkress.users.list();
233
+
234
+ // Get user details
235
+ await inkress.users.get(userId);
236
+
237
+ // Create user
238
+ await inkress.users.create({
239
+ email: 'user@example.com',
240
+ first_name: 'John',
241
+ last_name: 'Doe',
242
+ role: 'customer'
243
+ });
244
+
245
+ // Update user
246
+ await inkress.users.update(userId, { first_name: 'Jane' });
247
+
248
+ // Delete user
249
+ await inkress.users.delete(userId);
250
+ ```
251
+
252
+ ### Billing Plans Resource
253
+
254
+ ```typescript
255
+ // List billing plans
256
+ await inkress.billingPlans.list();
257
+
258
+ // Get plan details
259
+ await inkress.billingPlans.get(planId);
260
+
261
+ // Create billing plan
262
+ await inkress.billingPlans.create({
263
+ name: 'Premium Plan',
264
+ amount: 29.99,
265
+ currency: 'USD'
266
+ });
267
+ ```
268
+
269
+ ### Subscriptions Resource
270
+
271
+ ```typescript
272
+ // List subscriptions
273
+ await inkress.subscriptions.list();
274
+
275
+ // Get subscription details
276
+ await inkress.subscriptions.get(subscriptionId);
277
+
278
+ // Create subscription
279
+ await inkress.subscriptions.create({
280
+ plan_id: 1,
281
+ customer: {
282
+ email: 'customer@example.com',
283
+ first_name: 'John',
284
+ last_name: 'Doe'
285
+ }
286
+ });
287
+ ```
288
+
289
+ ## Error Handling
290
+
291
+ The SDK provides structured error handling with detailed error information:
292
+
293
+ ```typescript
294
+ try {
295
+ const product = await inkress.products.get(123);
296
+ } catch (error) {
297
+ if (error.response?.status === 404) {
298
+ console.log('Product not found');
299
+ } else if (error.response?.status === 422) {
300
+ console.log('Validation errors:', error.response.data);
301
+ } else {
302
+ console.log('Unexpected error:', error.message);
303
+ }
304
+ }
305
+ ```
306
+
307
+ ## TypeScript Support
308
+
309
+ The SDK is built with TypeScript and provides comprehensive type definitions:
310
+
311
+ ```typescript
312
+ import {
313
+ InkressSDK,
314
+ Product,
315
+ Category,
316
+ Order,
317
+ Merchant,
318
+ CreateProductData,
319
+ ApiResponse
320
+ } from '@inkress/admin-sdk';
321
+
322
+ // All API responses are properly typed
323
+ const response: ApiResponse<Product[]> = await inkress.products.list();
324
+ const products: Product[] = response.result || response.data || [];
325
+ ```
326
+
327
+ ## Environment Configuration
328
+
329
+ ### Development
330
+
331
+ ```typescript
332
+ const inkress = new InkressSDK({
333
+ bearerToken: process.env.INKRESS_DEV_TOKEN,
334
+ endpoint: 'https://api-dev.inkress.com',
335
+ clientId: 'm-your-dev-merchant'
336
+ });
337
+ ```
338
+
339
+ ### Production
340
+
341
+ ```typescript
342
+ const inkress = new InkressSDK({
343
+ bearerToken: process.env.INKRESS_PROD_TOKEN,
344
+ endpoint: 'https://api.inkress.com',
345
+ clientId: 'm-your-merchant'
346
+ });
347
+ ```
348
+
349
+ ## React/Next.js Integration
350
+
351
+ ### Server-Side Usage (API Routes)
352
+
353
+ ```typescript
354
+ // pages/api/products.ts or app/api/products/route.ts
355
+ import { InkressSDK } from '@inkress/admin-sdk';
356
+
357
+ const inkress = new InkressSDK({
358
+ bearerToken: process.env.INKRESS_TOKEN!,
359
+ clientId: process.env.INKRESS_CLIENT_ID!
360
+ });
361
+
362
+ export async function GET() {
363
+ const products = await inkress.products.list();
364
+ return Response.json(products);
365
+ }
366
+ ```
367
+
368
+ ### Client-Side Usage (Public Endpoints)
369
+
370
+ ```typescript
371
+ // hooks/usePublicMerchant.ts
372
+ import { InkressSDK } from '@inkress/admin-sdk';
373
+
374
+ const sdk = new InkressSDK({
375
+ bearerToken: '', // Empty for public endpoints
376
+ endpoint: 'https://api.inkress.com'
377
+ });
378
+
379
+ export async function getPublicMerchant(username: string) {
380
+ return await sdk.public.getMerchant({ username });
381
+ }
382
+ ```
383
+
384
+ ## Best Practices
385
+
386
+ ### 1. Environment Variables
387
+
388
+ Store sensitive configuration in environment variables:
389
+
390
+ ```env
391
+ INKRESS_TOKEN=your-jwt-token
392
+ INKRESS_CLIENT_ID=m-your-merchant
393
+ INKRESS_ENDPOINT=https://api.inkress.com
394
+ ```
395
+
396
+ ### 2. Error Handling
397
+
398
+ Always implement proper error handling:
399
+
400
+ ```typescript
401
+ async function fetchProducts() {
402
+ try {
403
+ const response = await inkress.products.list();
404
+ return response.result || response.data || [];
405
+ } catch (error) {
406
+ console.error('Failed to fetch products:', error);
407
+ return [];
408
+ }
409
+ }
410
+ ```
411
+
412
+ ### 3. Rate Limiting
413
+
414
+ Be mindful of API rate limits and implement appropriate throttling in your application.
415
+
416
+ ### 4. Caching
417
+
418
+ Cache frequently accessed data like merchant information and categories:
419
+
420
+ ```typescript
421
+ const merchantCache = new Map();
422
+
423
+ async function getCachedMerchant(username: string) {
424
+ if (merchantCache.has(username)) {
425
+ return merchantCache.get(username);
426
+ }
427
+
428
+ const merchant = await inkress.public.getMerchant({ username });
429
+ merchantCache.set(username, merchant);
430
+ return merchant;
431
+ }
432
+ ```
433
+
434
+ ## Contributing
435
+
436
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
437
+
438
+ ## Support
439
+
440
+ - 📚 [API Documentation](https://docs.inkress.com)
441
+ - 💬 [Discord Community](https://discord.gg/inkress)
442
+ - 🐛 [Issue Tracker](https://github.com/inkress/admin-sdk/issues)
443
+ - 📧 [Email Support](mailto:support@inkress.com)
444
+
445
+ ## License
446
+
447
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
448
+
449
+ ## Changelog
450
+
451
+ See [CHANGELOG.md](CHANGELOG.md) for a list of changes and version history.
452
+
453
+ ---
454
+
455
+ Made with ❤️ by the [Inkress](https://inkress.com) team.
@@ -0,0 +1,30 @@
1
+ import { InkressConfig, ApiResponse } from './types';
2
+ export interface RequestOptions {
3
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
+ body?: any;
5
+ headers?: Record<string, string>;
6
+ timeout?: number;
7
+ }
8
+ export declare class HttpClient {
9
+ private config;
10
+ constructor(config: InkressConfig);
11
+ private getBaseUrl;
12
+ private getHeaders;
13
+ private makeRequest;
14
+ private retryRequest;
15
+ private shouldRetry;
16
+ private delay;
17
+ get<T>(path: string, params?: Record<string, any>): Promise<ApiResponse<T>>;
18
+ post<T>(path: string, body?: any): Promise<ApiResponse<T>>;
19
+ put<T>(path: string, body?: any): Promise<ApiResponse<T>>;
20
+ delete<T>(path: string): Promise<ApiResponse<T>>;
21
+ patch<T>(path: string, body?: any): Promise<ApiResponse<T>>;
22
+ updateConfig(newConfig: Partial<InkressConfig>): void;
23
+ getConfig(): Omit<InkressConfig, 'bearerToken'>;
24
+ }
25
+ export declare class InkressApiError extends Error {
26
+ readonly status: number;
27
+ readonly data: any;
28
+ constructor(message: string, status: number, data?: any);
29
+ }
30
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAiB,MAAM,SAAS,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrD,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA0B;gBAE5B,MAAM,EAAE,aAAa;IAYjC,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,UAAU;YAgBJ,WAAW;YAkEX,YAAY;IAgB1B,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,KAAK;IAIP,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAkB3E,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAI1D,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIzD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIhD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAKjE,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAKrD,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC;CAIhD;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,GAAG,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;CAMxD"}
@@ -0,0 +1,76 @@
1
+ import { InkressConfig } from './types';
2
+ import { MerchantsResource } from './resources/merchants';
3
+ import { CategoriesResource } from './resources/categories';
4
+ import { OrdersResource } from './resources/orders';
5
+ import { ProductsResource } from './resources/products';
6
+ import { BillingPlansResource } from './resources/billing-plans';
7
+ import { SubscriptionsResource } from './resources/subscriptions';
8
+ import { UsersResource } from './resources/users';
9
+ import { PublicResource } from './resources/public';
10
+ /**
11
+ * Main Inkress Commerce API SDK class
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { InkressSDK } from '@inkress/admin-sdk';
16
+ *
17
+ * const inkress = new InkressSDK({
18
+ * bearerToken: 'your-jwt-token',
19
+ * clientId: 'm-merchant-username', // Required for merchant-specific endpoints
20
+ * endpoint: 'https://api.inkress.com', // Optional, defaults to production
21
+ * apiVersion: 'v1', // Optional, defaults to v1
22
+ * });
23
+ *
24
+ * // List merchants
25
+ * const merchants = await inkress.merchants.list();
26
+ *
27
+ * // Get public merchant information (no auth required)
28
+ * const publicMerchant = await inkress.public.getMerchant({ username: 'merchant-username' });
29
+ *
30
+ * // List categories
31
+ * const categories = await inkress.categories.list();
32
+ *
33
+ * // Create a category
34
+ * const category = await inkress.categories.create({
35
+ * name: 'Electronics',
36
+ * description: 'Electronic devices and accessories',
37
+ * kind: 1
38
+ * });
39
+ *
40
+ * // Create an order
41
+ * const order = await inkress.orders.create({
42
+ * currency_code: 'USD',
43
+ * customer: {
44
+ * email: 'customer@example.com',
45
+ * first_name: 'John',
46
+ * last_name: 'Doe'
47
+ * },
48
+ * total: 29.99,
49
+ * reference_id: 'order-123'
50
+ * });
51
+ * ```
52
+ */
53
+ export declare class InkressSDK {
54
+ private client;
55
+ readonly merchants: MerchantsResource;
56
+ readonly categories: CategoriesResource;
57
+ readonly orders: OrdersResource;
58
+ readonly products: ProductsResource;
59
+ readonly billingPlans: BillingPlansResource;
60
+ readonly subscriptions: SubscriptionsResource;
61
+ readonly users: UsersResource;
62
+ readonly public: PublicResource;
63
+ constructor(config: InkressConfig);
64
+ /**
65
+ * Update the SDK configuration
66
+ */
67
+ updateConfig(newConfig: Partial<InkressConfig>): void;
68
+ /**
69
+ * Get current configuration (without sensitive data)
70
+ */
71
+ getConfig(): Omit<InkressConfig, 'bearerToken'>;
72
+ }
73
+ export * from './types';
74
+ export * from './client';
75
+ export { InkressSDK as default };
76
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAa;IAG3B,SAAgB,SAAS,EAAE,iBAAiB,CAAC;IAC7C,SAAgB,UAAU,EAAE,kBAAkB,CAAC;IAC/C,SAAgB,MAAM,EAAE,cAAc,CAAC;IACvC,SAAgB,QAAQ,EAAE,gBAAgB,CAAC;IAC3C,SAAgB,YAAY,EAAE,oBAAoB,CAAC;IACnD,SAAgB,aAAa,EAAE,qBAAqB,CAAC;IACrD,SAAgB,KAAK,EAAE,aAAa,CAAC;IACrC,SAAgB,MAAM,EAAE,cAAc,CAAC;gBAE3B,MAAM,EAAE,aAAa;IAcjC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAIrD;;OAEG;IACH,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC;CAGhD;AAGD,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,UAAU,IAAI,OAAO,EAAE,CAAC"}