@usertour/helpers 0.0.9 → 0.0.11
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/dist/globals.d.cts +1 -1
- package/dist/globals.d.ts +1 -1
- package/dist/index.cjs +2 -913
- package/dist/index.d.cts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +20 -71
- package/package.json +7 -17
- package/dist/chunk-7IK5Q5N2.js +0 -591
- package/dist/chunk-DEG6MTU7.js +0 -318
- package/dist/chunk-HWWIAVVP.js +0 -112
- package/dist/chunk-Y5PCSFVZ.js +0 -183
- package/dist/chunk-Y6FPPOKF.js +0 -28
- package/dist/conditions.cjs +0 -1001
- package/dist/conditions.d.cts +0 -23
- package/dist/conditions.d.ts +0 -23
- package/dist/conditions.js +0 -45
- package/dist/finderx.cjs +0 -346
- package/dist/finderx.d.cts +0 -47
- package/dist/finderx.d.ts +0 -47
- package/dist/finderx.js +0 -15
- package/dist/jwt-license-signer.cjs +0 -147
- package/dist/jwt-license-signer.d.cts +0 -61
- package/dist/jwt-license-signer.d.ts +0 -61
- package/dist/jwt-license-signer.js +0 -7
- package/dist/jwt-license-validator.cjs +0 -217
- package/dist/jwt-license-validator.d.cts +0 -54
- package/dist/jwt-license-validator.d.ts +0 -54
- package/dist/jwt-license-validator.js +0 -7
- package/dist/listener.cjs +0 -68
- package/dist/listener.d.cts +0 -7
- package/dist/listener.d.ts +0 -7
- package/dist/listener.js +0 -16
- package/dist/server.cjs +0 -331
- package/dist/server.d.cts +0 -4
- package/dist/server.d.ts +0 -4
- package/dist/server.js +0 -11
package/dist/chunk-DEG6MTU7.js
DELETED
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
// src/finderx.ts
|
|
2
|
-
import { finder as finderLib } from "@medv/finder";
|
|
3
|
-
var finderAttrs = [
|
|
4
|
-
"data-for",
|
|
5
|
-
"data-id",
|
|
6
|
-
"data-testid",
|
|
7
|
-
"data-test-id",
|
|
8
|
-
"for",
|
|
9
|
-
"id",
|
|
10
|
-
"name",
|
|
11
|
-
"placeholder",
|
|
12
|
-
"role"
|
|
13
|
-
];
|
|
14
|
-
var defaultConfig = {
|
|
15
|
-
idName: () => false,
|
|
16
|
-
className: () => false,
|
|
17
|
-
tagName: () => false,
|
|
18
|
-
attr: () => false,
|
|
19
|
-
seedMinLength: 1,
|
|
20
|
-
optimizedMinLength: 2,
|
|
21
|
-
threshold: 1e3,
|
|
22
|
-
maxNumberOfTries: 1e4
|
|
23
|
-
};
|
|
24
|
-
var finderConfigs = [
|
|
25
|
-
{
|
|
26
|
-
...defaultConfig,
|
|
27
|
-
tagName: () => true
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
...defaultConfig,
|
|
31
|
-
idName: () => true
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
...defaultConfig,
|
|
35
|
-
tagName: () => true,
|
|
36
|
-
attr: (name) => finderAttrs.includes(name)
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
...defaultConfig,
|
|
40
|
-
className: () => true,
|
|
41
|
-
attr: (name) => finderAttrs.includes(name)
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
...defaultConfig,
|
|
45
|
-
tagName: () => true,
|
|
46
|
-
idName: () => true,
|
|
47
|
-
className: () => true,
|
|
48
|
-
attr: () => false
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
...defaultConfig,
|
|
52
|
-
tagName: () => true,
|
|
53
|
-
idName: () => true,
|
|
54
|
-
className: () => true,
|
|
55
|
-
attr: (name) => finderAttrs.includes(name)
|
|
56
|
-
}
|
|
57
|
-
];
|
|
58
|
-
function getMaxDepth(node) {
|
|
59
|
-
if (node.parentNode) {
|
|
60
|
-
return getMaxDepth(node.parentNode);
|
|
61
|
-
}
|
|
62
|
-
return node.depth;
|
|
63
|
-
}
|
|
64
|
-
function queryNodeListBySelectors(selectors, rootDocument, removeRepeat = true) {
|
|
65
|
-
const nodes = [];
|
|
66
|
-
if (!selectors) {
|
|
67
|
-
return nodes;
|
|
68
|
-
}
|
|
69
|
-
for (const s of selectors) {
|
|
70
|
-
const els = rootDocument.querySelectorAll(s.replace(/\\\\/g, "\\"));
|
|
71
|
-
if (els && els.length > 0) {
|
|
72
|
-
nodes.push(...Array.from(els));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return removeRepeat ? [...new Set(nodes)] : nodes;
|
|
76
|
-
}
|
|
77
|
-
function findMostRecurringNode(nodes) {
|
|
78
|
-
const m = /* @__PURE__ */ new Map();
|
|
79
|
-
let finalNode = nodes[0];
|
|
80
|
-
let count = 0;
|
|
81
|
-
for (const node of nodes) {
|
|
82
|
-
const i = m.get(node) ? m.get(node) + 1 : 1;
|
|
83
|
-
m.set(node, i);
|
|
84
|
-
}
|
|
85
|
-
m.forEach((value, key) => {
|
|
86
|
-
if (value > count) {
|
|
87
|
-
count = value;
|
|
88
|
-
finalNode = key;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
return finalNode;
|
|
92
|
-
}
|
|
93
|
-
function compareParentNode(node, el, rootDocument, isCompareSibings = false) {
|
|
94
|
-
let nodeParentNode = node.parentNode;
|
|
95
|
-
let elParentElement = el.parentElement;
|
|
96
|
-
const maxDepth = getMaxDepth(node);
|
|
97
|
-
const xresult = {
|
|
98
|
-
maxDepth,
|
|
99
|
-
failedDepth: 0,
|
|
100
|
-
success: true
|
|
101
|
-
};
|
|
102
|
-
while (nodeParentNode && elParentElement) {
|
|
103
|
-
if (elParentElement === rootDocument) {
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
if (elParentElement === document.body || elParentElement === document.documentElement || elParentElement.parentElement === document.body) {
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
const parentNodes = queryNodeListBySelectors(nodeParentNode.selectors, rootDocument);
|
|
110
|
-
const isMatchSibings = isCompareSibings ? compareSibingsNode(nodeParentNode, elParentElement, rootDocument) : true;
|
|
111
|
-
if (!parentNodes || parentNodes.length === 0 || !parentNodes.includes(elParentElement) || !isMatchSibings) {
|
|
112
|
-
xresult.failedDepth = nodeParentNode.depth;
|
|
113
|
-
xresult.success = false;
|
|
114
|
-
}
|
|
115
|
-
nodeParentNode = nodeParentNode.parentNode;
|
|
116
|
-
elParentElement = elParentElement.parentElement;
|
|
117
|
-
}
|
|
118
|
-
return xresult;
|
|
119
|
-
}
|
|
120
|
-
function compareSibingsNode(node, el, rootDocument) {
|
|
121
|
-
let isMatchNext = true;
|
|
122
|
-
let isMatchPrevious = true;
|
|
123
|
-
const { previousElementSelectors, nextElementSelectors } = node;
|
|
124
|
-
if (nextElementSelectors && nextElementSelectors.length > 0) {
|
|
125
|
-
const nextElementSiblings = queryNodeListBySelectors(nextElementSelectors, rootDocument);
|
|
126
|
-
isMatchNext = el.nextElementSibling && nextElementSiblings.includes(el.nextElementSibling);
|
|
127
|
-
}
|
|
128
|
-
if (previousElementSelectors && previousElementSelectors.length > 0) {
|
|
129
|
-
const previousElementSiblings = queryNodeListBySelectors(
|
|
130
|
-
previousElementSelectors,
|
|
131
|
-
rootDocument
|
|
132
|
-
);
|
|
133
|
-
isMatchPrevious = el.previousElementSibling && previousElementSiblings.includes(el.previousElementSibling);
|
|
134
|
-
}
|
|
135
|
-
return isMatchNext && isMatchPrevious;
|
|
136
|
-
}
|
|
137
|
-
function queryElementSelectors(input) {
|
|
138
|
-
const classes = Array.from(input.classList);
|
|
139
|
-
const selectors = [];
|
|
140
|
-
const configs = [...finderConfigs];
|
|
141
|
-
for (const className of classes) {
|
|
142
|
-
configs.push({
|
|
143
|
-
...defaultConfig,
|
|
144
|
-
className: (name) => {
|
|
145
|
-
if (classes.filter((cn) => cn !== className).includes(name)) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
try {
|
|
153
|
-
for (const cfg of configs) {
|
|
154
|
-
selectors.push(finder(input, cfg));
|
|
155
|
-
}
|
|
156
|
-
} catch (_) {
|
|
157
|
-
return selectors;
|
|
158
|
-
}
|
|
159
|
-
return [...new Set(selectors)];
|
|
160
|
-
}
|
|
161
|
-
function parseSelectorsTree(input, parentNode, depth = 0) {
|
|
162
|
-
const selectors = queryElementSelectors(input);
|
|
163
|
-
if (selectors.length === 0) {
|
|
164
|
-
return parentNode;
|
|
165
|
-
}
|
|
166
|
-
const currentNode = {
|
|
167
|
-
previousElementSelectors: [],
|
|
168
|
-
nextElementSelectors: [],
|
|
169
|
-
selectors,
|
|
170
|
-
depth
|
|
171
|
-
};
|
|
172
|
-
if (input.previousElementSibling) {
|
|
173
|
-
currentNode.previousElementSelectors = queryElementSelectors(input.previousElementSibling);
|
|
174
|
-
}
|
|
175
|
-
if (input.nextElementSibling) {
|
|
176
|
-
currentNode.nextElementSelectors = queryElementSelectors(input.nextElementSibling);
|
|
177
|
-
}
|
|
178
|
-
if (parentNode === null) {
|
|
179
|
-
if (input.parentElement) {
|
|
180
|
-
parseSelectorsTree(input.parentElement, currentNode, depth + 1);
|
|
181
|
-
}
|
|
182
|
-
return currentNode;
|
|
183
|
-
}
|
|
184
|
-
parentNode.parentNode = currentNode;
|
|
185
|
-
if (input.parentElement) {
|
|
186
|
-
parseSelectorsTree(input.parentElement, currentNode, depth + 1);
|
|
187
|
-
}
|
|
188
|
-
return parentNode;
|
|
189
|
-
}
|
|
190
|
-
function finderMostPrecisionElement(elements, node, rootDocument, precision) {
|
|
191
|
-
const successEls = [];
|
|
192
|
-
let failedData = {
|
|
193
|
-
el: null,
|
|
194
|
-
failedDepth: 0,
|
|
195
|
-
maxDepth: 0
|
|
196
|
-
};
|
|
197
|
-
for (const el of elements) {
|
|
198
|
-
const { success, failedDepth, maxDepth } = compareParentNode(node, el, rootDocument);
|
|
199
|
-
if (success) {
|
|
200
|
-
successEls.push(el);
|
|
201
|
-
} else if (!failedData.el || failedDepth > failedData.failedDepth) {
|
|
202
|
-
failedData = { el, failedDepth, maxDepth };
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (successEls.length === 1) {
|
|
206
|
-
return successEls[0];
|
|
207
|
-
}
|
|
208
|
-
if (successEls.length > 1) {
|
|
209
|
-
let tempEl = successEls[0];
|
|
210
|
-
let tempFailedDepth = 0;
|
|
211
|
-
for (const el of successEls) {
|
|
212
|
-
const { success, failedDepth } = compareParentNode(node, el, rootDocument, true);
|
|
213
|
-
if (success) {
|
|
214
|
-
return el;
|
|
215
|
-
}
|
|
216
|
-
if (failedDepth > tempFailedDepth) {
|
|
217
|
-
tempFailedDepth = failedDepth;
|
|
218
|
-
tempEl = el;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return tempEl;
|
|
222
|
-
}
|
|
223
|
-
if (failedData.el) {
|
|
224
|
-
const { failedDepth, maxDepth, el } = failedData;
|
|
225
|
-
const rate = (failedDepth - 1) / maxDepth * 10;
|
|
226
|
-
if (rate >= precision) {
|
|
227
|
-
return el;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
function finder(input, options) {
|
|
233
|
-
return finderLib(input, options);
|
|
234
|
-
}
|
|
235
|
-
function parserX(input) {
|
|
236
|
-
return parseSelectorsTree(input, null);
|
|
237
|
-
}
|
|
238
|
-
function parserV2(element) {
|
|
239
|
-
var _a;
|
|
240
|
-
const content = (_a = element.innerText) != null ? _a : "";
|
|
241
|
-
const selectors = parseSelectorsTree(element, null);
|
|
242
|
-
const selectorsList = queryElementSelectors(element);
|
|
243
|
-
return { content, selectors, selectorsList };
|
|
244
|
-
}
|
|
245
|
-
function finderV2(target, root) {
|
|
246
|
-
const {
|
|
247
|
-
selectors,
|
|
248
|
-
content = "",
|
|
249
|
-
sequence = 0,
|
|
250
|
-
precision = "strict",
|
|
251
|
-
isDynamicContent = false,
|
|
252
|
-
customSelector = "",
|
|
253
|
-
type = "auto"
|
|
254
|
-
} = target;
|
|
255
|
-
if (type === "auto") {
|
|
256
|
-
const mapping = {
|
|
257
|
-
looser: 1,
|
|
258
|
-
loose: 3,
|
|
259
|
-
loosest: 5,
|
|
260
|
-
strict: 7,
|
|
261
|
-
stricter: 8,
|
|
262
|
-
strictest: 10
|
|
263
|
-
};
|
|
264
|
-
const el = finderX(selectors, root, mapping[precision]);
|
|
265
|
-
if (el) {
|
|
266
|
-
if (isDynamicContent && content && el.innerText !== content) {
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
269
|
-
return el;
|
|
270
|
-
}
|
|
271
|
-
} else {
|
|
272
|
-
const sequenceMapping = {
|
|
273
|
-
"1st": 0,
|
|
274
|
-
"2st": 1,
|
|
275
|
-
"3st": 2,
|
|
276
|
-
"4st": 3,
|
|
277
|
-
"5st": 4
|
|
278
|
-
};
|
|
279
|
-
if (customSelector) {
|
|
280
|
-
const selector = customSelector.replace(/\\\\/g, "\\");
|
|
281
|
-
const els = root.querySelectorAll(selector);
|
|
282
|
-
if (els.length > 0) {
|
|
283
|
-
const el = els[sequenceMapping[sequence]] || els[0];
|
|
284
|
-
if (content && el.innerText.trim() !== content) {
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
return el;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
function finderX(node, root, precision = 10) {
|
|
294
|
-
if (!node || node.selectors.length === 0) {
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
297
|
-
const rootDocument = root || document;
|
|
298
|
-
const elements = [];
|
|
299
|
-
const nodeList = queryNodeListBySelectors(node.selectors, rootDocument, false);
|
|
300
|
-
if (!nodeList || nodeList.length === 0) {
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
if ([...new Set(nodeList)].length !== nodeList.length) {
|
|
304
|
-
const el = findMostRecurringNode(nodeList);
|
|
305
|
-
elements.push(el);
|
|
306
|
-
} else {
|
|
307
|
-
elements.push(...nodeList);
|
|
308
|
-
}
|
|
309
|
-
return finderMostPrecisionElement(elements, node, rootDocument, precision);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
export {
|
|
313
|
-
finder,
|
|
314
|
-
parserX,
|
|
315
|
-
parserV2,
|
|
316
|
-
finderV2,
|
|
317
|
-
finderX
|
|
318
|
-
};
|
package/dist/chunk-HWWIAVVP.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__publicField
|
|
3
|
-
} from "./chunk-XEO3YXBM.js";
|
|
4
|
-
|
|
5
|
-
// src/jwt-license-signer.ts
|
|
6
|
-
import * as fs from "fs";
|
|
7
|
-
import * as path from "path";
|
|
8
|
-
import jwt from "jsonwebtoken";
|
|
9
|
-
var JWTLicenseSigner = class {
|
|
10
|
-
constructor(options) {
|
|
11
|
-
__publicField(this, "privateKey");
|
|
12
|
-
__publicField(this, "issuer");
|
|
13
|
-
__publicField(this, "algorithm");
|
|
14
|
-
this.privateKey = this.loadPrivateKey(options.privateKeyPath);
|
|
15
|
-
this.issuer = options.issuer || "https://www.usertour.io";
|
|
16
|
-
this.algorithm = options.algorithm || "RS256";
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Load RSA private key from file
|
|
20
|
-
*/
|
|
21
|
-
loadPrivateKey(keyPath) {
|
|
22
|
-
try {
|
|
23
|
-
const fullPath = path.resolve(keyPath);
|
|
24
|
-
return fs.readFileSync(fullPath, "utf8");
|
|
25
|
-
} catch (error) {
|
|
26
|
-
throw new Error(`Failed to load private key from ${keyPath}: ${error}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Generate a JWT license token
|
|
31
|
-
*/
|
|
32
|
-
generateLicense(options) {
|
|
33
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
34
|
-
const expiresAt = now + options.expiresInDays * 24 * 60 * 60;
|
|
35
|
-
const payload = {
|
|
36
|
-
plan: options.plan,
|
|
37
|
-
sub: options.subject,
|
|
38
|
-
projectId: options.projectId,
|
|
39
|
-
iat: now,
|
|
40
|
-
exp: expiresAt,
|
|
41
|
-
issuer: options.issuer || this.issuer,
|
|
42
|
-
features: options.features
|
|
43
|
-
};
|
|
44
|
-
try {
|
|
45
|
-
return jwt.sign(payload, this.privateKey, {
|
|
46
|
-
algorithm: this.algorithm,
|
|
47
|
-
issuer: this.issuer
|
|
48
|
-
});
|
|
49
|
-
} catch (error) {
|
|
50
|
-
throw new Error(`Failed to generate JWT license: ${error}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Generate a license and return both token and payload info
|
|
55
|
-
*/
|
|
56
|
-
generateLicenseWithInfo(options) {
|
|
57
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
58
|
-
const expiresAt = now + options.expiresInDays * 24 * 60 * 60;
|
|
59
|
-
const payload = {
|
|
60
|
-
plan: options.plan,
|
|
61
|
-
sub: options.subject,
|
|
62
|
-
projectId: options.projectId,
|
|
63
|
-
iat: now,
|
|
64
|
-
exp: expiresAt,
|
|
65
|
-
issuer: options.issuer || this.issuer,
|
|
66
|
-
features: options.features
|
|
67
|
-
};
|
|
68
|
-
const token = jwt.sign(payload, this.privateKey, {
|
|
69
|
-
algorithm: this.algorithm,
|
|
70
|
-
issuer: this.issuer
|
|
71
|
-
});
|
|
72
|
-
return {
|
|
73
|
-
token,
|
|
74
|
-
payload,
|
|
75
|
-
expiresAt: new Date(expiresAt * 1e3)
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Decode a JWT token without verification (for debugging)
|
|
80
|
-
*/
|
|
81
|
-
decodeToken(token) {
|
|
82
|
-
try {
|
|
83
|
-
return jwt.decode(token);
|
|
84
|
-
} catch (error) {
|
|
85
|
-
console.error("Failed to decode JWT token:", error);
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Get token information without verification
|
|
91
|
-
*/
|
|
92
|
-
getTokenInfo(token) {
|
|
93
|
-
try {
|
|
94
|
-
const decoded = jwt.decode(token, { complete: true });
|
|
95
|
-
if (!decoded || typeof decoded === "string") {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
return {
|
|
99
|
-
header: decoded.header,
|
|
100
|
-
payload: decoded.payload,
|
|
101
|
-
signature: decoded.signature
|
|
102
|
-
};
|
|
103
|
-
} catch (error) {
|
|
104
|
-
console.error("Failed to get token info:", error);
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export {
|
|
111
|
-
JWTLicenseSigner
|
|
112
|
-
};
|
package/dist/chunk-Y5PCSFVZ.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
// src/jwt-license-validator.ts
|
|
2
|
-
import jwt from "jsonwebtoken";
|
|
3
|
-
var JWTLicenseValidator = {
|
|
4
|
-
/**
|
|
5
|
-
* Validate a JWT license
|
|
6
|
-
* @param license - JWT license string
|
|
7
|
-
* @param publicKey - RSA public key in PEM format
|
|
8
|
-
* @param options - Validation options
|
|
9
|
-
* @returns Validation result
|
|
10
|
-
*/
|
|
11
|
-
validateLicense(license, publicKey, options = {}) {
|
|
12
|
-
try {
|
|
13
|
-
const { checkExpiration = true, currentTime = /* @__PURE__ */ new Date() } = options;
|
|
14
|
-
const decoded = jwt.verify(license, publicKey, {
|
|
15
|
-
algorithms: ["RS256"],
|
|
16
|
-
ignoreExpiration: !checkExpiration
|
|
17
|
-
});
|
|
18
|
-
const fieldValidation = this.validateRequiredFields(decoded);
|
|
19
|
-
if (!fieldValidation.isValid) {
|
|
20
|
-
return fieldValidation;
|
|
21
|
-
}
|
|
22
|
-
if (checkExpiration) {
|
|
23
|
-
const expirationValidation = this.checkExpiration(decoded, currentTime);
|
|
24
|
-
if (!expirationValidation.isValid) {
|
|
25
|
-
return expirationValidation;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const hasFeature = (feature) => {
|
|
29
|
-
return decoded.features.includes("*") || decoded.features.includes(feature);
|
|
30
|
-
};
|
|
31
|
-
return {
|
|
32
|
-
isValid: true,
|
|
33
|
-
payload: decoded,
|
|
34
|
-
isExpired: false,
|
|
35
|
-
hasFeature
|
|
36
|
-
};
|
|
37
|
-
} catch (error) {
|
|
38
|
-
if (error instanceof jwt.JsonWebTokenError) {
|
|
39
|
-
return {
|
|
40
|
-
isValid: false,
|
|
41
|
-
error: `JWT validation failed: ${error.message}`
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
if (error instanceof jwt.TokenExpiredError) {
|
|
45
|
-
return {
|
|
46
|
-
isValid: false,
|
|
47
|
-
error: `License expired: ${error.message}`,
|
|
48
|
-
isExpired: true
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
isValid: false,
|
|
53
|
-
error: `License validation failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
/**
|
|
58
|
-
* Validate that all required fields are present in license payload
|
|
59
|
-
* @param payload - License payload to validate
|
|
60
|
-
* @returns Validation result
|
|
61
|
-
*/
|
|
62
|
-
validateRequiredFields(payload) {
|
|
63
|
-
const requiredFields = ["plan", "sub", "projectId", "iat", "exp", "issuer", "features"];
|
|
64
|
-
for (const field of requiredFields) {
|
|
65
|
-
if (!(field in payload)) {
|
|
66
|
-
return {
|
|
67
|
-
isValid: false,
|
|
68
|
-
error: `Missing required field: ${field}`
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (typeof payload.plan !== "string" || !payload.plan.trim()) {
|
|
73
|
-
return {
|
|
74
|
-
isValid: false,
|
|
75
|
-
error: "Invalid plan: must be a non-empty string"
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
if (typeof payload.sub !== "string" || !payload.sub.trim()) {
|
|
79
|
-
return {
|
|
80
|
-
isValid: false,
|
|
81
|
-
error: "Invalid sub: must be a non-empty string"
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
if (typeof payload.projectId !== "string" || !payload.projectId.trim()) {
|
|
85
|
-
return {
|
|
86
|
-
isValid: false,
|
|
87
|
-
error: "Invalid projectId: must be a non-empty string"
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
if (typeof payload.issuer !== "string" || !payload.issuer.trim()) {
|
|
91
|
-
return {
|
|
92
|
-
isValid: false,
|
|
93
|
-
error: "Invalid issuer: must be a non-empty string"
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
if (!Array.isArray(payload.features)) {
|
|
97
|
-
return {
|
|
98
|
-
isValid: false,
|
|
99
|
-
error: "Invalid features: must be an array"
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
if (typeof payload.iat !== "number" || payload.iat <= 0) {
|
|
103
|
-
return {
|
|
104
|
-
isValid: false,
|
|
105
|
-
error: "Invalid iat: must be a positive number"
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
if (typeof payload.exp !== "number" || payload.exp <= 0) {
|
|
109
|
-
return {
|
|
110
|
-
isValid: false,
|
|
111
|
-
error: "Invalid exp: must be a positive number"
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
if (payload.iat >= payload.exp) {
|
|
115
|
-
return {
|
|
116
|
-
isValid: false,
|
|
117
|
-
error: "Invalid timestamps: iat must be before exp"
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
return { isValid: true };
|
|
121
|
-
},
|
|
122
|
-
/**
|
|
123
|
-
* Check if license has expired
|
|
124
|
-
* @param payload - License payload
|
|
125
|
-
* @param currentTime - Current time to check against (defaults to now)
|
|
126
|
-
* @returns Validation result
|
|
127
|
-
*/
|
|
128
|
-
checkExpiration(payload, currentTime = /* @__PURE__ */ new Date()) {
|
|
129
|
-
const now = Math.floor(currentTime.getTime() / 1e3);
|
|
130
|
-
const expiresAt = payload.exp;
|
|
131
|
-
if (now > expiresAt) {
|
|
132
|
-
return {
|
|
133
|
-
isValid: false,
|
|
134
|
-
error: `License expired on ${new Date(expiresAt * 1e3).toISOString()}`,
|
|
135
|
-
isExpired: true
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return { isValid: true, isExpired: false };
|
|
139
|
-
},
|
|
140
|
-
/**
|
|
141
|
-
* Check if license has a specific feature
|
|
142
|
-
* @param payload - License payload
|
|
143
|
-
* @param feature - Feature to check
|
|
144
|
-
* @returns Whether the feature is available
|
|
145
|
-
*/
|
|
146
|
-
hasFeature(payload, feature) {
|
|
147
|
-
return payload.features.includes("*") || payload.features.includes(feature);
|
|
148
|
-
},
|
|
149
|
-
/**
|
|
150
|
-
* Get license expiration status
|
|
151
|
-
* @param payload - License payload
|
|
152
|
-
* @param currentTime - Current time to check against (defaults to now)
|
|
153
|
-
* @returns Expiration information
|
|
154
|
-
*/
|
|
155
|
-
getExpirationInfo(payload, currentTime = /* @__PURE__ */ new Date()) {
|
|
156
|
-
const now = Math.floor(currentTime.getTime() / 1e3);
|
|
157
|
-
const expiresAt = payload.exp;
|
|
158
|
-
const isExpired = now > expiresAt;
|
|
159
|
-
const daysUntilExpiration = Math.ceil((expiresAt - now) / (24 * 60 * 60));
|
|
160
|
-
return {
|
|
161
|
-
isExpired,
|
|
162
|
-
expiresAt: new Date(expiresAt * 1e3),
|
|
163
|
-
daysUntilExpiration: isExpired ? 0 : daysUntilExpiration
|
|
164
|
-
};
|
|
165
|
-
},
|
|
166
|
-
/**
|
|
167
|
-
* Decode JWT license without verification (for debugging)
|
|
168
|
-
* @param license - JWT license string
|
|
169
|
-
* @returns Decoded payload or null if invalid
|
|
170
|
-
*/
|
|
171
|
-
decodeLicense(license) {
|
|
172
|
-
try {
|
|
173
|
-
const decoded = jwt.decode(license);
|
|
174
|
-
return decoded;
|
|
175
|
-
} catch {
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
export {
|
|
182
|
-
JWTLicenseValidator
|
|
183
|
-
};
|
package/dist/chunk-Y6FPPOKF.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
navigator,
|
|
3
|
-
win
|
|
4
|
-
} from "./chunk-H7VA3ML2.js";
|
|
5
|
-
|
|
6
|
-
// src/listener.ts
|
|
7
|
-
var noop = () => {
|
|
8
|
-
};
|
|
9
|
-
function on(obj, ...args) {
|
|
10
|
-
if (obj == null ? void 0 : obj.addEventListener) {
|
|
11
|
-
obj.addEventListener(...args);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
function off(obj, ...args) {
|
|
15
|
-
if (obj == null ? void 0 : obj.removeEventListener) {
|
|
16
|
-
obj.removeEventListener(...args);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
var isBrowser = typeof win !== "undefined";
|
|
20
|
-
var isNavigator = typeof navigator !== "undefined";
|
|
21
|
-
|
|
22
|
-
export {
|
|
23
|
-
noop,
|
|
24
|
-
on,
|
|
25
|
-
off,
|
|
26
|
-
isBrowser,
|
|
27
|
-
isNavigator
|
|
28
|
-
};
|