@moonbase.sh/licensing 1.0.32 → 1.0.34

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 CHANGED
@@ -23,6 +23,13 @@ const licensing = new MoonbaseLicensing({
23
23
  publicKey: process.env.MOONBASE_PUBLIC_KEY!,
24
24
  accountId: process.env.MOONBASE_ACCOUNT_ID,
25
25
 
26
+ // Optional analytics reported with every activation and validation.
27
+ appVersion: '1.2.3',
28
+ metadata: {
29
+ Host: 'Console',
30
+ User: process.env.USER ?? '',
31
+ },
32
+
26
33
  // Optionally adjust the license store with path
27
34
  // to where the license should be stored, or use
28
35
  // alternate storage mechanisms to persist the token.
@@ -65,6 +72,18 @@ if (localLicense) {
65
72
  }
66
73
  ```
67
74
 
75
+ ## Metadata, platform, and app version
76
+
77
+ The SDK can report analytics with every activation, trial request, and validation. These are configured once on the `MoonbaseLicensing` config and sent automatically — there's no per-call parameter.
78
+
79
+ - `appVersion` and `platform` are first-class fields and sent as plain query params. `metadata` is for arbitrary customer-defined keys, sent as `meta[key]=value`.
80
+ - `platform` auto-detects from `process.platform` (`darwin` → `Mac`, `win32` → `Windows`, `linux` → `Linux`). Set it explicitly to override, or pass `null` to suppress.
81
+ - All three are sent on `requestActivation`, `requestTrial`, and `validateLicense` — never on `revokeLicense`.
82
+ - `metadata` accepts string keys and string values only; empty values are dropped client-side.
83
+ - Server-side, the metadata on the activation is **replaced on every call** (not merged) and surfaced in `LicenseActivatedEvent` / `LicenseValidatedEvent` webhooks.
84
+ - The config object is re-read on every call — mutate `metadata` between calls (e.g. to rotate a session id) and the next request picks it up.
85
+ - Keep payloads small; query-string length limits apply.
86
+
68
87
  ## Revoke a license activation
69
88
 
70
89
  ```ts
package/dist/index.cjs CHANGED
@@ -107,7 +107,7 @@ var LicenseClient = class {
107
107
  deviceName: await this.deviceIdResolver.resolveDeviceName(),
108
108
  deviceSignature: await this.deviceIdResolver.resolveDeviceId()
109
109
  };
110
- const response = await (0, import_cross_fetch.default)(this.configuration.endpoint + `/api/client/activations/${this.configuration.productId}/request?format=JWT`, {
110
+ const response = await (0, import_cross_fetch.default)(this.configuration.endpoint + `/api/client/activations/${this.configuration.productId}/request${this.buildQueryString()}`, {
111
111
  ...defaultFetchOptions,
112
112
  method: "POST",
113
113
  body: JSON.stringify(content)
@@ -137,7 +137,7 @@ var LicenseClient = class {
137
137
  deviceName: await this.deviceIdResolver.resolveDeviceName(),
138
138
  deviceSignature: await this.deviceIdResolver.resolveDeviceId()
139
139
  };
140
- const response = await (0, import_cross_fetch.default)(this.configuration.endpoint + `/api/client/trials/${this.configuration.productId}/request?format=JWT`, {
140
+ const response = await (0, import_cross_fetch.default)(this.configuration.endpoint + `/api/client/trials/${this.configuration.productId}/request${this.buildQueryString()}`, {
141
141
  ...defaultFetchOptions,
142
142
  method: "POST",
143
143
  headers: {
@@ -149,7 +149,7 @@ var LicenseClient = class {
149
149
  return await this.handleLicenseResponse(response);
150
150
  }
151
151
  async validateLicense(license) {
152
- const response = await (0, import_cross_fetch.default)(this.configuration.endpoint + `/api/client/licenses/${this.configuration.productId}/validate?format=JWT`, {
152
+ const response = await (0, import_cross_fetch.default)(this.configuration.endpoint + `/api/client/licenses/${this.configuration.productId}/validate${this.buildQueryString()}`, {
153
153
  ...defaultFetchOptions,
154
154
  method: "POST",
155
155
  headers: {
@@ -185,6 +185,19 @@ var LicenseClient = class {
185
185
  }
186
186
  return await this.licenseValidator.validateLicense(await response.text());
187
187
  }
188
+ buildQueryString() {
189
+ const parts = ["format=JWT"];
190
+ const { platform, appVersion, metadata } = this.configuration;
191
+ if (platform) parts.push(`platform=${encodeURIComponent(platform)}`);
192
+ if (appVersion) parts.push(`appVersion=${encodeURIComponent(appVersion)}`);
193
+ if (metadata) {
194
+ for (const [key, value] of Object.entries(metadata)) {
195
+ if (value === null || value === void 0 || value === "") continue;
196
+ parts.push(`meta[${encodeURIComponent(key)}]=${encodeURIComponent(value)}`);
197
+ }
198
+ }
199
+ return `?${parts.join("&")}`;
200
+ }
188
201
  };
189
202
 
190
203
  // src/deviceIdResolver.ts
@@ -412,12 +425,26 @@ var LicenseValidator = class {
412
425
  };
413
426
 
414
427
  // src/index.ts
428
+ function detectPlatform() {
429
+ if (typeof process === "undefined") return void 0;
430
+ switch (process.platform) {
431
+ case "darwin":
432
+ return "Mac";
433
+ case "win32":
434
+ return "Windows";
435
+ case "linux":
436
+ return "Linux";
437
+ default:
438
+ return void 0;
439
+ }
440
+ }
415
441
  var MoonbaseLicensing = class {
416
442
  constructor(configuration) {
417
443
  var _a, _b;
418
444
  this.configuration = {
419
445
  ...configuration,
420
- endpoint: configuration.endpoint.replace(/\/$/, "")
446
+ endpoint: configuration.endpoint.replace(/\/$/, ""),
447
+ platform: configuration.platform === void 0 ? detectPlatform() : configuration.platform
421
448
  };
422
449
  this.store = (_a = configuration.licenseStore) != null ? _a : new InMemoryLicenseStore();
423
450
  this.deviceIdResolver = (_b = configuration.deivceIdResolver) != null ? _b : new DefaultDeviceIdResolver();
package/dist/index.d.cts CHANGED
@@ -149,6 +149,8 @@ declare enum ActivationMethod {
149
149
  Online = "Online",
150
150
  Offline = "Offline"
151
151
  }
152
+ type Metadata = Record<string, string>;
153
+ type Platform = 'Windows' | 'Linux' | 'Mac';
152
154
  type License = z.infer<typeof licenseSchema>;
153
155
  type Product = z.infer<typeof productSchema>;
154
156
  type User = z.infer<typeof userSchema>;
@@ -233,6 +235,7 @@ declare class LicenseClient implements ILicenseClient {
233
235
  validateRawLicense(rawLicense: Buffer): Promise<License>;
234
236
  revokeLicense(license: License): Promise<void>;
235
237
  private handleLicenseResponse;
238
+ private buildQueryString;
236
239
  }
237
240
 
238
241
  interface ILicenseStore {
@@ -291,6 +294,29 @@ interface MoonbaseConfiguration {
291
294
  publicKey: string;
292
295
  productId: string;
293
296
  accountId?: string;
297
+ /**
298
+ * Optional analytics key/value pairs sent with every activation,
299
+ * trial request, and license validation. Recorded on the activation
300
+ * server-side and surfaced in LicenseActivatedEvent /
301
+ * LicenseValidatedEvent webhooks. Strings only; empty values are
302
+ * dropped on the wire. The object is re-read on every call, so
303
+ * mutating it (e.g. to rotate a sessionId) takes effect on the
304
+ * next request.
305
+ */
306
+ metadata?: Metadata;
307
+ /**
308
+ * Reported as ?platform=... on activation, trial, and validation
309
+ * requests. Defaults to auto-detection from `process.platform`
310
+ * (`darwin` → `Mac`, `win32` → `Windows`, `linux` → `Linux`). Set
311
+ * explicitly to override, or pass `null` to suppress.
312
+ */
313
+ platform?: Platform | null;
314
+ /**
315
+ * Reported as ?appVersion=... (semver expected by backend). No
316
+ * reliable auto-detection in Node, so callers must set this
317
+ * explicitly to opt in.
318
+ */
319
+ appVersion?: string;
294
320
  licenseStore?: ILicenseStore;
295
321
  deivceIdResolver?: IDeviceIdResolver;
296
322
  }
@@ -305,4 +331,4 @@ declare class MoonbaseLicensing {
305
331
  readRawLicense(license: Buffer): Promise<License>;
306
332
  }
307
333
 
308
- export { ActivationMethod, type ActivationRequestResponse, DefaultDeviceIdResolver, type DeviceToken, ErrorType, FileLicenseStore, type IDeviceIdResolver, type ILicenseClient, type ILicenseStore, type ILicenseValidator, InMemoryLicenseStore, type License, LicenseClient, LicenseValidator, type MoonbaseConfiguration, MoonbaseError, MoonbaseLicensing, type Product, type User };
334
+ export { ActivationMethod, type ActivationRequestResponse, DefaultDeviceIdResolver, type DeviceToken, ErrorType, FileLicenseStore, type IDeviceIdResolver, type ILicenseClient, type ILicenseStore, type ILicenseValidator, InMemoryLicenseStore, type License, LicenseClient, LicenseValidator, type Metadata, type MoonbaseConfiguration, MoonbaseError, MoonbaseLicensing, type Platform, type Product, type User };
package/dist/index.d.ts CHANGED
@@ -149,6 +149,8 @@ declare enum ActivationMethod {
149
149
  Online = "Online",
150
150
  Offline = "Offline"
151
151
  }
152
+ type Metadata = Record<string, string>;
153
+ type Platform = 'Windows' | 'Linux' | 'Mac';
152
154
  type License = z.infer<typeof licenseSchema>;
153
155
  type Product = z.infer<typeof productSchema>;
154
156
  type User = z.infer<typeof userSchema>;
@@ -233,6 +235,7 @@ declare class LicenseClient implements ILicenseClient {
233
235
  validateRawLicense(rawLicense: Buffer): Promise<License>;
234
236
  revokeLicense(license: License): Promise<void>;
235
237
  private handleLicenseResponse;
238
+ private buildQueryString;
236
239
  }
237
240
 
238
241
  interface ILicenseStore {
@@ -291,6 +294,29 @@ interface MoonbaseConfiguration {
291
294
  publicKey: string;
292
295
  productId: string;
293
296
  accountId?: string;
297
+ /**
298
+ * Optional analytics key/value pairs sent with every activation,
299
+ * trial request, and license validation. Recorded on the activation
300
+ * server-side and surfaced in LicenseActivatedEvent /
301
+ * LicenseValidatedEvent webhooks. Strings only; empty values are
302
+ * dropped on the wire. The object is re-read on every call, so
303
+ * mutating it (e.g. to rotate a sessionId) takes effect on the
304
+ * next request.
305
+ */
306
+ metadata?: Metadata;
307
+ /**
308
+ * Reported as ?platform=... on activation, trial, and validation
309
+ * requests. Defaults to auto-detection from `process.platform`
310
+ * (`darwin` → `Mac`, `win32` → `Windows`, `linux` → `Linux`). Set
311
+ * explicitly to override, or pass `null` to suppress.
312
+ */
313
+ platform?: Platform | null;
314
+ /**
315
+ * Reported as ?appVersion=... (semver expected by backend). No
316
+ * reliable auto-detection in Node, so callers must set this
317
+ * explicitly to opt in.
318
+ */
319
+ appVersion?: string;
294
320
  licenseStore?: ILicenseStore;
295
321
  deivceIdResolver?: IDeviceIdResolver;
296
322
  }
@@ -305,4 +331,4 @@ declare class MoonbaseLicensing {
305
331
  readRawLicense(license: Buffer): Promise<License>;
306
332
  }
307
333
 
308
- export { ActivationMethod, type ActivationRequestResponse, DefaultDeviceIdResolver, type DeviceToken, ErrorType, FileLicenseStore, type IDeviceIdResolver, type ILicenseClient, type ILicenseStore, type ILicenseValidator, InMemoryLicenseStore, type License, LicenseClient, LicenseValidator, type MoonbaseConfiguration, MoonbaseError, MoonbaseLicensing, type Product, type User };
334
+ export { ActivationMethod, type ActivationRequestResponse, DefaultDeviceIdResolver, type DeviceToken, ErrorType, FileLicenseStore, type IDeviceIdResolver, type ILicenseClient, type ILicenseStore, type ILicenseValidator, InMemoryLicenseStore, type License, LicenseClient, LicenseValidator, type Metadata, type MoonbaseConfiguration, MoonbaseError, MoonbaseLicensing, type Platform, type Product, type User };
package/dist/index.js CHANGED
@@ -63,7 +63,7 @@ var LicenseClient = class {
63
63
  deviceName: await this.deviceIdResolver.resolveDeviceName(),
64
64
  deviceSignature: await this.deviceIdResolver.resolveDeviceId()
65
65
  };
66
- const response = await fetch(this.configuration.endpoint + `/api/client/activations/${this.configuration.productId}/request?format=JWT`, {
66
+ const response = await fetch(this.configuration.endpoint + `/api/client/activations/${this.configuration.productId}/request${this.buildQueryString()}`, {
67
67
  ...defaultFetchOptions,
68
68
  method: "POST",
69
69
  body: JSON.stringify(content)
@@ -93,7 +93,7 @@ var LicenseClient = class {
93
93
  deviceName: await this.deviceIdResolver.resolveDeviceName(),
94
94
  deviceSignature: await this.deviceIdResolver.resolveDeviceId()
95
95
  };
96
- const response = await fetch(this.configuration.endpoint + `/api/client/trials/${this.configuration.productId}/request?format=JWT`, {
96
+ const response = await fetch(this.configuration.endpoint + `/api/client/trials/${this.configuration.productId}/request${this.buildQueryString()}`, {
97
97
  ...defaultFetchOptions,
98
98
  method: "POST",
99
99
  headers: {
@@ -105,7 +105,7 @@ var LicenseClient = class {
105
105
  return await this.handleLicenseResponse(response);
106
106
  }
107
107
  async validateLicense(license) {
108
- const response = await fetch(this.configuration.endpoint + `/api/client/licenses/${this.configuration.productId}/validate?format=JWT`, {
108
+ const response = await fetch(this.configuration.endpoint + `/api/client/licenses/${this.configuration.productId}/validate${this.buildQueryString()}`, {
109
109
  ...defaultFetchOptions,
110
110
  method: "POST",
111
111
  headers: {
@@ -141,6 +141,19 @@ var LicenseClient = class {
141
141
  }
142
142
  return await this.licenseValidator.validateLicense(await response.text());
143
143
  }
144
+ buildQueryString() {
145
+ const parts = ["format=JWT"];
146
+ const { platform, appVersion, metadata } = this.configuration;
147
+ if (platform) parts.push(`platform=${encodeURIComponent(platform)}`);
148
+ if (appVersion) parts.push(`appVersion=${encodeURIComponent(appVersion)}`);
149
+ if (metadata) {
150
+ for (const [key, value] of Object.entries(metadata)) {
151
+ if (value === null || value === void 0 || value === "") continue;
152
+ parts.push(`meta[${encodeURIComponent(key)}]=${encodeURIComponent(value)}`);
153
+ }
154
+ }
155
+ return `?${parts.join("&")}`;
156
+ }
144
157
  };
145
158
 
146
159
  // src/deviceIdResolver.ts
@@ -368,12 +381,26 @@ var LicenseValidator = class {
368
381
  };
369
382
 
370
383
  // src/index.ts
384
+ function detectPlatform() {
385
+ if (typeof process === "undefined") return void 0;
386
+ switch (process.platform) {
387
+ case "darwin":
388
+ return "Mac";
389
+ case "win32":
390
+ return "Windows";
391
+ case "linux":
392
+ return "Linux";
393
+ default:
394
+ return void 0;
395
+ }
396
+ }
371
397
  var MoonbaseLicensing = class {
372
398
  constructor(configuration) {
373
399
  var _a, _b;
374
400
  this.configuration = {
375
401
  ...configuration,
376
- endpoint: configuration.endpoint.replace(/\/$/, "")
402
+ endpoint: configuration.endpoint.replace(/\/$/, ""),
403
+ platform: configuration.platform === void 0 ? detectPlatform() : configuration.platform
377
404
  };
378
405
  this.store = (_a = configuration.licenseStore) != null ? _a : new InMemoryLicenseStore();
379
406
  this.deviceIdResolver = (_b = configuration.deivceIdResolver) != null ? _b : new DefaultDeviceIdResolver();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonbase.sh/licensing",
3
3
  "type": "module",
4
- "version": "1.0.32",
4
+ "version": "1.0.34",
5
5
  "description": "Package to add sotftware licensing using Moonbase.sh to your node.js apps",
6
6
  "author": "Tobias Lønnerød Madsen <m@dsen.tv>",
7
7
  "license": "MIT",