@regardio/js 0.2.4 → 0.4.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 +47 -1
- package/dist/async/delay.d.ts +7 -2
- package/dist/async/delay.js +7 -4
- package/dist/browser/base64.d.ts +8 -2
- package/dist/browser/base64.js +12 -9
- package/dist/format/bytes.d.ts +3 -2
- package/dist/format/bytes.js +12 -9
- package/dist/format/measure.d.ts +3 -2
- package/dist/format/measure.js +14 -12
- package/dist/http/cookie.d.ts +15 -3
- package/dist/http/cookie.js +44 -43
- package/dist/http/domain.d.ts +9 -2
- package/dist/http/domain.js +15 -12
- package/dist/http/request-helpers.d.ts +3 -2
- package/dist/http/request-helpers.js +9 -6
- package/dist/intl/language-detector.d.ts +64 -6
- package/dist/intl/language-detector.js +128 -123
- package/dist/time/time.d.ts +8 -7
- package/dist/time/time.js +121 -118
- package/dist/validation/invariant.d.ts +34 -3
- package/dist/validation/invariant.js +14 -11
- package/dist/validation/verify-file-accept.d.ts +10 -2
- package/dist/validation/verify-file-accept.js +6 -3
- package/package.json +4 -3
- package/dist/async/delay.d.ts.map +0 -1
- package/dist/async/delay.test.d.ts +0 -2
- package/dist/async/delay.test.d.ts.map +0 -1
- package/dist/async/delay.test.js +0 -35
- package/dist/browser/base64.d.ts.map +0 -1
- package/dist/format/bytes.d.ts.map +0 -1
- package/dist/format/bytes.test.d.ts +0 -2
- package/dist/format/bytes.test.d.ts.map +0 -1
- package/dist/format/bytes.test.js +0 -49
- package/dist/format/measure.d.ts.map +0 -1
- package/dist/format/measure.test.d.ts +0 -2
- package/dist/format/measure.test.d.ts.map +0 -1
- package/dist/format/measure.test.js +0 -50
- package/dist/http/cookie.d.ts.map +0 -1
- package/dist/http/domain.d.ts.map +0 -1
- package/dist/http/domain.test.d.ts +0 -2
- package/dist/http/domain.test.d.ts.map +0 -1
- package/dist/http/domain.test.js +0 -29
- package/dist/http/request-helpers.d.ts.map +0 -1
- package/dist/http/request-helpers.test.d.ts +0 -2
- package/dist/http/request-helpers.test.d.ts.map +0 -1
- package/dist/http/request-helpers.test.js +0 -37
- package/dist/intl/language-detector.d.ts.map +0 -1
- package/dist/intl/language-detector.test.d.ts +0 -2
- package/dist/intl/language-detector.test.d.ts.map +0 -1
- package/dist/intl/language-detector.test.js +0 -186
- package/dist/time/time.d.ts.map +0 -1
- package/dist/time/time.test.d.ts +0 -2
- package/dist/time/time.test.d.ts.map +0 -1
- package/dist/time/time.test.js +0 -202
- package/dist/validation/invariant.d.ts.map +0 -1
- package/dist/validation/invariant.test.d.ts +0 -2
- package/dist/validation/invariant.test.d.ts.map +0 -1
- package/dist/validation/invariant.test.js +0 -110
- package/dist/validation/verify-file-accept.d.ts.map +0 -1
- package/dist/validation/verify-file-accept.test.d.ts +0 -2
- package/dist/validation/verify-file-accept.test.d.ts.map +0 -1
- package/dist/validation/verify-file-accept.test.js +0 -71
package/README.md
CHANGED
|
@@ -5,12 +5,33 @@
|
|
|
5
5
|
A collection of lightweight, tree-shakeable utility functions for common tasks
|
|
6
6
|
like HTTP handling, internationalization, time formatting, and validation.
|
|
7
7
|
|
|
8
|
+
## ⚠️ Pre-release Notice
|
|
9
|
+
|
|
10
|
+
**This package is currently in pre-release (v0.x).** While we use these utilities in production across our own projects, the API may still change between minor versions. We recommend:
|
|
11
|
+
|
|
12
|
+
- Pinning to exact versions in your `package.json`
|
|
13
|
+
- Reviewing changelogs before upgrading
|
|
14
|
+
- Expecting potential breaking changes until v1.0
|
|
15
|
+
|
|
16
|
+
## Why This Package?
|
|
17
|
+
|
|
18
|
+
We created `@regardio/js` to:
|
|
19
|
+
|
|
20
|
+
- **Share battle-tested utilities** — These functions power real Regardio projects and have been refined through actual use
|
|
21
|
+
- **Reduce boilerplate** — Common patterns like cookie handling, language detection, and time formatting in one place
|
|
22
|
+
- **Stay framework-agnostic** — Works with any JavaScript/TypeScript project (React, Node, Deno, etc.)
|
|
23
|
+
- **Enable tree-shaking** — Import only what you need; unused utilities won't bloat your bundle
|
|
24
|
+
|
|
8
25
|
## Installation
|
|
9
26
|
|
|
10
27
|
```bash
|
|
11
28
|
pnpm add @regardio/js
|
|
12
29
|
```
|
|
13
30
|
|
|
31
|
+
## Documentation
|
|
32
|
+
|
|
33
|
+
See the [docs](./docs) folder for detailed documentation on each module.
|
|
34
|
+
|
|
14
35
|
## Modules
|
|
15
36
|
|
|
16
37
|
### async/delay
|
|
@@ -146,9 +167,34 @@ verifyAccept('image/png', 'image/*'); // true
|
|
|
146
167
|
verifyAccept('video/mp4', 'image/*'); // false
|
|
147
168
|
```
|
|
148
169
|
|
|
170
|
+
## Module Overview
|
|
171
|
+
|
|
172
|
+
| Module | Description |
|
|
173
|
+
|--------|-------------|
|
|
174
|
+
| `async/delay` | Promise-based delay utility |
|
|
175
|
+
| `browser/base64` | URL-safe base64 to Uint8Array conversion |
|
|
176
|
+
| `format/bytes` | Human-readable byte formatting |
|
|
177
|
+
| `format/measure` | Performance measurement with logging |
|
|
178
|
+
| `http/cookie` | Browser cookie get/set helpers |
|
|
179
|
+
| `http/domain` | Domain extraction from requests (proxy-aware) |
|
|
180
|
+
| `http/request-helpers` | URL cleaning utilities |
|
|
181
|
+
| `intl/language-detector` | Server-side language detection for i18n |
|
|
182
|
+
| `intl/locale` | Client locale extraction from headers |
|
|
183
|
+
| `time/time` | Time formatting and date utilities |
|
|
184
|
+
| `validation/invariant` | Runtime assertion utilities |
|
|
185
|
+
| `validation/verify-file-accept` | MIME type validation for file uploads |
|
|
186
|
+
|
|
187
|
+
## Contributing
|
|
188
|
+
|
|
189
|
+
This package is primarily maintained for Regardio's internal use, but we welcome:
|
|
190
|
+
|
|
191
|
+
- Bug reports and fixes
|
|
192
|
+
- Documentation improvements
|
|
193
|
+
- Feature suggestions (though we may not implement all requests)
|
|
194
|
+
|
|
149
195
|
## License
|
|
150
196
|
|
|
151
|
-
**MIT License**
|
|
197
|
+
**MIT License** — Free to use in commercial and open source projects.
|
|
152
198
|
|
|
153
199
|
---
|
|
154
200
|
|
package/dist/async/delay.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** Delays using a promise
|
|
2
|
+
* @param ms Milisecods of delay
|
|
3
|
+
* @return Promise
|
|
4
|
+
*/
|
|
5
|
+
declare function delay(ms: number): Promise<unknown>;
|
|
6
|
+
|
|
7
|
+
export { delay };
|
package/dist/async/delay.js
CHANGED
package/dist/browser/base64.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Converts a base64 string to a Uint8Array
|
|
3
|
+
* @param base64String The base64 string to convert
|
|
4
|
+
* @returns A Uint8Array containing the decoded data
|
|
5
|
+
*/
|
|
6
|
+
declare const urlBase64ToUint8Array: (base64String: string) => Uint8Array;
|
|
7
|
+
|
|
8
|
+
export { urlBase64ToUint8Array };
|
package/dist/browser/base64.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// src/browser/base64.ts
|
|
2
|
+
var urlBase64ToUint8Array = (base64String) => {
|
|
3
|
+
const padding = "=".repeat((4 - base64String.length % 4) % 4);
|
|
4
|
+
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
|
|
5
|
+
const rawData = window.atob(base64);
|
|
6
|
+
const outputArray = new Uint8Array(rawData.length);
|
|
7
|
+
for (let i = 0; i < rawData.length; ++i) {
|
|
8
|
+
outputArray[i] = rawData.charCodeAt(i);
|
|
9
|
+
}
|
|
10
|
+
return outputArray;
|
|
10
11
|
};
|
|
12
|
+
|
|
13
|
+
export { urlBase64ToUint8Array };
|
package/dist/format/bytes.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare function formatBytes(bytes: number, decimals?: number): string;
|
|
2
|
+
|
|
3
|
+
export { formatBytes };
|
package/dist/format/bytes.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// src/format/bytes.ts
|
|
2
|
+
function formatBytes(bytes, decimals = 2) {
|
|
3
|
+
if (!+bytes) {
|
|
4
|
+
return "0 Bytes";
|
|
5
|
+
}
|
|
6
|
+
const k = 1e3;
|
|
7
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
8
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
9
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
10
|
+
return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
|
|
10
11
|
}
|
|
12
|
+
|
|
13
|
+
export { formatBytes };
|
package/dist/format/measure.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare function measure<Result>(key: string, callback: () => Result | Promise<Result>): Promise<Result>;
|
|
2
|
+
|
|
3
|
+
export { measure };
|
package/dist/format/measure.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return result;
|
|
9
|
-
}
|
|
10
|
-
finally {
|
|
11
|
-
const end = Date.now();
|
|
12
|
-
console.log(`${key} took ${end - start}ms`);
|
|
1
|
+
// src/format/measure.ts
|
|
2
|
+
async function measure(key, callback) {
|
|
3
|
+
const start = Date.now();
|
|
4
|
+
try {
|
|
5
|
+
let result = callback();
|
|
6
|
+
if (result instanceof Promise) {
|
|
7
|
+
result = await result;
|
|
13
8
|
}
|
|
9
|
+
return result;
|
|
10
|
+
} finally {
|
|
11
|
+
const end = Date.now();
|
|
12
|
+
console.log(`${key} took ${end - start}ms`);
|
|
13
|
+
}
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
export { measure };
|
package/dist/http/cookie.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Helper function to set cookies in a more controlled way
|
|
3
|
+
* @param name - The name of the cookie
|
|
4
|
+
* @param value - The value to set
|
|
5
|
+
* @param options - Cookie options
|
|
6
|
+
*/
|
|
7
|
+
declare function setCookieValue(name: string, value: string, options?: {
|
|
2
8
|
expires?: Date;
|
|
3
9
|
path?: string;
|
|
4
10
|
sameSite?: string;
|
|
5
11
|
secure?: boolean;
|
|
6
12
|
domain?: string;
|
|
7
13
|
}): void;
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Get a cookie value by name
|
|
16
|
+
* @param name - The name of the cookie to get
|
|
17
|
+
* @returns The cookie value or null if not found
|
|
18
|
+
*/
|
|
19
|
+
declare function getCookieValue(name: string): string | null;
|
|
20
|
+
|
|
21
|
+
export { getCookieValue, setCookieValue };
|
package/dist/http/cookie.js
CHANGED
|
@@ -1,46 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
1
|
+
// src/http/cookie.ts
|
|
2
|
+
function setCookieValue(name, value, options = {}) {
|
|
3
|
+
if (typeof window === "undefined") {
|
|
4
|
+
console.warn("Cannot set cookie on server side");
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
8
|
+
if (options.expires) {
|
|
9
|
+
cookieString += `; expires=${options.expires.toUTCString()}`;
|
|
10
|
+
}
|
|
11
|
+
if (options.path) {
|
|
12
|
+
cookieString += `; path=${options.path}`;
|
|
13
|
+
}
|
|
14
|
+
if (options.sameSite) {
|
|
15
|
+
cookieString += `; SameSite=${options.sameSite}`;
|
|
16
|
+
}
|
|
17
|
+
if (options.secure) {
|
|
18
|
+
cookieString += "; Secure";
|
|
19
|
+
}
|
|
20
|
+
if (options.domain) {
|
|
21
|
+
cookieString += `; domain=${options.domain}`;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
document.cookie = cookieString;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
console.error(`Failed to set cookie '${name}':`, error.message);
|
|
28
|
+
} else {
|
|
29
|
+
console.error(`Failed to set cookie '${name}': Unknown error`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
const value = `; ${document.cookie}`;
|
|
40
|
-
const parts = value.split(`; ${name}=`);
|
|
41
|
-
if (parts.length === 2) {
|
|
42
|
-
const cookieValue = parts.pop()?.split(';').shift();
|
|
43
|
-
return cookieValue ? decodeURIComponent(cookieValue) : null;
|
|
44
|
-
}
|
|
33
|
+
function getCookieValue(name) {
|
|
34
|
+
if (typeof window === "undefined") {
|
|
35
|
+
console.warn("Cannot get cookie on server side");
|
|
45
36
|
return null;
|
|
37
|
+
}
|
|
38
|
+
const value = `; ${document.cookie}`;
|
|
39
|
+
const parts = value.split(`; ${name}=`);
|
|
40
|
+
if (parts.length === 2) {
|
|
41
|
+
const cookieValue = parts.pop()?.split(";").shift();
|
|
42
|
+
return cookieValue ? decodeURIComponent(cookieValue) : null;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
46
45
|
}
|
|
46
|
+
|
|
47
|
+
export { getCookieValue, setCookieValue };
|
package/dist/http/domain.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Helper utility used to extract the domain from the request even if it's
|
|
3
|
+
* behind a proxy. This is useful for sitemaps and other things.
|
|
4
|
+
* @param request Request object
|
|
5
|
+
* @returns Current domain
|
|
6
|
+
*/
|
|
7
|
+
declare const createDomain: (request: Request) => string;
|
|
8
|
+
|
|
9
|
+
export { createDomain };
|
package/dist/http/domain.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
1
|
+
// src/http/domain.ts
|
|
2
|
+
var createDomain = (request) => {
|
|
3
|
+
const headers = request.headers;
|
|
4
|
+
const maybeProto = headers.get("x-forwarded-proto");
|
|
5
|
+
const maybeHost = headers.get("host");
|
|
6
|
+
const url = new URL(request.url);
|
|
7
|
+
if (maybeProto) {
|
|
8
|
+
return `${maybeProto}://${maybeHost ?? url.host}`;
|
|
9
|
+
}
|
|
10
|
+
if (url.hostname === "localhost") {
|
|
11
|
+
return `http://${url.host}`;
|
|
12
|
+
}
|
|
13
|
+
return `https://${url.host}`;
|
|
13
14
|
};
|
|
15
|
+
|
|
16
|
+
export { createDomain };
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare function getCleanUrl(request: Request): string;
|
|
2
|
+
|
|
3
|
+
export { getCleanUrl };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
// src/http/request-helpers.ts
|
|
2
|
+
function getCleanUrl(request) {
|
|
3
|
+
const url = new URL(request.url);
|
|
4
|
+
url.searchParams.forEach((_, key) => {
|
|
5
|
+
url.searchParams.delete(key);
|
|
6
|
+
});
|
|
7
|
+
return url.toString();
|
|
7
8
|
}
|
|
9
|
+
|
|
10
|
+
export { getCleanUrl };
|
|
@@ -1,23 +1,80 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { Cookie, SessionStorage } from 'react-router';
|
|
2
|
+
|
|
3
|
+
interface LanguageDetectorOption {
|
|
4
|
+
/**
|
|
5
|
+
* Define the list of supported languages, this is used to determine if one of
|
|
6
|
+
* the languages requested by the user is supported by the application.
|
|
7
|
+
* This should be be same as the supportedLngs in the i18next options.
|
|
8
|
+
*/
|
|
3
9
|
supportedLanguages: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Define the fallback language that it's going to be used in the case user
|
|
12
|
+
* expected language is not supported.
|
|
13
|
+
* This should be be same as the fallbackLng in the i18next options.
|
|
14
|
+
*/
|
|
4
15
|
fallbackLanguage: string;
|
|
16
|
+
/**
|
|
17
|
+
* If you want to use a cookie to store the user preferred language, you can
|
|
18
|
+
* pass the Cookie object here.
|
|
19
|
+
*/
|
|
5
20
|
cookie?: Cookie;
|
|
21
|
+
/**
|
|
22
|
+
* If you want to use a session to store the user preferred language, you can
|
|
23
|
+
* pass the SessionStorage object here.
|
|
24
|
+
* When this is not defined, getting the locale will ignore the session.
|
|
25
|
+
*/
|
|
6
26
|
sessionStorage?: SessionStorage;
|
|
27
|
+
/**
|
|
28
|
+
* If defined a sessionStorage and want to change the default key used to
|
|
29
|
+
* store the user preferred language, you can pass the key here.
|
|
30
|
+
* @default "lng"
|
|
31
|
+
*/
|
|
7
32
|
sessionKey?: string;
|
|
33
|
+
/**
|
|
34
|
+
* If you want to use search parameters for language detection and want to
|
|
35
|
+
* change the default key used to for the parameter name,
|
|
36
|
+
* you can pass the key here.
|
|
37
|
+
* @default "lng"
|
|
38
|
+
*/
|
|
8
39
|
searchParamKey?: string;
|
|
40
|
+
/**
|
|
41
|
+
* The order the library will use to detect the user preferred language.
|
|
42
|
+
* By default the order is
|
|
43
|
+
* - urlPath (first segment like /de/ or /en/)
|
|
44
|
+
* - cookie
|
|
45
|
+
* - session
|
|
46
|
+
* - searchParams
|
|
47
|
+
* - header
|
|
48
|
+
* And finally the fallback language.
|
|
49
|
+
*/
|
|
9
50
|
order?: Array<'urlPath' | 'searchParams' | 'cookie' | 'session' | 'header'>;
|
|
10
51
|
}
|
|
11
|
-
|
|
52
|
+
interface LanguageDetectorLinguiOptions {
|
|
12
53
|
detection: LanguageDetectorOption;
|
|
13
54
|
}
|
|
14
|
-
|
|
55
|
+
declare class LanguageDetectorLingui {
|
|
15
56
|
private detector;
|
|
16
57
|
private options;
|
|
17
58
|
constructor(options: LanguageDetectorLinguiOptions);
|
|
59
|
+
/**
|
|
60
|
+
* Detect the current locale by following the order defined in the
|
|
61
|
+
* `detection.order` option.
|
|
62
|
+
* By default the order is
|
|
63
|
+
* - urlPath (first segment like /de/ or /en/)
|
|
64
|
+
* - cookie
|
|
65
|
+
* - session
|
|
66
|
+
* - searchParams
|
|
67
|
+
* - header
|
|
68
|
+
* And finally the fallback language.
|
|
69
|
+
*/
|
|
18
70
|
getLocale(request: Request): Promise<string>;
|
|
19
71
|
}
|
|
20
|
-
|
|
72
|
+
/**
|
|
73
|
+
* The LanguageDetector contains the logic to detect the user preferred language
|
|
74
|
+
* fully server-side by using a SessionStorage, Cookie, URLSearchParams, or
|
|
75
|
+
* Headers.
|
|
76
|
+
*/
|
|
77
|
+
declare class LanguageDetector {
|
|
21
78
|
private options;
|
|
22
79
|
constructor(options: LanguageDetectorOption);
|
|
23
80
|
detect(request: Request): Promise<string>;
|
|
@@ -30,4 +87,5 @@ export declare class LanguageDetector {
|
|
|
30
87
|
private fromHeader;
|
|
31
88
|
private fromSupported;
|
|
32
89
|
}
|
|
33
|
-
|
|
90
|
+
|
|
91
|
+
export { LanguageDetector, LanguageDetectorLingui, type LanguageDetectorLinguiOptions, type LanguageDetectorOption };
|