krawlet-js 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,436 @@
1
+ # krawlet-js
2
+
3
+ > TypeScript/JavaScript client library for the Krawlet Minecraft economy tracking API
4
+
5
+ [![npm version](https://img.shields.io/npm/v/krawlet-js.svg)](https://www.npmjs.com/package/krawlet-js)
6
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
7
+
8
+ ## Table of Contents
9
+
10
+ - [Installation](#installation)
11
+ - [Quick Start](#quick-start)
12
+ - [Configuration](#configuration)
13
+ - [API Reference](#api-reference)
14
+ - [Health](#health)
15
+ - [Players](#players)
16
+ - [Shops](#shops)
17
+ - [Items](#items)
18
+ - [Addresses](#addresses)
19
+ - [Storage](#storage)
20
+ - [Reports](#reports)
21
+ - [Error Handling](#error-handling)
22
+ - [Rate Limiting](#rate-limiting)
23
+ - [TypeScript Support](#typescript-support)
24
+ - [Examples](#examples)
25
+ - [Development](#development)
26
+ - [License](#license)
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ # Using pnpm
32
+ pnpm add krawlet-js
33
+
34
+ # Using npm
35
+ npm install krawlet-js
36
+
37
+ # Using yarn
38
+ yarn add krawlet-js
39
+ ```
40
+
41
+ **Requirements:**
42
+ - Node.js 18.x or higher (for native `fetch` support)
43
+ - TypeScript 5.x (optional, but recommended)
44
+
45
+ ## Quick Start
46
+
47
+ ```typescript
48
+ import { KrawletClient } from 'krawlet-js';
49
+
50
+ // Create a client (anonymous - 100 requests/hour)
51
+ const client = new KrawletClient();
52
+
53
+ // Get all shops
54
+ const shops = await client.shops.getAll();
55
+ console.log(`Found ${shops.length} shops`);
56
+
57
+ // Find a player by Kromer address
58
+ const players = await client.players.getByAddresses(['ks0d5iqb6p']);
59
+ console.log('Player:', players[0]?.minecraftName);
60
+ ```
61
+
62
+ ### With Authentication
63
+
64
+ ```typescript
65
+ import { KrawletClient } from 'krawlet-js';
66
+
67
+ // Authenticated client (1,000-5,000 requests/hour)
68
+ const client = new KrawletClient({
69
+ apiKey: 'kraw_your_api_key_here',
70
+ });
71
+
72
+ const shops = await client.shops.getAll();
73
+ ```
74
+
75
+ ## Configuration
76
+
77
+ ```typescript
78
+ const client = new KrawletClient({
79
+ // API base URL (default: 'https://api.krawlet.cc')
80
+ baseUrl: 'https://api.krawlet.cc',
81
+
82
+ // Optional API key for authentication
83
+ apiKey: 'kraw_your_key_here',
84
+
85
+ // Request timeout in milliseconds (default: 30000)
86
+ timeout: 30000,
87
+
88
+ // Custom headers to include in all requests
89
+ headers: {
90
+ 'X-Custom-Header': 'value',
91
+ },
92
+
93
+ // Enable automatic retry on failure (default: true)
94
+ enableRetry: true,
95
+
96
+ // Maximum number of retries (default: 3)
97
+ maxRetries: 3,
98
+
99
+ // Initial retry delay in milliseconds (default: 1000)
100
+ retryDelay: 1000,
101
+ });
102
+ ```
103
+
104
+ ### Local Development
105
+
106
+ ```typescript
107
+ const client = new KrawletClient({
108
+ baseUrl: 'http://localhost:3330/api',
109
+ });
110
+ ```
111
+
112
+ ## API Reference
113
+
114
+ ### Health
115
+
116
+ Check API status and health.
117
+
118
+ ```typescript
119
+ // Basic health check
120
+ const health = await client.health.check();
121
+ console.log(health.status); // "ok"
122
+
123
+ // Detailed health check with system metrics
124
+ const detailed = await client.health.detailed();
125
+ console.log(detailed.status); // "healthy" | "degraded"
126
+ console.log(detailed.details.memory);
127
+ ```
128
+
129
+ ### Players
130
+
131
+ Retrieve player information.
132
+
133
+ ```typescript
134
+ // Get all players
135
+ const allPlayers = await client.players.getAll();
136
+
137
+ // Find by Kromer addresses
138
+ const byAddress = await client.players.getByAddresses(['ks0d5iqb6p', 'k12345678']);
139
+
140
+ // Find by Minecraft names (case-insensitive)
141
+ const byName = await client.players.getByNames(['Twijn', 'Player2']);
142
+
143
+ // Find by Minecraft UUIDs
144
+ const byUuid = await client.players.getByUuids([
145
+ 'd98440d6-5117-4ac8-bd50-70b086101e3e',
146
+ ]);
147
+ ```
148
+
149
+ ### Shops
150
+
151
+ Manage shop data and listings.
152
+
153
+ ```typescript
154
+ // Get all shops
155
+ const shops = await client.shops.getAll();
156
+
157
+ // Get a specific shop by ID
158
+ const shop = await client.shops.get('123');
159
+
160
+ // Get items for a shop
161
+ const items = await client.shops.getItems('123');
162
+
163
+ // Update a shop (requires ShopSync authentication)
164
+ const shopData = {
165
+ info: {
166
+ name: 'My Shop',
167
+ description: 'A great shop',
168
+ owner: 'PlayerName',
169
+ computerID: 123,
170
+ software: { name: 'ShopSync', version: '1.0.0' },
171
+ location: {
172
+ coordinates: [100, 64, -200],
173
+ description: 'Near spawn',
174
+ dimension: 'overworld',
175
+ },
176
+ },
177
+ items: [
178
+ {
179
+ item: {
180
+ name: 'minecraft:diamond',
181
+ displayName: 'Diamond',
182
+ },
183
+ stock: 64,
184
+ prices: [{ value: 10, currency: 'KST', address: 'ks0d5iqb6p' }],
185
+ },
186
+ ],
187
+ };
188
+
189
+ await client.shops.update(shopData, 'kraw_shopsync_token');
190
+ ```
191
+
192
+ ### Items
193
+
194
+ Retrieve item listings across all shops.
195
+
196
+ ```typescript
197
+ // Get all items with prices
198
+ const items = await client.items.getAll();
199
+
200
+ // Filter diamonds
201
+ const diamonds = items.filter(item => item.itemName === 'minecraft:diamond');
202
+ ```
203
+
204
+ ### Addresses
205
+
206
+ Get known Kromer addresses.
207
+
208
+ ```typescript
209
+ // Get all known addresses
210
+ const addresses = await client.addresses.getAll();
211
+
212
+ // Filter by type
213
+ const shops = addresses.filter(addr => addr.type === 'shop');
214
+ ```
215
+
216
+ ### Storage
217
+
218
+ Manage ender storage data (requires authentication).
219
+
220
+ ```typescript
221
+ // Get stored data
222
+ const data = await client.storage.get();
223
+ console.log(data.data);
224
+ console.log(data.retrievedAt);
225
+
226
+ // Store new data
227
+ const newData = {
228
+ items: [
229
+ { name: 'minecraft:diamond', quantity: 64 },
230
+ ],
231
+ };
232
+
233
+ await client.storage.set(newData, 'kraw_storage_token');
234
+ ```
235
+
236
+ ### Reports
237
+
238
+ Access ShopSync statistics and change logs.
239
+
240
+ ```typescript
241
+ // Get overall statistics
242
+ const stats = await client.reports.getStats();
243
+
244
+ // Get shop change logs with filters
245
+ const shopChanges = await client.reports.getShopChangeLogs({
246
+ shopId: '123',
247
+ since: '2026-01-01T00:00:00Z',
248
+ limit: 100,
249
+ offset: 0,
250
+ });
251
+
252
+ // Get item changes
253
+ const itemChanges = await client.reports.getItemChangeLogs({
254
+ shopId: '123',
255
+ limit: 50,
256
+ });
257
+
258
+ // Get price changes
259
+ const priceChanges = await client.reports.getPriceChangeLogs({
260
+ since: '2026-01-15T00:00:00Z',
261
+ until: '2026-01-20T00:00:00Z',
262
+ });
263
+
264
+ // Get validation failures
265
+ const failures = await client.reports.getValidationFailures({ limit: 10 });
266
+
267
+ // Get successful posts
268
+ const successes = await client.reports.getSuccessfulPosts({ limit: 10 });
269
+
270
+ // Get specific report
271
+ const report = await client.reports.get('report-id');
272
+ ```
273
+
274
+ ## Error Handling
275
+
276
+ The library provides a custom `KrawletError` class for API errors.
277
+
278
+ ```typescript
279
+ import { KrawletError, ErrorCode } from 'krawlet-js';
280
+
281
+ try {
282
+ await client.shops.get('nonexistent');
283
+ } catch (error) {
284
+ if (error instanceof KrawletError) {
285
+ console.error('Error code:', error.code);
286
+ console.error('Status code:', error.statusCode);
287
+ console.error('Request ID:', error.requestId);
288
+ console.error('Message:', error.message);
289
+
290
+ // Check error type
291
+ if (error.isClientError()) {
292
+ console.log('Client error (4xx)');
293
+ }
294
+
295
+ if (error.isServerError()) {
296
+ console.log('Server error (5xx)');
297
+ }
298
+
299
+ if (error.isRateLimitError()) {
300
+ console.log('Rate limit exceeded');
301
+ }
302
+
303
+ // Check specific error codes
304
+ if (error.code === ErrorCode.SHOP_NOT_FOUND) {
305
+ console.log('Shop does not exist');
306
+ }
307
+ }
308
+ }
309
+ ```
310
+
311
+ ### Error Codes
312
+
313
+ Common error codes:
314
+
315
+ - `BAD_REQUEST` - Invalid request
316
+ - `UNAUTHORIZED` - Missing or invalid authentication
317
+ - `FORBIDDEN` - Insufficient permissions
318
+ - `NOT_FOUND` - Resource not found
319
+ - `VALIDATION_ERROR` - Request validation failed
320
+ - `RATE_LIMIT_EXCEEDED` - Too many requests
321
+ - `SHOP_NOT_FOUND` - Shop doesn't exist
322
+ - `PLAYER_NOT_FOUND` - Player doesn't exist
323
+ - `INTERNAL_ERROR` - Server error
324
+ - `DATABASE_ERROR` - Database error
325
+
326
+ ## Rate Limiting
327
+
328
+ The API enforces rate limits based on authentication:
329
+
330
+ - **Anonymous**: 100 requests/hour
331
+ - **Free tier**: 1,000 requests/hour
332
+ - **Premium tier**: 5,000 requests/hour
333
+
334
+ Check your current rate limit status:
335
+
336
+ ```typescript
337
+ const shops = await client.shops.getAll();
338
+
339
+ const rateLimit = client.getRateLimit();
340
+ if (rateLimit) {
341
+ console.log(`${rateLimit.remaining}/${rateLimit.limit} requests remaining`);
342
+
343
+ const resetDate = new Date(rateLimit.reset * 1000);
344
+ console.log(`Resets at: ${resetDate.toISOString()}`);
345
+ }
346
+ ```
347
+
348
+ The client automatically retries requests when rate limits are exceeded with exponential backoff.
349
+
350
+ ## TypeScript Support
351
+
352
+ The library is written in TypeScript and provides full type definitions.
353
+
354
+ ```typescript
355
+ import type { Shop, Item, Player, KrawletError } from 'krawlet-js';
356
+
357
+ // All responses are fully typed
358
+ const shops: Shop[] = await client.shops.getAll();
359
+ const shop: Shop = shops[0];
360
+ const items: Item[] = shop.items;
361
+ ```
362
+
363
+ ## Examples
364
+
365
+ See the [examples](./examples) directory for more usage examples:
366
+
367
+ - [Basic Usage](./examples/usage.ts#basicUsage)
368
+ - [Player Lookup](./examples/usage.ts#playerLookup)
369
+ - [Shop Data](./examples/usage.ts#shopData)
370
+ - [Reports & Analytics](./examples/usage.ts#reports)
371
+ - [Error Handling](./examples/usage.ts#errorHandling)
372
+ - [Custom Configuration](./examples/usage.ts#customConfiguration)
373
+
374
+ ## Development
375
+
376
+ ```bash
377
+ # Install dependencies
378
+ pnpm install
379
+
380
+ # Build the library
381
+ pnpm run build
382
+
383
+ # Run tests
384
+ pnpm test
385
+
386
+ # Run tests with coverage
387
+ pnpm run test:coverage
388
+
389
+ # Lint code
390
+ pnpm run lint
391
+
392
+ # Format code
393
+ pnpm run format
394
+
395
+ # Development mode (watch for changes)
396
+ pnpm run dev
397
+ ```
398
+
399
+ ### Project Structure
400
+
401
+ ```
402
+ krawlet-js/
403
+ ├── src/
404
+ │ ├── resources/ # API resource classes
405
+ │ │ ├── health.ts
406
+ │ │ ├── players.ts
407
+ │ │ ├── shops.ts
408
+ │ │ ├── items.ts
409
+ │ │ ├── addresses.ts
410
+ │ │ ├── storage.ts
411
+ │ │ └── reports.ts
412
+ │ ├── __tests__/ # Unit tests
413
+ │ ├── client.ts # Main client class
414
+ │ ├── http-client.ts # HTTP client implementation
415
+ │ ├── error.ts # Error handling
416
+ │ ├── types.ts # TypeScript types
417
+ │ └── index.ts # Main entry point
418
+ ├── examples/ # Usage examples
419
+ └── dist/ # Built output
420
+ ```
421
+
422
+ ## License
423
+
424
+ ISC
425
+
426
+ ---
427
+
428
+ ## Links
429
+
430
+ - **API Documentation**: https://api.krawlet.cc
431
+ - **Production URL**: https://api.krawlet.cc
432
+ - **Local Dev URL**: http://localhost:3330/api
433
+
434
+ ## Contributing
435
+
436
+ Contributions are welcome! Please feel free to submit a Pull Request.