oblien 1.0.7 → 1.1.1

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.
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Credits Module
3
+ * Manages credits, quotas, usage tracking, and transactions
4
+ */
5
+
6
+ export class OblienCredits {
7
+ /**
8
+ * @param {import('../client.js').OblienClient} client - Oblien client instance
9
+ */
10
+ constructor(client) {
11
+ if (!client) {
12
+ throw new Error('Oblien client is required');
13
+ }
14
+
15
+ this.client = client;
16
+ }
17
+
18
+ // =============================================================================
19
+ // Balance Management
20
+ // =============================================================================
21
+
22
+ /**
23
+ * Get client's total credit balance
24
+ * @returns {Promise<number>} Current credit balance
25
+ */
26
+ async getBalance() {
27
+ const response = await this.client.get('credits/balance');
28
+ return response.balance;
29
+ }
30
+
31
+ /**
32
+ * Add credits to client (internal use - requires admin permissions)
33
+ * @param {number} amount - Amount of credits to add
34
+ * @param {string} [reason] - Reason for adding credits
35
+ * @param {Object} [metadata] - Additional metadata
36
+ * @returns {Promise<Object>} Result with new balance
37
+ */
38
+ async addCredits(amount, reason = 'manual', metadata = {}) {
39
+ const response = await this.client.post('credits/add', {
40
+ amount,
41
+ reason,
42
+ metadata
43
+ });
44
+ return response;
45
+ }
46
+
47
+ // =============================================================================
48
+ // Quota Management
49
+ // =============================================================================
50
+
51
+ /**
52
+ * Get all namespace quotas with pagination and filtering
53
+ * @param {Object} [options] - Query options
54
+ * @param {number} [options.limit] - Max results (default: 100, max: 500)
55
+ * @param {number} [options.offset] - Offset for pagination
56
+ * @param {string} [options.after] - Cursor for pagination (format: "namespace:service")
57
+ * @param {string} [options.search] - Search query
58
+ * @param {string} [options.status] - Filter by status: 'active', 'warning', 'exceeded'
59
+ * @returns {Promise<Object>} Namespaces with quotas and pagination info
60
+ */
61
+ async getNamespaceQuotas(options = {}) {
62
+ const response = await this.client.get('credits/namespaces', options);
63
+ return response;
64
+ }
65
+
66
+ /**
67
+ * Get detailed namespace quota information
68
+ * @param {string} namespace - Namespace slug or ID
69
+ * @param {Object} [options] - Query options
70
+ * @param {number} [options.days] - Number of days for stats (default: 7, max: 90)
71
+ * @returns {Promise<Object>} Namespace details with quotas, usage, and transactions
72
+ */
73
+ async getNamespaceDetails(namespace, options = {}) {
74
+ const response = await this.client.get(`credits/namespaces/${namespace}`, options);
75
+ return response;
76
+ }
77
+
78
+ /**
79
+ * Set quota for a namespace and service
80
+ * @param {Object} options - Quota options
81
+ * @param {string} options.namespace - Namespace slug
82
+ * @param {string} options.service - Service name (e.g., 'ai', 'deployment', 'sandbox')
83
+ * @param {number} options.quotaLimit - Quota limit (null or 0 for unlimited)
84
+ * @param {string} [options.period] - Quota period: 'daily', 'monthly', 'unlimited'
85
+ * @returns {Promise<Object>} Created/updated quota
86
+ */
87
+ async setQuota(options) {
88
+ if (!options.namespace || !options.service) {
89
+ throw new Error('namespace and service are required');
90
+ }
91
+
92
+ if (options.quotaLimit === undefined) {
93
+ throw new Error('quotaLimit is required');
94
+ }
95
+
96
+ const response = await this.client.post('credits/namespace-quota', {
97
+ namespace: options.namespace,
98
+ service: options.service,
99
+ quotaLimit: options.quotaLimit,
100
+ period: options.period || 'unlimited'
101
+ });
102
+
103
+ return response;
104
+ }
105
+
106
+ /**
107
+ * Reset namespace quota (e.g., for monthly reset)
108
+ * @param {string} namespace - Namespace slug
109
+ * @param {string} service - Service name
110
+ * @returns {Promise<Object>} Reset result
111
+ */
112
+ async resetQuota(namespace, service) {
113
+ if (!namespace || !service) {
114
+ throw new Error('namespace and service are required');
115
+ }
116
+
117
+ const response = await this.client.post('credits/reset-quota', {
118
+ namespace,
119
+ service
120
+ });
121
+
122
+ return response;
123
+ }
124
+
125
+ // =============================================================================
126
+ // Usage History & Transactions
127
+ // =============================================================================
128
+
129
+ /**
130
+ * Get credit usage history with filtering and pagination
131
+ * @param {Object} [options] - Query options
132
+ * @param {string} [options.namespace] - Filter by namespace
133
+ * @param {string} [options.endUserId] - Filter by end user ID
134
+ * @param {string} [options.service] - Filter by service
135
+ * @param {string} [options.type] - Filter by type: 'deduction', 'addition', 'refund', 'adjustment'
136
+ * @param {string} [options.startDate] - Start date (ISO string)
137
+ * @param {string} [options.endDate] - End date (ISO string)
138
+ * @param {number} [options.limit] - Max results (default: 50)
139
+ * @param {number} [options.offset] - Offset for pagination
140
+ * @param {string} [options.after] - Cursor for pagination (timestamp)
141
+ * @param {number} [options.afterId] - Cursor ID for pagination
142
+ * @returns {Promise<Object>} History with transactions and pagination
143
+ */
144
+ async getHistory(options = {}) {
145
+ const response = await this.client.get('credits/history', options);
146
+ return response;
147
+ }
148
+
149
+ /**
150
+ * Get available filter options for history
151
+ * @returns {Promise<Object>} Available namespaces and services
152
+ */
153
+ async getHistoryFilters() {
154
+ const response = await this.client.get('credits/history/filters');
155
+ return response;
156
+ }
157
+
158
+ /**
159
+ * Get usage summary by namespace/service
160
+ * @param {Object} [options] - Query options
161
+ * @param {string} [options.namespace] - Filter by namespace
162
+ * @param {number} [options.days] - Number of days to look back (default: 30)
163
+ * @param {number} [options.limit] - Max results (default: 50, max: 500)
164
+ * @param {number} [options.offset] - Offset for pagination
165
+ * @param {number} [options.after] - Cursor for pagination (total_spent value)
166
+ * @returns {Promise<Object>} Summary with aggregated usage
167
+ */
168
+ async getSummary(options = {}) {
169
+ const response = await this.client.get('credits/summary', options);
170
+ return response;
171
+ }
172
+
173
+ /**
174
+ * Get daily usage statistics (for charts)
175
+ * @param {Object} [options] - Query options
176
+ * @param {number} [options.days] - Number of days (default: 7)
177
+ * @returns {Promise<Object>} Daily usage statistics
178
+ */
179
+ async getUsageStats(options = {}) {
180
+ const response = await this.client.get('credits/usage-stats', options);
181
+ return response;
182
+ }
183
+
184
+ // =============================================================================
185
+ // Pricing & Packages
186
+ // =============================================================================
187
+
188
+ /**
189
+ * Get available credit packages
190
+ * @returns {Promise<Array>} Array of credit packages
191
+ */
192
+ async getPackages() {
193
+ const response = await this.client.get('credits/packages');
194
+ return response.packages || response.data || response;
195
+ }
196
+
197
+ /**
198
+ * Get pricing information and limits
199
+ * @returns {Promise<Object>} Pricing info with rates and limits
200
+ */
201
+ async getPricingInfo() {
202
+ const response = await this.client.get('credits/pricing-info');
203
+ return response;
204
+ }
205
+
206
+ /**
207
+ * Calculate credits from money or vice versa
208
+ * @param {Object} options - Calculation options
209
+ * @param {string} [options.packageId] - Package ID to calculate
210
+ * @param {number} [options.amount] - Money amount to convert to credits
211
+ * @param {number} [options.credits] - Credits to convert to money
212
+ * @returns {Promise<Object>} Calculation result with amount and credits
213
+ */
214
+ async calculateCost(options) {
215
+ if (!options.packageId && !options.amount && !options.credits) {
216
+ throw new Error('Must provide either packageId, amount, or credits');
217
+ }
218
+
219
+ const response = await this.client.post('credits/calculate-cost', options);
220
+ return response;
221
+ }
222
+
223
+ /**
224
+ * Calculate credits for a given amount (preview)
225
+ * @param {number} amount - Money amount
226
+ * @returns {Promise<Object>} Credits calculation
227
+ */
228
+ async calculateCredits(amount) {
229
+ const response = await this.client.get('credits/calculate', { amount });
230
+ return response;
231
+ }
232
+
233
+ // =============================================================================
234
+ // Purchase Management
235
+ // =============================================================================
236
+
237
+ /**
238
+ * Create Stripe checkout to purchase credits
239
+ * @param {Object} options - Purchase options
240
+ * @param {string} [options.packageId] - Package ID to purchase
241
+ * @param {number} [options.amount] - Custom amount to purchase
242
+ * @param {Object} [options.metadata] - Additional metadata
243
+ * @returns {Promise<Object>} Checkout session with URL
244
+ */
245
+ async createCheckout(options) {
246
+ if (!options.packageId && !options.amount) {
247
+ throw new Error('Must provide either packageId or amount');
248
+ }
249
+
250
+ const response = await this.client.post('credits/purchase', options);
251
+ return response;
252
+ }
253
+
254
+ /**
255
+ * Get purchase history
256
+ * @param {Object} [options] - Query options
257
+ * @param {number} [options.limit] - Max results (default: 50, max: 100)
258
+ * @param {number} [options.offset] - Offset for pagination
259
+ * @param {boolean} [options.light] - If true, returns basic data only (faster)
260
+ * @returns {Promise<Object>} Purchase history with pagination
261
+ */
262
+ async getPurchaseHistory(options = {}) {
263
+ const response = await this.client.get('credits/purchases', options);
264
+ return response;
265
+ }
266
+
267
+ /**
268
+ * Get single purchase details
269
+ * @param {string} purchaseId - Purchase ID
270
+ * @returns {Promise<Object>} Purchase details
271
+ */
272
+ async getPurchaseDetails(purchaseId) {
273
+ const response = await this.client.get(`credits/purchases/${purchaseId}`);
274
+ return response;
275
+ }
276
+
277
+ /**
278
+ * Get Stripe checkout session URL for pending purchase
279
+ * @param {string} purchaseId - Purchase ID
280
+ * @returns {Promise<Object>} Session with checkout URL
281
+ */
282
+ async getPurchaseSession(purchaseId) {
283
+ const response = await this.client.get(`credits/purchases/${purchaseId}/session`);
284
+ return response;
285
+ }
286
+
287
+ /**
288
+ * Cancel a pending purchase
289
+ * @param {string} purchaseId - Purchase ID
290
+ * @returns {Promise<Object>} Cancellation result
291
+ */
292
+ async cancelPurchase(purchaseId) {
293
+ const response = await this.client.post(`credits/purchases/${purchaseId}/cancel`);
294
+ return response;
295
+ }
296
+ }
297
+
298
+ export default OblienCredits;
299
+
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Oblien Icons Module
3
+ * Search and fetch icons, images, and videos
4
+ */
5
+
6
+ export class OblienIcons {
7
+ constructor(client) {
8
+ if (!client) throw new Error('Oblien client is required');
9
+ this.client = client;
10
+ }
11
+
12
+ /**
13
+ * Search for icons using semantic search
14
+ *
15
+ * @param {string} query - Search query
16
+ * @param {Object} options - Search options
17
+ * @param {number} options.offset - Pagination offset (default: 0)
18
+ * @param {number} options.limit - Number of results (default: 100)
19
+ * @returns {Promise<Object>} Search results with pagination info
20
+ *
21
+ * @example
22
+ * const results = await icons.search('home', { limit: 50 });
23
+ * // Returns:
24
+ * // {
25
+ * // results: [
26
+ * // {
27
+ * // url: 'https://cdn.oblien.com/static/png-icons/...',
28
+ * // filename: 'home-outline.png',
29
+ * // name: 'home',
30
+ * // description: 'home',
31
+ * // style: 'Outline',
32
+ * // score: 0.95,
33
+ * // success: true
34
+ * // }
35
+ * // ],
36
+ * // hasMore: true,
37
+ * // offset: 50,
38
+ * // total: 245
39
+ * // }
40
+ */
41
+ async search(query, options = {}) {
42
+ if (!query || typeof query !== 'string') {
43
+ throw new Error('Query must be a non-empty string');
44
+ }
45
+
46
+ const { offset = 0, limit = 100 } = options;
47
+
48
+ return this.client.post('icons/search-icons', {
49
+ query: query.trim(),
50
+ offset,
51
+ limit
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Fetch multiple items (icons, images, videos) with semantic matching
57
+ *
58
+ * @param {Array<Object>} items - Array of items to fetch
59
+ * @param {string} items[].type - Type: 'icon', 'image', or 'video'
60
+ * @param {string} items[].description - Description for semantic matching
61
+ * @param {boolean} items[].is_vector - Whether the item is a vector (optional)
62
+ * @param {string} items[].variant - Variant type (optional, for images/videos)
63
+ * @returns {Promise<Array>} Array of fetched items with URLs
64
+ *
65
+ * @example
66
+ * const items = await icons.fetch([
67
+ * { type: 'icon', description: 'user profile' },
68
+ * { type: 'icon', description: 'settings gear' },
69
+ * { type: 'image', description: 'mountain landscape' },
70
+ * { type: 'video', description: 'ocean waves' }
71
+ * ]);
72
+ *
73
+ * // Returns:
74
+ * // [
75
+ * // {
76
+ * // url: 'https://cdn.oblien.com/static/icons/...',
77
+ * // description: 'user profile',
78
+ * // style: 'Outline',
79
+ * // success: true
80
+ * // },
81
+ * // {
82
+ * // url: 'https://cdn.oblien.com/static/assets/...',
83
+ * // type: 'image',
84
+ * // description: 'mountain landscape',
85
+ * // variant: 'regular',
86
+ * // success: true
87
+ * // }
88
+ * // ]
89
+ */
90
+ async fetch(items) {
91
+ if (!Array.isArray(items) || items.length === 0) {
92
+ throw new Error('Items must be a non-empty array');
93
+ }
94
+
95
+ // Validate items
96
+ for (const item of items) {
97
+ if (!item.type || !['icon', 'image', 'video'].includes(item.type)) {
98
+ throw new Error('Each item must have a valid type: icon, image, or video');
99
+ }
100
+ if (!item.description || typeof item.description !== 'string') {
101
+ throw new Error('Each item must have a description string');
102
+ }
103
+ }
104
+
105
+ return this.client.post('icons/fetch', { data: items });
106
+ }
107
+
108
+ /**
109
+ * Fetch a single icon
110
+ * Convenience method for fetching one icon
111
+ *
112
+ * @param {string} description - Icon description
113
+ * @returns {Promise<Object>} Icon object with URL
114
+ *
115
+ * @example
116
+ * const icon = await icons.fetchIcon('home');
117
+ * // Returns: { url: '...', description: 'home', style: 'Outline', success: true }
118
+ */
119
+ async fetchIcon(description) {
120
+ if (!description || typeof description !== 'string') {
121
+ throw new Error('Description must be a non-empty string');
122
+ }
123
+
124
+ const result = await this.fetch([{ type: 'icon', description }]);
125
+ return result[0] || null;
126
+ }
127
+
128
+ /**
129
+ * Fetch multiple icons at once
130
+ * Convenience method for fetching multiple icons
131
+ *
132
+ * @param {Array<string>} descriptions - Array of icon descriptions
133
+ * @returns {Promise<Array>} Array of icon objects
134
+ *
135
+ * @example
136
+ * const icons = await icons.fetchIcons(['home', 'settings', 'user']);
137
+ * // Returns: [{ url: '...', description: 'home', ... }, ...]
138
+ */
139
+ async fetchIcons(descriptions) {
140
+ if (!Array.isArray(descriptions) || descriptions.length === 0) {
141
+ throw new Error('Descriptions must be a non-empty array');
142
+ }
143
+
144
+ const items = descriptions.map(desc => ({ type: 'icon', description: desc }));
145
+ return this.fetch(items);
146
+ }
147
+
148
+ /**
149
+ * Search icons with pagination helper
150
+ * Automatically handles pagination and returns all results
151
+ *
152
+ * @param {string} query - Search query
153
+ * @param {Object} options - Search options
154
+ * @param {number} options.maxResults - Maximum results to fetch (default: 500)
155
+ * @param {number} options.batchSize - Results per batch (default: 100)
156
+ * @returns {Promise<Array>} All matching icons
157
+ *
158
+ * @example
159
+ * const allIcons = await icons.searchAll('home', { maxResults: 200 });
160
+ * // Returns: [{ url: '...', name: 'home', ... }, ...]
161
+ */
162
+ async searchAll(query, options = {}) {
163
+ const { maxResults = 500, batchSize = 100 } = options;
164
+ const allResults = [];
165
+ let offset = 0;
166
+ let hasMore = true;
167
+
168
+ while (hasMore && allResults.length < maxResults) {
169
+ const response = await this.search(query, {
170
+ offset,
171
+ limit: Math.min(batchSize, maxResults - allResults.length)
172
+ });
173
+
174
+ if (response.results && response.results.length > 0) {
175
+ allResults.push(...response.results);
176
+ }
177
+
178
+ hasMore = response.hasMore && allResults.length < maxResults;
179
+ offset = response.offset;
180
+ }
181
+
182
+ return allResults;
183
+ }
184
+ }
185
+