@licenseseat/js 0.1.0 → 0.2.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.
@@ -0,0 +1,321 @@
1
+ /**
2
+ * SDK Configuration options
3
+ */
4
+ export type LicenseSeatConfig = {
5
+ /**
6
+ * - Base URL for the LicenseSeat API
7
+ */
8
+ apiBaseUrl?: string;
9
+ /**
10
+ * - API key for authentication (required for most operations)
11
+ */
12
+ apiKey?: string;
13
+ /**
14
+ * - Prefix for localStorage keys
15
+ */
16
+ storagePrefix?: string;
17
+ /**
18
+ * - Interval in ms for automatic license validation (default: 1 hour)
19
+ */
20
+ autoValidateInterval?: number;
21
+ /**
22
+ * - Interval in ms to check network connectivity when offline (default: 30s)
23
+ */
24
+ networkRecheckInterval?: number;
25
+ /**
26
+ * - Maximum number of retry attempts for failed API calls
27
+ */
28
+ maxRetries?: number;
29
+ /**
30
+ * - Initial delay in ms between retries (exponential backoff applied)
31
+ */
32
+ retryDelay?: number;
33
+ /**
34
+ * - Enable debug logging to console
35
+ */
36
+ debug?: boolean;
37
+ /**
38
+ * - Interval in ms to refresh offline license (default: 72 hours)
39
+ */
40
+ offlineLicenseRefreshInterval?: number;
41
+ /**
42
+ * - Enable offline validation fallback on network errors
43
+ */
44
+ offlineFallbackEnabled?: boolean;
45
+ /**
46
+ * - Maximum days a license can be used offline (0 = disabled)
47
+ */
48
+ maxOfflineDays?: number;
49
+ /**
50
+ * - Maximum allowed clock skew in ms for offline validation (default: 5 minutes)
51
+ */
52
+ maxClockSkewMs?: number;
53
+ /**
54
+ * - Automatically initialize and validate cached license on construction
55
+ */
56
+ autoInitialize?: boolean;
57
+ };
58
+ /**
59
+ * License activation options
60
+ */
61
+ export type ActivationOptions = {
62
+ /**
63
+ * - Custom device identifier (auto-generated if not provided)
64
+ */
65
+ deviceIdentifier?: string;
66
+ /**
67
+ * - ISO8601 date string for version-aware activation
68
+ */
69
+ softwareReleaseDate?: string;
70
+ /**
71
+ * - Additional metadata to include with the activation
72
+ */
73
+ metadata?: any;
74
+ };
75
+ /**
76
+ * License validation options
77
+ */
78
+ export type ValidationOptions = {
79
+ /**
80
+ * - Device identifier to validate against
81
+ */
82
+ deviceIdentifier?: string;
83
+ /**
84
+ * - Product slug for product-specific validation
85
+ */
86
+ productSlug?: string;
87
+ };
88
+ /**
89
+ * Activation response from the API
90
+ */
91
+ export type ActivationResponse = {
92
+ /**
93
+ * - Activation ID
94
+ */
95
+ id: string;
96
+ /**
97
+ * - The activated license key
98
+ */
99
+ license_key: string;
100
+ /**
101
+ * - Device identifier used for activation
102
+ */
103
+ device_identifier: string;
104
+ /**
105
+ * - ISO8601 timestamp of activation
106
+ */
107
+ activated_at: string;
108
+ /**
109
+ * - Additional metadata
110
+ */
111
+ metadata?: any;
112
+ };
113
+ /**
114
+ * Cached license data
115
+ */
116
+ export type CachedLicense = {
117
+ /**
118
+ * - The license key
119
+ */
120
+ license_key: string;
121
+ /**
122
+ * - Device identifier
123
+ */
124
+ device_identifier: string;
125
+ /**
126
+ * - Original activation response
127
+ */
128
+ activation?: ActivationResponse;
129
+ /**
130
+ * - ISO8601 timestamp of activation
131
+ */
132
+ activated_at: string;
133
+ /**
134
+ * - ISO8601 timestamp of last validation
135
+ */
136
+ last_validated: string;
137
+ /**
138
+ * - Latest validation result
139
+ */
140
+ validation?: ValidationResult;
141
+ };
142
+ /**
143
+ * Entitlement object
144
+ */
145
+ export type Entitlement = {
146
+ /**
147
+ * - Unique entitlement key
148
+ */
149
+ key: string;
150
+ /**
151
+ * - Human-readable name
152
+ */
153
+ name: string | null;
154
+ /**
155
+ * - Description of the entitlement
156
+ */
157
+ description: string | null;
158
+ /**
159
+ * - ISO8601 expiration timestamp
160
+ */
161
+ expires_at: string | null;
162
+ /**
163
+ * - Additional metadata
164
+ */
165
+ metadata: any | null;
166
+ };
167
+ /**
168
+ * Validation result from API or offline verification
169
+ */
170
+ export type ValidationResult = {
171
+ /**
172
+ * - Whether the license is valid
173
+ */
174
+ valid: boolean;
175
+ /**
176
+ * - Whether this was an offline validation
177
+ */
178
+ offline?: boolean;
179
+ /**
180
+ * - Reason for invalid status (online)
181
+ */
182
+ reason?: string;
183
+ /**
184
+ * - Machine-readable reason code (offline)
185
+ */
186
+ reason_code?: string;
187
+ /**
188
+ * - List of active entitlements
189
+ */
190
+ active_entitlements?: Entitlement[];
191
+ /**
192
+ * - Whether this is an optimistic validation (pending server confirmation)
193
+ */
194
+ optimistic?: boolean;
195
+ };
196
+ /**
197
+ * Entitlement check result
198
+ */
199
+ export type EntitlementCheckResult = {
200
+ /**
201
+ * - Whether the entitlement is active
202
+ */
203
+ active: boolean;
204
+ /**
205
+ * - Reason if not active ("no_license" | "not_found" | "expired")
206
+ */
207
+ reason?: string;
208
+ /**
209
+ * - ISO8601 expiration timestamp if expired
210
+ */
211
+ expires_at?: string;
212
+ /**
213
+ * - Full entitlement object if active
214
+ */
215
+ entitlement?: Entitlement;
216
+ };
217
+ /**
218
+ * License status object
219
+ */
220
+ export type LicenseStatus = {
221
+ /**
222
+ * - Status string ("inactive" | "pending" | "invalid" | "offline-invalid" | "offline-valid" | "active")
223
+ */
224
+ status: string;
225
+ /**
226
+ * - Human-readable status message
227
+ */
228
+ message?: string;
229
+ /**
230
+ * - License key (if active)
231
+ */
232
+ license?: string;
233
+ /**
234
+ * - Device identifier (if active)
235
+ */
236
+ device?: string;
237
+ /**
238
+ * - ISO8601 activation timestamp
239
+ */
240
+ activated_at?: string;
241
+ /**
242
+ * - ISO8601 last validation timestamp
243
+ */
244
+ last_validated?: string;
245
+ /**
246
+ * - List of active entitlements
247
+ */
248
+ entitlements?: Entitlement[];
249
+ };
250
+ /**
251
+ * Offline license payload
252
+ */
253
+ export type OfflineLicensePayload = {
254
+ /**
255
+ * - License key
256
+ */
257
+ lic_k?: string;
258
+ /**
259
+ * - ISO8601 expiration timestamp
260
+ */
261
+ exp_at?: string;
262
+ /**
263
+ * - Key ID for signature verification
264
+ */
265
+ kid?: string;
266
+ /**
267
+ * - Active entitlements
268
+ */
269
+ active_ents?: Array<any>;
270
+ /**
271
+ * - Active entitlements (alternative key)
272
+ */
273
+ active_entitlements?: Array<any>;
274
+ /**
275
+ * - Additional metadata
276
+ */
277
+ metadata?: any;
278
+ };
279
+ /**
280
+ * Signed offline license data
281
+ */
282
+ export type SignedOfflineLicense = {
283
+ /**
284
+ * - The license payload
285
+ */
286
+ payload: OfflineLicensePayload;
287
+ /**
288
+ * - Base64URL-encoded Ed25519 signature
289
+ */
290
+ signature_b64u: string;
291
+ /**
292
+ * - Key ID for public key lookup
293
+ */
294
+ kid?: string;
295
+ };
296
+ /**
297
+ * Event callback function
298
+ */
299
+ export type EventCallback = (data: any) => void;
300
+ /**
301
+ * Event unsubscribe function
302
+ */
303
+ export type EventUnsubscribe = () => void;
304
+ /**
305
+ * API Error data
306
+ */
307
+ export type APIErrorData = {
308
+ /**
309
+ * - Error message
310
+ */
311
+ error?: string;
312
+ /**
313
+ * - Error code
314
+ */
315
+ code?: string;
316
+ /**
317
+ * - Additional error details
318
+ */
319
+ details?: any;
320
+ };
321
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.js"],"names":[],"mappings":";;;;;;;iBASc,MAAM;;;;aACN,MAAM;;;;oBACN,MAAM;;;;2BACN,MAAM;;;;6BACN,MAAM;;;;iBACN,MAAM;;;;iBACN,MAAM;;;;YACN,OAAO;;;;oCACP,MAAM;;;;6BACN,OAAO;;;;qBACP,MAAM;;;;qBACN,MAAM;;;;qBACN,OAAO;;;;;;;;;uBAMP,MAAM;;;;0BACN,MAAM;;;;;;;;;;;;;uBAON,MAAM;;;;kBACN,MAAM;;;;;;;;;QAMN,MAAM;;;;iBACN,MAAM;;;;uBACN,MAAM;;;;kBACN,MAAM;;;;;;;;;;;;;iBAON,MAAM;;;;uBACN,MAAM;;;;iBACN,kBAAkB;;;;kBAClB,MAAM;;;;oBACN,MAAM;;;;iBACN,gBAAgB;;;;;;;;;SAMhB,MAAM;;;;UACN,MAAM,GAAC,IAAI;;;;iBACX,MAAM,GAAC,IAAI;;;;gBACX,MAAM,GAAC,IAAI;;;;cACX,MAAO,IAAI;;;;;;;;;WAMX,OAAO;;;;cACP,OAAO;;;;aACP,MAAM;;;;kBACN,MAAM;;;;0BACN,WAAW,EAAE;;;;iBACb,OAAO;;;;;;;;;YAMP,OAAO;;;;aACP,MAAM;;;;iBACN,MAAM;;;;kBACN,WAAW;;;;;;;;;YAMX,MAAM;;;;cACN,MAAM;;;;cACN,MAAM;;;;aACN,MAAM;;;;mBACN,MAAM;;;;qBACN,MAAM;;;;mBACN,WAAW,EAAE;;;;;;;;;YAMb,MAAM;;;;aACN,MAAM;;;;UACN,MAAM;;;;kBACN,KAAK,KAAQ;;;;0BACb,KAAK,KAAQ;;;;;;;;;;;;;aAOb,qBAAqB;;;;oBACrB,MAAM;;;;UACN,MAAM;;;;;mCAMT,GAAC,KACC,IAAI;;;;qCAMJ,IAAI;;;;;;;;YAMH,MAAM;;;;WACN,MAAM"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Parse active entitlements from a raw API payload into a consistent shape
3
+ * @param {Object} [payload={}] - Raw payload from API or offline license
4
+ * @returns {import('./types.js').Entitlement[]} Normalized entitlements array
5
+ */
6
+ export function parseActiveEntitlements(payload?: any): import("./types.js").Entitlement[];
7
+ /**
8
+ * Constant-time string comparison to mitigate timing attacks
9
+ * @param {string} [a=""] - First string
10
+ * @param {string} [b=""] - Second string
11
+ * @returns {boolean} True if strings are equal
12
+ */
13
+ export function constantTimeEqual(a?: string, b?: string): boolean;
14
+ /**
15
+ * Generate a canonical JSON string from an object (keys sorted)
16
+ * This is crucial for consistent signature verification.
17
+ * @param {Object} obj - The object to stringify
18
+ * @returns {string} Canonical JSON string
19
+ */
20
+ export function canonicalJsonStringify(obj: any): string;
21
+ /**
22
+ * Decode a Base64URL string to a Uint8Array
23
+ * @param {string} base64UrlString - The Base64URL encoded string
24
+ * @returns {Uint8Array} Decoded bytes
25
+ */
26
+ export function base64UrlDecode(base64UrlString: string): Uint8Array;
27
+ /**
28
+ * Simple hash function for generating device fingerprints
29
+ * @param {string} str - String to hash
30
+ * @returns {string} Base36 encoded hash
31
+ */
32
+ export function hashCode(str: string): string;
33
+ /**
34
+ * Get canvas fingerprint for device identification
35
+ * @returns {string} Canvas fingerprint or "no-canvas" if unavailable
36
+ */
37
+ export function getCanvasFingerprint(): string;
38
+ /**
39
+ * Generate a unique device identifier based on browser characteristics
40
+ * @returns {string} Unique device identifier
41
+ */
42
+ export function generateDeviceId(): string;
43
+ /**
44
+ * Sleep for a specified duration
45
+ * @param {number} ms - Duration in milliseconds
46
+ * @returns {Promise<void>} Resolves after the specified duration
47
+ */
48
+ export function sleep(ms: number): Promise<void>;
49
+ /**
50
+ * Get CSRF token from meta tag (for browser form submissions)
51
+ * @returns {string} CSRF token or empty string if not found
52
+ */
53
+ export function getCsrfToken(): string;
54
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,wDAFa,OAAO,YAAY,EAAE,WAAW,EAAE,CAW9C;AAED;;;;;GAKG;AACH,sCAJW,MAAM,MACN,MAAM,GACJ,OAAO,CASnB;AAED;;;;;GAKG;AACH,kDAFa,MAAM,CAuBlB;AAED;;;;GAIG;AACH,iDAHW,MAAM,GACJ,UAAU,CAatB;AAED;;;;GAIG;AACH,8BAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;GAGG;AACH,wCAFa,MAAM,CAalB;AAED;;;GAGG;AACH,oCAFa,MAAM,CAgBlB;AAED;;;;GAIG;AACH,0BAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAIzB;AAED;;;GAGG;AACH,gCAFa,MAAM,CAMlB"}
package/package.json CHANGED
@@ -1,49 +1,85 @@
1
1
  {
2
2
  "name": "@licenseseat/js",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Official JavaScript SDK for LicenseSeat – simple, secure software licensing.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
7
+ "types": "dist/types/index.d.ts",
7
8
  "exports": {
8
- "import": "./dist/index.js"
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/types/index.d.ts"
12
+ }
9
13
  },
10
14
  "files": [
11
- "dist/"
15
+ "dist/",
16
+ "src/"
12
17
  ],
13
18
  "type": "module",
19
+ "sideEffects": false,
14
20
  "scripts": {
15
- "build": "esbuild src/index.js --bundle --format=esm --outfile=dist/index.js",
21
+ "build": "npm run build:js && npm run build:types",
22
+ "build:js": "esbuild src/index.js --bundle --format=esm --outfile=dist/index.js --external:@noble/ed25519 --external:@noble/hashes --external:canonical-json",
23
+ "build:bundle": "esbuild src/index.js --bundle --format=esm --outfile=dist/index.bundled.js",
24
+ "build:types": "tsc --project tsconfig.json",
25
+ "build:iife": "esbuild src/index.js --bundle --format=iife --global-name=LicenseSeat --outfile=dist/index.global.js",
16
26
  "dev": "esbuild src/index.js --bundle --format=esm --outfile=dist/index.js --watch",
17
- "test": "echo \"No tests yet\""
27
+ "typecheck": "tsc --noEmit",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "test:coverage": "vitest run --coverage",
31
+ "lint": "eslint src/",
32
+ "prepublishOnly": "npm run build"
18
33
  },
19
34
  "keywords": [
20
35
  "licensing",
21
36
  "licenseseat",
22
37
  "sdk",
23
38
  "javascript",
39
+ "typescript",
24
40
  "js",
41
+ "ts",
25
42
  "software licensing",
26
43
  "license manager",
27
44
  "licensing server",
28
45
  "license key",
29
- "api client"
46
+ "api client",
47
+ "license validation",
48
+ "offline licensing",
49
+ "entitlements"
30
50
  ],
31
51
  "repository": {
32
52
  "type": "git",
33
53
  "url": "https://github.com/licenseseat/licenseseat-js.git"
34
54
  },
35
- "author": "rameerez",
55
+ "author": "LicenseSeat <hello@licenseseat.com>",
36
56
  "license": "MIT",
37
57
  "bugs": {
38
58
  "url": "https://github.com/licenseseat/licenseseat-js/issues"
39
59
  },
40
60
  "homepage": "https://licenseseat.com",
61
+ "engines": {
62
+ "node": ">=18.0.0"
63
+ },
41
64
  "devDependencies": {
42
- "esbuild": "^0.20.2"
65
+ "@vitest/coverage-v8": "^1.6.0",
66
+ "esbuild": "^0.20.2",
67
+ "jsdom": "^24.1.3",
68
+ "msw": "^2.3.0",
69
+ "typescript": "^5.4.0",
70
+ "vitest": "^1.6.0"
43
71
  },
44
72
  "dependencies": {
45
73
  "@noble/ed25519": "^2.3.0",
46
74
  "@noble/hashes": "^1.8.0",
47
75
  "canonical-json": "^0.2.0"
76
+ },
77
+ "peerDependencies": {
78
+ "typescript": ">=4.7.0"
79
+ },
80
+ "peerDependenciesMeta": {
81
+ "typescript": {
82
+ "optional": true
83
+ }
48
84
  }
49
85
  }