@hkdigital/lib-core 0.5.17 → 0.5.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Get simplified platform identifier
3
+ *
4
+ * @example
5
+ * // 'macos', 'windows', 'linux', 'ios', 'android', 'unknown'
6
+ *
7
+ * @returns {string} platform identifier
8
+ */
9
+ export function getPlatform() {
10
+ const platform = navigator.platform.toLowerCase();
11
+ const ua = navigator.userAgent.toLowerCase();
12
+
13
+ // iOS devices
14
+ if (/iphone|ipod|ipad/.test(platform)) {
15
+ return 'ios';
16
+ }
17
+
18
+ // iPadOS (reports as MacIntel but has touch)
19
+ if (platform === 'macintel' && navigator.maxTouchPoints > 2) {
20
+ return 'ios';
21
+ }
22
+
23
+ // Android
24
+ if (/android/.test(ua)) {
25
+ return 'android';
26
+ }
27
+
28
+ // macOS
29
+ if (/mac/.test(platform)) {
30
+ return 'macos';
31
+ }
32
+
33
+ // Windows
34
+ if (/win/.test(platform)) {
35
+ return 'windows';
36
+ }
37
+
38
+ // Linux
39
+ if (/linux/.test(platform)) {
40
+ return 'linux';
41
+ }
42
+
43
+ return 'unknown';
44
+ }
45
+
46
+ /**
47
+ * Get raw platform string from navigator
48
+ *
49
+ * @example
50
+ * // 'MacIntel', 'Win32', 'Linux x86_64', 'iPhone', 'iPad'
51
+ *
52
+ * @returns {string} raw platform identifier
53
+ */
54
+ export function getPlatformRaw() {
55
+ return navigator.platform;
56
+ }
57
+
58
+ /**
59
+ * Get number of CPU cores (logical processors)
60
+ *
61
+ * @example
62
+ * // Desktop: 8, 16, 24
63
+ * // Mobile: 4, 6, 8
64
+ * // Older devices: 2
65
+ *
66
+ * @returns {number} number of logical processors
67
+ */
68
+ export function getCpuCores() {
69
+ return navigator.hardwareConcurrency || 1;
70
+ }
71
+
72
+ /**
73
+ * Check if device is online
74
+ *
75
+ * @example
76
+ * // true (connected), false (offline)
77
+ *
78
+ * @returns {boolean} true if online
79
+ */
80
+ export function isOnline() {
81
+ return navigator.onLine;
82
+ }
83
+
84
+ /**
85
+ * Get connection type if available (experimental API)
86
+ *
87
+ * @example
88
+ * // '4g', '3g', 'slow-2g', 'wifi', null
89
+ *
90
+ * @returns {string|null} connection type or null
91
+ */
92
+ export function getConnectionType() {
93
+ // @ts-ignore
94
+ const connection =
95
+ navigator.connection ||
96
+ // @ts-ignore
97
+ navigator.mozConnection ||
98
+ // @ts-ignore
99
+ navigator.webkitConnection;
100
+
101
+ return connection?.effectiveType || null;
102
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Get timezone offset in minutes
3
+ *
4
+ * @example
5
+ * // UTC: 0
6
+ * // PST (UTC-8): 480
7
+ * // CET (UTC+1): -60
8
+ *
9
+ * @returns {number} timezone offset
10
+ */
11
+ export function getTimezoneOffset(): number;
12
+ /**
13
+ * Get timezone name
14
+ *
15
+ * @example
16
+ * // 'America/New_York', 'Europe/Amsterdam', 'Asia/Tokyo'
17
+ *
18
+ * @returns {string} timezone identifier
19
+ */
20
+ export function getTimezone(): string;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Get timezone offset in minutes
3
+ *
4
+ * @example
5
+ * // UTC: 0
6
+ * // PST (UTC-8): 480
7
+ * // CET (UTC+1): -60
8
+ *
9
+ * @returns {number} timezone offset
10
+ */
11
+ export function getTimezoneOffset() {
12
+ return new Date().getTimezoneOffset();
13
+ }
14
+
15
+ /**
16
+ * Get timezone name
17
+ *
18
+ * @example
19
+ * // 'America/New_York', 'Europe/Amsterdam', 'Asia/Tokyo'
20
+ *
21
+ * @returns {string} timezone identifier
22
+ */
23
+ export function getTimezone() {
24
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
25
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @typedef {{
3
+ * deviceType?: boolean,
4
+ * isMobile?: boolean,
5
+ * platform?: boolean,
6
+ * browser?: boolean,
7
+ * browserEngine?: boolean,
8
+ * screenWidth?: boolean,
9
+ * screenHeight?: boolean,
10
+ * devicePixelRatio?: boolean,
11
+ * hasTouch?: boolean,
12
+ * language?: boolean,
13
+ * timezone?: boolean,
14
+ * isPwa?: boolean,
15
+ * viewportWidth?: boolean,
16
+ * viewportHeight?: boolean,
17
+ * orientation?: boolean,
18
+ * cpuCores?: boolean,
19
+ * connectionType?: boolean
20
+ * }} BrowserInfoOptions
21
+ */
22
+ /**
23
+ * @typedef {import('./typedef.js').BrowserInfo} BrowserInfo
24
+ */
25
+ /**
26
+ * Collect browser and device information for analytics/stats
27
+ *
28
+ * @param {BrowserInfoOptions} [options] - Enable/disable individual properties
29
+ *
30
+ * @returns {BrowserInfo} collected browser information
31
+ *
32
+ * @example
33
+ * // Get all essential info (default)
34
+ * const info = getBrowserInfo();
35
+ *
36
+ * @example
37
+ * // Get only specific properties
38
+ * const info = getBrowserInfo({
39
+ * deviceType: true,
40
+ * platform: true,
41
+ * browser: true
42
+ * });
43
+ *
44
+ * @example
45
+ * // Get essential + extended properties
46
+ * const info = getBrowserInfo({
47
+ * deviceType: true,
48
+ * platform: true,
49
+ * viewportWidth: true,
50
+ * viewportHeight: true,
51
+ * orientation: true,
52
+ * cpuCores: true
53
+ * });
54
+ */
55
+ export function getBrowserInfo(options?: BrowserInfoOptions): BrowserInfo;
56
+ export * from "./info/device.js";
57
+ export * from "./info/display.js";
58
+ export * from "./info/engine.js";
59
+ export * from "./info/language.js";
60
+ export * from "./info/system.js";
61
+ export * from "./info/timezone.js";
62
+ export type BrowserInfoOptions = {
63
+ deviceType?: boolean;
64
+ isMobile?: boolean;
65
+ platform?: boolean;
66
+ browser?: boolean;
67
+ browserEngine?: boolean;
68
+ screenWidth?: boolean;
69
+ screenHeight?: boolean;
70
+ devicePixelRatio?: boolean;
71
+ hasTouch?: boolean;
72
+ language?: boolean;
73
+ timezone?: boolean;
74
+ isPwa?: boolean;
75
+ viewportWidth?: boolean;
76
+ viewportHeight?: boolean;
77
+ orientation?: boolean;
78
+ cpuCores?: boolean;
79
+ connectionType?: boolean;
80
+ };
81
+ export type BrowserInfo = import("./typedef.js").BrowserInfo;
@@ -0,0 +1,185 @@
1
+ export * from './info/device.js';
2
+ export * from './info/display.js';
3
+ export * from './info/engine.js';
4
+ export * from './info/language.js';
5
+ export * from './info/system.js';
6
+ export * from './info/timezone.js';
7
+
8
+ import { getDeviceType, getIsMobile } from './info/device.js';
9
+ import { getBrowserName, getBrowserEngine } from './info/engine.js';
10
+
11
+ import {
12
+ getScreenSize,
13
+ getViewportSize,
14
+ getDevicePixelRatio,
15
+ getOrientation,
16
+ hasTouchSupport,
17
+ getIsPwa
18
+ } from './info/display.js';
19
+
20
+ import { getLanguage } from './info/language.js';
21
+ import { getPlatform, getCpuCores, getConnectionType } from './info/system.js';
22
+ import { getTimezone } from './info/timezone.js';
23
+
24
+ /**
25
+ * @typedef {{
26
+ * deviceType?: boolean,
27
+ * isMobile?: boolean,
28
+ * platform?: boolean,
29
+ * browser?: boolean,
30
+ * browserEngine?: boolean,
31
+ * screenWidth?: boolean,
32
+ * screenHeight?: boolean,
33
+ * devicePixelRatio?: boolean,
34
+ * hasTouch?: boolean,
35
+ * language?: boolean,
36
+ * timezone?: boolean,
37
+ * isPwa?: boolean,
38
+ * viewportWidth?: boolean,
39
+ * viewportHeight?: boolean,
40
+ * orientation?: boolean,
41
+ * cpuCores?: boolean,
42
+ * connectionType?: boolean
43
+ * }} BrowserInfoOptions
44
+ */
45
+
46
+ /**
47
+ * @typedef {import('./typedef.js').BrowserInfo} BrowserInfo
48
+ */
49
+
50
+ /**
51
+ * Collect browser and device information for analytics/stats
52
+ *
53
+ * @param {BrowserInfoOptions} [options] - Enable/disable individual properties
54
+ *
55
+ * @returns {BrowserInfo} collected browser information
56
+ *
57
+ * @example
58
+ * // Get all essential info (default)
59
+ * const info = getBrowserInfo();
60
+ *
61
+ * @example
62
+ * // Get only specific properties
63
+ * const info = getBrowserInfo({
64
+ * deviceType: true,
65
+ * platform: true,
66
+ * browser: true
67
+ * });
68
+ *
69
+ * @example
70
+ * // Get essential + extended properties
71
+ * const info = getBrowserInfo({
72
+ * deviceType: true,
73
+ * platform: true,
74
+ * viewportWidth: true,
75
+ * viewportHeight: true,
76
+ * orientation: true,
77
+ * cpuCores: true
78
+ * });
79
+ */
80
+ export function getBrowserInfo(options = {}) {
81
+ // Default to BrowserInfoEssential properties
82
+ const {
83
+ deviceType = true,
84
+ isMobile = true,
85
+ platform = true,
86
+ browser = true,
87
+ browserEngine = true,
88
+ screenWidth = true,
89
+ screenHeight = true,
90
+ devicePixelRatio = true,
91
+ hasTouch = true,
92
+ language = true,
93
+ timezone = true,
94
+ isPwa = true,
95
+ // Extended properties (default false)
96
+ viewportWidth = false,
97
+ viewportHeight = false,
98
+ orientation = false,
99
+ cpuCores = false,
100
+ connectionType = false
101
+ } = options;
102
+
103
+ const info = {};
104
+
105
+ // Device type
106
+ if (deviceType) {
107
+ info.deviceType = getDeviceType();
108
+ }
109
+
110
+ // Mobile check
111
+ if (isMobile) {
112
+ info.isMobile = getIsMobile();
113
+ }
114
+
115
+ // Platform
116
+ if (platform) {
117
+ info.platform = getPlatform();
118
+ }
119
+
120
+ // Browser name
121
+ if (browser) {
122
+ info.browser = getBrowserName();
123
+ }
124
+
125
+ // Browser engine
126
+ if (browserEngine) {
127
+ info.browserEngine = getBrowserEngine();
128
+ }
129
+
130
+ // Screen dimensions
131
+ if (screenWidth || screenHeight) {
132
+ const screenSize = getScreenSize();
133
+ if (screenWidth) info.screenWidth = screenSize.width;
134
+ if (screenHeight) info.screenHeight = screenSize.height;
135
+ }
136
+
137
+ // Device pixel ratio
138
+ if (devicePixelRatio) {
139
+ info.devicePixelRatio = getDevicePixelRatio();
140
+ }
141
+
142
+ // Touch support
143
+ if (hasTouch) {
144
+ info.hasTouch = hasTouchSupport();
145
+ }
146
+
147
+ // Language
148
+ if (language) {
149
+ info.language = getLanguage();
150
+ }
151
+
152
+ // Timezone
153
+ if (timezone) {
154
+ info.timezone = getTimezone();
155
+ }
156
+
157
+ // PWA
158
+ if (isPwa) {
159
+ info.isPwa = getIsPwa();
160
+ }
161
+
162
+ // Viewport dimensions (extended)
163
+ if (viewportWidth || viewportHeight) {
164
+ const viewportSize = getViewportSize();
165
+ if (viewportWidth) info.viewportWidth = viewportSize.width;
166
+ if (viewportHeight) info.viewportHeight = viewportSize.height;
167
+ }
168
+
169
+ // Orientation (extended)
170
+ if (orientation) {
171
+ info.orientation = getOrientation();
172
+ }
173
+
174
+ // CPU cores (extended)
175
+ if (cpuCores) {
176
+ info.cpuCores = getCpuCores();
177
+ }
178
+
179
+ // Connection type (extended)
180
+ if (connectionType) {
181
+ info.connectionType = getConnectionType();
182
+ }
183
+
184
+ return info;
185
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Essential browser info
3
+ */
4
+ export type BrowserInfoEssential = {
5
+ deviceType?: "phone" | "tablet" | "tv" | "desktop";
6
+ isMobile?: boolean;
7
+ platform?: string;
8
+ browser?: string;
9
+ browserEngine?: "blink" | "gecko" | "webkit" | "unknown";
10
+ screenWidth?: number;
11
+ screenHeight?: number;
12
+ devicePixelRatio?: number;
13
+ hasTouch?: boolean;
14
+ language?: string;
15
+ timezone?: string;
16
+ isPwa?: boolean;
17
+ };
18
+ /**
19
+ * Extended browser info (opt-in)
20
+ */
21
+ export type BrowserInfoExtended = {
22
+ viewportWidth?: number;
23
+ viewportHeight?: number;
24
+ orientation?: "portrait" | "landscape";
25
+ cpuCores?: number;
26
+ connectionType?: string | null;
27
+ };
28
+ /**
29
+ * Complete browser info (essential + extended)
30
+ */
31
+ export type BrowserInfo = BrowserInfoEssential & BrowserInfoExtended;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Essential browser info
3
+ *
4
+ * @typedef {{
5
+ * deviceType?: 'phone'|'tablet'|'tv'|'desktop',
6
+ * isMobile?: boolean,
7
+ * platform?: string,
8
+ * browser?: string,
9
+ * browserEngine?: 'blink'|'gecko'|'webkit'|'unknown',
10
+ * screenWidth?: number,
11
+ * screenHeight?: number,
12
+ * devicePixelRatio?: number,
13
+ * hasTouch?: boolean,
14
+ * language?: string,
15
+ * timezone?: string,
16
+ * isPwa?: boolean
17
+ * }} BrowserInfoEssential
18
+ */
19
+
20
+ /**
21
+ * Extended browser info (opt-in)
22
+ *
23
+ * @typedef {{
24
+ * viewportWidth?: number,
25
+ * viewportHeight?: number,
26
+ * orientation?: 'portrait'|'landscape',
27
+ * cpuCores?: number,
28
+ * connectionType?: string|null
29
+ * }} BrowserInfoExtended
30
+ */
31
+
32
+ /**
33
+ * Complete browser info (essential + extended)
34
+ *
35
+ * @typedef {BrowserInfoEssential & BrowserInfoExtended} BrowserInfo
36
+ */
37
+
38
+ export {};
@@ -25,38 +25,45 @@ const DEFAULT_PRESETS = {
25
25
  default: {
26
26
  format: 'avif',
27
27
  quality: '90',
28
- as: 'metadata'
28
+ as: 'metadata',
29
+ withMetadata: ''
29
30
  },
30
31
  render: {
31
32
  format: 'jpg',
32
33
  quality: '95',
33
- as: 'metadata'
34
+ as: 'metadata',
35
+ withMetadata: ''
34
36
  },
35
37
  photo: {
36
38
  format: 'jpg',
37
39
  quality: '95',
38
- as: 'metadata'
40
+ as: 'metadata',
41
+ withMetadata: ''
39
42
  },
40
43
  gradient: {
41
44
  format: 'jpg',
42
45
  quality: '95',
43
- as: 'metadata'
46
+ as: 'metadata',
47
+ withMetadata: ''
44
48
  },
45
49
  drawing: {
46
50
  format: 'avif',
47
51
  quality: '90',
48
- as: 'metadata'
52
+ as: 'metadata',
53
+ withMetadata: ''
49
54
  },
50
55
  savedata: {
51
56
  format: 'avif',
52
57
  quality: '85',
53
- as: 'metadata'
58
+ as: 'metadata',
59
+ withMetadata: ''
54
60
  },
55
61
  blur: {
56
62
  format: 'avif',
57
63
  quality: '50',
58
64
  blur: '75',
59
- as: 'metadata'
65
+ as: 'metadata',
66
+ withMetadata: ''
60
67
  }
61
68
  };
62
69
 
@@ -115,7 +122,8 @@ export function generateResponseConfigs(options) {
115
122
  return {
116
123
  ...configPairs,
117
124
  w: String(w),
118
- format: 'png'
125
+ format: 'png',
126
+ withMetadata: ''
119
127
  };
120
128
  });
121
129
  // console.log('Returning favicon configs:', faviconConfigs);
@@ -128,7 +136,8 @@ export function generateResponseConfigs(options) {
128
136
  return {
129
137
  ...configPairs,
130
138
  w: String(w),
131
- format: 'png'
139
+ format: 'png',
140
+ withMetadata: ''
132
141
  };
133
142
  });
134
143
  // console.log('Returning apple-touch-icon configs:', appleTouchConfigs);
@@ -392,7 +392,7 @@ export async function httpRequest(options) {
392
392
 
393
393
  if (!isTestEnv) {
394
394
  if (cachedResponse) {
395
- console.debug(`http:cache-hit [${url.pathname}]`);
395
+ // console.debug(`http:cache-hit [${url.pathname}]`);
396
396
  // console.debug(`cached-response has body: ${!!cachedResponse.body}`);
397
397
  // console.debug(`cached-response content-length: ${cachedResponse.headers.get('content-length')}`);
398
398
  return cachedResponse;