@nice2dev/licensing 1.1.6 → 1.1.9

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.
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
2
3
  const SEGMENT_LENGTH = 4;
3
4
  const NUM_SEGMENTS = 5;
4
5
  const KEY_CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
@@ -1365,7 +1366,61 @@ function initializeDefaults() {
1365
1366
  registerPlans(DEFAULT_PLANS);
1366
1367
  }
1367
1368
  initializeDefaults();
1369
+ const CheckMark = ({ style }) => /* @__PURE__ */ jsxRuntime.jsx(
1370
+ "span",
1371
+ {
1372
+ "aria-hidden": "true",
1373
+ style: {
1374
+ display: "inline-block",
1375
+ width: "0.3em",
1376
+ height: "0.6em",
1377
+ margin: "0 0.35em 0.15em 0.1em",
1378
+ borderRight: "0.12em solid currentColor",
1379
+ borderBottom: "0.12em solid currentColor",
1380
+ transform: "rotate(45deg)",
1381
+ ...style
1382
+ }
1383
+ }
1384
+ );
1385
+ const RefreshMark = ({ style }) => /* @__PURE__ */ jsxRuntime.jsx(
1386
+ "span",
1387
+ {
1388
+ "aria-hidden": "true",
1389
+ style: {
1390
+ display: "inline-block",
1391
+ width: "0.85em",
1392
+ height: "0.85em",
1393
+ borderRadius: "50%",
1394
+ border: "0.12em solid currentColor",
1395
+ borderTopColor: "transparent",
1396
+ transform: "rotate(-45deg)",
1397
+ ...style
1398
+ }
1399
+ }
1400
+ );
1401
+ const ChevronMark = ({
1402
+ direction,
1403
+ style
1404
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
1405
+ "span",
1406
+ {
1407
+ "aria-hidden": "true",
1408
+ style: {
1409
+ display: "inline-block",
1410
+ width: "0.45em",
1411
+ height: "0.45em",
1412
+ margin: direction === "down" ? "0 0 0.2em" : "0.2em 0 0",
1413
+ borderRight: "0.12em solid currentColor",
1414
+ borderBottom: "0.12em solid currentColor",
1415
+ transform: direction === "down" ? "rotate(45deg)" : "rotate(-135deg)",
1416
+ ...style
1417
+ }
1418
+ }
1419
+ );
1420
+ exports.CheckMark = CheckMark;
1421
+ exports.ChevronMark = ChevronMark;
1368
1422
  exports.LicenseValidator = LicenseValidator;
1423
+ exports.RefreshMark = RefreshMark;
1369
1424
  exports.checkFeatureAccess = checkFeatureAccess;
1370
1425
  exports.collectFingerprintData = collectFingerprintData;
1371
1426
  exports.compareFingerprintsData = compareFingerprintsData;
@@ -1,3 +1,4 @@
1
+ import { jsx } from "react/jsx-runtime";
1
2
  const SEGMENT_LENGTH = 4;
2
3
  const NUM_SEGMENTS = 5;
3
4
  const KEY_CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
@@ -1364,18 +1365,72 @@ function initializeDefaults() {
1364
1365
  registerPlans(DEFAULT_PLANS);
1365
1366
  }
1366
1367
  initializeDefaults();
1368
+ const CheckMark = ({ style }) => /* @__PURE__ */ jsx(
1369
+ "span",
1370
+ {
1371
+ "aria-hidden": "true",
1372
+ style: {
1373
+ display: "inline-block",
1374
+ width: "0.3em",
1375
+ height: "0.6em",
1376
+ margin: "0 0.35em 0.15em 0.1em",
1377
+ borderRight: "0.12em solid currentColor",
1378
+ borderBottom: "0.12em solid currentColor",
1379
+ transform: "rotate(45deg)",
1380
+ ...style
1381
+ }
1382
+ }
1383
+ );
1384
+ const RefreshMark = ({ style }) => /* @__PURE__ */ jsx(
1385
+ "span",
1386
+ {
1387
+ "aria-hidden": "true",
1388
+ style: {
1389
+ display: "inline-block",
1390
+ width: "0.85em",
1391
+ height: "0.85em",
1392
+ borderRadius: "50%",
1393
+ border: "0.12em solid currentColor",
1394
+ borderTopColor: "transparent",
1395
+ transform: "rotate(-45deg)",
1396
+ ...style
1397
+ }
1398
+ }
1399
+ );
1400
+ const ChevronMark = ({
1401
+ direction,
1402
+ style
1403
+ }) => /* @__PURE__ */ jsx(
1404
+ "span",
1405
+ {
1406
+ "aria-hidden": "true",
1407
+ style: {
1408
+ display: "inline-block",
1409
+ width: "0.45em",
1410
+ height: "0.45em",
1411
+ margin: direction === "down" ? "0 0 0.2em" : "0.2em 0 0",
1412
+ borderRight: "0.12em solid currentColor",
1413
+ borderBottom: "0.12em solid currentColor",
1414
+ transform: direction === "down" ? "rotate(45deg)" : "rotate(-135deg)",
1415
+ ...style
1416
+ }
1417
+ }
1418
+ );
1367
1419
  export {
1368
1420
  initializeDefaults as A,
1369
1421
  isFeatureLicensed as B,
1370
- maskLicenseKey as C,
1371
- normalizeLicenseKey as D,
1372
- registerFeature as E,
1373
- registerFeatures as F,
1374
- registerPlan as G,
1375
- registerPlans as H,
1376
- storeFingerprint as I,
1377
- validateLicense as J,
1422
+ CheckMark as C,
1423
+ maskLicenseKey as D,
1424
+ normalizeLicenseKey as E,
1425
+ registerFeature as F,
1426
+ registerFeatures as G,
1427
+ registerPlan as H,
1428
+ registerPlans as I,
1429
+ storeFingerprint as J,
1430
+ validateLicense as K,
1378
1431
  LicenseValidator as L,
1432
+ ChevronMark as M,
1433
+ RefreshMark as R,
1379
1434
  generateFingerprint as a,
1380
1435
  collectFingerprintData as b,
1381
1436
  checkFeatureAccess as c,
package/dist/react.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
- const FeatureGate$1 = require("./FeatureGate-9rvyns7j.cjs");
5
+ const marks = require("./marks-KVqpGsfU.cjs");
6
6
  const LicenseContext = React.createContext(null);
7
7
  function LicenseProvider({
8
8
  serverUrl = "https://license.nice2dev.com/api/v1",
@@ -24,7 +24,7 @@ function LicenseProvider({
24
24
  features: /* @__PURE__ */ new Set(),
25
25
  fingerprint: null
26
26
  });
27
- const [validator] = React.useState(() => new FeatureGate$1.LicenseValidator({ serverUrl, apiKey }));
27
+ const [validator] = React.useState(() => new marks.LicenseValidator({ serverUrl, apiKey }));
28
28
  const loadStoredKey = React.useCallback(() => {
29
29
  if (typeof localStorage === "undefined") {
30
30
  return null;
@@ -93,7 +93,7 @@ function LicenseProvider({
93
93
  );
94
94
  const activate = React.useCallback(
95
95
  async (key) => {
96
- const normalized = FeatureGate$1.normalizeLicenseKey(key);
96
+ const normalized = marks.normalizeLicenseKey(key);
97
97
  if (!normalized) {
98
98
  const result2 = {
99
99
  valid: false,
@@ -137,7 +137,7 @@ function LicenseProvider({
137
137
  }, [(_a = state.license) == null ? void 0 : _a.key, loadStoredKey, validateLicense]);
138
138
  const checkFeature = React.useCallback(
139
139
  (featureId) => {
140
- return FeatureGate$1.hasFeature(state.license, featureId);
140
+ return marks.hasFeature(state.license, featureId);
141
141
  },
142
142
  [state.license]
143
143
  );
@@ -180,7 +180,7 @@ function useLicense() {
180
180
  }
181
181
  function useFeature(featureId) {
182
182
  const { license, loading, error } = useLicense();
183
- const allowed = FeatureGate$1.hasFeature(license, featureId);
183
+ const allowed = marks.hasFeature(license, featureId);
184
184
  return { allowed, loading, error };
185
185
  }
186
186
  function FeatureGate({
@@ -194,7 +194,7 @@ function FeatureGate({
194
194
  if (loading) {
195
195
  return null;
196
196
  }
197
- const result = FeatureGate$1.checkFeatureAccess(license, feature);
197
+ const result = marks.checkFeatureAccess(license, feature);
198
198
  if (result.allowed) {
199
199
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
200
200
  }
@@ -218,15 +218,12 @@ function LicenseStatus({ detailed = false, style, className }) {
218
218
  ...style
219
219
  };
220
220
  if (loading) {
221
- return /* @__PURE__ */ jsxRuntime.jsxs(
221
+ return /* @__PURE__ */ jsxRuntime.jsx(
222
222
  "div",
223
223
  {
224
224
  style: { ...baseStyle, backgroundColor: "#f0f0f0", color: "#666" },
225
225
  className,
226
- children: [
227
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "⏳" }),
228
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Checking license..." })
229
- ]
226
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Checking license..." })
230
227
  }
231
228
  );
232
229
  }
@@ -237,7 +234,7 @@ function LicenseStatus({ detailed = false, style, className }) {
237
234
  style: { ...baseStyle, backgroundColor: "#fee2e2", color: "#991b1b" },
238
235
  className,
239
236
  children: [
240
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "⚠️" }),
237
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 700 }, "aria-hidden": "true", children: "!" }),
241
238
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: error || "No license" })
242
239
  ]
243
240
  }
@@ -262,14 +259,14 @@ function LicenseStatus({ detailed = false, style, className }) {
262
259
  const bgColor = tierColors[license.tier] || "#f0f0f0";
263
260
  const textColor = tierTextColors[license.tier] || "#333";
264
261
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...baseStyle, backgroundColor: bgColor, color: textColor }, className, children: [
265
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "✓" }),
262
+ /* @__PURE__ */ jsxRuntime.jsx(marks.CheckMark, {}),
266
263
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600 }, children: license.tier.charAt(0).toUpperCase() + license.tier.slice(1) }),
267
264
  (validation == null ? void 0 : validation.inGracePeriod) && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#dc2626", fontSize: "12px" }, children: "(Grace period)" }),
268
265
  detailed && (validation == null ? void 0 : validation.daysRemaining) !== void 0 && validation.daysRemaining > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "12px", opacity: 0.8 }, children: [
269
266
  validation.daysRemaining,
270
267
  " days remaining"
271
268
  ] }),
272
- detailed && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12px", opacity: 0.6 }, children: FeatureGate$1.maskLicenseKey(license.key) })
269
+ detailed && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12px", opacity: 0.6 }, children: marks.maskLicenseKey(license.key) })
273
270
  ] });
274
271
  }
275
272
  function LicenseActivator({
@@ -356,7 +353,7 @@ function UpgradePrompt({
356
353
  compact = false
357
354
  }) {
358
355
  const { license } = useLicense();
359
- const missingFeatures = FeatureGate$1.getMissingFeatures(license, targetTier);
356
+ const missingFeatures = marks.getMissingFeatures(license, targetTier);
360
357
  const handleUpgrade = () => {
361
358
  onUpgrade == null ? void 0 : onUpgrade(targetTier);
362
359
  if (!onUpgrade) {
@@ -389,7 +386,7 @@ function UpgradePrompt({
389
386
  };
390
387
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
391
388
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: titleStyle, children: [
392
- "🚀 Upgrade to ",
389
+ "Upgrade to ",
393
390
  targetTier.charAt(0).toUpperCase() + targetTier.slice(1)
394
391
  ] }),
395
392
  !compact && missingFeatures.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("ul", { style: { margin: "8px 0", paddingLeft: "20px", color: "#374151", fontSize: "14px" }, children: [
@@ -411,7 +408,7 @@ function LicenseComparison({
411
408
  }) {
412
409
  const { license } = useLicense();
413
410
  const tier = currentTier || (license == null ? void 0 : license.tier);
414
- const plans = customPlans || FeatureGate$1.getAllPlans().filter((p) => p.priceMonthly > 0 || p.id === "trial");
411
+ const plans = customPlans || marks.getAllPlans().filter((p) => p.priceMonthly > 0 || p.id === "trial");
415
412
  const formatPrice = (cents) => {
416
413
  if (cents === 0) {
417
414
  return "Free";
@@ -459,7 +456,8 @@ function LicenseComparison({
459
456
  plan.priceMonthly > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "14px", color: "#6b7280" }, children: "/month" })
460
457
  ] }),
461
458
  /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { listStyle: "none", padding: 0, margin: "0 0 16px" }, children: plan.highlights.map((h, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { padding: "6px 0", fontSize: "14px", color: "#374151" }, children: [
462
- "✓ ",
459
+ /* @__PURE__ */ jsxRuntime.jsx(marks.CheckMark, {}),
460
+ " ",
463
461
  h
464
462
  ] }, i)) }),
465
463
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -715,7 +713,8 @@ function LicensePortal({
715
713
  fontSize: "14px"
716
714
  },
717
715
  children: [
718
- "✓ ",
716
+ /* @__PURE__ */ jsxRuntime.jsx(marks.CheckMark, {}),
717
+ " ",
719
718
  f
720
719
  ]
721
720
  },
@@ -849,7 +848,7 @@ function NiceLicenseManager({
849
848
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500, fontSize: "14px", color: "#111" }, children: lic.licensee }),
850
849
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "12px", color: "#6b7280" }, children: lic.email })
851
850
  ] }),
852
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "12px", fontFamily: "monospace", color: "#6b7280" }, children: FeatureGate$1.maskLicenseKey(lic.key) }),
851
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "12px", fontFamily: "monospace", color: "#6b7280" }, children: marks.maskLicenseKey(lic.key) }),
853
852
  /* @__PURE__ */ jsxRuntime.jsx(
854
853
  "div",
855
854
  {
@@ -874,7 +873,7 @@ function NiceLicenseManager({
874
873
  children: lic.tier
875
874
  }
876
875
  ),
877
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px", color: "#6b7280", textAlign: "right" }, children: isExpanded ? "▲" : "▼" })
876
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px", color: "#6b7280", textAlign: "right" }, children: /* @__PURE__ */ jsxRuntime.jsx(marks.ChevronMark, { direction: isExpanded ? "up" : "down" }) })
878
877
  ]
879
878
  }
880
879
  ),
package/dist/react.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useState, useCallback, useEffect, useContext } from "react";
3
- import { c as checkFeatureAccess, k as getAllPlans, L as LicenseValidator, D as normalizeLicenseKey, y as hasFeature, C as maskLicenseKey, r as getMissingFeatures } from "./FeatureGate-cIgJ8Gq2.js";
3
+ import { c as checkFeatureAccess, k as getAllPlans, C as CheckMark, L as LicenseValidator, E as normalizeLicenseKey, y as hasFeature, D as maskLicenseKey, M as ChevronMark, r as getMissingFeatures } from "./marks-KzIFNheE.js";
4
4
  const LicenseContext = createContext(null);
5
5
  function LicenseProvider({
6
6
  serverUrl = "https://license.nice2dev.com/api/v1",
@@ -216,15 +216,12 @@ function LicenseStatus({ detailed = false, style, className }) {
216
216
  ...style
217
217
  };
218
218
  if (loading) {
219
- return /* @__PURE__ */ jsxs(
219
+ return /* @__PURE__ */ jsx(
220
220
  "div",
221
221
  {
222
222
  style: { ...baseStyle, backgroundColor: "#f0f0f0", color: "#666" },
223
223
  className,
224
- children: [
225
- /* @__PURE__ */ jsx("span", { children: "⏳" }),
226
- /* @__PURE__ */ jsx("span", { children: "Checking license..." })
227
- ]
224
+ children: /* @__PURE__ */ jsx("span", { children: "Checking license..." })
228
225
  }
229
226
  );
230
227
  }
@@ -235,7 +232,7 @@ function LicenseStatus({ detailed = false, style, className }) {
235
232
  style: { ...baseStyle, backgroundColor: "#fee2e2", color: "#991b1b" },
236
233
  className,
237
234
  children: [
238
- /* @__PURE__ */ jsx("span", { children: "⚠️" }),
235
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 700 }, "aria-hidden": "true", children: "!" }),
239
236
  /* @__PURE__ */ jsx("span", { children: error || "No license" })
240
237
  ]
241
238
  }
@@ -260,7 +257,7 @@ function LicenseStatus({ detailed = false, style, className }) {
260
257
  const bgColor = tierColors[license.tier] || "#f0f0f0";
261
258
  const textColor = tierTextColors[license.tier] || "#333";
262
259
  return /* @__PURE__ */ jsxs("div", { style: { ...baseStyle, backgroundColor: bgColor, color: textColor }, className, children: [
263
- /* @__PURE__ */ jsx("span", { children: "✓" }),
260
+ /* @__PURE__ */ jsx(CheckMark, {}),
264
261
  /* @__PURE__ */ jsx("span", { style: { fontWeight: 600 }, children: license.tier.charAt(0).toUpperCase() + license.tier.slice(1) }),
265
262
  (validation == null ? void 0 : validation.inGracePeriod) && /* @__PURE__ */ jsx("span", { style: { color: "#dc2626", fontSize: "12px" }, children: "(Grace period)" }),
266
263
  detailed && (validation == null ? void 0 : validation.daysRemaining) !== void 0 && validation.daysRemaining > 0 && /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", opacity: 0.8 }, children: [
@@ -387,7 +384,7 @@ function UpgradePrompt({
387
384
  };
388
385
  return /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
389
386
  /* @__PURE__ */ jsxs("div", { style: titleStyle, children: [
390
- "🚀 Upgrade to ",
387
+ "Upgrade to ",
391
388
  targetTier.charAt(0).toUpperCase() + targetTier.slice(1)
392
389
  ] }),
393
390
  !compact && missingFeatures.length > 0 && /* @__PURE__ */ jsxs("ul", { style: { margin: "8px 0", paddingLeft: "20px", color: "#374151", fontSize: "14px" }, children: [
@@ -457,7 +454,8 @@ function LicenseComparison({
457
454
  plan.priceMonthly > 0 && /* @__PURE__ */ jsx("span", { style: { fontSize: "14px", color: "#6b7280" }, children: "/month" })
458
455
  ] }),
459
456
  /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", padding: 0, margin: "0 0 16px" }, children: plan.highlights.map((h, i) => /* @__PURE__ */ jsxs("li", { style: { padding: "6px 0", fontSize: "14px", color: "#374151" }, children: [
460
- "✓ ",
457
+ /* @__PURE__ */ jsx(CheckMark, {}),
458
+ " ",
461
459
  h
462
460
  ] }, i)) }),
463
461
  /* @__PURE__ */ jsx(
@@ -713,7 +711,8 @@ function LicensePortal({
713
711
  fontSize: "14px"
714
712
  },
715
713
  children: [
716
- "✓ ",
714
+ /* @__PURE__ */ jsx(CheckMark, {}),
715
+ " ",
717
716
  f
718
717
  ]
719
718
  },
@@ -872,7 +871,7 @@ function NiceLicenseManager({
872
871
  children: lic.tier
873
872
  }
874
873
  ),
875
- /* @__PURE__ */ jsx("div", { style: { fontSize: "14px", color: "#6b7280", textAlign: "right" }, children: isExpanded ? "▲" : "▼" })
874
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "14px", color: "#6b7280", textAlign: "right" }, children: /* @__PURE__ */ jsx(ChevronMark, { direction: isExpanded ? "up" : "down" }) })
876
875
  ]
877
876
  }
878
877
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice2dev/licensing",
3
- "version": "1.1.6",
3
+ "version": "1.1.9",
4
4
  "description": "Nice2Dev Enterprise Licensing System — license key generation, validation, hardware fingerprinting, seat management and feature gating",
5
5
  "author": "NiceToDev <contact@nicetodev.com>",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -37,6 +37,7 @@
37
37
  ],
38
38
  "sideEffects": false,
39
39
  "scripts": {
40
+ "typecheck": "tsc --noEmit",
40
41
  "build": "vite build",
41
42
  "build:types": "tsc -p tsconfig.build.json",
42
43
  "dev": "vite",
@@ -1 +0,0 @@
1
- {"version":3,"file":"FeatureGate-9rvyns7j.cjs","sources":["../src/LicenseKeyGenerator.ts","../src/HardwareFingerprint.ts","../src/LicenseValidator.ts","../src/FeatureGate.ts"],"sourcesContent":["/* ────────────────────────────────────────────────────────────────\r\n License Key Generator — RSA-signed license keys\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseKey, LicenseKeyOptions, LicenseInfo, LicenseTier, FeatureId } from './types';\r\n\r\n/** Key segment length */\r\nconst SEGMENT_LENGTH = 4;\r\n/** Number of segments */\r\nconst NUM_SEGMENTS = 5;\r\n/** Characters used in license keys (no ambiguous chars) */\r\nconst KEY_CHARS = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\r\n\r\n/** Tier numeric codes for embedding in key */\r\nconst TIER_CODES: Record<LicenseTier, number> = {\r\n trial: 1,\r\n personal: 2,\r\n team: 3,\r\n enterprise: 4,\r\n site: 5,\r\n oem: 6,\r\n};\r\n\r\n/** Reverse lookup */\r\nconst CODE_TO_TIER: Record<number, LicenseTier> = Object.entries(TIER_CODES).reduce(\r\n (acc, [tier, code]) => ({ ...acc, [code]: tier as LicenseTier }),\r\n {} as Record<number, LicenseTier>,\r\n);\r\n\r\n/**\r\n * Generate a cryptographically secure random string\r\n */\r\nfunction secureRandom(length: number): string {\r\n const array = new Uint8Array(length);\r\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\r\n crypto.getRandomValues(array);\r\n } else {\r\n // Fallback for Node.js\r\n for (let i = 0; i < length; i++) {\r\n array[i] = Math.floor(Math.random() * 256);\r\n }\r\n }\r\n return Array.from(array)\r\n .map((b) => KEY_CHARS[b % KEY_CHARS.length])\r\n .join('');\r\n}\r\n\r\n/**\r\n * Calculate checksum for license key validation\r\n */\r\nfunction calculateChecksum(data: string): string {\r\n let hash = 0;\r\n for (let i = 0; i < data.length; i++) {\r\n const char = data.charCodeAt(i);\r\n hash = ((hash << 5) - hash + char) | 0;\r\n }\r\n // Convert to 4-character checksum\r\n const positive = Math.abs(hash);\r\n let checksum = '';\r\n let remaining = positive;\r\n for (let i = 0; i < SEGMENT_LENGTH; i++) {\r\n checksum += KEY_CHARS[remaining % KEY_CHARS.length];\r\n remaining = Math.floor(remaining / KEY_CHARS.length);\r\n }\r\n return checksum;\r\n}\r\n\r\n/**\r\n * Encode metadata into key segment\r\n */\r\nfunction encodeMetadata(tier: LicenseTier, year: number, month: number): string {\r\n const tierCode = TIER_CODES[tier];\r\n const yearOffset = year - 2024; // Base year\r\n const encoded = tierCode * 1000 + yearOffset * 12 + month;\r\n\r\n let segment = '';\r\n let remaining = encoded;\r\n for (let i = 0; i < SEGMENT_LENGTH; i++) {\r\n segment += KEY_CHARS[remaining % KEY_CHARS.length];\r\n remaining = Math.floor(remaining / KEY_CHARS.length);\r\n }\r\n return segment;\r\n}\r\n\r\n/**\r\n * Decode metadata from key segment\r\n */\r\nfunction decodeMetadata(\r\n segment: string,\r\n): { tier: LicenseTier; year: number; month: number } | null {\r\n let decoded = 0;\r\n for (let i = segment.length - 1; i >= 0; i--) {\r\n const idx = KEY_CHARS.indexOf(segment[i]);\r\n if (idx === -1) {\r\n return null;\r\n }\r\n decoded = decoded * KEY_CHARS.length + idx;\r\n }\r\n\r\n const tierCode = Math.floor(decoded / 1000);\r\n const remainder = decoded % 1000;\r\n const yearOffset = Math.floor(remainder / 12);\r\n const month = remainder % 12;\r\n\r\n const tier = CODE_TO_TIER[tierCode];\r\n if (!tier) {\r\n return null;\r\n }\r\n\r\n return {\r\n tier,\r\n year: 2024 + yearOffset,\r\n month,\r\n };\r\n}\r\n\r\n/**\r\n * Generate a new license key\r\n * Format: XXXX-XXXX-XXXX-XXXX-XXXX\r\n * - Segment 1: Encoded metadata (tier, date)\r\n * - Segment 2-4: Random unique identifier\r\n * - Segment 5: Checksum\r\n */\r\nexport function generateLicenseKey(tier: LicenseTier = 'personal'): LicenseKey {\r\n const now = new Date();\r\n const metadataSegment = encodeMetadata(tier, now.getFullYear(), now.getMonth());\r\n const randomSegments = [\r\n secureRandom(SEGMENT_LENGTH),\r\n secureRandom(SEGMENT_LENGTH),\r\n secureRandom(SEGMENT_LENGTH),\r\n ];\r\n\r\n const dataWithoutChecksum = [metadataSegment, ...randomSegments].join('-');\r\n const checksumSegment = calculateChecksum(dataWithoutChecksum);\r\n\r\n return `${dataWithoutChecksum}-${checksumSegment}`;\r\n}\r\n\r\n/**\r\n * Validate license key format and checksum\r\n */\r\nexport function validateKeyFormat(key: LicenseKey): boolean {\r\n // Check format\r\n const pattern = new RegExp(\r\n `^[${KEY_CHARS}]{${SEGMENT_LENGTH}}(-[${KEY_CHARS}]{${SEGMENT_LENGTH}}){${NUM_SEGMENTS - 1}}$`,\r\n );\r\n if (!pattern.test(key)) {\r\n return false;\r\n }\r\n\r\n // Verify checksum\r\n const segments = key.split('-');\r\n const dataSegments = segments.slice(0, -1).join('-');\r\n const providedChecksum = segments[segments.length - 1];\r\n const calculatedChecksum = calculateChecksum(dataSegments);\r\n\r\n return providedChecksum === calculatedChecksum;\r\n}\r\n\r\n/**\r\n * Extract metadata from license key\r\n */\r\nexport function extractKeyMetadata(key: LicenseKey): {\r\n tier: LicenseTier;\r\n year: number;\r\n month: number;\r\n} | null {\r\n if (!validateKeyFormat(key)) {\r\n return null;\r\n }\r\n\r\n const segments = key.split('-');\r\n return decodeMetadata(segments[0]);\r\n}\r\n\r\n/**\r\n * Generate license info from key options\r\n */\r\nexport function generateLicenseInfo(options: LicenseKeyOptions): LicenseInfo {\r\n const key = generateLicenseKey(options.tier);\r\n const now = new Date();\r\n const issuedAt = now.toISOString();\r\n\r\n let expiresAt: string | null = null;\r\n let graceUntil: string | undefined;\r\n\r\n if (options.durationDays !== null) {\r\n const expiry = new Date(now);\r\n expiry.setDate(expiry.getDate() + options.durationDays);\r\n expiresAt = expiry.toISOString();\r\n\r\n if (options.graceDays) {\r\n const grace = new Date(expiry);\r\n grace.setDate(grace.getDate() + options.graceDays);\r\n graceUntil = grace.toISOString();\r\n }\r\n }\r\n\r\n return {\r\n key,\r\n tier: options.tier,\r\n status: 'valid',\r\n licensee: options.licensee,\r\n email: options.email,\r\n issuedAt,\r\n expiresAt,\r\n graceUntil,\r\n features: options.features ?? getDefaultFeatures(options.tier),\r\n maxSeats: options.maxSeats ?? getDefaultSeats(options.tier),\r\n activeSeats: 0,\r\n boundMachines: [],\r\n maxMachines: options.maxMachines ?? getDefaultMachines(options.tier),\r\n floatingSeats: options.floatingSeats,\r\n metadata: options.metadata,\r\n };\r\n}\r\n\r\n/**\r\n * Get default features for tier\r\n */\r\nexport function getDefaultFeatures(tier: LicenseTier): FeatureId[] {\r\n const features: FeatureId[] = ['core', 'basic-components'];\r\n\r\n if (tier === 'trial') {\r\n features.push('trial-watermark');\r\n }\r\n\r\n if (['personal', 'team', 'enterprise', 'site', 'oem'].includes(tier)) {\r\n features.push('advanced-components', 'theming', 'i18n');\r\n }\r\n\r\n if (['team', 'enterprise', 'site', 'oem'].includes(tier)) {\r\n features.push('collaboration', 'analytics', 'priority-support');\r\n }\r\n\r\n if (['enterprise', 'site', 'oem'].includes(tier)) {\r\n features.push('white-label', 'sso', 'audit-log', 'custom-branding', 'api-access');\r\n }\r\n\r\n if (['site', 'oem'].includes(tier)) {\r\n features.push('unlimited-seats', 'source-code-access', 'dedicated-support');\r\n }\r\n\r\n if (tier === 'oem') {\r\n features.push('redistribution', 'custom-licensing');\r\n }\r\n\r\n return features;\r\n}\r\n\r\n/**\r\n * Get default max seats for tier\r\n */\r\nexport function getDefaultSeats(tier: LicenseTier): number | null {\r\n switch (tier) {\r\n case 'trial':\r\n return 1;\r\n case 'personal':\r\n return 1;\r\n case 'team':\r\n return 10;\r\n case 'enterprise':\r\n return 50;\r\n case 'site':\r\n return null; // unlimited\r\n case 'oem':\r\n return null;\r\n default:\r\n return 1;\r\n }\r\n}\r\n\r\n/**\r\n * Get default max machines for tier\r\n */\r\nexport function getDefaultMachines(tier: LicenseTier): number {\r\n switch (tier) {\r\n case 'trial':\r\n return 1;\r\n case 'personal':\r\n return 2;\r\n case 'team':\r\n return 20;\r\n case 'enterprise':\r\n return 100;\r\n case 'site':\r\n return 1000;\r\n case 'oem':\r\n return 10000;\r\n default:\r\n return 1;\r\n }\r\n}\r\n\r\n/**\r\n * Compare two tiers, returns positive if a > b\r\n */\r\nexport function compareTiers(a: LicenseTier, b: LicenseTier): number {\r\n return TIER_CODES[a] - TIER_CODES[b];\r\n}\r\n\r\n/**\r\n * Check if tier meets minimum requirement\r\n */\r\nexport function tierMeetsRequirement(userTier: LicenseTier, requiredTier: LicenseTier): boolean {\r\n return compareTiers(userTier, requiredTier) >= 0;\r\n}\r\n\r\n/**\r\n * Mask license key for display (show first and last segments)\r\n */\r\nexport function maskLicenseKey(key: LicenseKey): string {\r\n const segments = key.split('-');\r\n if (segments.length !== NUM_SEGMENTS) {\r\n return '****-****-****-****-****';\r\n }\r\n return `${segments[0]}-****-****-****-${segments[segments.length - 1]}`;\r\n}\r\n\r\n/**\r\n * Parse license key from various formats (with or without dashes)\r\n */\r\nexport function normalizeLicenseKey(input: string): LicenseKey | null {\r\n // Remove whitespace and convert to uppercase\r\n const cleaned = input.replace(/\\s/g, '').toUpperCase();\r\n\r\n // If already has dashes, validate format\r\n if (cleaned.includes('-')) {\r\n return validateKeyFormat(cleaned) ? cleaned : null;\r\n }\r\n\r\n // Add dashes if plain string\r\n if (cleaned.length === SEGMENT_LENGTH * NUM_SEGMENTS) {\r\n const segments: string[] = [];\r\n for (let i = 0; i < NUM_SEGMENTS; i++) {\r\n segments.push(cleaned.substring(i * SEGMENT_LENGTH, (i + 1) * SEGMENT_LENGTH));\r\n }\r\n const formatted = segments.join('-');\r\n return validateKeyFormat(formatted) ? formatted : null;\r\n }\r\n\r\n return null;\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n Hardware Fingerprint — Machine binding for license protection\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { HardwareFingerprint, HardwareFingerprintData, MachineId } from './types';\r\n\r\n/**\r\n * Simple hash function (FNV-1a)\r\n */\r\nfunction fnv1aHash(str: string): number {\r\n let hash = 2166136261;\r\n for (let i = 0; i < str.length; i++) {\r\n hash ^= str.charCodeAt(i);\r\n hash = Math.imul(hash, 16777619);\r\n }\r\n return hash >>> 0;\r\n}\r\n\r\n/**\r\n * Convert hash to hex string\r\n */\r\nfunction hashToHex(hash: number): string {\r\n return hash.toString(16).padStart(8, '0');\r\n}\r\n\r\n/**\r\n * Hash a string using multiple passes for stronger fingerprint\r\n */\r\nfunction strongHash(input: string): string {\r\n const h1 = fnv1aHash(input);\r\n const h2 = fnv1aHash(input + h1.toString());\r\n const h3 = fnv1aHash(h2.toString() + input);\r\n return hashToHex(h1) + hashToHex(h2) + hashToHex(h3);\r\n}\r\n\r\n/**\r\n * Get WebGL renderer info (GPU fingerprint)\r\n */\r\nfunction getWebGLFingerprint(): string | undefined {\r\n if (typeof document === 'undefined') {\r\n return undefined;\r\n }\r\n\r\n try {\r\n const canvas = document.createElement('canvas');\r\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\r\n if (!gl) {\r\n return undefined;\r\n }\r\n\r\n const glAny = gl as WebGLRenderingContext;\r\n const debugInfo = glAny.getExtension('WEBGL_debug_renderer_info');\r\n if (!debugInfo) {\r\n return undefined;\r\n }\r\n\r\n const vendor = glAny.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);\r\n const renderer = glAny.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);\r\n\r\n return strongHash(`${vendor}|${renderer}`);\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Get canvas fingerprint\r\n */\r\nfunction getCanvasFingerprint(): string | undefined {\r\n if (typeof document === 'undefined') {\r\n return undefined;\r\n }\r\n\r\n try {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = 200;\r\n canvas.height = 50;\r\n\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return undefined;\r\n }\r\n\r\n // Draw text with specific styles\r\n ctx.textBaseline = 'top';\r\n ctx.font = '14px Arial';\r\n ctx.fillStyle = '#f60';\r\n ctx.fillRect(125, 1, 62, 20);\r\n ctx.fillStyle = '#069';\r\n ctx.fillText('Nice2Dev Licensing', 2, 15);\r\n ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';\r\n ctx.fillText('Nice2Dev Licensing', 4, 17);\r\n\r\n return strongHash(canvas.toDataURL());\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Get audio context fingerprint\r\n */\r\nfunction getAudioFingerprint(): Promise<string | undefined> {\r\n if (typeof window === 'undefined' || !window.AudioContext) {\r\n return Promise.resolve(undefined);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n try {\r\n const audioContext = new AudioContext();\r\n const oscillator = audioContext.createOscillator();\r\n const analyser = audioContext.createAnalyser();\r\n const gainNode = audioContext.createGain();\r\n const scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);\r\n\r\n gainNode.gain.value = 0; // Mute\r\n oscillator.type = 'triangle';\r\n oscillator.frequency.value = 10000;\r\n\r\n oscillator.connect(analyser);\r\n analyser.connect(scriptProcessor);\r\n scriptProcessor.connect(gainNode);\r\n gainNode.connect(audioContext.destination);\r\n\r\n let fingerprint = '';\r\n scriptProcessor.onaudioprocess = (e) => {\r\n const buffer = e.inputBuffer.getChannelData(0);\r\n fingerprint = strongHash(buffer.slice(0, 100).join(','));\r\n\r\n scriptProcessor.disconnect();\r\n oscillator.disconnect();\r\n analyser.disconnect();\r\n gainNode.disconnect();\r\n audioContext.close();\r\n\r\n resolve(fingerprint);\r\n };\r\n\r\n oscillator.start(0);\r\n\r\n // Timeout fallback\r\n setTimeout(() => {\r\n if (!fingerprint) {\r\n resolve(undefined);\r\n }\r\n }, 1000);\r\n } catch {\r\n resolve(undefined);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Get user agent hash\r\n */\r\nfunction getUserAgentHash(): string | undefined {\r\n if (typeof navigator === 'undefined') {\r\n return undefined;\r\n }\r\n return strongHash(navigator.userAgent);\r\n}\r\n\r\n/**\r\n * Get timezone info\r\n */\r\nfunction getTimezoneInfo(): string {\r\n try {\r\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\r\n } catch {\r\n return 'unknown';\r\n }\r\n}\r\n\r\n/**\r\n * Get screen info\r\n */\r\nfunction getScreenInfo(): string | undefined {\r\n if (typeof screen === 'undefined') {\r\n return undefined;\r\n }\r\n return `${screen.width}x${screen.height}x${screen.colorDepth}`;\r\n}\r\n\r\n/**\r\n * Get language info\r\n */\r\nfunction getLanguageInfo(): string | undefined {\r\n if (typeof navigator === 'undefined') {\r\n return undefined;\r\n }\r\n return navigator.language || (navigator as { userLanguage?: string }).userLanguage || 'unknown';\r\n}\r\n\r\n/**\r\n * Get platform info\r\n */\r\nfunction getPlatformInfo(): string | undefined {\r\n if (typeof navigator === 'undefined') {\r\n return undefined;\r\n }\r\n return navigator.platform;\r\n}\r\n\r\n/**\r\n * Get hardware concurrency\r\n */\r\nfunction getHardwareConcurrency(): number | undefined {\r\n if (typeof navigator === 'undefined') {\r\n return undefined;\r\n }\r\n return navigator.hardwareConcurrency;\r\n}\r\n\r\n/**\r\n * Get device memory (if available)\r\n */\r\nfunction getDeviceMemory(): number | undefined {\r\n if (typeof navigator === 'undefined') {\r\n return undefined;\r\n }\r\n return (navigator as { deviceMemory?: number }).deviceMemory;\r\n}\r\n\r\n/**\r\n * Collect all fingerprint components\r\n */\r\nexport async function collectFingerprintData(): Promise<HardwareFingerprintData> {\r\n const audioFingerprint = await getAudioFingerprint();\r\n\r\n return {\r\n webglHash: getWebGLFingerprint(),\r\n canvasFingerprint: getCanvasFingerprint(),\r\n audioFingerprint,\r\n userAgentHash: getUserAgentHash(),\r\n browserFingerprint: strongHash(\r\n [\r\n getTimezoneInfo(),\r\n getScreenInfo(),\r\n getLanguageInfo(),\r\n getPlatformInfo(),\r\n getHardwareConcurrency()?.toString(),\r\n getDeviceMemory()?.toString(),\r\n ]\r\n .filter(Boolean)\r\n .join('|'),\r\n ),\r\n };\r\n}\r\n\r\n/**\r\n * Generate hardware fingerprint\r\n */\r\nexport async function generateFingerprint(): Promise<HardwareFingerprint> {\r\n const data = await collectFingerprintData();\r\n\r\n // Combine all components\r\n const components = [\r\n data.webglHash,\r\n data.canvasFingerprint,\r\n data.audioFingerprint,\r\n data.userAgentHash,\r\n data.browserFingerprint,\r\n ].filter(Boolean);\r\n\r\n if (components.length === 0) {\r\n // Fallback: use timestamp + random for environments without fingerprint support\r\n const fallback = Date.now().toString() + Math.random().toString(36);\r\n return strongHash(fallback);\r\n }\r\n\r\n return strongHash(components.join(':'));\r\n}\r\n\r\n/**\r\n * Generate machine ID (stable identifier for this machine)\r\n */\r\nexport async function generateMachineId(): Promise<MachineId> {\r\n const fingerprint = await generateFingerprint();\r\n // Machine ID is the first 16 characters of the fingerprint\r\n return fingerprint.substring(0, 16).toUpperCase();\r\n}\r\n\r\n/**\r\n * Compare two fingerprints with tolerance (fuzzy match)\r\n * Returns similarity score 0-1\r\n */\r\nexport function compareFingerprintsData(\r\n fp1: HardwareFingerprintData,\r\n fp2: HardwareFingerprintData,\r\n): number {\r\n const fields: (keyof HardwareFingerprintData)[] = [\r\n 'webglHash',\r\n 'canvasFingerprint',\r\n 'audioFingerprint',\r\n 'userAgentHash',\r\n 'browserFingerprint',\r\n ];\r\n\r\n let matches = 0;\r\n let total = 0;\r\n\r\n for (const field of fields) {\r\n const v1 = fp1[field];\r\n const v2 = fp2[field];\r\n\r\n if (v1 !== undefined || v2 !== undefined) {\r\n total++;\r\n if (v1 === v2) {\r\n matches++;\r\n }\r\n }\r\n }\r\n\r\n return total > 0 ? matches / total : 0;\r\n}\r\n\r\n/**\r\n * Store fingerprint in local storage\r\n */\r\nexport function storeFingerprint(fingerprint: HardwareFingerprint): void {\r\n if (typeof localStorage === 'undefined') {\r\n return;\r\n }\r\n try {\r\n localStorage.setItem('nice2dev_fp', fingerprint);\r\n } catch {\r\n // Storage not available\r\n }\r\n}\r\n\r\n/**\r\n * Retrieve stored fingerprint\r\n */\r\nexport function getStoredFingerprint(): HardwareFingerprint | null {\r\n if (typeof localStorage === 'undefined') {\r\n return null;\r\n }\r\n try {\r\n return localStorage.getItem('nice2dev_fp');\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get or generate fingerprint (uses cached value if available)\r\n */\r\nexport async function getOrGenerateFingerprint(): Promise<HardwareFingerprint> {\r\n const stored = getStoredFingerprint();\r\n if (stored) {\r\n return stored;\r\n }\r\n\r\n const fingerprint = await generateFingerprint();\r\n storeFingerprint(fingerprint);\r\n return fingerprint;\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n License Validator — Online/Offline license validation\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport { generateMachineId } from './HardwareFingerprint';\r\nimport { validateKeyFormat, extractKeyMetadata } from './LicenseKeyGenerator';\r\nimport type {\r\n LicenseKey,\r\n LicenseInfo,\r\n LicenseValidationResult,\r\n LicenseServerConfig,\r\n LicenseErrorCode,\r\n FeatureId,\r\n HardwareFingerprint,\r\n OfflineChallenge,\r\n OfflineResponse,\r\n} from './types';\r\n\r\n/** Default server config */\r\nconst DEFAULT_CONFIG: LicenseServerConfig = {\r\n serverUrl: 'https://license.nice2dev.com/api/v1',\r\n timeout: 10000,\r\n retries: 3,\r\n cacheTtl: 3600, // 1 hour\r\n offlineMode: false,\r\n telemetryEnabled: false,\r\n};\r\n\r\n/** Cache key prefix */\r\nconst CACHE_PREFIX = 'nice2dev_license_';\r\n\r\n/** Validation result cache */\r\ninterface CachedValidation {\r\n result: LicenseValidationResult;\r\n cachedAt: number;\r\n expiresAt: number;\r\n}\r\n\r\n/**\r\n * License Validator Service\r\n */\r\nexport class LicenseValidator {\r\n private config: LicenseServerConfig;\r\n private cache: Map<string, CachedValidation> = new Map();\r\n\r\n constructor(config: Partial<LicenseServerConfig> = {}) {\r\n this.config = { ...DEFAULT_CONFIG, ...config };\r\n this.loadCacheFromStorage();\r\n }\r\n\r\n /**\r\n * Validate a license key\r\n */\r\n async validate(\r\n key: LicenseKey,\r\n fingerprint?: HardwareFingerprint,\r\n ): Promise<LicenseValidationResult> {\r\n const now = new Date().toISOString();\r\n\r\n // First, validate format locally\r\n if (!validateKeyFormat(key)) {\r\n return {\r\n valid: false,\r\n errorCode: 'INVALID_KEY',\r\n errorMessage: 'Invalid license key format',\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n // Check cache\r\n const cached = this.getFromCache(key);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n // Get machine fingerprint if not provided\r\n const machineFingerprint = fingerprint || (await generateMachineId());\r\n\r\n // Try online validation first\r\n if (!this.config.offlineMode) {\r\n try {\r\n const result = await this.validateOnline(key, machineFingerprint);\r\n this.setCache(key, result);\r\n return result;\r\n } catch (error) {\r\n // Fall back to offline validation\r\n console.warn('Online validation failed, trying offline:', error);\r\n }\r\n }\r\n\r\n // Offline validation\r\n return this.validateOffline(key, machineFingerprint);\r\n }\r\n\r\n /**\r\n * Online license validation\r\n */\r\n private async validateOnline(\r\n key: LicenseKey,\r\n fingerprint: HardwareFingerprint,\r\n ): Promise<LicenseValidationResult> {\r\n const url = `${this.config.serverUrl}/validate`;\r\n const now = new Date().toISOString();\r\n\r\n let lastError: Error | null = null;\r\n\r\n for (let attempt = 0; attempt < (this.config.retries || 1); attempt++) {\r\n try {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.apiKey ? { 'X-API-Key': this.config.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey: key,\r\n machineFingerprint: fingerprint,\r\n timestamp: now,\r\n }),\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (!response.ok) {\r\n if (response.status === 404) {\r\n return {\r\n valid: false,\r\n errorCode: 'INVALID_KEY',\r\n errorMessage: 'License key not found',\r\n validatedAt: now,\r\n };\r\n }\r\n throw new Error(`Server error: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n return this.parseServerResponse(data, now);\r\n } catch (error) {\r\n lastError = error as Error;\r\n // Wait before retry (exponential backoff)\r\n if (attempt < (this.config.retries || 1) - 1) {\r\n await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 1000));\r\n }\r\n }\r\n }\r\n\r\n throw lastError || new Error('Validation failed');\r\n }\r\n\r\n /**\r\n * Parse server validation response\r\n */\r\n private parseServerResponse(\r\n data: Record<string, unknown>,\r\n validatedAt: string,\r\n ): LicenseValidationResult {\r\n // Handle server response format\r\n if (data.valid === false) {\r\n return {\r\n valid: false,\r\n errorCode: data.errorCode as LicenseErrorCode,\r\n errorMessage: data.errorMessage as string,\r\n validatedAt,\r\n };\r\n }\r\n\r\n const license = data.license as LicenseInfo;\r\n const now = new Date();\r\n\r\n // Check expiration\r\n let daysRemaining: number | undefined;\r\n let inGracePeriod = false;\r\n\r\n if (license.expiresAt) {\r\n const expiry = new Date(license.expiresAt);\r\n const diffMs = expiry.getTime() - now.getTime();\r\n daysRemaining = Math.ceil(diffMs / (1000 * 60 * 60 * 24));\r\n\r\n if (daysRemaining < 0 && license.graceUntil) {\r\n const graceEnd = new Date(license.graceUntil);\r\n if (now < graceEnd) {\r\n inGracePeriod = true;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n valid: true,\r\n license,\r\n daysRemaining,\r\n inGracePeriod,\r\n availableFeatures: license.features,\r\n validatedAt,\r\n };\r\n }\r\n\r\n /**\r\n * Offline license validation\r\n */\r\n private validateOffline(\r\n key: LicenseKey,\r\n fingerprint: HardwareFingerprint,\r\n ): LicenseValidationResult {\r\n const now = new Date().toISOString();\r\n\r\n // Extract metadata from key\r\n const metadata = extractKeyMetadata(key);\r\n if (!metadata) {\r\n return {\r\n valid: false,\r\n errorCode: 'INVALID_KEY',\r\n errorMessage: 'Cannot decode license key',\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n // Check for locally stored license data\r\n const storedLicense = this.getStoredLicense(key);\r\n if (storedLicense) {\r\n // Verify fingerprint matches\r\n if (!storedLicense.boundMachines.some((m) => m.startsWith(fingerprint.substring(0, 8)))) {\r\n return {\r\n valid: false,\r\n errorCode: 'MACHINE_LIMIT',\r\n errorMessage: 'This machine is not authorized for this license',\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n // Check expiration\r\n if (storedLicense.expiresAt) {\r\n const expiry = new Date(storedLicense.expiresAt);\r\n const nowDate = new Date();\r\n\r\n if (nowDate > expiry) {\r\n // Check grace period\r\n if (storedLicense.graceUntil) {\r\n const graceEnd = new Date(storedLicense.graceUntil);\r\n if (nowDate > graceEnd) {\r\n return {\r\n valid: false,\r\n errorCode: 'EXPIRED',\r\n errorMessage: 'License has expired',\r\n validatedAt: now,\r\n };\r\n }\r\n // In grace period\r\n return {\r\n valid: true,\r\n license: storedLicense,\r\n inGracePeriod: true,\r\n daysRemaining: 0,\r\n availableFeatures: storedLicense.features,\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n return {\r\n valid: false,\r\n errorCode: 'EXPIRED',\r\n errorMessage: 'License has expired',\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n const diffMs = expiry.getTime() - nowDate.getTime();\r\n const daysRemaining = Math.ceil(diffMs / (1000 * 60 * 60 * 24));\r\n\r\n return {\r\n valid: true,\r\n license: storedLicense,\r\n daysRemaining,\r\n inGracePeriod: false,\r\n availableFeatures: storedLicense.features,\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n // Perpetual license\r\n return {\r\n valid: true,\r\n license: storedLicense,\r\n availableFeatures: storedLicense.features,\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n // No stored license data - limited offline validation\r\n // Only validate format and metadata\r\n return {\r\n valid: true, // Trust the key format\r\n license: {\r\n key,\r\n tier: metadata.tier,\r\n status: 'pending', // Needs online verification\r\n licensee: 'Unknown (offline)',\r\n email: '',\r\n issuedAt: `${metadata.year}-${String(metadata.month + 1).padStart(2, '0')}-01T00:00:00Z`,\r\n expiresAt: null,\r\n features: [], // Limited features offline\r\n maxSeats: null,\r\n activeSeats: 0,\r\n boundMachines: [fingerprint],\r\n maxMachines: 1,\r\n },\r\n availableFeatures: ['core'], // Only core features offline\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n /**\r\n * Generate offline activation challenge\r\n */\r\n async generateChallenge(key: LicenseKey): Promise<OfflineChallenge> {\r\n const fingerprint = await generateMachineId();\r\n const challengeId = crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Math.random().toString(36).substring(2) + Date.now().toString(36);\r\n\r\n const challengeData = JSON.stringify({\r\n key,\r\n fingerprint,\r\n timestamp: Date.now(),\r\n });\r\n\r\n // Base64 encode (simple encoding for challenge)\r\n const challengeCode =\r\n typeof btoa !== 'undefined'\r\n ? btoa(challengeData)\r\n : Buffer.from(challengeData).toString('base64');\r\n\r\n const expiresAt = new Date();\r\n expiresAt.setHours(expiresAt.getHours() + 24); // 24 hour validity\r\n\r\n return {\r\n challengeId,\r\n challengeCode,\r\n fingerprint,\r\n expiresAt: expiresAt.toISOString(),\r\n };\r\n }\r\n\r\n /**\r\n * Apply offline activation response\r\n */\r\n applyOfflineResponse(response: OfflineResponse): LicenseValidationResult {\r\n const now = new Date().toISOString();\r\n\r\n try {\r\n // Decode license data\r\n const licenseDataJson =\r\n typeof atob !== 'undefined'\r\n ? atob(response.licenseData)\r\n : Buffer.from(response.licenseData, 'base64').toString('utf-8');\r\n\r\n const license = JSON.parse(licenseDataJson) as LicenseInfo;\r\n\r\n // Store license locally\r\n this.storeLicense(license);\r\n\r\n return {\r\n valid: true,\r\n license,\r\n availableFeatures: license.features,\r\n validatedAt: now,\r\n };\r\n } catch {\r\n return {\r\n valid: false,\r\n errorCode: 'TAMPERED',\r\n errorMessage: 'Invalid offline activation response',\r\n validatedAt: now,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Check if feature is available\r\n */\r\n async hasFeature(key: LicenseKey, feature: FeatureId): Promise<boolean> {\r\n const result = await this.validate(key);\r\n if (!result.valid) {\r\n return false;\r\n }\r\n return result.availableFeatures?.includes(feature) ?? false;\r\n }\r\n\r\n /**\r\n * Activate machine for license\r\n */\r\n async activateMachine(key: LicenseKey): Promise<LicenseValidationResult> {\r\n const fingerprint = await generateMachineId();\r\n const url = `${this.config.serverUrl}/activate`;\r\n const now = new Date().toISOString();\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.apiKey ? { 'X-API-Key': this.config.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey: key,\r\n machineFingerprint: fingerprint,\r\n machineName: this.getMachineName(),\r\n timestamp: now,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const data = await response.json();\r\n return {\r\n valid: false,\r\n errorCode: data.errorCode || 'SERVER_ERROR',\r\n errorMessage: data.errorMessage || 'Activation failed',\r\n validatedAt: now,\r\n };\r\n }\r\n\r\n const data = await response.json();\r\n const license = data.license as LicenseInfo;\r\n\r\n // Store license locally\r\n this.storeLicense(license);\r\n this.clearCache(key);\r\n\r\n return {\r\n valid: true,\r\n license,\r\n availableFeatures: license.features,\r\n validatedAt: now,\r\n };\r\n } catch (_error) {\r\n return {\r\n valid: false,\r\n errorCode: 'NETWORK_ERROR',\r\n errorMessage: 'Cannot connect to license server',\r\n validatedAt: now,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Deactivate machine from license\r\n */\r\n async deactivateMachine(key: LicenseKey): Promise<boolean> {\r\n const fingerprint = await generateMachineId();\r\n const url = `${this.config.serverUrl}/deactivate`;\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.apiKey ? { 'X-API-Key': this.config.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey: key,\r\n machineFingerprint: fingerprint,\r\n }),\r\n });\r\n\r\n if (response.ok) {\r\n this.clearStoredLicense(key);\r\n this.clearCache(key);\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n // ─── Cache Management ─────────────────────────────────────────\r\n\r\n private getFromCache(key: LicenseKey): LicenseValidationResult | null {\r\n const cached = this.cache.get(key);\r\n if (!cached) {\r\n return null;\r\n }\r\n\r\n if (Date.now() > cached.expiresAt) {\r\n this.cache.delete(key);\r\n return null;\r\n }\r\n\r\n return cached.result;\r\n }\r\n\r\n private setCache(key: LicenseKey, result: LicenseValidationResult): void {\r\n const now = Date.now();\r\n const ttl = (this.config.cacheTtl || 3600) * 1000;\r\n\r\n this.cache.set(key, {\r\n result,\r\n cachedAt: now,\r\n expiresAt: now + ttl,\r\n });\r\n\r\n this.saveCacheToStorage();\r\n }\r\n\r\n private clearCache(key: LicenseKey): void {\r\n this.cache.delete(key);\r\n this.saveCacheToStorage();\r\n }\r\n\r\n // ─── Storage Management ───────────────────────────────────────\r\n\r\n private getStoredLicense(key: LicenseKey): LicenseInfo | null {\r\n if (typeof localStorage === 'undefined') {\r\n return null;\r\n }\r\n\r\n try {\r\n const data = localStorage.getItem(`${CACHE_PREFIX}info_${key}`);\r\n return data ? JSON.parse(data) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n private storeLicense(license: LicenseInfo): void {\r\n if (typeof localStorage === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n localStorage.setItem(`${CACHE_PREFIX}info_${license.key}`, JSON.stringify(license));\r\n } catch {\r\n // Storage not available\r\n }\r\n }\r\n\r\n private clearStoredLicense(key: LicenseKey): void {\r\n if (typeof localStorage === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n localStorage.removeItem(`${CACHE_PREFIX}info_${key}`);\r\n } catch {\r\n // Ignore\r\n }\r\n }\r\n\r\n private loadCacheFromStorage(): void {\r\n if (typeof localStorage === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n const data = localStorage.getItem(`${CACHE_PREFIX}cache`);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n for (const [key, value] of Object.entries(parsed)) {\r\n this.cache.set(key, value as CachedValidation);\r\n }\r\n }\r\n } catch {\r\n // Ignore\r\n }\r\n }\r\n\r\n private saveCacheToStorage(): void {\r\n if (typeof localStorage === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n const obj: Record<string, CachedValidation> = {};\r\n for (const [key, value] of this.cache.entries()) {\r\n obj[key] = value;\r\n }\r\n localStorage.setItem(`${CACHE_PREFIX}cache`, JSON.stringify(obj));\r\n } catch {\r\n // Ignore\r\n }\r\n }\r\n\r\n private getMachineName(): string {\r\n if (typeof navigator !== 'undefined') {\r\n return navigator.userAgent.split(/[()]/)[1] || 'Unknown Device';\r\n }\r\n return 'Server';\r\n }\r\n}\r\n\r\n/** Global validator instance */\r\nlet globalValidator: LicenseValidator | null = null;\r\n\r\n/**\r\n * Get or create global validator instance\r\n */\r\nexport function getValidator(config?: Partial<LicenseServerConfig>): LicenseValidator {\r\n if (!globalValidator || config) {\r\n globalValidator = new LicenseValidator(config);\r\n }\r\n return globalValidator;\r\n}\r\n\r\n/**\r\n * Validate license key (convenience function)\r\n */\r\nexport async function validateLicense(key: LicenseKey): Promise<LicenseValidationResult> {\r\n return getValidator().validate(key);\r\n}\r\n\r\n/**\r\n * Check if feature is licensed (convenience function)\r\n */\r\nexport async function isFeatureLicensed(key: LicenseKey, feature: FeatureId): Promise<boolean> {\r\n return getValidator().hasFeature(key, feature);\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n Feature Gate — Component gating based on license tier/features\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport { tierMeetsRequirement, getDefaultFeatures } from './LicenseKeyGenerator';\r\nimport type { LicenseInfo, LicenseTier, FeatureId, FeatureDefinition, LicensePlan } from './types';\r\n\r\n/** Feature registry */\r\nconst featureRegistry = new Map<FeatureId, FeatureDefinition>();\r\n\r\n/** Plan registry */\r\nconst planRegistry = new Map<LicenseTier, LicensePlan>();\r\n\r\n/**\r\n * Register a feature definition\r\n */\r\nexport function registerFeature(feature: FeatureDefinition): void {\r\n featureRegistry.set(feature.id, feature);\r\n}\r\n\r\n/**\r\n * Register multiple features\r\n */\r\nexport function registerFeatures(features: FeatureDefinition[]): void {\r\n features.forEach(registerFeature);\r\n}\r\n\r\n/**\r\n * Get feature definition\r\n */\r\nexport function getFeature(id: FeatureId): FeatureDefinition | undefined {\r\n return featureRegistry.get(id);\r\n}\r\n\r\n/**\r\n * Get all registered features\r\n */\r\nexport function getAllFeatures(): FeatureDefinition[] {\r\n return Array.from(featureRegistry.values());\r\n}\r\n\r\n/**\r\n * Get features by category\r\n */\r\nexport function getFeaturesByCategory(category: string): FeatureDefinition[] {\r\n return getAllFeatures().filter((f) => f.category === category);\r\n}\r\n\r\n/**\r\n * Register a license plan\r\n */\r\nexport function registerPlan(plan: LicensePlan): void {\r\n planRegistry.set(plan.id, plan);\r\n}\r\n\r\n/**\r\n * Register multiple plans\r\n */\r\nexport function registerPlans(plans: LicensePlan[]): void {\r\n plans.forEach(registerPlan);\r\n}\r\n\r\n/**\r\n * Get plan by tier\r\n */\r\nexport function getPlan(tier: LicenseTier): LicensePlan | undefined {\r\n return planRegistry.get(tier);\r\n}\r\n\r\n/**\r\n * Get all plans\r\n */\r\nexport function getAllPlans(): LicensePlan[] {\r\n return Array.from(planRegistry.values());\r\n}\r\n\r\n/**\r\n * Check if license has specific feature\r\n */\r\nexport function hasFeature(license: LicenseInfo | null, featureId: FeatureId): boolean {\r\n if (!license) {\r\n return false;\r\n }\r\n\r\n // Check explicit features list\r\n if (license.features.includes(featureId)) {\r\n return true;\r\n }\r\n\r\n // Check tier-based access\r\n const feature = getFeature(featureId);\r\n if (feature) {\r\n return tierMeetsRequirement(license.tier, feature.requiredTier);\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Check if license meets tier requirement\r\n */\r\nexport function hasTier(license: LicenseInfo | null, requiredTier: LicenseTier): boolean {\r\n if (!license) {\r\n return false;\r\n }\r\n return tierMeetsRequirement(license.tier, requiredTier);\r\n}\r\n\r\n/**\r\n * Get all available features for a license\r\n */\r\nexport function getAvailableFeatures(license: LicenseInfo | null): FeatureId[] {\r\n if (!license) {\r\n return [];\r\n }\r\n\r\n const available = new Set<FeatureId>(license.features);\r\n\r\n // Add tier-based features\r\n for (const feature of getAllFeatures()) {\r\n if (tierMeetsRequirement(license.tier, feature.requiredTier)) {\r\n available.add(feature.id);\r\n }\r\n }\r\n\r\n return Array.from(available);\r\n}\r\n\r\n/**\r\n * Get missing features for upgrade promotion\r\n */\r\nexport function getMissingFeatures(\r\n license: LicenseInfo | null,\r\n targetTier: LicenseTier,\r\n): FeatureDefinition[] {\r\n const currentFeatures = new Set(license ? getAvailableFeatures(license) : []);\r\n const targetFeatures = getDefaultFeatures(targetTier);\r\n\r\n return getAllFeatures().filter(\r\n (f) => targetFeatures.includes(f.id) && !currentFeatures.has(f.id),\r\n );\r\n}\r\n\r\n/**\r\n * Feature check result\r\n */\r\nexport interface FeatureCheckResult {\r\n allowed: boolean;\r\n reason?: 'no-license' | 'tier-insufficient' | 'feature-not-included' | 'expired';\r\n requiredTier?: LicenseTier;\r\n upgradeTarget?: LicenseTier;\r\n}\r\n\r\n/**\r\n * Check feature access with detailed result\r\n */\r\nexport function checkFeatureAccess(\r\n license: LicenseInfo | null,\r\n featureId: FeatureId,\r\n): FeatureCheckResult {\r\n if (!license) {\r\n return {\r\n allowed: false,\r\n reason: 'no-license',\r\n requiredTier: 'personal',\r\n };\r\n }\r\n\r\n if (license.status === 'expired') {\r\n return {\r\n allowed: false,\r\n reason: 'expired',\r\n };\r\n }\r\n\r\n const feature = getFeature(featureId);\r\n if (!feature) {\r\n // Unknown feature - check explicit list\r\n return {\r\n allowed: license.features.includes(featureId),\r\n reason: license.features.includes(featureId) ? undefined : 'feature-not-included',\r\n };\r\n }\r\n\r\n if (!tierMeetsRequirement(license.tier, feature.requiredTier)) {\r\n return {\r\n allowed: false,\r\n reason: 'tier-insufficient',\r\n requiredTier: feature.requiredTier,\r\n upgradeTarget: feature.requiredTier,\r\n };\r\n }\r\n\r\n // Check dependencies\r\n if (feature.dependencies) {\r\n for (const dep of feature.dependencies) {\r\n const depResult = checkFeatureAccess(license, dep);\r\n if (!depResult.allowed) {\r\n return depResult;\r\n }\r\n }\r\n }\r\n\r\n return { allowed: true };\r\n}\r\n\r\n// ─── Default Feature Definitions ────────────────────────────────\r\n\r\nconst DEFAULT_FEATURES: FeatureDefinition[] = [\r\n // Core features\r\n {\r\n id: 'core',\r\n name: 'Core Components',\r\n description: 'Basic UI components',\r\n requiredTier: 'trial',\r\n category: 'core',\r\n },\r\n {\r\n id: 'basic-components',\r\n name: 'Basic Components',\r\n description: 'Buttons, inputs, cards',\r\n requiredTier: 'trial',\r\n category: 'core',\r\n },\r\n\r\n // Personal tier\r\n {\r\n id: 'advanced-components',\r\n name: 'Advanced Components',\r\n description: 'Data grids, charts, editors',\r\n requiredTier: 'personal',\r\n category: 'components',\r\n },\r\n {\r\n id: 'theming',\r\n name: 'Custom Theming',\r\n description: 'Theme customization',\r\n requiredTier: 'personal',\r\n category: 'customization',\r\n },\r\n {\r\n id: 'i18n',\r\n name: 'Internationalization',\r\n description: 'Multi-language support',\r\n requiredTier: 'personal',\r\n category: 'customization',\r\n },\r\n\r\n // Team tier\r\n {\r\n id: 'collaboration',\r\n name: 'Collaboration',\r\n description: 'Real-time collaboration features',\r\n requiredTier: 'team',\r\n category: 'team',\r\n },\r\n {\r\n id: 'analytics',\r\n name: 'Analytics',\r\n description: 'Usage analytics dashboard',\r\n requiredTier: 'team',\r\n category: 'team',\r\n },\r\n {\r\n id: 'priority-support',\r\n name: 'Priority Support',\r\n description: '24-hour response time',\r\n requiredTier: 'team',\r\n category: 'support',\r\n },\r\n\r\n // Enterprise tier\r\n {\r\n id: 'white-label',\r\n name: 'White Labeling',\r\n description: 'Remove Nice2Dev branding',\r\n requiredTier: 'enterprise',\r\n category: 'enterprise',\r\n },\r\n {\r\n id: 'sso',\r\n name: 'Single Sign-On',\r\n description: 'SAML/OIDC integration',\r\n requiredTier: 'enterprise',\r\n category: 'enterprise',\r\n },\r\n {\r\n id: 'audit-log',\r\n name: 'Audit Log',\r\n description: 'Detailed activity logging',\r\n requiredTier: 'enterprise',\r\n category: 'enterprise',\r\n },\r\n {\r\n id: 'custom-branding',\r\n name: 'Custom Branding',\r\n description: 'Full brand customization',\r\n requiredTier: 'enterprise',\r\n category: 'enterprise',\r\n },\r\n {\r\n id: 'api-access',\r\n name: 'API Access',\r\n description: 'Full REST API access',\r\n requiredTier: 'enterprise',\r\n category: 'enterprise',\r\n },\r\n\r\n // Site tier\r\n {\r\n id: 'unlimited-seats',\r\n name: 'Unlimited Seats',\r\n description: 'No user limits',\r\n requiredTier: 'site',\r\n category: 'site',\r\n },\r\n {\r\n id: 'source-code-access',\r\n name: 'Source Code Access',\r\n description: 'Access to source code',\r\n requiredTier: 'site',\r\n category: 'site',\r\n },\r\n {\r\n id: 'dedicated-support',\r\n name: 'Dedicated Support',\r\n description: 'Dedicated support engineer',\r\n requiredTier: 'site',\r\n category: 'support',\r\n },\r\n\r\n // OEM tier\r\n {\r\n id: 'redistribution',\r\n name: 'Redistribution Rights',\r\n description: 'Include in your products',\r\n requiredTier: 'oem',\r\n category: 'oem',\r\n },\r\n {\r\n id: 'custom-licensing',\r\n name: 'Custom Licensing',\r\n description: 'Your own license terms',\r\n requiredTier: 'oem',\r\n category: 'oem',\r\n },\r\n\r\n // Trial marker\r\n {\r\n id: 'trial-watermark',\r\n name: 'Trial Watermark',\r\n description: 'Watermark for trial versions',\r\n requiredTier: 'trial',\r\n category: 'trial',\r\n },\r\n\r\n // Game Engine features\r\n {\r\n id: 'game-editor',\r\n name: 'Game Editor',\r\n description: 'Visual game editor',\r\n requiredTier: 'personal',\r\n category: 'game-engine',\r\n },\r\n {\r\n id: 'game-export',\r\n name: 'Game Export',\r\n description: 'Export to various platforms',\r\n requiredTier: 'team',\r\n category: 'game-engine',\r\n },\r\n {\r\n id: 'game-multiplayer',\r\n name: 'Multiplayer',\r\n description: 'Online multiplayer support',\r\n requiredTier: 'team',\r\n category: 'game-engine',\r\n },\r\n {\r\n id: 'game-build-cloud',\r\n name: 'Build Cloud',\r\n description: 'Cloud compilation for games',\r\n requiredTier: 'enterprise',\r\n category: 'game-engine',\r\n },\r\n\r\n // Spatial features\r\n {\r\n id: 'spatial-editor',\r\n name: 'Spatial Editor',\r\n description: 'Floor plan editor',\r\n requiredTier: 'personal',\r\n category: 'spatial',\r\n },\r\n {\r\n id: 'spatial-3d',\r\n name: '3D Visualization',\r\n description: '3D building visualization',\r\n requiredTier: 'team',\r\n category: 'spatial',\r\n },\r\n {\r\n id: 'spatial-bim',\r\n name: 'BIM Integration',\r\n description: 'IFC/BIM file support',\r\n requiredTier: 'enterprise',\r\n category: 'spatial',\r\n },\r\n];\r\n\r\nconst DEFAULT_PLANS: LicensePlan[] = [\r\n {\r\n id: 'trial',\r\n name: 'Trial',\r\n description: '14-day free trial with all features',\r\n priceMonthly: 0,\r\n priceYearly: 0,\r\n features: ['core', 'basic-components', 'trial-watermark'],\r\n maxSeats: 1,\r\n maxMachines: 1,\r\n highlights: ['All features for 14 days', 'No credit card required'],\r\n },\r\n {\r\n id: 'personal',\r\n name: 'Personal',\r\n description: 'For individual developers',\r\n priceMonthly: 1900, // $19\r\n priceYearly: 15900, // $159 (2 months free)\r\n features: ['core', 'basic-components', 'advanced-components', 'theming', 'i18n'],\r\n maxSeats: 1,\r\n maxMachines: 2,\r\n highlights: ['All UI components', 'Custom theming', 'Email support'],\r\n },\r\n {\r\n id: 'team',\r\n name: 'Team',\r\n description: 'For small to medium teams',\r\n priceMonthly: 4900, // $49/seat\r\n priceYearly: 41900, // $419/seat\r\n features: [\r\n 'core',\r\n 'basic-components',\r\n 'advanced-components',\r\n 'theming',\r\n 'i18n',\r\n 'collaboration',\r\n 'analytics',\r\n 'priority-support',\r\n ],\r\n maxSeats: 10,\r\n maxMachines: 20,\r\n highlights: ['Up to 10 seats', 'Collaboration tools', 'Priority support'],\r\n recommended: true,\r\n },\r\n {\r\n id: 'enterprise',\r\n name: 'Enterprise',\r\n description: 'For large organizations',\r\n priceMonthly: 19900, // $199/month base\r\n priceYearly: 199900, // $1999/year\r\n features: [\r\n 'core',\r\n 'basic-components',\r\n 'advanced-components',\r\n 'theming',\r\n 'i18n',\r\n 'collaboration',\r\n 'analytics',\r\n 'priority-support',\r\n 'white-label',\r\n 'sso',\r\n 'audit-log',\r\n 'custom-branding',\r\n 'api-access',\r\n ],\r\n maxSeats: 50,\r\n maxMachines: 100,\r\n highlights: ['Up to 50 seats', 'SSO & SAML', 'White labeling', 'API access'],\r\n },\r\n {\r\n id: 'site',\r\n name: 'Site License',\r\n description: 'Unlimited usage for your organization',\r\n priceMonthly: 0, // Contact sales\r\n priceYearly: 0,\r\n features: [\r\n 'core',\r\n 'basic-components',\r\n 'advanced-components',\r\n 'theming',\r\n 'i18n',\r\n 'collaboration',\r\n 'analytics',\r\n 'priority-support',\r\n 'white-label',\r\n 'sso',\r\n 'audit-log',\r\n 'custom-branding',\r\n 'api-access',\r\n 'unlimited-seats',\r\n 'source-code-access',\r\n 'dedicated-support',\r\n ],\r\n maxSeats: null,\r\n maxMachines: 1000,\r\n highlights: ['Unlimited seats', 'Source code access', 'Dedicated support engineer'],\r\n },\r\n {\r\n id: 'oem',\r\n name: 'OEM',\r\n description: 'Embed in your products',\r\n priceMonthly: 0, // Contact sales\r\n priceYearly: 0,\r\n features: [\r\n 'core',\r\n 'basic-components',\r\n 'advanced-components',\r\n 'theming',\r\n 'i18n',\r\n 'collaboration',\r\n 'analytics',\r\n 'priority-support',\r\n 'white-label',\r\n 'sso',\r\n 'audit-log',\r\n 'custom-branding',\r\n 'api-access',\r\n 'unlimited-seats',\r\n 'source-code-access',\r\n 'dedicated-support',\r\n 'redistribution',\r\n 'custom-licensing',\r\n ],\r\n maxSeats: null,\r\n maxMachines: 10000,\r\n highlights: ['Redistribution rights', 'Custom licensing', 'Full support'],\r\n },\r\n];\r\n\r\n/**\r\n * Initialize default features and plans\r\n */\r\nexport function initializeDefaults(): void {\r\n registerFeatures(DEFAULT_FEATURES);\r\n registerPlans(DEFAULT_PLANS);\r\n}\r\n\r\n// Auto-initialize\r\ninitializeDefaults();\r\n"],"names":["data"],"mappings":"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"}