@planet-matrix/mobius-model 0.6.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.
Files changed (233) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/index.js +706 -36
  3. package/dist/index.js.map +855 -59
  4. package/package.json +28 -16
  5. package/src/ai/README.md +1 -0
  6. package/src/ai/ai.ts +107 -0
  7. package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
  8. package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
  9. package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
  10. package/src/ai/chat-completion-ai/index.ts +7 -0
  11. package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
  12. package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
  13. package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
  14. package/src/ai/embedding-ai/embedding-ai.ts +63 -0
  15. package/src/ai/embedding-ai/embedding.ts +50 -0
  16. package/src/ai/embedding-ai/index.ts +4 -0
  17. package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
  18. package/src/ai/index.ts +4 -0
  19. package/src/aio/README.md +100 -0
  20. package/src/aio/content.ts +141 -0
  21. package/src/aio/index.ts +3 -0
  22. package/src/aio/json.ts +127 -0
  23. package/src/aio/prompt.ts +246 -0
  24. package/src/basic/README.md +20 -15
  25. package/src/basic/error.ts +19 -5
  26. package/src/basic/function.ts +2 -2
  27. package/src/basic/index.ts +1 -0
  28. package/src/basic/schedule.ts +111 -0
  29. package/src/basic/stream.ts +135 -25
  30. package/src/credential/README.md +107 -0
  31. package/src/credential/api-key.ts +158 -0
  32. package/src/credential/bearer.ts +73 -0
  33. package/src/credential/index.ts +4 -0
  34. package/src/credential/json-web-token.ts +96 -0
  35. package/src/credential/password.ts +170 -0
  36. package/src/cron/README.md +86 -0
  37. package/src/cron/cron.ts +87 -0
  38. package/src/cron/index.ts +1 -0
  39. package/src/drizzle/README.md +1 -0
  40. package/src/drizzle/drizzle.ts +1 -0
  41. package/src/drizzle/helper.ts +47 -0
  42. package/src/drizzle/index.ts +5 -0
  43. package/src/drizzle/infer.ts +52 -0
  44. package/src/drizzle/kysely.ts +8 -0
  45. package/src/drizzle/pagination.ts +200 -0
  46. package/src/email/README.md +1 -0
  47. package/src/email/index.ts +1 -0
  48. package/src/email/resend.ts +25 -0
  49. package/src/event/class-event-proxy.ts +6 -5
  50. package/src/event/common.ts +13 -3
  51. package/src/event/event-manager.ts +3 -3
  52. package/src/event/instance-event-proxy.ts +6 -5
  53. package/src/event/internal.ts +4 -4
  54. package/src/form/README.md +25 -0
  55. package/src/form/index.ts +1 -0
  56. package/src/form/inputor-controller/base.ts +874 -0
  57. package/src/form/inputor-controller/boolean.ts +39 -0
  58. package/src/form/inputor-controller/file.ts +39 -0
  59. package/src/form/inputor-controller/form.ts +181 -0
  60. package/src/form/inputor-controller/helper.ts +117 -0
  61. package/src/form/inputor-controller/index.ts +17 -0
  62. package/src/form/inputor-controller/multi-select.ts +99 -0
  63. package/src/form/inputor-controller/number.ts +116 -0
  64. package/src/form/inputor-controller/select.ts +109 -0
  65. package/src/form/inputor-controller/text.ts +82 -0
  66. package/src/http/READMD.md +1 -0
  67. package/src/http/api/api-core.ts +84 -0
  68. package/src/http/api/api-handler.ts +79 -0
  69. package/src/http/api/api-host.ts +47 -0
  70. package/src/http/api/api-result.ts +56 -0
  71. package/src/http/api/api-schema.ts +154 -0
  72. package/src/http/api/api-server.ts +130 -0
  73. package/src/http/api/api-test.ts +142 -0
  74. package/src/http/api/api-type.ts +37 -0
  75. package/src/http/api/api.ts +81 -0
  76. package/src/http/api/index.ts +11 -0
  77. package/src/http/api-adapter/api-core-node-http.ts +260 -0
  78. package/src/http/api-adapter/api-host-node-http.ts +156 -0
  79. package/src/http/api-adapter/api-result-arktype.ts +297 -0
  80. package/src/http/api-adapter/api-result-zod.ts +286 -0
  81. package/src/http/api-adapter/index.ts +5 -0
  82. package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
  83. package/src/http/bin/gen-api-list/index.ts +1 -0
  84. package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
  85. package/src/http/bin/gen-api-test/index.ts +1 -0
  86. package/src/http/bin/gen-api-type/calc-code.ts +25 -0
  87. package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
  88. package/src/http/bin/gen-api-type/index.ts +2 -0
  89. package/src/http/bin/index.ts +2 -0
  90. package/src/http/index.ts +3 -0
  91. package/src/huawei/README.md +1 -0
  92. package/src/huawei/index.ts +2 -0
  93. package/src/huawei/moderation/index.ts +1 -0
  94. package/src/huawei/moderation/moderation.ts +355 -0
  95. package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
  96. package/src/huawei/obs/index.ts +1 -0
  97. package/src/huawei/obs/obs.ts +42 -0
  98. package/src/index.ts +19 -2
  99. package/src/json/README.md +92 -0
  100. package/src/json/index.ts +1 -0
  101. package/src/json/repair.ts +18 -0
  102. package/src/log/logger.ts +15 -4
  103. package/src/openai/README.md +1 -0
  104. package/src/openai/index.ts +1 -0
  105. package/src/openai/openai.ts +510 -0
  106. package/src/orchestration/README.md +9 -7
  107. package/src/orchestration/dispatching/dispatcher.ts +83 -0
  108. package/src/orchestration/dispatching/index.ts +2 -0
  109. package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
  110. package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
  111. package/src/orchestration/dispatching/selector/index.ts +2 -0
  112. package/src/orchestration/index.ts +2 -0
  113. package/src/orchestration/scheduling/index.ts +2 -0
  114. package/src/orchestration/scheduling/scheduler.ts +103 -0
  115. package/src/orchestration/scheduling/task.ts +32 -0
  116. package/src/random/README.md +8 -7
  117. package/src/random/base.ts +66 -0
  118. package/src/random/index.ts +5 -1
  119. package/src/random/random-boolean.ts +40 -0
  120. package/src/random/random-integer.ts +60 -0
  121. package/src/random/random-number.ts +72 -0
  122. package/src/random/random-string.ts +66 -0
  123. package/src/request/README.md +108 -0
  124. package/src/request/fetch/base.ts +108 -0
  125. package/src/request/fetch/browser.ts +285 -0
  126. package/src/request/fetch/general.ts +20 -0
  127. package/src/request/fetch/index.ts +4 -0
  128. package/src/request/fetch/nodejs.ts +285 -0
  129. package/src/request/index.ts +2 -0
  130. package/src/request/request/base.ts +250 -0
  131. package/src/request/request/general.ts +64 -0
  132. package/src/request/request/index.ts +3 -0
  133. package/src/request/request/resource.ts +68 -0
  134. package/src/result/README.md +4 -0
  135. package/src/result/controller.ts +54 -0
  136. package/src/result/either.ts +193 -0
  137. package/src/result/index.ts +2 -0
  138. package/src/route/README.md +105 -0
  139. package/src/route/adapter/browser.ts +122 -0
  140. package/src/route/adapter/driver.ts +56 -0
  141. package/src/route/adapter/index.ts +2 -0
  142. package/src/route/index.ts +3 -0
  143. package/src/route/router/index.ts +2 -0
  144. package/src/route/router/route.ts +630 -0
  145. package/src/route/router/router.ts +1642 -0
  146. package/src/route/uri/hash.ts +308 -0
  147. package/src/route/uri/index.ts +7 -0
  148. package/src/route/uri/pathname.ts +376 -0
  149. package/src/route/uri/search.ts +413 -0
  150. package/src/socket/README.md +105 -0
  151. package/src/socket/client/index.ts +2 -0
  152. package/src/socket/client/socket-unit.ts +660 -0
  153. package/src/socket/client/socket.ts +203 -0
  154. package/src/socket/common/index.ts +2 -0
  155. package/src/socket/common/socket-unit-common.ts +23 -0
  156. package/src/socket/common/socket-unit-heartbeat.ts +427 -0
  157. package/src/socket/index.ts +3 -0
  158. package/src/socket/server/index.ts +3 -0
  159. package/src/socket/server/server.ts +183 -0
  160. package/src/socket/server/socket-unit.ts +449 -0
  161. package/src/socket/server/socket.ts +264 -0
  162. package/src/storage/table.ts +3 -3
  163. package/src/timer/expiration/expiration-manager.ts +3 -3
  164. package/src/timer/expiration/remaining-manager.ts +3 -3
  165. package/src/tube/README.md +99 -0
  166. package/src/tube/helper.ts +138 -0
  167. package/src/tube/index.ts +2 -0
  168. package/src/tube/tube.ts +880 -0
  169. package/src/weixin/README.md +1 -0
  170. package/src/weixin/index.ts +2 -0
  171. package/src/weixin/official-account/authorization.ts +159 -0
  172. package/src/weixin/official-account/index.ts +2 -0
  173. package/src/weixin/official-account/js-api.ts +134 -0
  174. package/src/weixin/open/index.ts +1 -0
  175. package/src/weixin/open/oauth2.ts +133 -0
  176. package/tests/unit/ai/ai.spec.ts +85 -0
  177. package/tests/unit/aio/content.spec.ts +105 -0
  178. package/tests/unit/aio/json.spec.ts +147 -0
  179. package/tests/unit/aio/prompt.spec.ts +111 -0
  180. package/tests/unit/basic/error.spec.ts +16 -4
  181. package/tests/unit/basic/schedule.spec.ts +74 -0
  182. package/tests/unit/basic/stream.spec.ts +90 -37
  183. package/tests/unit/credential/api-key.spec.ts +37 -0
  184. package/tests/unit/credential/bearer.spec.ts +23 -0
  185. package/tests/unit/credential/json-web-token.spec.ts +23 -0
  186. package/tests/unit/credential/password.spec.ts +41 -0
  187. package/tests/unit/cron/cron.spec.ts +84 -0
  188. package/tests/unit/event/class-event-proxy.spec.ts +3 -3
  189. package/tests/unit/event/event-manager.spec.ts +3 -3
  190. package/tests/unit/event/instance-event-proxy.spec.ts +3 -3
  191. package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
  192. package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
  193. package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
  194. package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
  195. package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
  196. package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
  197. package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
  198. package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
  199. package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
  200. package/tests/unit/http/api/api-core-host.spec.ts +207 -0
  201. package/tests/unit/http/api/api-schema.spec.ts +120 -0
  202. package/tests/unit/http/api/api-server.spec.ts +363 -0
  203. package/tests/unit/http/api/api-test.spec.ts +117 -0
  204. package/tests/unit/http/api/api.spec.ts +121 -0
  205. package/tests/unit/http/api-adapter/node-http.spec.ts +191 -0
  206. package/tests/unit/json/repair.spec.ts +11 -0
  207. package/tests/unit/log/logger.spec.ts +19 -4
  208. package/tests/unit/openai/openai.spec.ts +64 -0
  209. package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
  210. package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
  211. package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
  212. package/tests/unit/random/base.spec.ts +58 -0
  213. package/tests/unit/random/random-boolean.spec.ts +25 -0
  214. package/tests/unit/random/random-integer.spec.ts +32 -0
  215. package/tests/unit/random/random-number.spec.ts +33 -0
  216. package/tests/unit/random/random-string.spec.ts +22 -0
  217. package/tests/unit/request/fetch/browser.spec.ts +222 -0
  218. package/tests/unit/request/fetch/general.spec.ts +43 -0
  219. package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
  220. package/tests/unit/request/request/base.spec.ts +385 -0
  221. package/tests/unit/request/request/general.spec.ts +161 -0
  222. package/tests/unit/route/router/route.spec.ts +431 -0
  223. package/tests/unit/route/router/router.spec.ts +407 -0
  224. package/tests/unit/route/uri/hash.spec.ts +72 -0
  225. package/tests/unit/route/uri/pathname.spec.ts +147 -0
  226. package/tests/unit/route/uri/search.spec.ts +107 -0
  227. package/tests/unit/socket/client.spec.ts +208 -0
  228. package/tests/unit/socket/server.spec.ts +135 -0
  229. package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
  230. package/tests/unit/tube/helper.spec.ts +139 -0
  231. package/tests/unit/tube/tube.spec.ts +501 -0
  232. package/src/random/string.ts +0 -35
  233. package/tests/unit/random/string.spec.ts +0 -11
@@ -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>