@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,109 @@
|
|
|
1
|
+
// oxlint-disable typescript/no-explicit-any
|
|
2
|
+
|
|
3
|
+
import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema, InputorControllerInitializeHooks } from "./base.ts"
|
|
4
|
+
import { BaseInputorController } from "./base.ts"
|
|
5
|
+
|
|
6
|
+
export const SELECT_INPUTOR_TYPE_NAME = "select" as const
|
|
7
|
+
export type SelectInputorTypeName = typeof SELECT_INPUTOR_TYPE_NAME
|
|
8
|
+
|
|
9
|
+
export interface SelectOption<Value = any> {
|
|
10
|
+
name: string
|
|
11
|
+
label: string
|
|
12
|
+
value: Value
|
|
13
|
+
isSelected: boolean
|
|
14
|
+
description?: string | undefined
|
|
15
|
+
isDisabled?: boolean | undefined
|
|
16
|
+
}
|
|
17
|
+
export type SelectOptions<Value = any> = Array<SelectOption<Value>>
|
|
18
|
+
export type SelectInputorExternalValue<Value = any> = SelectOptions<Value>
|
|
19
|
+
export type SelectInputorInternalValue<Value = any> = SelectOptions<Value>
|
|
20
|
+
export interface SelectInputorSchema<Value = any> extends BaseInputorSchema<SelectInputorExternalValue<Value>> {
|
|
21
|
+
inputorTypeName: SelectInputorTypeName
|
|
22
|
+
}
|
|
23
|
+
export interface SelectInputorContext<Value = any> extends BaseInputorContext<SelectInputorExternalValue<Value>, SelectInputorInternalValue<Value>> {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SelectInputorControllerOptions<Value = any> extends BaseInputorControllerOptions<
|
|
27
|
+
SelectInputorExternalValue<Value>,
|
|
28
|
+
SelectInputorSchema<Value>
|
|
29
|
+
> {
|
|
30
|
+
/**
|
|
31
|
+
* 是否允许取消选择。
|
|
32
|
+
*
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
enableUnselect?: boolean
|
|
36
|
+
}
|
|
37
|
+
export class SelectInputorController<Value = any> extends BaseInputorController<
|
|
38
|
+
SelectInputorExternalValue<Value>,
|
|
39
|
+
SelectInputorInternalValue<Value>,
|
|
40
|
+
SelectInputorSchema<Value>,
|
|
41
|
+
SelectInputorContext<Value>
|
|
42
|
+
> {
|
|
43
|
+
declare schemaType: SelectInputorSchema<Value>
|
|
44
|
+
declare optionsType: SelectInputorControllerOptions<Value>
|
|
45
|
+
declare constructorType: typeof SelectInputorController<Value>
|
|
46
|
+
|
|
47
|
+
static inputorTypeName: SelectInputorTypeName = SELECT_INPUTOR_TYPE_NAME
|
|
48
|
+
|
|
49
|
+
inputorTypeName: SelectInputorTypeName = SELECT_INPUTOR_TYPE_NAME
|
|
50
|
+
voidExternalValue = [] as SelectInputorExternalValue<Value>
|
|
51
|
+
voidInternalValue = [] as SelectInputorInternalValue<Value>
|
|
52
|
+
|
|
53
|
+
private enableUnselect!: boolean
|
|
54
|
+
|
|
55
|
+
constructor(options: SelectInputorControllerOptions<Value>) {
|
|
56
|
+
super(options)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected override async initialize(
|
|
60
|
+
options: SelectInputorControllerOptions<Value>,
|
|
61
|
+
hooks?: InputorControllerInitializeHooks,
|
|
62
|
+
): Promise<void> {
|
|
63
|
+
await super.initialize(options, {
|
|
64
|
+
...hooks,
|
|
65
|
+
onSchemaReady: async () => {
|
|
66
|
+
this.enableUnselect = options.enableUnselect ?? false
|
|
67
|
+
await hooks?.onSchemaReady?.()
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async select(name: string): Promise<void> {
|
|
73
|
+
if (this.isDisabled === true) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const internalValue = this.getInternalValue()
|
|
78
|
+
const disabledSelectedName = internalValue.find(option => {
|
|
79
|
+
return option.isSelected && (option.isDisabled === true)
|
|
80
|
+
})?.name
|
|
81
|
+
const updatedInternalValue = internalValue.map((option) => {
|
|
82
|
+
const { name: optionName, isSelected: _isSelected, isDisabled } = option
|
|
83
|
+
|
|
84
|
+
if (disabledSelectedName !== undefined) {
|
|
85
|
+
return {
|
|
86
|
+
...option,
|
|
87
|
+
isSelected: optionName === disabledSelectedName,
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (isDisabled === true) {
|
|
92
|
+
return option
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (optionName !== name) {
|
|
96
|
+
return {
|
|
97
|
+
...option,
|
|
98
|
+
isSelected: false,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
...option,
|
|
104
|
+
isSelected: this.enableUnselect ? !option.isSelected : true,
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
await this.updateInternalValue(updatedInternalValue)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema, InputorControllerInitializeHooks } from "./base.ts"
|
|
2
|
+
import { BaseInputorController } from "./base.ts"
|
|
3
|
+
|
|
4
|
+
export const TEXT_INPUTOR_TYPE_NAME = "text" as const
|
|
5
|
+
export type TextInputorTypeName = typeof TEXT_INPUTOR_TYPE_NAME
|
|
6
|
+
|
|
7
|
+
export type TextInputorExternalValue = string | undefined
|
|
8
|
+
export type TextInputorInternalValue = string | undefined
|
|
9
|
+
export interface TextInputorSchema extends BaseInputorSchema<TextInputorExternalValue> {
|
|
10
|
+
inputorTypeName: TextInputorTypeName
|
|
11
|
+
minLength?: number | undefined
|
|
12
|
+
maxLength?: number | undefined
|
|
13
|
+
}
|
|
14
|
+
export interface TextInputorContext extends BaseInputorContext<TextInputorExternalValue, TextInputorInternalValue> {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TextInputorControllerOptions extends BaseInputorControllerOptions<
|
|
18
|
+
TextInputorExternalValue,
|
|
19
|
+
TextInputorSchema
|
|
20
|
+
> {
|
|
21
|
+
minLength?: number | undefined
|
|
22
|
+
maxLength?: number | undefined
|
|
23
|
+
}
|
|
24
|
+
export class TextInputorController extends BaseInputorController<
|
|
25
|
+
TextInputorExternalValue,
|
|
26
|
+
TextInputorInternalValue,
|
|
27
|
+
TextInputorSchema,
|
|
28
|
+
TextInputorContext
|
|
29
|
+
> {
|
|
30
|
+
declare schemaType: TextInputorSchema
|
|
31
|
+
declare optionsType: TextInputorControllerOptions
|
|
32
|
+
declare constructorType: typeof TextInputorController
|
|
33
|
+
|
|
34
|
+
static inputorTypeName: TextInputorTypeName = TEXT_INPUTOR_TYPE_NAME
|
|
35
|
+
|
|
36
|
+
inputorTypeName: TextInputorTypeName = TEXT_INPUTOR_TYPE_NAME
|
|
37
|
+
voidExternalValue = undefined
|
|
38
|
+
voidInternalValue = undefined
|
|
39
|
+
|
|
40
|
+
private minLength!: number
|
|
41
|
+
private maxLength!: number
|
|
42
|
+
|
|
43
|
+
constructor(options: TextInputorControllerOptions) {
|
|
44
|
+
super(options)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected override async initialize(
|
|
48
|
+
options: TextInputorControllerOptions,
|
|
49
|
+
hooks?: InputorControllerInitializeHooks,
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
await super.initialize(options, {
|
|
52
|
+
...hooks,
|
|
53
|
+
onSchemaReady: async () => {
|
|
54
|
+
this.minLength = options.minLength ?? 0
|
|
55
|
+
this.maxLength = options.maxLength ?? Infinity
|
|
56
|
+
await hooks?.onSchemaReady?.()
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
override async getSchema(): Promise<TextInputorSchema> {
|
|
62
|
+
return {
|
|
63
|
+
...await super.getSchema(),
|
|
64
|
+
minLength: this.minLength,
|
|
65
|
+
maxLength: this.maxLength,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
protected override async constrainExternalValue(externalValue: TextInputorExternalValue): Promise<TextInputorExternalValue> {
|
|
70
|
+
if (externalValue === undefined) {
|
|
71
|
+
return await Promise.resolve(undefined)
|
|
72
|
+
}
|
|
73
|
+
return await Promise.resolve(externalValue.slice(0, this.maxLength))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected override async constrainInternalValue(internalValue: TextInputorInternalValue): Promise<TextInputorInternalValue> {
|
|
77
|
+
if (internalValue === undefined) {
|
|
78
|
+
return await Promise.resolve(undefined)
|
|
79
|
+
}
|
|
80
|
+
return await Promise.resolve(internalValue.slice(0, this.maxLength))
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Http
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type ApiCoreHeaderValue = [string, ...string[]] | undefined
|
|
2
|
+
export interface ApiCoreHeaders {
|
|
3
|
+
[key: string]: ApiCoreHeaderValue
|
|
4
|
+
}
|
|
5
|
+
export interface ApiCoreRequestFormDataEntry {
|
|
6
|
+
name: string
|
|
7
|
+
value: string | File
|
|
8
|
+
}
|
|
9
|
+
export type ApiCoreRequestFormData = ApiCoreRequestFormDataEntry[]
|
|
10
|
+
export interface ApiCoreRequestFile {
|
|
11
|
+
name: string
|
|
12
|
+
value: File
|
|
13
|
+
}
|
|
14
|
+
export type ApiCoreRequestFiles = ApiCoreRequestFile[]
|
|
15
|
+
export interface ApiCoreStream {
|
|
16
|
+
write(chunk: Buffer | string, encoding: BufferEncoding): Promise<void>
|
|
17
|
+
end(): Promise<void>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 参考 WHATWG 语义的稳定内部抽象类,适配不同环境的 HTTP 请求和响应。
|
|
22
|
+
*/
|
|
23
|
+
export abstract class ApiCore {
|
|
24
|
+
/**
|
|
25
|
+
* Header names are in lowercase for consistency.
|
|
26
|
+
*/
|
|
27
|
+
abstract getRequestHeaders(): Promise<ApiCoreHeaders>
|
|
28
|
+
async getRequestHeader(name: string): Promise<ApiCoreHeaderValue> {
|
|
29
|
+
const headers = await this.getRequestHeaders()
|
|
30
|
+
const headerValue = headers[name.toLowerCase()]
|
|
31
|
+
return headerValue
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Method names are in uppercase for consistency with the standard HTTP method names.
|
|
36
|
+
*/
|
|
37
|
+
abstract getRequestMethod(): Promise<string>
|
|
38
|
+
|
|
39
|
+
abstract getRequestUrl(): string
|
|
40
|
+
async getRequestPath(): Promise<string> {
|
|
41
|
+
const urlInString = this.getRequestUrl()
|
|
42
|
+
const url = new URL(urlInString)
|
|
43
|
+
const path = url.pathname
|
|
44
|
+
return await Promise.resolve(path)
|
|
45
|
+
}
|
|
46
|
+
async getRequestSearch(): Promise<string> {
|
|
47
|
+
const urlInString = this.getRequestUrl()
|
|
48
|
+
const url = new URL(urlInString)
|
|
49
|
+
const search = url.search
|
|
50
|
+
return await Promise.resolve(search)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
abstract getRequestBodyText(): Promise<string>
|
|
54
|
+
async getRequestBodyJson(): Promise<unknown> {
|
|
55
|
+
const bodyText = await this.getRequestBodyText()
|
|
56
|
+
|
|
57
|
+
if (bodyText.trim().length === 0) {
|
|
58
|
+
return {}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return JSON.parse(bodyText) as unknown
|
|
62
|
+
}
|
|
63
|
+
abstract getRequestBodyFormData(): Promise<ApiCoreRequestFormData>
|
|
64
|
+
async getRequestFiles(): Promise<ApiCoreRequestFiles> {
|
|
65
|
+
const formData = await this.getRequestBodyFormData()
|
|
66
|
+
const files: ApiCoreRequestFiles = []
|
|
67
|
+
|
|
68
|
+
for (const entry of formData) {
|
|
69
|
+
if (entry.value instanceof File) {
|
|
70
|
+
files.push({
|
|
71
|
+
name: entry.name,
|
|
72
|
+
value: entry.value,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return files
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
abstract text(data: unknown): Promise<void>
|
|
81
|
+
abstract json(data: unknown): Promise<void>
|
|
82
|
+
abstract stream(): Promise<ApiCoreStream>
|
|
83
|
+
abstract error(): Promise<void>
|
|
84
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec"
|
|
2
|
+
|
|
3
|
+
import type { Logger } from "#Source/log/index.ts"
|
|
4
|
+
|
|
5
|
+
import type { ApiCore } from "./api-core.ts"
|
|
6
|
+
import type { ErrorResult, SuccessResult } from "./api-result.ts"
|
|
7
|
+
import type { ApiSchemaOptions } from "./api-schema.ts"
|
|
8
|
+
|
|
9
|
+
export interface ApiHandlerContext<
|
|
10
|
+
Path extends string,
|
|
11
|
+
Method extends "get" | "post",
|
|
12
|
+
InputQuerySchema extends StandardSchemaV1,
|
|
13
|
+
InputBodySchema extends StandardSchemaV1,
|
|
14
|
+
OutputSuccessSchema extends StandardSchemaV1,
|
|
15
|
+
OutputErrorSchema extends StandardSchemaV1,
|
|
16
|
+
> extends ApiSchemaOptions<Path, Method, InputQuerySchema, InputBodySchema, OutputSuccessSchema, OutputErrorSchema> {
|
|
17
|
+
inputQuery: StandardSchemaV1.InferOutput<InputQuerySchema>
|
|
18
|
+
inputBody: StandardSchemaV1.InferOutput<InputBodySchema>
|
|
19
|
+
|
|
20
|
+
apiCore: ApiCore
|
|
21
|
+
logger: Logger
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type AnyApiHandlerContext = ApiHandlerContext<string, "get" | "post", StandardSchemaV1, StandardSchemaV1, StandardSchemaV1, StandardSchemaV1>
|
|
25
|
+
|
|
26
|
+
export type GetInputQuerySchemaFromApiHandlerContext<Target extends AnyApiHandlerContext> = Target extends ApiHandlerContext<
|
|
27
|
+
infer _,
|
|
28
|
+
infer __,
|
|
29
|
+
infer InputQuerySchema,
|
|
30
|
+
infer ___,
|
|
31
|
+
infer ____,
|
|
32
|
+
infer ______
|
|
33
|
+
> ? InputQuerySchema : never
|
|
34
|
+
export type GetInputBodySchemaFromApiHandlerContext<Target extends AnyApiHandlerContext> = Target extends ApiHandlerContext<
|
|
35
|
+
infer _,
|
|
36
|
+
infer __,
|
|
37
|
+
infer ___,
|
|
38
|
+
infer InputBodySchema,
|
|
39
|
+
infer ____,
|
|
40
|
+
infer ______
|
|
41
|
+
> ? InputBodySchema : never
|
|
42
|
+
export type GetOutputSuccessSchemaFromApiHandlerContext<Target extends AnyApiHandlerContext> = Target extends ApiHandlerContext<
|
|
43
|
+
infer _,
|
|
44
|
+
infer __,
|
|
45
|
+
infer ___,
|
|
46
|
+
infer ____,
|
|
47
|
+
infer OutputSuccessSchema,
|
|
48
|
+
infer ______
|
|
49
|
+
> ? OutputSuccessSchema : never
|
|
50
|
+
export type GetOutputErrorSchemaFromApiHandlerContext<Target extends AnyApiHandlerContext> = Target extends ApiHandlerContext<
|
|
51
|
+
infer _,
|
|
52
|
+
infer __,
|
|
53
|
+
infer ___,
|
|
54
|
+
infer ____,
|
|
55
|
+
infer ______,
|
|
56
|
+
infer OutputErrorSchema
|
|
57
|
+
> ? OutputErrorSchema : never
|
|
58
|
+
|
|
59
|
+
export type GetInputQueryFromApiHandlerContext<Target extends AnyApiHandlerContext> = StandardSchemaV1.InferOutput<GetInputQuerySchemaFromApiHandlerContext<Target>>
|
|
60
|
+
export type GetInputBodyFromApiHandlerContext<Target extends AnyApiHandlerContext> = StandardSchemaV1.InferOutput<GetInputBodySchemaFromApiHandlerContext<Target>>
|
|
61
|
+
export type GetOutputSuccessFromApiHandlerContext<Target extends AnyApiHandlerContext> = StandardSchemaV1.InferOutput<GetOutputSuccessSchemaFromApiHandlerContext<Target>>
|
|
62
|
+
export type GetOutputErrorFromApiHandlerContext<Target extends AnyApiHandlerContext> = StandardSchemaV1.InferOutput<GetOutputErrorSchemaFromApiHandlerContext<Target>>
|
|
63
|
+
export type GetOutputFromApiHandlerContext<Target extends AnyApiHandlerContext> = GetOutputSuccessFromApiHandlerContext<Target> | GetOutputErrorFromApiHandlerContext<Target>
|
|
64
|
+
|
|
65
|
+
export type ApiHandlerResult<
|
|
66
|
+
OutputSuccessSchema extends StandardSchemaV1,
|
|
67
|
+
OutputErrorSchema extends StandardSchemaV1,
|
|
68
|
+
> = SuccessResult<StandardSchemaV1.InferOutput<OutputSuccessSchema>> | ErrorResult<StandardSchemaV1.InferOutput<OutputErrorSchema>>
|
|
69
|
+
|
|
70
|
+
export type ApiHandler<
|
|
71
|
+
Path extends string,
|
|
72
|
+
Method extends "get" | "post",
|
|
73
|
+
InputQuerySchema extends StandardSchemaV1,
|
|
74
|
+
InputBodySchema extends StandardSchemaV1,
|
|
75
|
+
OutputSuccessSchema extends StandardSchemaV1,
|
|
76
|
+
OutputErrorSchema extends StandardSchemaV1,
|
|
77
|
+
> = (
|
|
78
|
+
context: ApiHandlerContext<Path, Method, InputQuerySchema, InputBodySchema, OutputSuccessSchema, OutputErrorSchema>
|
|
79
|
+
) => Promise<ApiHandlerResult<OutputSuccessSchema, OutputErrorSchema>>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/logger.ts"
|
|
2
|
+
import { Logger } from "#Source/log/logger.ts"
|
|
3
|
+
|
|
4
|
+
import type { ApiCore } from "./api-core.ts"
|
|
5
|
+
|
|
6
|
+
export type ApiCoreHandler = (apiCore: ApiCore) => void | Promise<void>
|
|
7
|
+
export interface ApiHostStartResult {
|
|
8
|
+
urlList: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ApiHostOptions extends LoggerFriendlyOptions {
|
|
12
|
+
port: number
|
|
13
|
+
}
|
|
14
|
+
export abstract class ApiHost<Server> implements LoggerFriendly {
|
|
15
|
+
protected readonly options: ApiHostOptions
|
|
16
|
+
|
|
17
|
+
readonly logger: Logger
|
|
18
|
+
protected server: Server | undefined
|
|
19
|
+
|
|
20
|
+
constructor(options: ApiHostOptions) {
|
|
21
|
+
this.options = options
|
|
22
|
+
|
|
23
|
+
this.logger = Logger.fromOptions(options).setDefaultName("ApiHost")
|
|
24
|
+
this.server = undefined
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
safeGetServer(): Server {
|
|
28
|
+
if (this.server === undefined) {
|
|
29
|
+
throw new Error("Server is not running.")
|
|
30
|
+
}
|
|
31
|
+
return this.server
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
isRunning(): boolean {
|
|
35
|
+
if (this.server === undefined) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
abstract attachApiCoreHandler(apiCoreHandler: ApiCoreHandler): void
|
|
42
|
+
abstract start(): Promise<ApiHostStartResult>
|
|
43
|
+
abstract close(): Promise<void>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
47
|
+
export type AnyApiHost = ApiHost<any>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts"
|
|
2
|
+
import { Logger } from "#Source/log/index.ts"
|
|
3
|
+
|
|
4
|
+
import type { ApiCore } from "./api-core.ts"
|
|
5
|
+
|
|
6
|
+
export interface ResultOptions<_T> extends LoggerFriendlyOptions {
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* {@link Api} 的处理器无法获得 Request 和 Response 对象,它不应该直接返回数据给前端,而应该通过
|
|
10
|
+
* {@link SuccessResult} 或 {@link ErrorResult} 定义自己想要返回什么,然后 {@link ApiServer} 会
|
|
11
|
+
* 负责执行返回逻辑,将结果返回给前端,这样做既可以使 Api 的核心逻辑更纯粹,也可以保证所有的接口始终
|
|
12
|
+
* 给前端返回一致的数据结构。
|
|
13
|
+
*/
|
|
14
|
+
export abstract class Result<T> implements LoggerFriendly {
|
|
15
|
+
protected __PhantomType__?: T
|
|
16
|
+
|
|
17
|
+
protected options: ResultOptions<T>
|
|
18
|
+
readonly logger: Logger
|
|
19
|
+
|
|
20
|
+
constructor(options: ResultOptions<T>) {
|
|
21
|
+
this.options = options
|
|
22
|
+
this.logger = Logger.fromOptions(options).setDefaultName("Result")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
abstract handle(apiCore: ApiCore): Promise<void>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ======================
|
|
29
|
+
|
|
30
|
+
export interface SuccessResultOptions<T> extends ResultOptions<T> {
|
|
31
|
+
}
|
|
32
|
+
export abstract class SuccessResult<T> extends Result<T> {
|
|
33
|
+
protected __SuccessResultPhantomType__ = true
|
|
34
|
+
|
|
35
|
+
protected declare options: SuccessResultOptions<T>
|
|
36
|
+
|
|
37
|
+
constructor(options: SuccessResultOptions<T>) {
|
|
38
|
+
super(options)
|
|
39
|
+
this.logger.setDefaultName("SuccessResult")
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ======================
|
|
44
|
+
|
|
45
|
+
export interface ErrorResultOptions<T> extends ResultOptions<T> {
|
|
46
|
+
}
|
|
47
|
+
export abstract class ErrorResult<T> extends Result<T> {
|
|
48
|
+
protected __ErrorResultPhantomType__ = true
|
|
49
|
+
|
|
50
|
+
protected declare options: ErrorResultOptions<T>
|
|
51
|
+
|
|
52
|
+
constructor(options: ErrorResultOptions<T>) {
|
|
53
|
+
super(options)
|
|
54
|
+
this.logger.setDefaultName("ErrorResult")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec"
|
|
2
|
+
|
|
3
|
+
export interface ApiSchemaOptions<
|
|
4
|
+
Path extends string,
|
|
5
|
+
Method extends "get" | "post",
|
|
6
|
+
InputQuerySchema extends StandardSchemaV1,
|
|
7
|
+
InputBodySchema extends StandardSchemaV1,
|
|
8
|
+
OutputSuccessSchema extends StandardSchemaV1,
|
|
9
|
+
OutputErrorSchema extends StandardSchemaV1,
|
|
10
|
+
> {
|
|
11
|
+
path: Path
|
|
12
|
+
method: Method
|
|
13
|
+
inputQuerySchema: InputQuerySchema
|
|
14
|
+
inputBodySchema: InputBodySchema
|
|
15
|
+
outputSuccessSchema: OutputSuccessSchema
|
|
16
|
+
outputErrorSchema: OutputErrorSchema
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 每一个请求都由一个且仅由一个接口(Api)处理。每个 Api 在实现之前需要对其进行描述,
|
|
20
|
+
* 描述中包含此接口处理的路径(Path)、方法(Method)、query 输入的数据形状(InputQuerySchema)、
|
|
21
|
+
* body 输入的数据形状(InputBodySchema)、成功输出的数据形状(OutputSuccessSchema)和错误输出的数据形状
|
|
22
|
+
* (OutputErrorSchema)等,这些描述共同构成 ApiSchema。
|
|
23
|
+
*
|
|
24
|
+
* 具体来说:
|
|
25
|
+
* - path:不能有通配符, 必须是完整的, 具体的路径。
|
|
26
|
+
* - method:暂时只支持 get 和 post。
|
|
27
|
+
* - inputQuerySchema:描述接口 query 输入的数据形状。
|
|
28
|
+
* - inputBodySchema:描述接口 body 输入的数据形状。
|
|
29
|
+
* - outputSuccessSchema:描述接口成功输出的数据形状。
|
|
30
|
+
* - outputErrorSchema:描述接口失败输出的数据形状。
|
|
31
|
+
*
|
|
32
|
+
* ApiSchema 的主要用途是定义接口的类型,将接口的类型和实现分开,提高代码的可读性和
|
|
33
|
+
* 可维护性的同时让我们能够将接口类型独立导出给前端。
|
|
34
|
+
*/
|
|
35
|
+
export class ApiSchema<
|
|
36
|
+
Path extends string,
|
|
37
|
+
Method extends "get" | "post",
|
|
38
|
+
InputQuerySchema extends StandardSchemaV1,
|
|
39
|
+
InputBodySchema extends StandardSchemaV1,
|
|
40
|
+
OutputSuccessSchema extends StandardSchemaV1,
|
|
41
|
+
OutputErrorSchema extends StandardSchemaV1,
|
|
42
|
+
> {
|
|
43
|
+
protected __PathPhantomType__?: Path
|
|
44
|
+
protected __MethodPhantomType__?: Method
|
|
45
|
+
protected __InputQuerySchemaPhantomType__?: InputQuerySchema
|
|
46
|
+
protected __InputBodySchemaPhantomType__?: InputBodySchema
|
|
47
|
+
protected __OutputSuccessSchemaPhantomType__?: OutputSuccessSchema
|
|
48
|
+
protected __OutputErrorSchemaPhantomType__?: OutputErrorSchema
|
|
49
|
+
|
|
50
|
+
private readonly path: Path
|
|
51
|
+
private readonly method: Method
|
|
52
|
+
private readonly inputQuerySchema: InputQuerySchema
|
|
53
|
+
private readonly inputBodySchema: InputBodySchema
|
|
54
|
+
private readonly outputSuccessSchema: OutputSuccessSchema
|
|
55
|
+
private readonly outputErrorSchema: OutputErrorSchema
|
|
56
|
+
|
|
57
|
+
constructor(options: ApiSchemaOptions<Path, Method, InputQuerySchema, InputBodySchema, OutputSuccessSchema, OutputErrorSchema>) {
|
|
58
|
+
this.path = options.path
|
|
59
|
+
this.method = options.method
|
|
60
|
+
this.inputQuerySchema = options.inputQuerySchema
|
|
61
|
+
this.inputBodySchema = options.inputBodySchema
|
|
62
|
+
this.outputSuccessSchema = options.outputSuccessSchema
|
|
63
|
+
this.outputErrorSchema = options.outputErrorSchema
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getApiSchemaOptions(): ApiSchemaOptions<Path, Method, InputQuerySchema, InputBodySchema, OutputSuccessSchema, OutputErrorSchema> {
|
|
67
|
+
return {
|
|
68
|
+
path: this.path,
|
|
69
|
+
method: this.method,
|
|
70
|
+
inputQuerySchema: this.inputQuerySchema,
|
|
71
|
+
inputBodySchema: this.inputBodySchema,
|
|
72
|
+
outputSuccessSchema: this.outputSuccessSchema,
|
|
73
|
+
outputErrorSchema: this.outputErrorSchema,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getPath(): Path {
|
|
78
|
+
return this.path
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getMethod(): Method {
|
|
82
|
+
return this.method
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
getInputQuerySchema(): InputQuerySchema {
|
|
86
|
+
return this.inputQuerySchema
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
getInputBodySchema(): InputBodySchema {
|
|
90
|
+
return this.inputBodySchema
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getOutputSuccessSchema(): OutputSuccessSchema {
|
|
94
|
+
return this.outputSuccessSchema
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getOutputErrorSchema(): OutputErrorSchema {
|
|
98
|
+
return this.outputErrorSchema
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const createApiSchema = <
|
|
103
|
+
Path extends string,
|
|
104
|
+
Method extends "get" | "post",
|
|
105
|
+
InputQuerySchema extends StandardSchemaV1,
|
|
106
|
+
InputBodySchema extends StandardSchemaV1,
|
|
107
|
+
OutputSuccessSchema extends StandardSchemaV1,
|
|
108
|
+
OutputErrorSchema extends StandardSchemaV1,
|
|
109
|
+
>(
|
|
110
|
+
options: ApiSchemaOptions<Path, Method, InputQuerySchema, InputBodySchema, OutputSuccessSchema, OutputErrorSchema>
|
|
111
|
+
): ApiSchema<Path, Method, InputQuerySchema, InputBodySchema, OutputSuccessSchema, OutputErrorSchema> => {
|
|
112
|
+
return new ApiSchema(options)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type AnyApiSchema = ApiSchema<string, "get" | "post", StandardSchemaV1, StandardSchemaV1, StandardSchemaV1, StandardSchemaV1>
|
|
116
|
+
|
|
117
|
+
export type GetInputQuerySchemaFromApiSchema<Target extends AnyApiSchema> = Target extends ApiSchema<
|
|
118
|
+
infer _,
|
|
119
|
+
infer __,
|
|
120
|
+
infer InputQuerySchema,
|
|
121
|
+
infer ___,
|
|
122
|
+
infer ____,
|
|
123
|
+
infer ______
|
|
124
|
+
> ? InputQuerySchema : never
|
|
125
|
+
export type GetInputBodySchemaFromApiSchema<Target extends AnyApiSchema> = Target extends ApiSchema<
|
|
126
|
+
infer _,
|
|
127
|
+
infer __,
|
|
128
|
+
infer ___,
|
|
129
|
+
infer InputBodySchema,
|
|
130
|
+
infer ____,
|
|
131
|
+
infer ______
|
|
132
|
+
> ? InputBodySchema : never
|
|
133
|
+
export type GetOutputSuccessSchemaFromApiSchema<Target extends AnyApiSchema> = Target extends ApiSchema<
|
|
134
|
+
infer _,
|
|
135
|
+
infer __,
|
|
136
|
+
infer ___,
|
|
137
|
+
infer ____,
|
|
138
|
+
infer OutputSuccessSchema,
|
|
139
|
+
infer ______
|
|
140
|
+
> ? OutputSuccessSchema : never
|
|
141
|
+
export type GetOutputErrorSchemaFromApiSchema<Target extends AnyApiSchema> = Target extends ApiSchema<
|
|
142
|
+
infer _,
|
|
143
|
+
infer __,
|
|
144
|
+
infer ___,
|
|
145
|
+
infer ____,
|
|
146
|
+
infer _____,
|
|
147
|
+
infer OutputErrorSchema
|
|
148
|
+
> ? OutputErrorSchema : never
|
|
149
|
+
|
|
150
|
+
export type GetInputQueryFromApiSchema<Target extends AnyApiSchema> = StandardSchemaV1.InferOutput<GetInputQuerySchemaFromApiSchema<Target>>
|
|
151
|
+
export type GetInputBodyFromApiSchema<Target extends AnyApiSchema> = StandardSchemaV1.InferOutput<GetInputBodySchemaFromApiSchema<Target>>
|
|
152
|
+
export type GetOutputSuccessFromApiSchema<Target extends AnyApiSchema> = StandardSchemaV1.InferOutput<GetOutputSuccessSchemaFromApiSchema<Target>>
|
|
153
|
+
export type GetOutputErrorFromApiSchema<Target extends AnyApiSchema> = StandardSchemaV1.InferOutput<GetOutputErrorSchemaFromApiSchema<Target>>
|
|
154
|
+
export type GetOutputFromApiSchema<Target extends AnyApiSchema> = GetOutputSuccessFromApiSchema<Target> | GetOutputErrorFromApiSchema<Target>
|