@resq-sw/helpers 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +218 -0
- package/lib/browser/html-entities.d.ts +34 -0
- package/lib/browser/html-entities.d.ts.map +1 -0
- package/lib/browser/html-entities.js +63 -0
- package/lib/browser/html-entities.js.map +1 -0
- package/lib/browser/index.d.ts +3 -0
- package/lib/browser/index.js +3 -0
- package/lib/browser/platform.d.ts +252 -0
- package/lib/browser/platform.d.ts.map +1 -0
- package/lib/browser/platform.js +272 -0
- package/lib/browser/platform.js.map +1 -0
- package/lib/formatting/date.d.ts +80 -0
- package/lib/formatting/date.d.ts.map +1 -0
- package/lib/formatting/date.js +135 -0
- package/lib/formatting/date.js.map +1 -0
- package/lib/formatting/date.types.d.ts +35 -0
- package/lib/formatting/date.types.d.ts.map +1 -0
- package/lib/formatting/date.types.js +0 -0
- package/lib/formatting/index.d.ts +5 -0
- package/lib/formatting/index.js +4 -0
- package/lib/formatting/number.d.ts +22 -0
- package/lib/formatting/number.d.ts.map +1 -0
- package/lib/formatting/number.js +39 -0
- package/lib/formatting/number.js.map +1 -0
- package/lib/formatting/string.d.ts +22 -0
- package/lib/formatting/string.d.ts.map +1 -0
- package/lib/formatting/string.js +30 -0
- package/lib/formatting/string.js.map +1 -0
- package/lib/helpers.d.ts +142 -0
- package/lib/helpers.d.ts.map +1 -0
- package/lib/helpers.js +159 -0
- package/lib/helpers.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +9 -0
- package/lib/parse-code-path.d.ts +85 -0
- package/lib/parse-code-path.d.ts.map +1 -0
- package/lib/parse-code-path.js +160 -0
- package/lib/parse-code-path.js.map +1 -0
- package/lib/task-exec.d.ts +26 -0
- package/lib/task-exec.d.ts.map +1 -0
- package/lib/task-exec.js +45 -0
- package/lib/task-exec.js.map +1 -0
- package/lib/task-exec.types.d.ts +23 -0
- package/lib/task-exec.types.d.ts.map +1 -0
- package/lib/task-exec.types.js +0 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# @resq-sw/helpers
|
|
2
|
+
|
|
3
|
+
> Functional utilities, type guards, result types, formatting, browser detection, and async task execution.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @resq-sw/helpers
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Dependencies: `@resq-sw/logger`, `tinyqueue`.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { catchError, success, failure, isString, Stringify, getURL } from "@resq-sw/helpers";
|
|
17
|
+
|
|
18
|
+
const result = await catchError(fetch, "/api/data");
|
|
19
|
+
if (result.success) console.log(result.value);
|
|
20
|
+
|
|
21
|
+
const json = Stringify({ name: "ResQ" });
|
|
22
|
+
const url = getURL("api/users"); // origin-relative URL
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API Reference
|
|
26
|
+
|
|
27
|
+
### Result Types
|
|
28
|
+
|
|
29
|
+
Railway-oriented programming primitives for error handling without exceptions.
|
|
30
|
+
|
|
31
|
+
#### `success(value): Success<T>`
|
|
32
|
+
|
|
33
|
+
Creates a successful result wrapping `value`.
|
|
34
|
+
|
|
35
|
+
#### `failure(error): Failure<E>`
|
|
36
|
+
|
|
37
|
+
Creates a failed result wrapping `error`.
|
|
38
|
+
|
|
39
|
+
#### `catchError(asyncFn, ...args): Promise<Result<T, Error>>`
|
|
40
|
+
|
|
41
|
+
Wraps an async function call in a `Result`. Returns `Success` on resolve, `Failure` on rejection.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
const result = await catchError(fetchUser, userId);
|
|
45
|
+
if (result.success) console.log(result.value);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### `map(fn): (result) => Result<U, E>`
|
|
49
|
+
|
|
50
|
+
Transforms the value inside a successful result.
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const double = map((n: number) => n * 2);
|
|
54
|
+
double(success(5)); // success(10)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### `bindResult(fn): (result) => Result<U, E>`
|
|
58
|
+
|
|
59
|
+
Chains a result-returning function after a successful result (flatMap).
|
|
60
|
+
|
|
61
|
+
#### `railway(input, ...fns): Result<T, E>`
|
|
62
|
+
|
|
63
|
+
Pipes an input through a chain of result-returning functions, short-circuiting on the first failure. Supports up to 5 functions with full type inference.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const result = railway(
|
|
67
|
+
"42",
|
|
68
|
+
(s) => success(parseInt(s)),
|
|
69
|
+
(n) => n > 0 ? success(n) : failure("must be positive"),
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### `recover(fn): (result) => Result<T, E2>`
|
|
74
|
+
|
|
75
|
+
Recovers from a failure by applying `fn` to the error.
|
|
76
|
+
|
|
77
|
+
#### `tap(fn): (result) => Result<T, E>`
|
|
78
|
+
|
|
79
|
+
Executes a side effect on success without modifying the result.
|
|
80
|
+
|
|
81
|
+
### Utilities
|
|
82
|
+
|
|
83
|
+
#### `Stringify(obj): string`
|
|
84
|
+
|
|
85
|
+
Converts an object to a pretty-printed JSON string (2-space indent).
|
|
86
|
+
|
|
87
|
+
#### `getURL(path?): string`
|
|
88
|
+
|
|
89
|
+
Builds a full URL from `globalThis.location.origin` (browser) or environment variables (`VITE_BASE_URL`, `NEXT_PUBLIC_BASE_URL`, `BASE_URL`).
|
|
90
|
+
|
|
91
|
+
- **path** (`string`, default `""`) -- path to append.
|
|
92
|
+
- Returns `""` if no origin is available.
|
|
93
|
+
|
|
94
|
+
### Type Guards
|
|
95
|
+
|
|
96
|
+
| Function | Narrows to |
|
|
97
|
+
|----------|-----------|
|
|
98
|
+
| `isNumber(value)` | `number` |
|
|
99
|
+
| `isString(value)` | `string` |
|
|
100
|
+
| `isFunction(value)` | `Function` |
|
|
101
|
+
| `isPromise(value)` | `Promise<unknown>` |
|
|
102
|
+
|
|
103
|
+
### TaskExec
|
|
104
|
+
|
|
105
|
+
Priority-queue-based delayed task executor. Tasks are sorted by execution time and fired in order.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { TaskExec } from "@resq-sw/helpers";
|
|
109
|
+
|
|
110
|
+
const exec = new TaskExec();
|
|
111
|
+
exec.exec(() => console.log("later"), 5000); // runs after 5s
|
|
112
|
+
exec.exec(() => console.log("sooner"), 1000); // runs after 1s
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### `exec(func, ttl): void`
|
|
116
|
+
|
|
117
|
+
Schedules `func` to run after `ttl` milliseconds.
|
|
118
|
+
|
|
119
|
+
### parseCodePath / parseCodePathDetailed
|
|
120
|
+
|
|
121
|
+
Constructs formatted source-location strings for debugging.
|
|
122
|
+
|
|
123
|
+
#### `parseCodePath(context, entity): string`
|
|
124
|
+
|
|
125
|
+
- **context** -- description of the operation.
|
|
126
|
+
- **entity** -- function, class, string, or symbol whose name is extracted.
|
|
127
|
+
- Returns `"location: <path> @<entity>: <context>"`.
|
|
128
|
+
|
|
129
|
+
#### `parseCodePathDetailed(context, entity, options?): string`
|
|
130
|
+
|
|
131
|
+
Extended version with optional line number, ISO timestamp, and custom prefix.
|
|
132
|
+
|
|
133
|
+
| Option | Type | Description |
|
|
134
|
+
|--------|------|-------------|
|
|
135
|
+
| `includeLineNumber` | `boolean` | Append call-site line number |
|
|
136
|
+
| `includeTimestamp` | `boolean` | Append ISO 8601 timestamp |
|
|
137
|
+
| `customPrefix` | `string` | Replace default `"location"` prefix |
|
|
138
|
+
|
|
139
|
+
### Formatting (`@resq-sw/helpers/formatting`)
|
|
140
|
+
|
|
141
|
+
#### Date Formatting
|
|
142
|
+
|
|
143
|
+
| Function | Signature | Description |
|
|
144
|
+
|----------|-----------|-------------|
|
|
145
|
+
| `formatDate` | `(date: string \| Date, options?: DateFormatOptions) => string` | Formats a date with Intl.DateTimeFormat (UTC) |
|
|
146
|
+
| `formatDatePeriod` | `(start, end?, isCurrent?) => string` | Formats a date range (e.g. `"Jan 2023 - Present"`) |
|
|
147
|
+
| `formatDateTime` | `(date) => string` | Full date + time (e.g. `"January 15, 2023, 02:30 PM"`) |
|
|
148
|
+
| `formatDateOnly` | `(date) => string` | Date without time (e.g. `"January 15, 2023"`) |
|
|
149
|
+
| `formatMonthYear` | `(date) => string` | Short month + year (e.g. `"Jan 2023"`) |
|
|
150
|
+
| `formatRelativeTime` | `(date) => string` | Relative time (e.g. `"2 days ago"`, `"Just now"`) |
|
|
151
|
+
|
|
152
|
+
#### Number Formatting
|
|
153
|
+
|
|
154
|
+
| Function | Signature | Description |
|
|
155
|
+
|----------|-----------|-------------|
|
|
156
|
+
| `formatNumber` | `(num: number) => string` | Locale-formatted number (`1,234,567`) |
|
|
157
|
+
| `formatBytes` | `(bytes: number) => string` | Human-readable bytes (`1.5 MB`) |
|
|
158
|
+
| `formatPercent` | `(value: number) => string` | Percentage from decimal (`0.85` -> `"85.0%"`) |
|
|
159
|
+
|
|
160
|
+
#### String Formatting
|
|
161
|
+
|
|
162
|
+
| Function | Signature | Description |
|
|
163
|
+
|----------|-----------|-------------|
|
|
164
|
+
| `capitalize` | `(str: string) => string` | Capitalize first character |
|
|
165
|
+
| `truncate` | `(str: string, length: number) => string` | Truncate with `...` |
|
|
166
|
+
| `slugify` | `(str: string) => string` | URL-safe slug |
|
|
167
|
+
|
|
168
|
+
### Browser (`@resq-sw/helpers/browser`)
|
|
169
|
+
|
|
170
|
+
#### Platform Detection
|
|
171
|
+
|
|
172
|
+
| Function | Returns |
|
|
173
|
+
|----------|---------|
|
|
174
|
+
| `isIOS()` | `boolean` |
|
|
175
|
+
| `isAndroid()` | `boolean` |
|
|
176
|
+
| `isMacOS()` | `boolean` |
|
|
177
|
+
| `isWindows()` | `boolean` |
|
|
178
|
+
| `isChromeOS()` | `boolean` |
|
|
179
|
+
| `getPlatform()` | `"ios" \| "android" \| "macos" \| "chromeos" \| "windows" \| "unknown"` |
|
|
180
|
+
| `isTouchScreen()` | `boolean` |
|
|
181
|
+
|
|
182
|
+
#### Browser Detection
|
|
183
|
+
|
|
184
|
+
| Function | Returns |
|
|
185
|
+
|----------|---------|
|
|
186
|
+
| `getBrowser()` | `"edge" \| "chrome" \| "firefox" \| "safari" \| "opera" \| "android" \| "iphone" \| "unknown"` |
|
|
187
|
+
| `isChrome()` | `boolean` |
|
|
188
|
+
| `isFirefox()` | `boolean` |
|
|
189
|
+
| `isSafari()` | `boolean` |
|
|
190
|
+
| `isOpera()` | `boolean` |
|
|
191
|
+
| `isEdge()` | `boolean` |
|
|
192
|
+
|
|
193
|
+
Combo detectors: `isIOSSafari`, `isIOSChrome`, `isAndroidChrome`, `isMacOSChrome`, `isWindowsChrome`, `isIOSFirefox`, `isAndroidFirefox`, `isIOSEdge`, `isAndroidEdge`, `isMacOSEdge`, `isWindowsEdge`, `isIOSOpera`, `isAndroidOpera`.
|
|
194
|
+
|
|
195
|
+
#### HTML Entities
|
|
196
|
+
|
|
197
|
+
#### `obfuscateLink(opts): { href, encodedText }`
|
|
198
|
+
|
|
199
|
+
Encodes contact links (mailto/tel) as HTML character references for spam protection.
|
|
200
|
+
|
|
201
|
+
| Option | Type | Description |
|
|
202
|
+
|--------|------|-------------|
|
|
203
|
+
| `scheme` | `"mailto" \| "tel"` | URI scheme |
|
|
204
|
+
| `address` | `string` | Email or phone |
|
|
205
|
+
| `params` | `Record<string, string>` | Optional query params |
|
|
206
|
+
| `text` | `string` | Display text (defaults to address) |
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
const { href, encodedText } = obfuscateLink({
|
|
210
|
+
scheme: "mailto",
|
|
211
|
+
address: "jane@example.com",
|
|
212
|
+
text: "Contact Jane",
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
Apache-2.0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/browser/html-entities.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Obfuscates and encodes a contact hyperlink (such as mailto or tel) as HTML entities.
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} opts Configuration options for link obfuscation.
|
|
6
|
+
* @param {'mailto'|'tel'|string} opts.scheme The URI scheme (e.g., 'mailto', 'tel', or custom).
|
|
7
|
+
* @param {string} opts.address The contact address (email or phone number).
|
|
8
|
+
* @param {Record<string, string>} [opts.params] Optional query parameters (used for mailto links).
|
|
9
|
+
* @param {string} [opts.text] Optional visible link text. Defaults to address.
|
|
10
|
+
* @returns {{ encodedHref: string, encodedText: string }} Object containing the obfuscated/encoded href and visible text.
|
|
11
|
+
* @throws {TypeError} If required fields are missing or invalid.
|
|
12
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#security_and_privacy
|
|
13
|
+
* @see https://github.com/resq-software/resQ
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const { encodedHref, encodedText } = obfuscateLink({
|
|
17
|
+
* scheme: 'mailto',
|
|
18
|
+
* address: 'jane.doe@example.com',
|
|
19
|
+
* text: 'Contact Jane'
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare const obfuscateLink: (opts: {
|
|
24
|
+
scheme: "mailto" | "tel";
|
|
25
|
+
address: string;
|
|
26
|
+
params?: Record<string, string>;
|
|
27
|
+
text?: string;
|
|
28
|
+
}) => {
|
|
29
|
+
href: string;
|
|
30
|
+
encodedText: string;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { obfuscateLink };
|
|
34
|
+
//# sourceMappingURL=html-entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-entities.d.ts","names":[],"sources":["../../src/browser/html-entities.ts"],"mappings":";;AAmDA;;;;;;;;;;;;;;;;;;;;cAAa,aAAA,GAAiB,IAAA;EAC5B,MAAA;EACA,OAAA;EACA,MAAA,GAAS,MAAA;EACT,IAAA;AAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/browser/html-entities.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Encodes every character in a string as a decimal HTML character reference.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} str The string to encode.
|
|
21
|
+
* @returns {string} The string with every character replaced by its HTML decimal entity.
|
|
22
|
+
* @throws {TypeError} If the provided value is not a string.
|
|
23
|
+
* @see https://developer.mozilla.org/en-US/docs/Glossary/Entity
|
|
24
|
+
* @see https://dev.w3.org/html5/html-author/charref
|
|
25
|
+
*/
|
|
26
|
+
const toEntities = (str) => str.split("").map((c) => `&#${c.codePointAt(0)};`).join("");
|
|
27
|
+
/**
|
|
28
|
+
* Obfuscates and encodes a contact hyperlink (such as mailto or tel) as HTML entities.
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} opts Configuration options for link obfuscation.
|
|
31
|
+
* @param {'mailto'|'tel'|string} opts.scheme The URI scheme (e.g., 'mailto', 'tel', or custom).
|
|
32
|
+
* @param {string} opts.address The contact address (email or phone number).
|
|
33
|
+
* @param {Record<string, string>} [opts.params] Optional query parameters (used for mailto links).
|
|
34
|
+
* @param {string} [opts.text] Optional visible link text. Defaults to address.
|
|
35
|
+
* @returns {{ encodedHref: string, encodedText: string }} Object containing the obfuscated/encoded href and visible text.
|
|
36
|
+
* @throws {TypeError} If required fields are missing or invalid.
|
|
37
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#security_and_privacy
|
|
38
|
+
* @see https://github.com/resq-software/resQ
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* const { encodedHref, encodedText } = obfuscateLink({
|
|
42
|
+
* scheme: 'mailto',
|
|
43
|
+
* address: 'jane.doe@example.com',
|
|
44
|
+
* text: 'Contact Jane'
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
const obfuscateLink = (opts) => {
|
|
49
|
+
const { scheme, address, params, text } = opts;
|
|
50
|
+
let uri = `${scheme}:${address}`;
|
|
51
|
+
if (params && Object.keys(params).length) {
|
|
52
|
+
const qs = Object.entries(params).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
|
|
53
|
+
uri += `?${qs}`;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
href: uri,
|
|
57
|
+
encodedText: toEntities(text ?? address)
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { obfuscateLink };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=html-entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-entities.js","names":[],"sources":["../../src/browser/html-entities.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Encodes every character in a string as a decimal HTML character reference.\n *\n * @param {string} str The string to encode.\n * @returns {string} The string with every character replaced by its HTML decimal entity.\n * @throws {TypeError} If the provided value is not a string.\n * @see https://developer.mozilla.org/en-US/docs/Glossary/Entity\n * @see https://dev.w3.org/html5/html-author/charref\n */\nconst toEntities = (str: string): string =>\n str\n .split('')\n .map((c) => `&#${c.codePointAt(0)};`)\n .join('');\n\n/**\n * Obfuscates and encodes a contact hyperlink (such as mailto or tel) as HTML entities.\n *\n * @param {Object} opts Configuration options for link obfuscation.\n * @param {'mailto'|'tel'|string} opts.scheme The URI scheme (e.g., 'mailto', 'tel', or custom).\n * @param {string} opts.address The contact address (email or phone number).\n * @param {Record<string, string>} [opts.params] Optional query parameters (used for mailto links).\n * @param {string} [opts.text] Optional visible link text. Defaults to address.\n * @returns {{ encodedHref: string, encodedText: string }} Object containing the obfuscated/encoded href and visible text.\n * @throws {TypeError} If required fields are missing or invalid.\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#security_and_privacy\n * @see https://github.com/resq-software/resQ\n * @example\n * ```ts\n * const { encodedHref, encodedText } = obfuscateLink({\n * scheme: 'mailto',\n * address: 'jane.doe@example.com',\n * text: 'Contact Jane'\n * });\n * ```\n */\nexport const obfuscateLink = (opts: {\n scheme: 'mailto' | 'tel';\n address: string;\n params?: Record<string, string>;\n text?: string;\n}) => {\n const { scheme, address, params, text } = opts;\n\n let uri = `${scheme}:${address}`;\n\n if (params && Object.keys(params).length) {\n const qs = Object.entries(params)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n uri += `?${qs}`;\n }\n\n const href = uri;\n const encodedText = toEntities(text ?? address);\n\n return { href, encodedText };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,cAAc,QAClB,IACG,MAAM,GAAG,CACT,KAAK,MAAM,KAAK,EAAE,YAAY,EAAE,CAAC,GAAG,CACpC,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;AAuBb,MAAa,iBAAiB,SAKxB;CACJ,MAAM,EAAE,QAAQ,SAAS,QAAQ,SAAS;CAE1C,IAAI,MAAM,GAAG,OAAO,GAAG;AAEvB,KAAI,UAAU,OAAO,KAAK,OAAO,CAAC,QAAQ;EACxC,MAAM,KAAK,OAAO,QAAQ,OAAO,CAC9B,KAAK,CAAC,GAAG,OAAO,GAAG,mBAAmB,EAAE,CAAC,GAAG,mBAAmB,EAAE,GAAG,CACpE,KAAK,IAAI;AACZ,SAAO,IAAI;;AAMb,QAAO;EAAE,MAHI;EAGE,aAFK,WAAW,QAAQ,QAAQ;EAEnB"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { obfuscateLink } from "./html-entities.js";
|
|
2
|
+
import { getBrowser, getPlatform, isAndroid, isAndroidChrome, isAndroidEdge, isAndroidFirefox, isAndroidOpera, isChrome, isChromeOS, isEdge, isFirefox, isIOS, isIOSChrome, isIOSEdge, isIOSFirefox, isIOSOpera, isIOSSafari, isMacOS, isMacOSChrome, isMacOSEdge, isOpera, isSafari, isTouchScreen, isWindows, isWindowsChrome, isWindowsEdge } from "./platform.js";
|
|
3
|
+
export { getBrowser, getPlatform, isAndroid, isAndroidChrome, isAndroidEdge, isAndroidFirefox, isAndroidOpera, isChrome, isChromeOS, isEdge, isFirefox, isIOS, isIOSChrome, isIOSEdge, isIOSFirefox, isIOSOpera, isIOSSafari, isMacOS, isMacOSChrome, isMacOSEdge, isOpera, isSafari, isTouchScreen, isWindows, isWindowsChrome, isWindowsEdge, obfuscateLink };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { getBrowser, getPlatform, isAndroid, isAndroidChrome, isAndroidEdge, isAndroidFirefox, isAndroidOpera, isChrome, isChromeOS, isEdge, isFirefox, isIOS, isIOSChrome, isIOSEdge, isIOSFirefox, isIOSOpera, isIOSSafari, isMacOS, isMacOSChrome, isMacOSEdge, isOpera, isSafari, isTouchScreen, isWindows, isWindowsChrome, isWindowsEdge } from "./platform.js";
|
|
2
|
+
import { obfuscateLink } from "./html-entities.js";
|
|
3
|
+
export { getBrowser, getPlatform, isAndroid, isAndroidChrome, isAndroidEdge, isAndroidFirefox, isAndroidOpera, isChrome, isChromeOS, isEdge, isFirefox, isIOS, isIOSChrome, isIOSEdge, isIOSFirefox, isIOSOpera, isIOSSafari, isMacOS, isMacOSChrome, isMacOSEdge, isOpera, isSafari, isTouchScreen, isWindows, isWindowsChrome, isWindowsEdge, obfuscateLink };
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
//#region src/browser/platform.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Detects if the current user agent is an iOS device (iPad, iPhone, iPod).
|
|
19
|
+
*
|
|
20
|
+
* @returns {boolean} True if the platform is iOS, otherwise false.
|
|
21
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* if (isIOS()) { console.log('Running on iOS'); }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare const isIOS: () => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Detects if the current user agent is an Android device.
|
|
30
|
+
*
|
|
31
|
+
* @returns {boolean} True if the platform is Android, otherwise false.
|
|
32
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* if (isAndroid()) { console.log('Running on Android'); }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare const isAndroid: () => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Detects if the current user agent is a macOS device.
|
|
41
|
+
*
|
|
42
|
+
* @returns {boolean} True if the platform is macOS, otherwise false.
|
|
43
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* if (isMacOS()) { console.log('Running on macOS'); }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare const isMacOS: () => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Detects if the current user agent is a Windows device.
|
|
52
|
+
*
|
|
53
|
+
* @returns {boolean} True if the platform is Windows, otherwise false.
|
|
54
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* if (isWindows()) { console.log('Running on Windows'); }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare const isWindows: () => boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Detects if the current user agent is Chrome OS.
|
|
63
|
+
*
|
|
64
|
+
* @returns {boolean} True if the platform is Chrome OS, otherwise false.
|
|
65
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* if (isChromeOS()) { console.log('Running on Chrome OS'); }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare const isChromeOS: () => boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Retrieves the browser name based on the user agent string.
|
|
74
|
+
*
|
|
75
|
+
* @returns {string} The browser name: 'edge', 'chrome', 'firefox', 'safari', 'opera', 'android', 'iphone', or 'unknown'.
|
|
76
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
77
|
+
* @throws {TypeError} Throws if navigator.userAgent is not accessible.
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* const browser = getBrowser(); // 'chrome', 'firefox', etc.
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare const getBrowser: () => string;
|
|
84
|
+
/**
|
|
85
|
+
* Determines the device platform as a string: 'ios', 'android', 'macos', 'chromeos', 'windows', or 'unknown'.
|
|
86
|
+
*
|
|
87
|
+
* @returns {string} The detected platform.
|
|
88
|
+
* @see isIOS
|
|
89
|
+
* @see isAndroid
|
|
90
|
+
* @see isMacOS
|
|
91
|
+
* @see isChromeOS
|
|
92
|
+
* @see isWindows
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const platform = getPlatform(); // 'android', 'ios', etc.
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
declare const getPlatform: () => string;
|
|
99
|
+
/**
|
|
100
|
+
* Checks if the current device has a touchscreen capability.
|
|
101
|
+
*
|
|
102
|
+
* @returns {boolean} True if touch screen is supported, otherwise false.
|
|
103
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/maxTouchPoints
|
|
104
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* if (isTouchScreen()) { console.log('Device supports touch.'); }
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
declare const isTouchScreen: () => boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Determines if the current browser is Google Chrome.
|
|
113
|
+
*
|
|
114
|
+
* @returns {boolean} True if Chrome, otherwise false.
|
|
115
|
+
* @see getBrowser
|
|
116
|
+
*/
|
|
117
|
+
declare const isChrome: () => boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Determines if the current browser is Mozilla Firefox.
|
|
120
|
+
*
|
|
121
|
+
* @returns {boolean} True if Firefox, otherwise false.
|
|
122
|
+
* @see getBrowser
|
|
123
|
+
*/
|
|
124
|
+
declare const isFirefox: () => boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Determines if the current browser is Safari.
|
|
127
|
+
*
|
|
128
|
+
* @returns {boolean} True if Safari, otherwise false.
|
|
129
|
+
* @see getBrowser
|
|
130
|
+
*/
|
|
131
|
+
declare const isSafari: () => boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Determines if the current browser is Opera.
|
|
134
|
+
*
|
|
135
|
+
* @returns {boolean} True if Opera, otherwise false.
|
|
136
|
+
* @see getBrowser
|
|
137
|
+
*/
|
|
138
|
+
declare const isOpera: () => boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Determines if the current browser is Microsoft Edge.
|
|
141
|
+
*
|
|
142
|
+
* @returns {boolean} True if Edge, otherwise false.
|
|
143
|
+
* @see getBrowser
|
|
144
|
+
*/
|
|
145
|
+
declare const isEdge: () => boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Detects Safari running on iOS devices.
|
|
148
|
+
*
|
|
149
|
+
* @returns {boolean} True if iOS Safari, otherwise false.
|
|
150
|
+
* @see isIOS
|
|
151
|
+
* @see isSafari
|
|
152
|
+
*/
|
|
153
|
+
declare const isIOSSafari: () => boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Detects Chrome running on iOS devices.
|
|
156
|
+
*
|
|
157
|
+
* @returns {boolean} True if iOS Chrome, otherwise false.
|
|
158
|
+
* @see isIOS
|
|
159
|
+
* @see isChrome
|
|
160
|
+
*/
|
|
161
|
+
declare const isIOSChrome: () => boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Detects Chrome running on Android devices.
|
|
164
|
+
*
|
|
165
|
+
* @returns {boolean} True if Android Chrome, otherwise false.
|
|
166
|
+
* @see isAndroid
|
|
167
|
+
* @see isChrome
|
|
168
|
+
*/
|
|
169
|
+
declare const isAndroidChrome: () => boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Detects Chrome running on macOS devices.
|
|
172
|
+
*
|
|
173
|
+
* @returns {boolean} True if macOS Chrome, otherwise false.
|
|
174
|
+
* @see isMacOS
|
|
175
|
+
* @see isChrome
|
|
176
|
+
*/
|
|
177
|
+
declare const isMacOSChrome: () => boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Detects Chrome running on Windows devices.
|
|
180
|
+
*
|
|
181
|
+
* @returns {boolean} True if Windows Chrome, otherwise false.
|
|
182
|
+
* @see isWindows
|
|
183
|
+
* @see isChrome
|
|
184
|
+
*/
|
|
185
|
+
declare const isWindowsChrome: () => boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Detects Firefox running on iOS devices.
|
|
188
|
+
*
|
|
189
|
+
* @returns {boolean} True if iOS Firefox, otherwise false.
|
|
190
|
+
* @see isIOS
|
|
191
|
+
* @see isFirefox
|
|
192
|
+
*/
|
|
193
|
+
declare const isIOSFirefox: () => boolean;
|
|
194
|
+
/**
|
|
195
|
+
* Detects Firefox running on Android devices.
|
|
196
|
+
*
|
|
197
|
+
* @returns {boolean} True if Android Firefox, otherwise false.
|
|
198
|
+
* @see isAndroid
|
|
199
|
+
* @see isFirefox
|
|
200
|
+
*/
|
|
201
|
+
declare const isAndroidFirefox: () => boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Detects Edge running on iOS devices.
|
|
204
|
+
*
|
|
205
|
+
* @returns {boolean} True if iOS Edge, otherwise false.
|
|
206
|
+
* @see isIOS
|
|
207
|
+
* @see isEdge
|
|
208
|
+
*/
|
|
209
|
+
declare const isIOSEdge: () => boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Detects Edge running on Android devices.
|
|
212
|
+
*
|
|
213
|
+
* @returns {boolean} True if Android Edge, otherwise false.
|
|
214
|
+
* @see isAndroid
|
|
215
|
+
* @see isEdge
|
|
216
|
+
*/
|
|
217
|
+
declare const isAndroidEdge: () => boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Detects Edge running on macOS devices.
|
|
220
|
+
*
|
|
221
|
+
* @returns {boolean} True if macOS Edge, otherwise false.
|
|
222
|
+
* @see isMacOS
|
|
223
|
+
* @see isEdge
|
|
224
|
+
*/
|
|
225
|
+
declare const isMacOSEdge: () => boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Detects Edge running on Windows devices.
|
|
228
|
+
*
|
|
229
|
+
* @returns {boolean} True if Windows Edge, otherwise false.
|
|
230
|
+
* @see isWindows
|
|
231
|
+
* @see isEdge
|
|
232
|
+
*/
|
|
233
|
+
declare const isWindowsEdge: () => boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Detects Opera running on iOS devices.
|
|
236
|
+
*
|
|
237
|
+
* @returns {boolean} True if iOS Opera, otherwise false.
|
|
238
|
+
* @see isIOS
|
|
239
|
+
* @see isOpera
|
|
240
|
+
*/
|
|
241
|
+
declare const isIOSOpera: () => boolean;
|
|
242
|
+
/**
|
|
243
|
+
* Detects Opera running on Android devices.
|
|
244
|
+
*
|
|
245
|
+
* @returns {boolean} True if Android Opera, otherwise false.
|
|
246
|
+
* @see isAndroid
|
|
247
|
+
* @see isOpera
|
|
248
|
+
*/
|
|
249
|
+
declare const isAndroidOpera: () => boolean;
|
|
250
|
+
//#endregion
|
|
251
|
+
export { getBrowser, getPlatform, isAndroid, isAndroidChrome, isAndroidEdge, isAndroidFirefox, isAndroidOpera, isChrome, isChromeOS, isEdge, isFirefox, isIOS, isIOSChrome, isIOSEdge, isIOSFirefox, isIOSOpera, isIOSSafari, isMacOS, isMacOSChrome, isMacOSEdge, isOpera, isSafari, isTouchScreen, isWindows, isWindowsChrome, isWindowsEdge };
|
|
252
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","names":[],"sources":["../../src/browser/platform.ts"],"mappings":";;AA0BA;;;;;AAaA;;;;;AAYA;;;;;AAaA;;;;;AAaA;;;;cAnDa,KAAA;AAgEb;;;;;AAyCA;;;;;AAzCA,cAnDa,SAAA;;;;;AAuIb;;;;;AAQA;cAnIa,OAAA;;;;AA2Ib;;;;;AAQA;;cAtIa,SAAA;;;AA8Ib;;;;;AASA;;;cA1Ia,UAAA;;AAmJb;;;;;AASA;;;;;cA/Ia,UAAA;;;;;AAiKb;;;;;AASA;;;;;cAjIa,WAAA;;;;;AAmJb;;;;;AASA;;cA9Ha,aAAA;;;AAuIb;;;;cA1Ha,QAAA;AAmIb;;;;;AASA;AATA,cA3Ha,SAAA;;;;AA6Ib;;;cArIa,QAAA;;;;;;;cAQA,OAAA;;;;;;;cAQA,MAAA;;;;;;;;cASA,WAAA;;;;;;;;cASA,WAAA;;;;;;;;cASA,eAAA;;;;;;;;cASA,aAAA;;;;;;;;cASA,eAAA;;;;;;;;cASA,YAAA;;;;;;;;cASA,gBAAA;;;;;;;;cASA,SAAA;;;;;;;;cASA,aAAA;;;;;;;;cASA,WAAA;;;;;;;;cASA,aAAA;;;;;;;;cASA,UAAA;;;;;;;;cASA,cAAA"}
|