labelinn 1.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to the LabelInn Node.js SDK will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [1.1.0] - 2026-03-18
8
+
9
+ ### Added
10
+
11
+ - `ConnectResource` — universal data ingestion (XML, CSV, JSON, TSV, NDJSON)
12
+ - `connect.ingest()` — push data in any format
13
+ - `connect.testParse()` — dry-run parse without storing
14
+ - `connect.sources.create/list/get/update/delete()` — manage connector sources
15
+ - `connect.sources.records()` — list ingested records
16
+ - `connect.sources.schema()` — get auto-discovered schema
17
+ - `connect.sources.getMappings/updateMappings()` — field→label mappings
18
+ - `connect.sources.print()` — print labels from connector data
19
+ - CLI: `npx labelinn connect sources`, `connect ingest`, `connect parse`
20
+
21
+ ## [1.0.0] - 2026-03-30
22
+
23
+ ### Added
24
+
25
+ - Initial public release
26
+ - `PrintResource` — create, list, get, cancel, reprint print jobs
27
+ - `FleetResource` — list printers, get details, check status
28
+ - `DesignsResource` — full design CRUD, element management, variables, clone, render, print
29
+ - `WebhooksResource` — create, list, delete, test webhook subscriptions
30
+ - `LabelInnError` and `LabelInnRateLimitError` error classes
31
+ - Idempotency support via `X-Idempotency-Key` header
32
+ - Test mode detection (`sk_test_*` keys)
33
+ - Rate limit info on every response (`_rateLimit`)
34
+ - CLI tool: `npx labelinn test|printers|print|jobs|designs|webhooks`
35
+ - Full TypeScript type definitions
36
+ - Zero external dependencies (uses Node.js 18+ built-in `fetch`)
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LabelInn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,458 @@
1
+ # LabelInn Node.js SDK
2
+
3
+ [![npm version](https://img.shields.io/npm/v/labelinn.svg)](https://www.npmjs.com/package/labelinn)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
6
+
7
+ Official Node.js SDK for the [LabelInn](https://labelinn.com) Cloud Print API. Send labels to thermal printers (Zebra, TSC, Honeywell), manage your fleet, and build print automation workflows — all from code.
8
+
9
+ **Zero dependencies.** Uses Node.js 18+ built-in `fetch`.
10
+
11
+ ## Table of Contents
12
+
13
+ - [Installation](#installation)
14
+ - [Quick Start](#quick-start)
15
+ - [Authentication](#authentication)
16
+ - [Print Jobs](#print-jobs)
17
+ - [Fleet Management](#fleet-management)
18
+ - [Designs (Templates)](#designs-templates)
19
+ - [Webhooks](#webhooks)
20
+ - [Data Connect](#data-connect)
21
+ - [Rate Limits](#rate-limits)
22
+ - [Error Handling](#error-handling)
23
+ - [CLI Tool](#cli-tool)
24
+ - [Configuration](#configuration)
25
+ - [Requirements](#requirements)
26
+ - [Contributing](#contributing)
27
+ - [License](#license)
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ npm install labelinn
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ```js
38
+ const LabelInn = require('labelinn');
39
+
40
+ // Use a test key for development (no real prints, no quota cost)
41
+ const client = new LabelInn('sk_test_xxxxx');
42
+
43
+ // Print a ZPL label
44
+ const job = await client.print.create({
45
+ printer_id: 'prt_abc123',
46
+ payload_type: 'zpl',
47
+ payload_data: '^XA^FO50,50^ADN,36,20^FDHello World^FS^XZ',
48
+ });
49
+
50
+ console.log(`Job ${job.id} → ${job.status}`);
51
+ ```
52
+
53
+ ## Authentication
54
+
55
+ Get your API key from **LabelInn → Settings → API Keys**.
56
+
57
+ | Key prefix | Mode | Description |
58
+ |---------------|---------|------------------------------------|
59
+ | `sk_test_xxx` | Sandbox | No real prints, separate quota |
60
+ | `sk_live_xxx` | Live | Sends jobs to physical printers |
61
+
62
+ ```js
63
+ // Test mode — safe for development
64
+ const dev = new LabelInn('sk_test_xxxxx');
65
+ console.log(dev.isTestMode); // true
66
+
67
+ // Live mode — real prints
68
+ const prod = new LabelInn('sk_live_xxxxx');
69
+ ```
70
+
71
+ ## Print Jobs
72
+
73
+ ### Send a ZPL label
74
+ ```js
75
+ const job = await client.print.create({
76
+ printer_id: 'prt_abc123',
77
+ payload_type: 'zpl',
78
+ payload_data: '^XA^FO50,50^ADN,36,20^FDShipping Label^FS^XZ',
79
+ copies: 2,
80
+ job_name: 'Order #1234',
81
+ });
82
+ ```
83
+
84
+ ### Send an image label
85
+ ```js
86
+ // From a URL (HTTPS only, max 500KB)
87
+ const job = await client.print.create({
88
+ printer_id: 'prt_abc123',
89
+ payload_type: 'image',
90
+ image_url: 'https://example.com/labels/shipping.png',
91
+ });
92
+ ```
93
+
94
+ ### Print from a template
95
+ ```js
96
+ const job = await client.print.create({
97
+ printer_id: 'prt_abc123',
98
+ payload_type: 'template',
99
+ design_id: 'dsg_shipping_v2',
100
+ data: {
101
+ order_id: 'ORD-9876',
102
+ customer: 'Ali Yilmaz',
103
+ barcode: 'TR123456789',
104
+ },
105
+ });
106
+ ```
107
+
108
+ ### Idempotency (prevent duplicate prints)
109
+ ```js
110
+ const job = await client.print.create(
111
+ { printer_id: 'prt_abc123', payload_type: 'zpl', payload_data: '...' },
112
+ { idempotencyKey: 'order-9876-label' }
113
+ );
114
+ // Calling again with the same key returns the original job
115
+ ```
116
+
117
+ ### List & manage jobs
118
+ ```js
119
+ // List recent jobs
120
+ const { jobs } = await client.print.list({ limit: 10 });
121
+
122
+ // Filter by status
123
+ const { jobs: failed } = await client.print.list({ status: 'failed' });
124
+
125
+ // Get job details
126
+ const job = await client.print.get('job_abc123');
127
+
128
+ // Cancel a queued job
129
+ await client.print.cancel('job_abc123');
130
+
131
+ // Reprint with different printer
132
+ await client.print.reprint('job_abc123', { printer_id: 'prt_backup' });
133
+ ```
134
+
135
+ ## Fleet Management
136
+
137
+ ```js
138
+ // List all printers
139
+ const { printers } = await client.fleet.list();
140
+
141
+ // Filter by status
142
+ const { printers: online } = await client.fleet.list({ status: 'online' });
143
+
144
+ // Get printer details
145
+ const printer = await client.fleet.get('prt_abc123');
146
+
147
+ // Quick status check
148
+ const status = await client.fleet.status('prt_abc123');
149
+ console.log(`${status.status} — Paper: ${status.paper_status}`);
150
+ ```
151
+
152
+ ## Designs (Templates)
153
+
154
+ ```js
155
+ // List designs
156
+ const { designs } = await client.designs.list();
157
+
158
+ // Get design with elements
159
+ const design = await client.designs.get('dsg_abc123');
160
+
161
+ // Create a design
162
+ const newDesign = await client.designs.create({
163
+ name: 'Shipping Label v3',
164
+ width_mm: 100,
165
+ height_mm: 60,
166
+ });
167
+
168
+ // Add elements
169
+ await client.designs.addElement('dsg_abc123', {
170
+ type: 'text',
171
+ x: 10, y: 10,
172
+ text: '{{order_id}}',
173
+ font_size: 14,
174
+ });
175
+
176
+ await client.designs.addElement('dsg_abc123', {
177
+ type: 'barcode',
178
+ x: 10, y: 40,
179
+ barcode_type: 'code128',
180
+ data: '{{tracking_number}}',
181
+ });
182
+
183
+ // Clone a design
184
+ const clone = await client.designs.clone('dsg_abc123');
185
+
186
+ // Print directly from a design
187
+ await client.designs.print('dsg_abc123', {
188
+ printer_id: 'prt_abc123',
189
+ data: { order_id: 'ORD-5555', tracking_number: 'TR999' },
190
+ copies: 1,
191
+ });
192
+ ```
193
+
194
+ ## Webhooks
195
+
196
+ ```js
197
+ // Subscribe to events
198
+ const webhook = await client.webhooks.create({
199
+ url: 'https://yourapp.com/webhooks/labelinn',
200
+ events: ['print_job.completed', 'print_job.failed', 'printer.offline'],
201
+ description: 'Production monitoring',
202
+ });
203
+
204
+ // Save the signing secret!
205
+ console.log('Signing secret:', webhook.signing_secret);
206
+
207
+ // List subscriptions
208
+ const { webhooks } = await client.webhooks.list();
209
+
210
+ // Send a test ping
211
+ await client.webhooks.test(webhook.id);
212
+
213
+ // Unsubscribe
214
+ await client.webhooks.delete(webhook.id);
215
+ ```
216
+
217
+ ### Verifying webhook signatures
218
+
219
+ ```js
220
+ const crypto = require('crypto');
221
+
222
+ function verifyWebhook(payload, signature, secret) {
223
+ const expected = crypto
224
+ .createHmac('sha256', secret)
225
+ .update(payload)
226
+ .digest('hex');
227
+ return crypto.timingSafeEqual(
228
+ Buffer.from(signature),
229
+ Buffer.from(expected)
230
+ );
231
+ }
232
+
233
+ // In your Express handler:
234
+ app.post('/webhooks/labelinn', (req, res) => {
235
+ const signature = req.headers['x-labelinn-signature'];
236
+ const valid = verifyWebhook(JSON.stringify(req.body), signature, WEBHOOK_SECRET);
237
+ if (!valid) return res.status(401).send('Invalid signature');
238
+
239
+ const { event, data } = req.body;
240
+ console.log(`Event: ${event}`, data);
241
+ res.sendStatus(200);
242
+ });
243
+ ```
244
+
245
+ ## Data Connect
246
+
247
+ Data Connect lets you ingest data from any enterprise system (SAP, Oracle, CSV exports, custom APIs) and print labels from it. Supports XML/IDoc, CSV/TSV, and JSON/NDJSON formats with auto-detection.
248
+
249
+ ### Ingest Data
250
+
251
+ ```js
252
+ // From a JSON payload
253
+ const result = await client.connect.ingest({
254
+ source_id: 'src_abc123',
255
+ payload: JSON.stringify([
256
+ { sku: 'A001', name: 'Widget', qty: 10 },
257
+ { sku: 'A002', name: 'Gadget', qty: 5 },
258
+ ]),
259
+ format: 'json',
260
+ });
261
+ console.log(`Ingested ${result.records_count} records`);
262
+
263
+ // From XML/IDoc
264
+ const xmlResult = await client.connect.ingest({
265
+ source_id: 'src_sap',
266
+ payload: xmlString,
267
+ format: 'xml',
268
+ });
269
+ ```
270
+
271
+ ### Test Parse (Dry Run)
272
+
273
+ ```js
274
+ const parsed = await client.connect.testParse({
275
+ payload: csvString,
276
+ format: 'csv',
277
+ });
278
+ console.log(`Detected ${parsed.records.length} records`);
279
+ console.log('Schema:', parsed.schema.map(f => f.path));
280
+ ```
281
+
282
+ ### Manage Sources
283
+
284
+ ```js
285
+ // Create a source
286
+ const source = await client.connect.createSource({
287
+ name: 'SAP Orders',
288
+ format: 'xml',
289
+ });
290
+
291
+ // List all sources
292
+ const sources = await client.connect.listSources();
293
+
294
+ // Get source details
295
+ const detail = await client.connect.getSource('src_abc123');
296
+
297
+ // Update a source
298
+ await client.connect.updateSource('src_abc123', { name: 'SAP Orders v2' });
299
+
300
+ // Delete a source
301
+ await client.connect.deleteSource('src_abc123');
302
+ ```
303
+
304
+ ### Schema & Records
305
+
306
+ ```js
307
+ // Get detected schema
308
+ const schema = await client.connect.getSchema('src_abc123');
309
+ schema.fields.forEach(f => console.log(`${f.path} (${f.type}): ${f.sample}`));
310
+
311
+ // List ingested records
312
+ const records = await client.connect.listRecords('src_abc123', 50);
313
+ ```
314
+
315
+ ### Field Mappings
316
+
317
+ ```js
318
+ // Get current mappings
319
+ const mappings = await client.connect.getMappings('src_abc123');
320
+
321
+ // Update mappings
322
+ await client.connect.updateMappings('src_abc123', {
323
+ sku: 'product_code',
324
+ name: 'product_name',
325
+ });
326
+ ```
327
+
328
+ ### Print from Connector
329
+
330
+ ```js
331
+ const printResult = await client.connect.print({
332
+ source_id: 'src_abc123',
333
+ design_id: 'dsg_shipping',
334
+ printer_id: 'prt_warehouse1',
335
+ copies: 1,
336
+ });
337
+ console.log(`Created ${printResult.count} print jobs`);
338
+ ```
339
+
340
+ ## Rate Limits
341
+
342
+ Every response includes rate limit info:
343
+
344
+ ```js
345
+ const result = await client.print.list();
346
+ console.log(result._rateLimit);
347
+ // { limit: 2000, remaining: 1847, reset: 3600 }
348
+ ```
349
+
350
+ | Plan | Daily Limit |
351
+ |------------|-------------|
352
+ | Pro | 2,000 |
353
+ | Enterprise | 50,000 |
354
+ | Test keys | 500 minimum |
355
+
356
+ When rate-limited, the SDK throws `LabelInnRateLimitError`:
357
+
358
+ ```js
359
+ const { LabelInnRateLimitError } = require('labelinn');
360
+
361
+ try {
362
+ await client.print.create({ ... });
363
+ } catch (err) {
364
+ if (err instanceof LabelInnRateLimitError) {
365
+ console.log(`Rate limited. Retry in ${err.retryAfter}s`);
366
+ }
367
+ }
368
+ ```
369
+
370
+ ## Error Handling
371
+
372
+ ```js
373
+ const { LabelInnError } = require('labelinn');
374
+
375
+ try {
376
+ await client.print.create({ ... });
377
+ } catch (err) {
378
+ if (err instanceof LabelInnError) {
379
+ console.error(`[${err.status}] ${err.code}: ${err.message}`);
380
+ // err.raw contains the full response body
381
+ }
382
+ }
383
+ ```
384
+
385
+ ## CLI Tool
386
+
387
+ The SDK includes a CLI for quick testing:
388
+
389
+ ```bash
390
+ # Set your API key
391
+ export LABELINN_API_KEY=sk_test_xxxxx
392
+
393
+ # Verify connectivity
394
+ npx labelinn test
395
+
396
+ # List printers
397
+ npx labelinn printers
398
+
399
+ # Print a ZPL label
400
+ npx labelinn print prt_abc123 --zpl "^XA^FO50,50^ADN,36,20^FDHello^FS^XZ"
401
+
402
+ # Print from a template
403
+ npx labelinn print prt_abc123 --design dsg_shipping --data '{"name":"Ali"}'
404
+
405
+ # List jobs
406
+ npx labelinn jobs
407
+
408
+ # Get raw JSON output
409
+ npx labelinn printers --json
410
+
411
+ # --- Data Connect ---
412
+ # List connected data sources
413
+ npx labelinn connect sources
414
+
415
+ # Ingest data from a file
416
+ npx labelinn connect ingest conn_abc123 --file data.csv
417
+
418
+ # Test-parse a local file
419
+ npx labelinn connect parse --file data.csv --format csv
420
+ ```
421
+
422
+ Run `npx labelinn --help` for all commands.
423
+
424
+ ## Configuration
425
+
426
+ ```js
427
+ const client = new LabelInn('sk_test_xxxxx', {
428
+ baseUrl: 'https://labelinn.com/v1', // default
429
+ timeout: 30000, // 30s default
430
+ });
431
+ ```
432
+
433
+ ## Requirements
434
+
435
+ - Node.js 18+ (uses built-in `fetch`)
436
+ - No external dependencies
437
+
438
+ ## Contributing
439
+
440
+ Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/ArisHub/labelinn-node).
441
+
442
+ 1. Fork the repository
443
+ 2. Create your feature branch (`git checkout -b feature/my-feature`)
444
+ 3. Commit your changes (`git commit -am 'Add my feature'`)
445
+ 4. Push to the branch (`git push origin feature/my-feature`)
446
+ 5. Open a Pull Request
447
+
448
+ ## Links
449
+
450
+ - [LabelInn Website](https://labelinn.com)
451
+ - [API Documentation](https://labelinn.com/developers)
452
+ - [Python SDK](https://github.com/ArisHub/labelinn-python)
453
+ - [Changelog](./CHANGELOG.md)
454
+ - [Report a Bug](https://github.com/ArisHub/labelinn-node/issues)
455
+
456
+ ## License
457
+
458
+ MIT — see [LICENSE](./LICENSE) for details.