cynx-lib 1.3.85 → 1.3.87

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cynx-lib",
3
- "version": "1.3.85",
3
+ "version": "1.3.87",
4
4
  "type": "module",
5
5
  "main": "./index.cjs",
6
6
  "module": "./index.js",
@@ -38,8 +38,8 @@
38
38
  "require": "./utils/utils/storage_manager.cjs"
39
39
  },
40
40
  "./session": {
41
- "import": "./utils/utils/session_manager.js",
42
- "require": "./utils/utils/session_manager.cjs"
41
+ "import": "./utils/utils/session.js",
42
+ "require": "./utils/utils/session.cjs"
43
43
  },
44
44
  "./gen": "./gen.js"
45
45
  },
@@ -24,8 +24,10 @@ __export(session_exports, {
24
24
  extractToken: () => import_session_manager.extractToken,
25
25
  formatToken: () => import_session_manager.formatToken,
26
26
  genSessionToken: () => genSessionToken,
27
+ getDeviceLabel: () => getDeviceLabel,
27
28
  getSessionId: () => import_session_manager.getSessionId,
28
- parseToken: () => import_session_manager.parseToken
29
+ parseToken: () => import_session_manager.parseToken,
30
+ parseUserAgent: () => parseUserAgent
29
31
  });
30
32
  module.exports = __toCommonJS(session_exports);
31
33
  var import_uid = require("./uid.cjs");
@@ -38,6 +40,71 @@ function genSessionToken(byteLength = 32) {
38
40
  }
39
41
  return `st_${hex}`;
40
42
  }
43
+ function getDeviceLabel(ua) {
44
+ if (!ua) return "PC";
45
+ if (/windows phone/i.test(ua)) return "Windows Phone";
46
+ if (/windows nt 10\.0/i.test(ua)) return "Windows 10/11 PC";
47
+ if (/windows nt 6\.3/i.test(ua)) return "Windows 8.1 PC";
48
+ if (/windows nt 6\.1/i.test(ua)) return "Windows 7 PC";
49
+ if (/win64|win32|windows/i.test(ua)) return "Windows PC";
50
+ if (/ipad/i.test(ua)) return "iPad";
51
+ if (/iphone/i.test(ua)) return "iPhone";
52
+ if (/macintosh|mac os x/i.test(ua)) return "MacBook / Mac";
53
+ if (/android/i.test(ua)) return /mobile/i.test(ua) ? "Android Phone" : "Android Tablet";
54
+ if (/cros/i.test(ua)) return "Chromebook";
55
+ if (/linux/i.test(ua)) return "Linux PC";
56
+ return "Desktop PC";
57
+ }
58
+ function parseUserAgent(ua) {
59
+ if (!ua) return { browser: "Unknown", os: "Unknown", deviceType: "desktop" };
60
+ let os = "Unknown";
61
+ let browser = "Unknown";
62
+ let deviceType = "desktop";
63
+ if (/windows phone/i.test(ua)) {
64
+ os = "Windows Phone";
65
+ deviceType = "mobile";
66
+ } else if (/win64|win32|windows/i.test(ua)) {
67
+ os = "Windows";
68
+ deviceType = "desktop";
69
+ } else if (/ipad/i.test(ua)) {
70
+ os = "iPadOS";
71
+ deviceType = "tablet";
72
+ } else if (/iphone|ipod/i.test(ua)) {
73
+ os = "iOS";
74
+ deviceType = "mobile";
75
+ } else if (/android/i.test(ua)) {
76
+ os = "Android";
77
+ deviceType = /mobile/i.test(ua) ? "mobile" : "tablet";
78
+ } else if (/macintosh|mac os x/i.test(ua)) {
79
+ os = "macOS";
80
+ deviceType = "desktop";
81
+ } else if (/cros/i.test(ua)) {
82
+ os = "Chrome OS";
83
+ deviceType = "desktop";
84
+ } else if (/linux/i.test(ua)) {
85
+ os = "Linux";
86
+ deviceType = "desktop";
87
+ }
88
+ if (/edg\//i.test(ua)) {
89
+ const m = ua.match(/edg\/(\d+)/i);
90
+ browser = m ? `Edge ${m[1]}` : "Edge";
91
+ } else if (/opr\/|opera/i.test(ua)) {
92
+ const m = ua.match(/(?:opr|opera)\/(\d+)/i);
93
+ browser = m ? `Opera ${m[1]}` : "Opera";
94
+ } else if (/chrome|crios/i.test(ua)) {
95
+ const m = ua.match(/(?:chrome|crios)\/(\d+)/i);
96
+ browser = m ? `Chrome ${m[1]}` : "Chrome";
97
+ } else if (/firefox|fxios/i.test(ua)) {
98
+ const m = ua.match(/(?:firefox|fxios)\/(\d+)/i);
99
+ browser = m ? `Firefox ${m[1]}` : "Firefox";
100
+ } else if (/safari/i.test(ua) && !/chrome|crios/i.test(ua)) {
101
+ const m = ua.match(/version\/(\d+)/i);
102
+ browser = m ? `Safari ${m[1]}` : "Safari";
103
+ } else if (/postman/i.test(ua)) {
104
+ browser = "Postman API";
105
+ }
106
+ return { browser, os, deviceType };
107
+ }
41
108
  function deriveDeviceName(req, userAgent = "") {
42
109
  const headers = req?.headers || {};
43
110
  const fromHeader = headers["x-device-name"] || headers["x-pc-name"] || headers["x-computer-name"] || "";
@@ -49,16 +116,12 @@ function deriveDeviceName(req, userAgent = "") {
49
116
  return fromBody.trim().slice(0, 120);
50
117
  }
51
118
  const ua = userAgent || headers["user-agent"] || "";
52
- if (/windows/i.test(ua)) return "Windows PC";
53
- if (/macintosh|mac os/i.test(ua)) return "Mac";
54
- if (/iphone/i.test(ua)) return "iPhone";
55
- if (/ipad/i.test(ua)) return "iPad";
56
- if (/android/i.test(ua)) return "Android Device";
57
- if (/linux/i.test(ua)) return "Linux PC";
58
- return "Desktop PC";
119
+ return getDeviceLabel(ua);
59
120
  }
60
121
  var session_default = {
61
122
  genSessionToken,
123
+ getDeviceLabel,
124
+ parseUserAgent,
62
125
  deriveDeviceName
63
126
  };
64
127
  // Annotate the CommonJS export names for ESM import in node:
@@ -69,6 +132,8 @@ var session_default = {
69
132
  extractToken,
70
133
  formatToken,
71
134
  genSessionToken,
135
+ getDeviceLabel,
72
136
  getSessionId,
73
- parseToken
137
+ parseToken,
138
+ parseUserAgent
74
139
  });
@@ -1,67 +1,131 @@
1
- /**
2
- * cynx/utils — Session and Device Resolution Utilities (session.js)
3
- *
4
- * Helpers for generating secure session tokens and extracting human-friendly device names
5
- * from request headers and user-agent strings.
6
- */
7
-
8
- import { getRandomBytes } from './uid.js';
9
-
10
- /**
11
- * Generate a cryptographically secure random session token.
12
- * Example: "st_9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d..."
13
- *
14
- * @param {number} [byteLength=32]
15
- * @returns {string}
16
- */
17
- export function genSessionToken(byteLength = 32) {
18
- const bytes = getRandomBytes(byteLength);
19
- let hex = '';
20
- for (let i = 0; i < bytes.length; i++) {
21
- hex += bytes[i].toString(16).padStart(2, '0');
22
- }
23
- return `st_${hex}`;
24
- }
25
-
26
- /**
27
- * Derive human-readable device name from Express/Fastify request or User-Agent string.
28
- *
29
- * @param {object} [req] HTTP request object
30
- * @param {string} [userAgent=''] User-Agent string
31
- * @returns {string} e.g. "Windows PC", "Mac", "iPhone", "Android Device", "Desktop PC"
32
- */
33
- export function deriveDeviceName(req, userAgent = '') {
34
- const headers = req?.headers || {};
35
- const fromHeader = headers['x-device-name'] || headers['x-pc-name'] || headers['x-computer-name'] || '';
36
- if (typeof fromHeader === 'string' && fromHeader.trim()) {
37
- return fromHeader.trim().slice(0, 120);
38
- }
39
-
40
- const fromBody = req?.body?.deviceName || req?.body?.device_name || req?.body?.pcName || req?.body?.pc_name;
41
- if (typeof fromBody === 'string' && fromBody.trim()) {
42
- return fromBody.trim().slice(0, 120);
43
- }
44
-
45
- const ua = userAgent || headers['user-agent'] || '';
46
- if (/windows/i.test(ua)) return 'Windows PC';
47
- if (/macintosh|mac os/i.test(ua)) return 'Mac';
48
- if (/iphone/i.test(ua)) return 'iPhone';
49
- if (/ipad/i.test(ua)) return 'iPad';
50
- if (/android/i.test(ua)) return 'Android Device';
51
- if (/linux/i.test(ua)) return 'Linux PC';
52
- return 'Desktop PC';
53
- }
54
-
55
- export {
56
- formatToken,
57
- parseToken,
58
- getSessionId,
59
- extractToken,
60
- SessionManager,
61
- createSessionManager,
62
- } from './session_manager.js';
63
-
64
- export default {
65
- genSessionToken,
66
- deriveDeviceName,
67
- };
1
+ /**
2
+ * cynx/utils — Session and Device Resolution Utilities (session.js)
3
+ *
4
+ * Helpers for generating secure session tokens and extracting human-friendly device names
5
+ * from request headers and user-agent strings.
6
+ *
7
+ * STRICT NO EMOJIS!
8
+ */
9
+
10
+ import { getRandomBytes } from './uid.js';
11
+
12
+ /**
13
+ * Generate a cryptographically secure random session token.
14
+ * Example: "st_9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d..."
15
+ *
16
+ * @param {number} [byteLength=32]
17
+ * @returns {string}
18
+ */
19
+ export function genSessionToken(byteLength = 32) {
20
+ const bytes = getRandomBytes(byteLength);
21
+ let hex = '';
22
+ for (let i = 0; i < bytes.length; i++) {
23
+ hex += bytes[i].toString(16).padStart(2, '0');
24
+ }
25
+ return `st_${hex}`;
26
+ }
27
+
28
+ /**
29
+ * Extract human-readable device label from User-Agent string.
30
+ *
31
+ * @param {string} ua User-Agent string
32
+ * @returns {string} e.g. "Windows 10/11 PC", "MacBook / Mac", "iPhone", "Android Phone", "Linux PC"
33
+ */
34
+ export function getDeviceLabel(ua) {
35
+ if (!ua) return 'PC';
36
+ if (/windows phone/i.test(ua)) return 'Windows Phone';
37
+ if (/windows nt 10\.0/i.test(ua)) return 'Windows 10/11 PC';
38
+ if (/windows nt 6\.3/i.test(ua)) return 'Windows 8.1 PC';
39
+ if (/windows nt 6\.1/i.test(ua)) return 'Windows 7 PC';
40
+ if (/win64|win32|windows/i.test(ua)) return 'Windows PC';
41
+ if (/ipad/i.test(ua)) return 'iPad';
42
+ if (/iphone/i.test(ua)) return 'iPhone';
43
+ if (/macintosh|mac os x/i.test(ua)) return 'MacBook / Mac';
44
+ if (/android/i.test(ua)) return /mobile/i.test(ua) ? 'Android Phone' : 'Android Tablet';
45
+ if (/cros/i.test(ua)) return 'Chromebook';
46
+ if (/linux/i.test(ua)) return 'Linux PC';
47
+ return 'Desktop PC';
48
+ }
49
+
50
+ /**
51
+ * Parse User-Agent string into browser, OS, and device type.
52
+ *
53
+ * @param {string} ua User-Agent string
54
+ * @returns {{ browser: string, os: string, deviceType: 'desktop' | 'mobile' | 'tablet' }}
55
+ */
56
+ export function parseUserAgent(ua) {
57
+ if (!ua) return { browser: 'Unknown', os: 'Unknown', deviceType: 'desktop' };
58
+
59
+ let os = 'Unknown';
60
+ let browser = 'Unknown';
61
+ let deviceType = 'desktop';
62
+
63
+ if (/windows phone/i.test(ua)) { os = 'Windows Phone'; deviceType = 'mobile'; }
64
+ else if (/win64|win32|windows/i.test(ua)) { os = 'Windows'; deviceType = 'desktop'; }
65
+ else if (/ipad/i.test(ua)) { os = 'iPadOS'; deviceType = 'tablet'; }
66
+ else if (/iphone|ipod/i.test(ua)) { os = 'iOS'; deviceType = 'mobile'; }
67
+ else if (/android/i.test(ua)) { os = 'Android'; deviceType = /mobile/i.test(ua) ? 'mobile' : 'tablet'; }
68
+ else if (/macintosh|mac os x/i.test(ua)) { os = 'macOS'; deviceType = 'desktop'; }
69
+ else if (/cros/i.test(ua)) { os = 'Chrome OS'; deviceType = 'desktop'; }
70
+ else if (/linux/i.test(ua)) { os = 'Linux'; deviceType = 'desktop'; }
71
+
72
+ if (/edg\//i.test(ua)) {
73
+ const m = ua.match(/edg\/(\d+)/i);
74
+ browser = m ? `Edge ${m[1]}` : 'Edge';
75
+ } else if (/opr\/|opera/i.test(ua)) {
76
+ const m = ua.match(/(?:opr|opera)\/(\d+)/i);
77
+ browser = m ? `Opera ${m[1]}` : 'Opera';
78
+ } else if (/chrome|crios/i.test(ua)) {
79
+ const m = ua.match(/(?:chrome|crios)\/(\d+)/i);
80
+ browser = m ? `Chrome ${m[1]}` : 'Chrome';
81
+ } else if (/firefox|fxios/i.test(ua)) {
82
+ const m = ua.match(/(?:firefox|fxios)\/(\d+)/i);
83
+ browser = m ? `Firefox ${m[1]}` : 'Firefox';
84
+ } else if (/safari/i.test(ua) && !/chrome|crios/i.test(ua)) {
85
+ const m = ua.match(/version\/(\d+)/i);
86
+ browser = m ? `Safari ${m[1]}` : 'Safari';
87
+ } else if (/postman/i.test(ua)) {
88
+ browser = 'Postman API';
89
+ }
90
+
91
+ return { browser, os, deviceType };
92
+ }
93
+
94
+ /**
95
+ * Derive human-readable device name from Express/Fastify request or User-Agent string.
96
+ *
97
+ * @param {object} [req] HTTP request object
98
+ * @param {string} [userAgent=''] User-Agent string
99
+ * @returns {string} e.g. "Windows 10/11 PC", "MacBook / Mac", "iPhone", "Android Phone", "Desktop PC"
100
+ */
101
+ export function deriveDeviceName(req, userAgent = '') {
102
+ const headers = req?.headers || {};
103
+ const fromHeader = headers['x-device-name'] || headers['x-pc-name'] || headers['x-computer-name'] || '';
104
+ if (typeof fromHeader === 'string' && fromHeader.trim()) {
105
+ return fromHeader.trim().slice(0, 120);
106
+ }
107
+
108
+ const fromBody = req?.body?.deviceName || req?.body?.device_name || req?.body?.pcName || req?.body?.pc_name;
109
+ if (typeof fromBody === 'string' && fromBody.trim()) {
110
+ return fromBody.trim().slice(0, 120);
111
+ }
112
+
113
+ const ua = userAgent || headers['user-agent'] || '';
114
+ return getDeviceLabel(ua);
115
+ }
116
+
117
+ export {
118
+ formatToken,
119
+ parseToken,
120
+ getSessionId,
121
+ extractToken,
122
+ SessionManager,
123
+ createSessionManager,
124
+ } from './session_manager.js';
125
+
126
+ export default {
127
+ genSessionToken,
128
+ getDeviceLabel,
129
+ parseUserAgent,
130
+ deriveDeviceName,
131
+ };
@@ -20,15 +20,20 @@ __export(session_manager_exports, {
20
20
  SessionManager: () => SessionManager,
21
21
  createSessionManager: () => createSessionManager,
22
22
  default: () => session_manager_default,
23
+ deriveDeviceName: () => import_session2.deriveDeviceName,
23
24
  extractToken: () => extractToken,
24
25
  formatToken: () => formatToken,
26
+ genSessionToken: () => import_session2.genSessionToken,
27
+ getDeviceLabel: () => import_session2.getDeviceLabel,
25
28
  getSessionId: () => getSessionId,
26
- parseToken: () => parseToken
29
+ parseToken: () => parseToken,
30
+ parseUserAgent: () => import_session2.parseUserAgent
27
31
  });
28
32
  module.exports = __toCommonJS(session_manager_exports);
29
33
  var import_uid = require("./uid.cjs");
30
34
  var import_duration = require("./duration.cjs");
31
35
  var import_session = require("./session.cjs");
36
+ var import_session2 = require("./session.cjs");
32
37
  function formatToken(sessionId, secret, prefix = "st_") {
33
38
  return `${prefix}${sessionId}$${secret}`;
34
39
  }
@@ -483,8 +488,12 @@ var session_manager_default = {
483
488
  0 && (module.exports = {
484
489
  SessionManager,
485
490
  createSessionManager,
491
+ deriveDeviceName,
486
492
  extractToken,
487
493
  formatToken,
494
+ genSessionToken,
495
+ getDeviceLabel,
488
496
  getSessionId,
489
- parseToken
497
+ parseToken,
498
+ parseUserAgent
490
499
  });
@@ -539,6 +539,13 @@ export function createSessionManager(options) {
539
539
  return new SessionManager(options);
540
540
  }
541
541
 
542
+ export {
543
+ genSessionToken,
544
+ getDeviceLabel,
545
+ parseUserAgent,
546
+ deriveDeviceName,
547
+ } from './session.js';
548
+
542
549
  export default {
543
550
  SessionManager,
544
551
  createSessionManager,