@planet-matrix/mobius-model 0.5.0 → 0.9.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/CHANGELOG.md +61 -0
- package/README.md +123 -36
- package/dist/index.js +715 -4
- package/dist/index.js.map +981 -13
- package/oxlint.config.ts +6 -0
- package/package.json +36 -18
- package/src/abort/README.md +92 -0
- package/src/abort/abort-manager.ts +278 -0
- package/src/abort/abort-signal-listener-manager.ts +81 -0
- package/src/abort/index.ts +2 -0
- package/src/ai/README.md +1 -0
- package/src/ai/ai.ts +107 -0
- package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
- package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
- package/src/ai/chat-completion-ai/index.ts +7 -0
- package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
- package/src/ai/embedding-ai/embedding-ai.ts +63 -0
- package/src/ai/embedding-ai/embedding.ts +50 -0
- package/src/ai/embedding-ai/index.ts +4 -0
- package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
- package/src/ai/index.ts +4 -0
- package/src/aio/README.md +100 -0
- package/src/aio/content.ts +141 -0
- package/src/aio/index.ts +3 -0
- package/src/aio/json.ts +127 -0
- package/src/aio/prompt.ts +246 -0
- package/src/basic/README.md +72 -116
- package/src/basic/error.ts +19 -5
- package/src/basic/function.ts +83 -64
- package/src/basic/index.ts +1 -0
- package/src/basic/is.ts +152 -71
- package/src/basic/promise.ts +29 -8
- package/src/basic/schedule.ts +111 -0
- package/src/basic/stream.ts +135 -25
- package/src/basic/string.ts +2 -33
- package/src/color/README.md +105 -0
- package/src/color/index.ts +3 -0
- package/src/color/internal.ts +42 -0
- package/src/color/rgb/analyze.ts +236 -0
- package/src/color/rgb/construct.ts +130 -0
- package/src/color/rgb/convert.ts +227 -0
- package/src/color/rgb/derive.ts +303 -0
- package/src/color/rgb/index.ts +6 -0
- package/src/color/rgb/internal.ts +208 -0
- package/src/color/rgb/parse.ts +302 -0
- package/src/color/rgb/serialize.ts +144 -0
- package/src/color/types.ts +57 -0
- package/src/color/xyz/analyze.ts +80 -0
- package/src/color/xyz/construct.ts +19 -0
- package/src/color/xyz/convert.ts +71 -0
- package/src/color/xyz/index.ts +3 -0
- package/src/color/xyz/internal.ts +23 -0
- package/src/credential/README.md +107 -0
- package/src/credential/api-key.ts +158 -0
- package/src/credential/bearer.ts +73 -0
- package/src/credential/index.ts +4 -0
- package/src/credential/json-web-token.ts +96 -0
- package/src/credential/password.ts +170 -0
- package/src/cron/README.md +86 -0
- package/src/cron/cron.ts +87 -0
- package/src/cron/index.ts +1 -0
- package/src/css/README.md +93 -0
- package/src/css/class.ts +559 -0
- package/src/css/index.ts +1 -0
- package/src/drizzle/README.md +1 -0
- package/src/drizzle/drizzle.ts +1 -0
- package/src/drizzle/helper.ts +47 -0
- package/src/drizzle/index.ts +5 -0
- package/src/drizzle/infer.ts +52 -0
- package/src/drizzle/kysely.ts +8 -0
- package/src/drizzle/pagination.ts +200 -0
- package/src/email/README.md +1 -0
- package/src/email/index.ts +1 -0
- package/src/email/resend.ts +25 -0
- package/src/encoding/README.md +66 -79
- package/src/encoding/base64.ts +13 -4
- package/src/environment/README.md +97 -0
- package/src/environment/basic.ts +26 -0
- package/src/environment/device.ts +311 -0
- package/src/environment/feature.ts +285 -0
- package/src/environment/geo.ts +337 -0
- package/src/environment/index.ts +7 -0
- package/src/environment/runtime.ts +400 -0
- package/src/environment/snapshot.ts +60 -0
- package/src/environment/variable.ts +239 -0
- package/src/event/README.md +90 -0
- package/src/event/class-event-proxy.ts +229 -0
- package/src/event/common.ts +29 -0
- package/src/event/event-manager.ts +203 -0
- package/src/event/index.ts +4 -0
- package/src/event/instance-event-proxy.ts +187 -0
- package/src/event/internal.ts +24 -0
- package/src/exception/README.md +96 -0
- package/src/exception/browser.ts +219 -0
- package/src/exception/index.ts +4 -0
- package/src/exception/nodejs.ts +169 -0
- package/src/exception/normalize.ts +106 -0
- package/src/exception/types.ts +99 -0
- package/src/form/README.md +25 -0
- package/src/form/index.ts +1 -0
- package/src/form/inputor-controller/base.ts +874 -0
- package/src/form/inputor-controller/boolean.ts +39 -0
- package/src/form/inputor-controller/file.ts +39 -0
- package/src/form/inputor-controller/form.ts +181 -0
- package/src/form/inputor-controller/helper.ts +117 -0
- package/src/form/inputor-controller/index.ts +17 -0
- package/src/form/inputor-controller/multi-select.ts +99 -0
- package/src/form/inputor-controller/number.ts +116 -0
- package/src/form/inputor-controller/select.ts +109 -0
- package/src/form/inputor-controller/text.ts +82 -0
- package/src/http/READMD.md +1 -0
- package/src/http/api/api-core.ts +84 -0
- package/src/http/api/api-handler.ts +79 -0
- package/src/http/api/api-host.ts +47 -0
- package/src/http/api/api-result.ts +56 -0
- package/src/http/api/api-schema.ts +154 -0
- package/src/http/api/api-server.ts +130 -0
- package/src/http/api/api-test.ts +142 -0
- package/src/http/api/api-type.ts +37 -0
- package/src/http/api/api.ts +81 -0
- package/src/http/api/index.ts +11 -0
- package/src/http/api-adapter/api-core-node-http.ts +260 -0
- package/src/http/api-adapter/api-host-node-http.ts +156 -0
- package/src/http/api-adapter/api-result-arktype.ts +297 -0
- package/src/http/api-adapter/api-result-zod.ts +286 -0
- package/src/http/api-adapter/index.ts +5 -0
- package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
- package/src/http/bin/gen-api-list/index.ts +1 -0
- package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
- package/src/http/bin/gen-api-test/index.ts +1 -0
- package/src/http/bin/gen-api-type/calc-code.ts +25 -0
- package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
- package/src/http/bin/gen-api-type/index.ts +2 -0
- package/src/http/bin/index.ts +2 -0
- package/src/http/index.ts +3 -0
- package/src/huawei/README.md +1 -0
- package/src/huawei/index.ts +2 -0
- package/src/huawei/moderation/index.ts +1 -0
- package/src/huawei/moderation/moderation.ts +355 -0
- package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
- package/src/huawei/obs/index.ts +1 -0
- package/src/huawei/obs/obs.ts +42 -0
- package/src/identifier/README.md +92 -0
- package/src/identifier/id.ts +119 -0
- package/src/identifier/index.ts +2 -0
- package/src/identifier/uuid.ts +187 -0
- package/src/index.ts +33 -1
- package/src/json/README.md +92 -0
- package/src/json/index.ts +1 -0
- package/src/json/repair.ts +18 -0
- package/src/log/README.md +79 -0
- package/src/log/index.ts +5 -0
- package/src/log/log-emitter.ts +72 -0
- package/src/log/log-record.ts +10 -0
- package/src/log/log-scheduler.ts +74 -0
- package/src/log/log-type.ts +8 -0
- package/src/log/logger.ts +554 -0
- package/src/openai/README.md +1 -0
- package/src/openai/index.ts +1 -0
- package/src/openai/openai.ts +510 -0
- package/src/orchestration/README.md +91 -0
- package/src/orchestration/coordination/barrier.ts +214 -0
- package/src/orchestration/coordination/count-down-latch.ts +215 -0
- package/src/orchestration/coordination/errors.ts +98 -0
- package/src/orchestration/coordination/index.ts +16 -0
- package/src/orchestration/coordination/internal/wait-constraints.ts +95 -0
- package/src/orchestration/coordination/internal/wait-queue.ts +109 -0
- package/src/orchestration/coordination/keyed-lock.ts +168 -0
- package/src/orchestration/coordination/mutex.ts +257 -0
- package/src/orchestration/coordination/permit.ts +127 -0
- package/src/orchestration/coordination/read-write-lock.ts +444 -0
- package/src/orchestration/coordination/semaphore.ts +280 -0
- package/src/orchestration/dispatching/dispatcher.ts +83 -0
- package/src/orchestration/dispatching/index.ts +2 -0
- package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
- package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
- package/src/orchestration/dispatching/selector/index.ts +2 -0
- package/src/orchestration/index.ts +3 -0
- package/src/orchestration/scheduling/index.ts +2 -0
- package/src/orchestration/scheduling/scheduler.ts +103 -0
- package/src/orchestration/scheduling/task.ts +32 -0
- package/src/random/README.md +56 -86
- package/src/random/base.ts +66 -0
- package/src/random/index.ts +5 -1
- package/src/random/random-boolean.ts +40 -0
- package/src/random/random-integer.ts +60 -0
- package/src/random/random-number.ts +72 -0
- package/src/random/random-string.ts +66 -0
- package/src/reactor/README.md +4 -0
- package/src/reactor/reactor-core/primitive.ts +9 -9
- package/src/reactor/reactor-core/reactive-system.ts +5 -5
- package/src/request/README.md +108 -0
- package/src/request/fetch/base.ts +108 -0
- package/src/request/fetch/browser.ts +285 -0
- package/src/request/fetch/general.ts +20 -0
- package/src/request/fetch/index.ts +4 -0
- package/src/request/fetch/nodejs.ts +285 -0
- package/src/request/index.ts +2 -0
- package/src/request/request/base.ts +250 -0
- package/src/request/request/general.ts +64 -0
- package/src/request/request/index.ts +3 -0
- package/src/request/request/resource.ts +68 -0
- package/src/result/README.md +4 -0
- package/src/result/controller.ts +54 -0
- package/src/result/either.ts +193 -0
- package/src/result/index.ts +2 -0
- package/src/route/README.md +105 -0
- package/src/route/adapter/browser.ts +122 -0
- package/src/route/adapter/driver.ts +56 -0
- package/src/route/adapter/index.ts +2 -0
- package/src/route/index.ts +3 -0
- package/src/route/router/index.ts +2 -0
- package/src/route/router/route.ts +630 -0
- package/src/route/router/router.ts +1642 -0
- package/src/route/uri/hash.ts +308 -0
- package/src/route/uri/index.ts +7 -0
- package/src/route/uri/pathname.ts +376 -0
- package/src/route/uri/search.ts +413 -0
- package/src/singleton/README.md +79 -0
- package/src/singleton/factory.ts +55 -0
- package/src/singleton/index.ts +2 -0
- package/src/singleton/manager.ts +204 -0
- package/src/socket/README.md +105 -0
- package/src/socket/client/index.ts +2 -0
- package/src/socket/client/socket-unit.ts +660 -0
- package/src/socket/client/socket.ts +203 -0
- package/src/socket/common/index.ts +2 -0
- package/src/socket/common/socket-unit-common.ts +23 -0
- package/src/socket/common/socket-unit-heartbeat.ts +427 -0
- package/src/socket/index.ts +3 -0
- package/src/socket/server/index.ts +3 -0
- package/src/socket/server/server.ts +183 -0
- package/src/socket/server/socket-unit.ts +449 -0
- package/src/socket/server/socket.ts +264 -0
- package/src/storage/README.md +107 -0
- package/src/storage/index.ts +1 -0
- package/src/storage/table.ts +449 -0
- package/src/timer/README.md +86 -0
- package/src/timer/expiration/expiration-manager.ts +594 -0
- package/src/timer/expiration/index.ts +3 -0
- package/src/timer/expiration/min-heap.ts +208 -0
- package/src/timer/expiration/remaining-manager.ts +241 -0
- package/src/timer/index.ts +1 -0
- package/src/tube/README.md +99 -0
- package/src/tube/helper.ts +138 -0
- package/src/tube/index.ts +2 -0
- package/src/tube/tube.ts +880 -0
- package/src/type/README.md +54 -307
- package/src/type/class.ts +2 -2
- package/src/type/index.ts +14 -14
- package/src/type/is.ts +265 -2
- package/src/type/object.ts +37 -0
- package/src/type/string.ts +7 -2
- package/src/type/tuple.ts +6 -6
- package/src/type/union.ts +16 -0
- package/src/web/README.md +77 -0
- package/src/web/capture.ts +35 -0
- package/src/web/clipboard.ts +97 -0
- package/src/web/dom.ts +117 -0
- package/src/web/download.ts +16 -0
- package/src/web/event.ts +46 -0
- package/src/web/index.ts +10 -0
- package/src/web/local-storage.ts +113 -0
- package/src/web/location.ts +28 -0
- package/src/web/permission.ts +172 -0
- package/src/web/script-loader.ts +432 -0
- package/src/weixin/README.md +1 -0
- package/src/weixin/index.ts +2 -0
- package/src/weixin/official-account/authorization.ts +159 -0
- package/src/weixin/official-account/index.ts +2 -0
- package/src/weixin/official-account/js-api.ts +134 -0
- package/src/weixin/open/index.ts +1 -0
- package/src/weixin/open/oauth2.ts +133 -0
- package/tests/unit/abort/abort-manager.spec.ts +225 -0
- package/tests/unit/abort/abort-signal-listener-manager.spec.ts +62 -0
- package/tests/unit/ai/ai.spec.ts +85 -0
- package/tests/unit/aio/content.spec.ts +105 -0
- package/tests/unit/aio/json.spec.ts +147 -0
- package/tests/unit/aio/prompt.spec.ts +111 -0
- package/tests/unit/basic/array.spec.ts +1 -1
- package/tests/unit/basic/error.spec.ts +16 -4
- package/tests/unit/basic/schedule.spec.ts +74 -0
- package/tests/unit/basic/stream.spec.ts +91 -38
- package/tests/unit/basic/string.spec.ts +0 -9
- package/tests/unit/color/rgb/analyze.spec.ts +110 -0
- package/tests/unit/color/rgb/construct.spec.ts +56 -0
- package/tests/unit/color/rgb/convert.spec.ts +60 -0
- package/tests/unit/color/rgb/derive.spec.ts +103 -0
- package/tests/unit/color/rgb/parse.spec.ts +66 -0
- package/tests/unit/color/rgb/serialize.spec.ts +46 -0
- package/tests/unit/color/xyz/analyze.spec.ts +33 -0
- package/tests/unit/color/xyz/construct.spec.ts +10 -0
- package/tests/unit/color/xyz/convert.spec.ts +18 -0
- package/tests/unit/credential/api-key.spec.ts +37 -0
- package/tests/unit/credential/bearer.spec.ts +23 -0
- package/tests/unit/credential/json-web-token.spec.ts +23 -0
- package/tests/unit/credential/password.spec.ts +41 -0
- package/tests/unit/cron/cron.spec.ts +84 -0
- package/tests/unit/css/class.spec.ts +157 -0
- package/tests/unit/environment/basic.spec.ts +20 -0
- package/tests/unit/environment/device.spec.ts +146 -0
- package/tests/unit/environment/feature.spec.ts +388 -0
- package/tests/unit/environment/geo.spec.ts +111 -0
- package/tests/unit/environment/runtime.spec.ts +364 -0
- package/tests/unit/environment/snapshot.spec.ts +4 -0
- package/tests/unit/environment/variable.spec.ts +190 -0
- package/tests/unit/event/class-event-proxy.spec.ts +225 -0
- package/tests/unit/event/event-manager.spec.ts +246 -0
- package/tests/unit/event/instance-event-proxy.spec.ts +187 -0
- package/tests/unit/exception/browser.spec.ts +213 -0
- package/tests/unit/exception/nodejs.spec.ts +144 -0
- package/tests/unit/exception/normalize.spec.ts +57 -0
- package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
- package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
- package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
- package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
- package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
- package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
- package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
- package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
- package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
- package/tests/unit/http/api/api-core-host.spec.ts +207 -0
- package/tests/unit/http/api/api-schema.spec.ts +120 -0
- package/tests/unit/http/api/api-server.spec.ts +363 -0
- package/tests/unit/http/api/api-test.spec.ts +117 -0
- package/tests/unit/http/api/api.spec.ts +121 -0
- package/tests/unit/http/api-adapter/node-http.spec.ts +191 -0
- package/tests/unit/identifier/id.spec.ts +71 -0
- package/tests/unit/identifier/uuid.spec.ts +85 -0
- package/tests/unit/json/repair.spec.ts +11 -0
- package/tests/unit/log/log-emitter.spec.ts +33 -0
- package/tests/unit/log/log-scheduler.spec.ts +40 -0
- package/tests/unit/log/log-type.spec.ts +7 -0
- package/tests/unit/log/logger.spec.ts +237 -0
- package/tests/unit/openai/openai.spec.ts +64 -0
- package/tests/unit/orchestration/coordination/barrier.spec.ts +96 -0
- package/tests/unit/orchestration/coordination/count-down-latch.spec.ts +63 -0
- package/tests/unit/orchestration/coordination/errors.spec.ts +29 -0
- package/tests/unit/orchestration/coordination/keyed-lock.spec.ts +109 -0
- package/tests/unit/orchestration/coordination/mutex.spec.ts +132 -0
- package/tests/unit/orchestration/coordination/permit.spec.ts +43 -0
- package/tests/unit/orchestration/coordination/read-write-lock.spec.ts +154 -0
- package/tests/unit/orchestration/coordination/semaphore.spec.ts +135 -0
- package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
- package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
- package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
- package/tests/unit/random/base.spec.ts +58 -0
- package/tests/unit/random/random-boolean.spec.ts +25 -0
- package/tests/unit/random/random-integer.spec.ts +32 -0
- package/tests/unit/random/random-number.spec.ts +33 -0
- package/tests/unit/random/random-string.spec.ts +22 -0
- package/tests/unit/reactor/alien-signals-effect.spec.ts +11 -10
- package/tests/unit/reactor/preact-signal.spec.ts +1 -2
- package/tests/unit/request/fetch/browser.spec.ts +222 -0
- package/tests/unit/request/fetch/general.spec.ts +43 -0
- package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
- package/tests/unit/request/request/base.spec.ts +385 -0
- package/tests/unit/request/request/general.spec.ts +161 -0
- package/tests/unit/route/router/route.spec.ts +431 -0
- package/tests/unit/route/router/router.spec.ts +407 -0
- package/tests/unit/route/uri/hash.spec.ts +72 -0
- package/tests/unit/route/uri/pathname.spec.ts +147 -0
- package/tests/unit/route/uri/search.spec.ts +107 -0
- package/tests/unit/singleton/singleton.spec.ts +49 -0
- package/tests/unit/socket/client.spec.ts +208 -0
- package/tests/unit/socket/server.spec.ts +135 -0
- package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
- package/tests/unit/storage/table.spec.ts +620 -0
- package/tests/unit/timer/expiration/expiration-manager.spec.ts +464 -0
- package/tests/unit/timer/expiration/min-heap.spec.ts +71 -0
- package/tests/unit/timer/expiration/remaining-manager.spec.ts +234 -0
- package/tests/unit/tube/helper.spec.ts +139 -0
- package/tests/unit/tube/tube.spec.ts +501 -0
- package/.oxlintrc.json +0 -5
- package/src/random/uuid.ts +0 -103
- package/tests/unit/random/uuid.spec.ts +0 -37
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import type { BrowserName, BrowserType, CPUArch, DeviceType, DeviceVendor, EngineName, Extension, OSName } from "ua-parser-js/enums"
|
|
2
|
+
|
|
3
|
+
import { UAParser } from "ua-parser-js"
|
|
4
|
+
import { isAppleSilicon } from "ua-parser-js/device-detection"
|
|
5
|
+
import { isFrozenUA } from "ua-parser-js/helpers"
|
|
6
|
+
import { isAIAssistant, isAICrawler, isBot } from "ua-parser-js/bot-detection"
|
|
7
|
+
import { isChromeFamily, isElectron, isFromEU, isStandalonePWA } from "ua-parser-js/browser-detection"
|
|
8
|
+
|
|
9
|
+
import { Bots, CLIs, Crawlers, Emails, ExtraDevices, Fetchers, InApps, Libraries, MediaPlayers, Vehicles } from "ua-parser-js/extensions"
|
|
10
|
+
|
|
11
|
+
import type { IResult } from "ua-parser-js"
|
|
12
|
+
|
|
13
|
+
interface NetworkInformation {
|
|
14
|
+
downlink: number
|
|
15
|
+
downlinkMax: number
|
|
16
|
+
effectiveType: "slow-2g" | "2g" | "3g" | "4g"
|
|
17
|
+
rtt: number
|
|
18
|
+
saveData: boolean
|
|
19
|
+
type: "bluetooth" | "cellular" | "ethernet" | "none" | "wifi" | "wimax" | "other" | "unknown"
|
|
20
|
+
}
|
|
21
|
+
const getNetworkInformation = (): NetworkInformation | undefined => {
|
|
22
|
+
let connection: NetworkInformation | undefined;
|
|
23
|
+
if ("connection" in navigator) {
|
|
24
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
25
|
+
connection = navigator.connection as NetworkInformation;
|
|
26
|
+
} else if ("mozConnection" in navigator) {
|
|
27
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
28
|
+
connection = navigator.mozConnection as NetworkInformation;
|
|
29
|
+
} else if ("webkitConnection" in navigator) {
|
|
30
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
31
|
+
connection = navigator.webkitConnection as NetworkInformation;
|
|
32
|
+
}
|
|
33
|
+
return connection;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Describe navigator-level device and network metadata.
|
|
38
|
+
*/
|
|
39
|
+
export interface DeviceNavigatorInfo {
|
|
40
|
+
oscpu: string | undefined
|
|
41
|
+
deviceMemory: number | undefined
|
|
42
|
+
hardwareConcurrency: number | undefined
|
|
43
|
+
maxTouchPoints: number | undefined
|
|
44
|
+
platform: Navigator['platform']
|
|
45
|
+
|
|
46
|
+
devicePosture: "continuous" | "folded" | undefined
|
|
47
|
+
connectionDownlink: NetworkInformation['downlink'] | undefined
|
|
48
|
+
connectionDownlinkMax: NetworkInformation['downlinkMax'] | undefined
|
|
49
|
+
connectionEffectiveType: NetworkInformation['effectiveType'] | undefined
|
|
50
|
+
connectionRtt: NetworkInformation['rtt'] | undefined
|
|
51
|
+
connectionSaveData: NetworkInformation['saveData'] | undefined
|
|
52
|
+
connectionType: NetworkInformation['type'] | undefined
|
|
53
|
+
online: boolean
|
|
54
|
+
cookiesEnabled: boolean
|
|
55
|
+
language: string
|
|
56
|
+
languages: string[]
|
|
57
|
+
pdfViewerEnabled: boolean
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Collect device information from the Navigator API.
|
|
61
|
+
*/
|
|
62
|
+
export const getDeviceNavigatorInfo = (): DeviceNavigatorInfo => {
|
|
63
|
+
const connection = getNetworkInformation();
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
oscpu: "oscpu" in navigator ? String(navigator.oscpu) : undefined,
|
|
67
|
+
hardwareConcurrency: "hardwareConcurrency" in navigator ? Number.parseInt(String(navigator.hardwareConcurrency), 10) : undefined,
|
|
68
|
+
deviceMemory: "deviceMemory" in navigator ? Number.parseFloat(String(navigator.deviceMemory)) : undefined,
|
|
69
|
+
maxTouchPoints: navigator.maxTouchPoints,
|
|
70
|
+
platform: navigator.platform,
|
|
71
|
+
|
|
72
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
73
|
+
devicePosture: "devicePosture" in navigator ? (navigator.devicePosture as { type: "continuous" | "folded" }).type : undefined,
|
|
74
|
+
connectionDownlink: connection?.downlink ?? undefined,
|
|
75
|
+
connectionDownlinkMax: connection?.downlinkMax ?? undefined,
|
|
76
|
+
connectionEffectiveType: connection?.effectiveType ?? undefined,
|
|
77
|
+
connectionRtt: connection?.rtt ?? undefined,
|
|
78
|
+
connectionSaveData: connection?.saveData ?? undefined,
|
|
79
|
+
connectionType: connection?.type ?? undefined,
|
|
80
|
+
online: navigator.onLine,
|
|
81
|
+
cookiesEnabled: navigator.cookieEnabled,
|
|
82
|
+
language: navigator.language,
|
|
83
|
+
languages: [...navigator.languages],
|
|
84
|
+
pdfViewerEnabled: navigator.pdfViewerEnabled,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Describe device metadata parsed from a user-agent string.
|
|
90
|
+
*/
|
|
91
|
+
export interface DeviceUserAgentInfo {
|
|
92
|
+
ua: string
|
|
93
|
+
uaIsFrozen: boolean
|
|
94
|
+
|
|
95
|
+
cpuArchitecture: typeof CPUArch[keyof typeof CPUArch] | undefined
|
|
96
|
+
|
|
97
|
+
osName: typeof OSName[keyof typeof OSName] | undefined
|
|
98
|
+
osVersion: IResult['os']['version'] | undefined
|
|
99
|
+
|
|
100
|
+
engineName: typeof EngineName[keyof typeof EngineName] | undefined
|
|
101
|
+
engineVersion: IResult['engine']['version'] | undefined
|
|
102
|
+
|
|
103
|
+
browserName:
|
|
104
|
+
| typeof BrowserName[keyof typeof BrowserName]
|
|
105
|
+
| typeof Extension['BrowserName']['CLI'][keyof typeof Extension['BrowserName']['CLI']]
|
|
106
|
+
| typeof Extension['BrowserName']['Crawler'][keyof typeof Extension['BrowserName']['Crawler']]
|
|
107
|
+
| typeof Extension['BrowserName']['Email'][keyof typeof Extension['BrowserName']['Email']]
|
|
108
|
+
| typeof Extension['BrowserName']['Fetcher'][keyof typeof Extension['BrowserName']['Fetcher']]
|
|
109
|
+
| typeof Extension['BrowserName']['InApp'][keyof typeof Extension['BrowserName']['InApp']]
|
|
110
|
+
| typeof Extension['BrowserName']['Library'][keyof typeof Extension['BrowserName']['Library']]
|
|
111
|
+
| undefined
|
|
112
|
+
browserVersion: IResult['browser']['version'] | undefined
|
|
113
|
+
browserMajor: IResult['browser']['major'] | undefined
|
|
114
|
+
browserType: typeof BrowserType[keyof typeof BrowserType] | undefined
|
|
115
|
+
browserIsAiAssistant: boolean
|
|
116
|
+
browserIsAiCrawler: boolean
|
|
117
|
+
browserIsBot: boolean
|
|
118
|
+
browserIsChromeFamily: boolean
|
|
119
|
+
browserIsElectron: boolean
|
|
120
|
+
browserIsFromEU: boolean
|
|
121
|
+
browserIsStandalonePWA: boolean
|
|
122
|
+
|
|
123
|
+
deviceType: typeof DeviceType[keyof typeof DeviceType] | undefined
|
|
124
|
+
deviceVendor:
|
|
125
|
+
| typeof DeviceVendor[keyof typeof DeviceVendor]
|
|
126
|
+
| typeof Extension['DeviceVendor']['Vehicle'][keyof typeof Extension['DeviceVendor']['Vehicle']]
|
|
127
|
+
| undefined
|
|
128
|
+
deviceModel: IResult['device']['model'] | undefined
|
|
129
|
+
deviceIsAppleSilicon: boolean
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Parse the user-agent string into normalized device metadata.
|
|
133
|
+
*
|
|
134
|
+
* @see {@link https://docs.uaparser.dev/ | UAParser.js}
|
|
135
|
+
*/
|
|
136
|
+
export const parseUserAgent = (userAgent: string): DeviceUserAgentInfo => {
|
|
137
|
+
// @ts-expect-error - UAParser.js type definitions has unknown issue with extensions
|
|
138
|
+
const parser = new UAParser([Bots, CLIs, Crawlers, Emails, ExtraDevices, Fetchers, InApps, Libraries, MediaPlayers, Vehicles])
|
|
139
|
+
parser.setUA(userAgent)
|
|
140
|
+
const result = parser.getResult()
|
|
141
|
+
|
|
142
|
+
let browserIsElectron: boolean
|
|
143
|
+
try {
|
|
144
|
+
browserIsElectron = isElectron()
|
|
145
|
+
} catch {
|
|
146
|
+
browserIsElectron = false
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let browserIsStandalonePWA: boolean
|
|
150
|
+
try {
|
|
151
|
+
browserIsStandalonePWA = isStandalonePWA()
|
|
152
|
+
} catch {
|
|
153
|
+
browserIsStandalonePWA = false
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
ua: userAgent,
|
|
158
|
+
uaIsFrozen: isFrozenUA(userAgent),
|
|
159
|
+
|
|
160
|
+
cpuArchitecture: result.cpu.architecture,
|
|
161
|
+
|
|
162
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
163
|
+
osName: result.os.name as typeof OSName[keyof typeof OSName],
|
|
164
|
+
osVersion: result.os.version,
|
|
165
|
+
|
|
166
|
+
engineName: result.engine.name,
|
|
167
|
+
engineVersion: result.engine.version,
|
|
168
|
+
|
|
169
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
170
|
+
browserName: result.browser.name as typeof BrowserName[keyof typeof BrowserName],
|
|
171
|
+
browserVersion: result.browser.version,
|
|
172
|
+
browserMajor: result.browser.major,
|
|
173
|
+
browserType: result.browser.type,
|
|
174
|
+
browserIsAiAssistant: isAIAssistant(userAgent),
|
|
175
|
+
browserIsAiCrawler: isAICrawler(userAgent),
|
|
176
|
+
browserIsBot: isBot(userAgent),
|
|
177
|
+
browserIsChromeFamily: isChromeFamily(userAgent),
|
|
178
|
+
browserIsElectron,
|
|
179
|
+
browserIsFromEU: isFromEU(),
|
|
180
|
+
browserIsStandalonePWA,
|
|
181
|
+
|
|
182
|
+
deviceType: result.device.type,
|
|
183
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
184
|
+
deviceVendor: result.device.vendor as typeof DeviceVendor[keyof typeof DeviceVendor],
|
|
185
|
+
deviceModel: result.device.model,
|
|
186
|
+
deviceIsAppleSilicon: isAppleSilicon(userAgent),
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const getSafeAreaInset = (edge: "top" | "bottom" | "left" | "right"): number => {
|
|
191
|
+
const style = getComputedStyle(document.documentElement);
|
|
192
|
+
|
|
193
|
+
// 尝试 env(),现代 Safari
|
|
194
|
+
let value = style.getPropertyValue(`env(safe-area-inset-${edge})`);
|
|
195
|
+
if (value === "") {
|
|
196
|
+
// 尝试 constant(),旧版 iOS
|
|
197
|
+
value = style.getPropertyValue(`constant(safe-area-inset-${edge})`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return value !== "" ? Number.parseFloat(value) : 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Describe screen, viewport, and safe-area metadata.
|
|
205
|
+
*/
|
|
206
|
+
export interface DeviceScreenInfo {
|
|
207
|
+
pixelRatio: number
|
|
208
|
+
orientationOriginal: OrientationType | 'unknown'
|
|
209
|
+
orientationCalculated: 'portrait' | 'landscape'
|
|
210
|
+
|
|
211
|
+
screenWidth: number
|
|
212
|
+
screenHeight: number
|
|
213
|
+
screenAvailableWidth: number
|
|
214
|
+
screenAvailableHeight: number
|
|
215
|
+
browserWidth: number
|
|
216
|
+
browserHeight: number
|
|
217
|
+
/**
|
|
218
|
+
* With scrollbar.
|
|
219
|
+
*/
|
|
220
|
+
viewportWidth: number
|
|
221
|
+
/**
|
|
222
|
+
* With scrollbar.
|
|
223
|
+
*/
|
|
224
|
+
viewportHeight: number
|
|
225
|
+
/**
|
|
226
|
+
* Without scrollbar.
|
|
227
|
+
*/
|
|
228
|
+
viewportAvailableWidth: number
|
|
229
|
+
/**
|
|
230
|
+
* Without scrollbar.
|
|
231
|
+
*/
|
|
232
|
+
viewportAvailableHeight: number
|
|
233
|
+
/**
|
|
234
|
+
* Without scrollbar.
|
|
235
|
+
*/
|
|
236
|
+
visualViewportWidth: number | undefined
|
|
237
|
+
/**
|
|
238
|
+
* Without scrollbar.
|
|
239
|
+
*/
|
|
240
|
+
visualViewportHeight: number | undefined
|
|
241
|
+
visualViewportOffsetLeft: number | undefined
|
|
242
|
+
visualViewportOffsetTop: number | undefined
|
|
243
|
+
visualViewportPageLeft: number | undefined
|
|
244
|
+
visualViewportPageTop: number | undefined
|
|
245
|
+
visualViewportScale: number | undefined
|
|
246
|
+
safeAreaTop: number
|
|
247
|
+
safeAreaBottom: number
|
|
248
|
+
safeAreaLeft: number
|
|
249
|
+
safeAreaRight: number
|
|
250
|
+
contentWidth: number
|
|
251
|
+
contentHeight: number
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Collect screen and viewport information from the current window.
|
|
255
|
+
*
|
|
256
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/visualViewport}
|
|
257
|
+
*/
|
|
258
|
+
export const getDeviceScreenInfo = (): DeviceScreenInfo => {
|
|
259
|
+
return {
|
|
260
|
+
pixelRatio: window.devicePixelRatio,
|
|
261
|
+
orientationOriginal: window.screen.orientation?.type || 'unknown',
|
|
262
|
+
orientationCalculated: window.innerWidth > window.innerHeight ? 'landscape' : 'portrait',
|
|
263
|
+
|
|
264
|
+
screenWidth: window.screen.width,
|
|
265
|
+
screenHeight: window.screen.height,
|
|
266
|
+
screenAvailableWidth: window.screen.availWidth,
|
|
267
|
+
screenAvailableHeight: window.screen.availHeight,
|
|
268
|
+
browserWidth: window.outerWidth,
|
|
269
|
+
browserHeight: window.outerHeight,
|
|
270
|
+
viewportWidth: window.innerWidth,
|
|
271
|
+
viewportHeight: window.innerHeight,
|
|
272
|
+
viewportAvailableWidth: document.documentElement.clientWidth,
|
|
273
|
+
viewportAvailableHeight: document.documentElement.clientHeight,
|
|
274
|
+
visualViewportWidth: window.visualViewport?.width,
|
|
275
|
+
visualViewportHeight: window.visualViewport?.height,
|
|
276
|
+
visualViewportOffsetLeft: window.visualViewport?.offsetLeft,
|
|
277
|
+
visualViewportOffsetTop: window.visualViewport?.offsetTop,
|
|
278
|
+
visualViewportPageLeft: window.visualViewport?.pageLeft,
|
|
279
|
+
visualViewportPageTop: window.visualViewport?.pageTop,
|
|
280
|
+
visualViewportScale: window.visualViewport?.scale,
|
|
281
|
+
safeAreaTop: getSafeAreaInset('top'),
|
|
282
|
+
safeAreaBottom: getSafeAreaInset('bottom'),
|
|
283
|
+
safeAreaLeft: getSafeAreaInset('left'),
|
|
284
|
+
safeAreaRight: getSafeAreaInset('right'),
|
|
285
|
+
contentWidth: document.documentElement.scrollWidth,
|
|
286
|
+
contentHeight: document.documentElement.scrollHeight
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Describe merged device information from navigator, UA, and screen.
|
|
292
|
+
*/
|
|
293
|
+
export interface DeviceInfo {
|
|
294
|
+
navigator: DeviceNavigatorInfo
|
|
295
|
+
userAgent: DeviceUserAgentInfo
|
|
296
|
+
screen: DeviceScreenInfo
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get merged device information from navigator, user-agent, and screen.
|
|
300
|
+
*/
|
|
301
|
+
export const getDeviceInfo = (userAgent: string): DeviceInfo => {
|
|
302
|
+
const navigatorInfo = getDeviceNavigatorInfo();
|
|
303
|
+
const userAgentInfo = parseUserAgent(userAgent);
|
|
304
|
+
const screenInfo = getDeviceScreenInfo();
|
|
305
|
+
|
|
306
|
+
return {
|
|
307
|
+
navigator: navigatorInfo,
|
|
308
|
+
userAgent: userAgentInfo,
|
|
309
|
+
screen: screenInfo
|
|
310
|
+
};
|
|
311
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { useFactory } from "./basic.ts"
|
|
2
|
+
|
|
3
|
+
import type { Use } from "./basic.ts"
|
|
4
|
+
|
|
5
|
+
import type { StringAutoCompletable } from "../type/string.ts"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Define built-in and custom feature keys for capability detection.
|
|
9
|
+
*/
|
|
10
|
+
export type Feature =
|
|
11
|
+
| StringAutoCompletable
|
|
12
|
+
| "process"
|
|
13
|
+
| "navigator"
|
|
14
|
+
| "permissions"
|
|
15
|
+
| "document"
|
|
16
|
+
| "css"
|
|
17
|
+
|
|
18
|
+
interface FeatureRegistryItem {
|
|
19
|
+
feature: Feature
|
|
20
|
+
detect: () => boolean
|
|
21
|
+
}
|
|
22
|
+
const internalFeatureRegistry = new Map<Feature, FeatureRegistryItem>();
|
|
23
|
+
/**
|
|
24
|
+
* Check whether a feature is registered.
|
|
25
|
+
*/
|
|
26
|
+
export const isFeatureRegistered = (feature: Feature): boolean => {
|
|
27
|
+
return internalFeatureRegistry.has(feature);
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Register a feature detector.
|
|
31
|
+
*/
|
|
32
|
+
export const registerFeature = (item: FeatureRegistryItem): void => {
|
|
33
|
+
internalFeatureRegistry.set(item.feature, item);
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Unregister a feature detector.
|
|
37
|
+
*/
|
|
38
|
+
export const unregisterFeature = (feature: Feature): void => {
|
|
39
|
+
internalFeatureRegistry.delete(feature);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* List all registered feature keys.
|
|
43
|
+
*/
|
|
44
|
+
export const listFeatures = (): Feature[] => {
|
|
45
|
+
return Array.from(internalFeatureRegistry.keys());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get a feature registry item by feature key.
|
|
50
|
+
*/
|
|
51
|
+
export const getFeatureRegistryItem = (feature: Feature): FeatureRegistryItem | undefined => {
|
|
52
|
+
return internalFeatureRegistry.get(feature);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Define detection results for registered features.
|
|
57
|
+
*/
|
|
58
|
+
export type FeatureFlags = Record<Feature, boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Get the flags for all registered features.
|
|
61
|
+
*/
|
|
62
|
+
export const getFeatureFlags = (): FeatureFlags => {
|
|
63
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
64
|
+
const flags: FeatureFlags = {} as FeatureFlags;
|
|
65
|
+
|
|
66
|
+
for (const [name, item] of internalFeatureRegistry) {
|
|
67
|
+
flags[name] = item.detect();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return flags;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if the current environment satisfies the specified feature.
|
|
75
|
+
*/
|
|
76
|
+
export const isSatisfiesFeature = (feature: Feature): boolean => {
|
|
77
|
+
const featureRegistryItem = getFeatureRegistryItem(feature);
|
|
78
|
+
if (featureRegistryItem === undefined) {
|
|
79
|
+
throw new Error(`Feature "${feature}" is not registered.`);
|
|
80
|
+
}
|
|
81
|
+
return featureRegistryItem.detect() === true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if the current environment satisfies the specified feature conditions.
|
|
86
|
+
*/
|
|
87
|
+
export const isSatisfiesFeatures = (condition: Partial<FeatureFlags>): boolean => {
|
|
88
|
+
let result = true;
|
|
89
|
+
Object.keys(condition).forEach((feature) => {
|
|
90
|
+
const featureRegistryItem = getFeatureRegistryItem(feature as Feature);
|
|
91
|
+
if (featureRegistryItem === undefined) {
|
|
92
|
+
throw new Error(`Feature "${feature}" is not registered.`);
|
|
93
|
+
}
|
|
94
|
+
if (featureRegistryItem.detect() !== condition[feature]) {
|
|
95
|
+
result = false;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Check if the `process` object is available in the environment.
|
|
103
|
+
*/
|
|
104
|
+
export const supportProcess = (): boolean => {
|
|
105
|
+
return typeof process !== "undefined" && process !== null && typeof process === "object"
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get the `process` object from the current environment.
|
|
109
|
+
*/
|
|
110
|
+
export const getProcess = (): NodeJS.Process => {
|
|
111
|
+
return globalThis.process
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the `process` object if it is available, otherwise throw an error.
|
|
115
|
+
*/
|
|
116
|
+
export const ensureProcess = (): NodeJS.Process => {
|
|
117
|
+
if (supportProcess() === true) {
|
|
118
|
+
return getProcess()
|
|
119
|
+
} else {
|
|
120
|
+
throw new Error("The process object is not supported in the current environment.")
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Execute a function with the `process` object if it is available.
|
|
125
|
+
*/
|
|
126
|
+
export const useProcess: Use<NodeJS.Process> = useFactory(getProcess, supportProcess)
|
|
127
|
+
registerFeature({
|
|
128
|
+
feature: "process",
|
|
129
|
+
detect: supportProcess,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if the `navigator` object is available in the environment.
|
|
134
|
+
*/
|
|
135
|
+
export const supportNavigator = (): boolean => {
|
|
136
|
+
return typeof navigator !== "undefined" && navigator !== null && typeof navigator === "object"
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get the `navigator` object from the current environment.
|
|
140
|
+
*/
|
|
141
|
+
export const getNavigator = (): Navigator => {
|
|
142
|
+
return globalThis.navigator
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get the `navigator` object if it is available, otherwise throw an error.
|
|
146
|
+
*/
|
|
147
|
+
export const ensureNavigator = (): Navigator => {
|
|
148
|
+
if (supportNavigator() === true) {
|
|
149
|
+
return getNavigator()
|
|
150
|
+
} else {
|
|
151
|
+
throw new Error("The navigator object is not supported in the current environment.")
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Execute a function with the `navigator` object if it is available.
|
|
156
|
+
*/
|
|
157
|
+
export const useNavigator: Use<Navigator> = useFactory(getNavigator, supportNavigator)
|
|
158
|
+
registerFeature({
|
|
159
|
+
feature: "navigator",
|
|
160
|
+
detect: supportNavigator,
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Check if the `clipboard` API is available in the environment.
|
|
165
|
+
*/
|
|
166
|
+
export const supportClipboard = (): boolean => {
|
|
167
|
+
return supportNavigator() && "clipboard" in navigator
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get the `clipboard` API from the current environment.
|
|
171
|
+
*/
|
|
172
|
+
export const getClipboard = (): Clipboard => {
|
|
173
|
+
return navigator.clipboard
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get the `clipboard` API if it is available, otherwise throw an error.
|
|
177
|
+
*/
|
|
178
|
+
export const ensureClipboard = (): Clipboard => {
|
|
179
|
+
if (supportClipboard() === true) {
|
|
180
|
+
return getClipboard()
|
|
181
|
+
} else {
|
|
182
|
+
throw new Error("The clipboard API is not supported in the current environment.")
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Execute a function with the `clipboard` API if it is available.
|
|
187
|
+
*/
|
|
188
|
+
export const useClipboard: Use<Clipboard> = useFactory(getClipboard, supportClipboard)
|
|
189
|
+
registerFeature({
|
|
190
|
+
feature: "clipboard",
|
|
191
|
+
detect: supportClipboard,
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check if the `permissions` API is available in the environment.
|
|
196
|
+
*/
|
|
197
|
+
export const supportPermissions = (): boolean => {
|
|
198
|
+
return supportNavigator() && "permissions" in navigator
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get the `permissions` API from the current environment.
|
|
202
|
+
*/
|
|
203
|
+
export const getPermissions = (): Permissions => {
|
|
204
|
+
return navigator.permissions
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get the `permissions` API if it is available, otherwise throw an error.
|
|
208
|
+
*/
|
|
209
|
+
export const ensurePermissions = (): Permissions => {
|
|
210
|
+
if (supportPermissions() === true) {
|
|
211
|
+
return getPermissions()
|
|
212
|
+
} else {
|
|
213
|
+
throw new Error("The permissions API is not supported in the current environment.")
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Execute a function with the `permissions` API if it is available.
|
|
218
|
+
*/
|
|
219
|
+
export const usePermissions: Use<Permissions> = useFactory(getPermissions, supportPermissions)
|
|
220
|
+
registerFeature({
|
|
221
|
+
feature: "permissions",
|
|
222
|
+
detect: supportPermissions,
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Check if the `document` object is available in the environment.
|
|
227
|
+
*/
|
|
228
|
+
export const supportDocument = (): boolean => {
|
|
229
|
+
return typeof document !== "undefined" && document !== null && typeof document === "object"
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get the `document` object from the current environment.
|
|
233
|
+
*/
|
|
234
|
+
export const getDocument = (): Document => {
|
|
235
|
+
return globalThis.document
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get the `document` object if it is available, otherwise throw an error.
|
|
239
|
+
*/
|
|
240
|
+
export const ensureDocument = (): Document => {
|
|
241
|
+
if (supportDocument() === true) {
|
|
242
|
+
return getDocument()
|
|
243
|
+
} else {
|
|
244
|
+
throw new Error("The document object is not supported in the current environment.")
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Execute a function with the `document` object if it is available.
|
|
249
|
+
*/
|
|
250
|
+
export const useDocument: Use<Document> = useFactory(getDocument, supportDocument)
|
|
251
|
+
registerFeature({
|
|
252
|
+
feature: "document",
|
|
253
|
+
detect: supportDocument,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Check if the `CSS` object is available in the environment.
|
|
258
|
+
*/
|
|
259
|
+
export const supportCSS = (): boolean => {
|
|
260
|
+
return typeof CSS !== "undefined" && CSS !== null && typeof CSS === "object"
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get the `CSS` object from the current environment.
|
|
264
|
+
*/
|
|
265
|
+
export const getCSS = (): typeof CSS => {
|
|
266
|
+
return globalThis.CSS
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get the `CSS` object if it is available, otherwise throw an error.
|
|
270
|
+
*/
|
|
271
|
+
export const ensureCSS = (): typeof CSS => {
|
|
272
|
+
if (supportCSS() === true) {
|
|
273
|
+
return getCSS()
|
|
274
|
+
} else {
|
|
275
|
+
throw new Error("The CSS object is not supported in the current environment.")
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Execute a function with the `CSS` object if it is available.
|
|
280
|
+
*/
|
|
281
|
+
export const useCSS: Use<typeof CSS> = useFactory(getCSS, supportCSS)
|
|
282
|
+
registerFeature({
|
|
283
|
+
feature: "css",
|
|
284
|
+
detect: supportCSS,
|
|
285
|
+
})
|