@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,39 @@
1
+ import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema } from "./base.ts"
2
+ import { BaseInputorController } from "./base.ts"
3
+
4
+ export const BOOLEAN_INPUTOR_TYPE_NAME = "boolean" as const
5
+ export type BooleanInputorTypeName = typeof BOOLEAN_INPUTOR_TYPE_NAME
6
+
7
+ export type BooleanInputorExternalValue = boolean | undefined
8
+ export type BooleanInputorInternalValue = boolean | undefined
9
+ export interface BooleanInputorSchema extends BaseInputorSchema<BooleanInputorExternalValue> {
10
+ inputorTypeName: BooleanInputorTypeName
11
+ }
12
+ export interface BooleanInputorContext extends BaseInputorContext<BooleanInputorExternalValue, BooleanInputorInternalValue> {
13
+ }
14
+
15
+ export interface BooleanInputorControllerOptions extends BaseInputorControllerOptions<
16
+ BooleanInputorExternalValue,
17
+ BooleanInputorSchema
18
+ > {
19
+ }
20
+ export class BooleanInputorController extends BaseInputorController<
21
+ BooleanInputorExternalValue,
22
+ BooleanInputorInternalValue,
23
+ BooleanInputorSchema,
24
+ BooleanInputorContext
25
+ > {
26
+ declare schemaType: BooleanInputorSchema
27
+ declare optionsType: BooleanInputorControllerOptions
28
+ declare constructorType: typeof BooleanInputorController
29
+
30
+ static inputorTypeName: BooleanInputorTypeName = BOOLEAN_INPUTOR_TYPE_NAME
31
+
32
+ inputorTypeName: BooleanInputorTypeName = BOOLEAN_INPUTOR_TYPE_NAME
33
+ voidExternalValue = undefined
34
+ voidInternalValue = undefined
35
+
36
+ constructor(options: BooleanInputorControllerOptions) {
37
+ super(options)
38
+ }
39
+ }
@@ -0,0 +1,39 @@
1
+ import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema } from "./base.ts"
2
+ import { BaseInputorController } from "./base.ts"
3
+
4
+ export const FILE_INPUTOR_TYPE_NAME = "file" as const
5
+ export type FileInputorTypeName = typeof FILE_INPUTOR_TYPE_NAME
6
+
7
+ export type FileInputorExternalValue = File | undefined
8
+ export type FileInputorInternalValue = File | undefined
9
+ export interface FileInputorSchema extends BaseInputorSchema<FileInputorExternalValue> {
10
+ inputorTypeName: FileInputorTypeName
11
+ }
12
+ export interface FileInputorContext extends BaseInputorContext<FileInputorExternalValue, FileInputorInternalValue> {
13
+ }
14
+
15
+ export interface FileInputorControllerOptions extends BaseInputorControllerOptions<
16
+ FileInputorExternalValue,
17
+ FileInputorSchema
18
+ > {
19
+ }
20
+ export class FileInputorController extends BaseInputorController<
21
+ FileInputorExternalValue,
22
+ FileInputorInternalValue,
23
+ FileInputorSchema,
24
+ FileInputorContext
25
+ > {
26
+ declare schemaType: FileInputorSchema
27
+ declare optionsType: FileInputorControllerOptions
28
+ declare constructorType: typeof FileInputorController
29
+
30
+ static inputorTypeName: FileInputorTypeName = FILE_INPUTOR_TYPE_NAME
31
+
32
+ inputorTypeName: FileInputorTypeName = FILE_INPUTOR_TYPE_NAME
33
+ voidExternalValue = undefined
34
+ voidInternalValue = undefined
35
+
36
+ constructor(options: FileInputorControllerOptions) {
37
+ super(options)
38
+ }
39
+ }
@@ -0,0 +1,181 @@
1
+ import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema, InputorControllerInitializeHooks } from "./base.ts"
2
+ import { BaseInputorController } from "./base.ts"
3
+
4
+ import type * as Boolean from "./boolean.ts"
5
+ import type * as Number from "./number.ts"
6
+ import type * as Text from "./text.ts"
7
+ import type * as File from "./file.ts"
8
+ import type * as Select from "./select.ts"
9
+ import type * as MultiSelect from "./multi-select.ts"
10
+
11
+ interface InternalInputorControllerDict {
12
+ [FormInputorController.inputorTypeName]: FormInputorController
13
+ [Boolean.BooleanInputorController.inputorTypeName]: Boolean.BooleanInputorController
14
+ [Number.NumberInputorController.inputorTypeName]: Number.NumberInputorController
15
+ [Text.TextInputorController.inputorTypeName]: Text.TextInputorController
16
+ [File.FileInputorController.inputorTypeName]: File.FileInputorController
17
+ [Select.SelectInputorController.inputorTypeName]: Select.SelectInputorController
18
+ [MultiSelect.MultiSelectInputorController.inputorTypeName]: MultiSelect.MultiSelectInputorController
19
+ // Year
20
+ // Month
21
+ // Day
22
+ // Hour
23
+ // Minute
24
+ // Second
25
+ // Week
26
+ // Time
27
+ // TimeRange
28
+ // Url
29
+ // Color
30
+ }
31
+ type InternalInputorControllerUnion = InternalInputorControllerDict[keyof InternalInputorControllerDict]
32
+
33
+ // 下面是 Form Inputor Controller 的实现
34
+
35
+ export const FORM_INPUTOR_TYPE_NAME = "form" as const
36
+ export type FormInputorTypeName = typeof FORM_INPUTOR_TYPE_NAME
37
+
38
+ export type FormInputorInternalValue = Record<string, unknown> | undefined
39
+ export interface FormInputorSchema<ExternalValue = unknown> extends BaseInputorSchema<ExternalValue> {
40
+ inputorTypeName: FormInputorTypeName
41
+ }
42
+ export interface FormInputorContext<ExternalValue = unknown, InternalValue = unknown> extends BaseInputorContext<ExternalValue, InternalValue> {
43
+ }
44
+
45
+ export type FormInputorControllerItems = Record<string, InternalInputorControllerUnion>
46
+ type GetSchema<Item extends InternalInputorControllerUnion> = Item["schemaType"]
47
+ type GetSchemaDict<Items extends FormInputorControllerItems> = {
48
+ [Key in keyof Items]: GetSchema<Items[Key]>
49
+ }
50
+ // type GetSchemaUnion<Items extends InputorControllerItems> = GetSchemaDict<Items>[keyof GetSchemaDict<Items>]
51
+ type GetValue<Item extends InternalInputorControllerUnion> = GetSchema<Item>["value"]
52
+ type GetValueDict<Items extends FormInputorControllerItems> = {
53
+ [Key in keyof Items]: GetValue<Items[Key]>
54
+ }
55
+ type GetValueUnion<Items extends FormInputorControllerItems> = GetValueDict<Items>[keyof GetValueDict<Items>]
56
+ type GeneralUpdateValue<Items extends FormInputorControllerItems> = (value: GetValueUnion<Items>) => Promise<void>
57
+
58
+ export interface FormInputorControllerOptions<
59
+ // NOTE: use any to avoid contravariance error
60
+ // oxlint-disable-next-line typescript/no-explicit-any
61
+ ExternalValue = any,
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ Items extends FormInputorControllerItems = any,
64
+ > extends BaseInputorControllerOptions<ExternalValue, FormInputorSchema<ExternalValue>> {
65
+ voidExternalValue?: ExternalValue
66
+ items: Items
67
+ encodeValue: (schemaDict: GetSchemaDict<Items>) => ExternalValue
68
+ decodeValue: (value: ExternalValue) => GetValueDict<Items>
69
+ }
70
+
71
+ const VOID_EXTERNAL_VALUE = Symbol("voidExternalValue")
72
+
73
+ export class FormInputorController<
74
+ // ! Use `any` to avoid contravariance error
75
+ // oxlint-disable-next-line typescript/no-explicit-any
76
+ ExternalValue = any,
77
+ // ! Use `any` to avoid circular reference error
78
+ // ! Use `any` to avoid contravariance error
79
+ // oxlint-disable-next-line typescript/no-explicit-any
80
+ Items extends FormInputorControllerItems = any,
81
+ > extends BaseInputorController<
82
+ ExternalValue,
83
+ FormInputorInternalValue,
84
+ FormInputorSchema<ExternalValue>,
85
+ FormInputorContext<ExternalValue, FormInputorInternalValue>
86
+ > {
87
+ declare schemaType: FormInputorSchema<ExternalValue>
88
+ declare optionsType: FormInputorControllerOptions<ExternalValue, Items>
89
+ declare constructorType: typeof FormInputorController<ExternalValue, Items>
90
+
91
+ static inputorTypeName: FormInputorTypeName = FORM_INPUTOR_TYPE_NAME
92
+
93
+ inputorTypeName: FormInputorTypeName = FORM_INPUTOR_TYPE_NAME
94
+ voidExternalValue!: ExternalValue
95
+ voidInternalValue = undefined
96
+
97
+ protected items!: Record<string, InternalInputorControllerUnion>
98
+ protected encodeValue!: FormInputorControllerOptions<ExternalValue, Items>["encodeValue"]
99
+ protected decodeValue!: FormInputorControllerOptions<ExternalValue, Items>["decodeValue"]
100
+
101
+ constructor(options: FormInputorControllerOptions<ExternalValue, Items>) {
102
+ super(options)
103
+ }
104
+
105
+ protected override async initialize(
106
+ options: FormInputorControllerOptions<ExternalValue, Items>,
107
+ hooks?: InputorControllerInitializeHooks,
108
+ ): Promise<void> {
109
+ await super.initialize(options, {
110
+ ...hooks,
111
+ onSchemaReady: async () => {
112
+ if ("voidExternalValue" in options) {
113
+ this.voidExternalValue = options.voidExternalValue
114
+ }
115
+ else {
116
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
117
+ this.voidExternalValue = VOID_EXTERNAL_VALUE as unknown as ExternalValue
118
+ }
119
+ this.items = options.items
120
+ this.encodeValue = options.encodeValue
121
+ this.decodeValue = options.decodeValue
122
+ this.subscribeItemSchemaChange()
123
+ await hooks?.onSchemaReady?.()
124
+ },
125
+ })
126
+ }
127
+
128
+ /**
129
+ * 订阅所有子 Inputor 的 Schema,当子 Inputor 的 Schema 发生变化时,更新自己。
130
+ * 1. 当子项 value 发生变化时,更新自己的 value;
131
+ * 2. 待遇到实际情况再补充……
132
+ */
133
+ protected subscribeItemSchemaChange(): void {
134
+ Object.values(this.items).forEach((item) => {
135
+ item.subscribeSchemaChange(() => {
136
+ void this.updateValueFromItems()
137
+ })
138
+ })
139
+ }
140
+
141
+ protected async getSchemaDict(): Promise<GetSchemaDict<Items>> {
142
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
143
+ const schemaDict = {} as GetSchemaDict<Items>
144
+ await Promise.all(Object.entries(this.items).map(async ([key, item]) => {
145
+ Object.assign(schemaDict, {
146
+ [key]: await item.getSchema(),
147
+ })
148
+ }))
149
+ return schemaDict
150
+ }
151
+
152
+ protected async updateValueFromItems(): Promise<void> {
153
+ const schemaDict = await this.getSchemaDict()
154
+ const value = this.encodeValue(schemaDict)
155
+ await this.updateValue(value)
156
+ }
157
+
158
+ protected override async isVoidExternalValue(value: ExternalValue): Promise<boolean> {
159
+ if (this.voidExternalValue === VOID_EXTERNAL_VALUE && value === VOID_EXTERNAL_VALUE) {
160
+ return true
161
+ }
162
+ else {
163
+ return await super.isVoidExternalValue(value)
164
+ }
165
+ }
166
+
167
+ /**
168
+ * 在更新自己之前会先更新所有子 Inputor。
169
+ */
170
+ override async updateValue(value: ExternalValue): Promise<void> {
171
+ await this.updateItemsFromValue(value)
172
+ await super.updateValue(value)
173
+ }
174
+
175
+ protected async updateItemsFromValue(value: ExternalValue): Promise<void> {
176
+ const valueDict = this.decodeValue(value)
177
+ await Promise.all(Object.entries(this.items).map(async ([key, item]) => {
178
+ await (item.updateValue as GeneralUpdateValue<Items>)(valueDict[key])
179
+ }))
180
+ }
181
+ }
@@ -0,0 +1,117 @@
1
+ import * as Boolean from "./boolean.ts"
2
+ import * as Number from "./number.ts"
3
+ import * as Text from "./text.ts"
4
+ import * as File from "./file.ts"
5
+ import * as Select from "./select.ts"
6
+ import * as MultiSelect from "./multi-select.ts"
7
+ import * as Form from "./form.ts"
8
+
9
+ interface InternalInputorControllerDict {
10
+ [Form.FormInputorController.inputorTypeName]: Form.FormInputorController
11
+ [Boolean.BooleanInputorController.inputorTypeName]: Boolean.BooleanInputorController
12
+ [Number.NumberInputorController.inputorTypeName]: Number.NumberInputorController
13
+ [Text.TextInputorController.inputorTypeName]: Text.TextInputorController
14
+ [File.FileInputorController.inputorTypeName]: File.FileInputorController
15
+ [Select.SelectInputorController.inputorTypeName]: Select.SelectInputorController
16
+ [MultiSelect.MultiSelectInputorController.inputorTypeName]: MultiSelect.MultiSelectInputorController
17
+ // Year
18
+ // Month
19
+ // Day
20
+ // Hour
21
+ // Minute
22
+ // Second
23
+ // Week
24
+ // Time
25
+ // TimeRange
26
+ // Url
27
+ // Color
28
+ }
29
+ export type InputorControllerUnion = InternalInputorControllerDict[keyof InternalInputorControllerDict]
30
+
31
+ export type InputorSchemaUnion = InputorControllerUnion["schemaType"]
32
+ export type InputorControllerOptionsUnion = InputorControllerUnion["optionsType"]
33
+ export type InputorControllerConstructorUnion = InputorControllerUnion["constructorType"]
34
+
35
+ export type GeneralUpdateSchema<Controller extends InputorControllerUnion> = (
36
+ schema: Controller["schemaType"],
37
+ ) => Promise<void>
38
+ export type GeneralUpdateValue<Controller extends InputorControllerUnion> = (
39
+ value: Controller["schemaType"]["value"],
40
+ ) => Promise<void>
41
+
42
+ export interface SupportInputor<Controller extends InputorControllerUnion> {
43
+ controller?: Controller | undefined
44
+ controllerOptions?: Controller["optionsType"] | undefined
45
+ }
46
+
47
+ export interface SupportBoolean {
48
+ controller?: Boolean.BooleanInputorController | undefined
49
+ controllerOptions?: Boolean.BooleanInputorControllerOptions | undefined
50
+ }
51
+ export const boolean = (
52
+ options: Boolean.BooleanInputorControllerOptions,
53
+ ): Boolean.BooleanInputorController => {
54
+ return new Boolean.BooleanInputorController(options)
55
+ }
56
+
57
+ export interface SupportNumber {
58
+ controller?: Number.NumberInputorController | undefined
59
+ controllerOptions?: Number.NumberInputorControllerOptions | undefined
60
+ }
61
+ export const number = (
62
+ options: Number.NumberInputorControllerOptions,
63
+ ): Number.NumberInputorController => {
64
+ return new Number.NumberInputorController(options)
65
+ }
66
+
67
+ export interface SupportText {
68
+ controller?: Text.TextInputorController | undefined
69
+ controllerOptions?: Text.TextInputorControllerOptions | undefined
70
+ }
71
+ export const text = (
72
+ options: Text.TextInputorControllerOptions,
73
+ ): Text.TextInputorController => {
74
+ return new Text.TextInputorController(options)
75
+ }
76
+
77
+ export interface SupportFile {
78
+ controller?: File.FileInputorController | undefined
79
+ controllerOptions?: File.FileInputorControllerOptions | undefined
80
+ }
81
+ export const file = (
82
+ options: File.FileInputorControllerOptions,
83
+ ): File.FileInputorController => {
84
+ return new File.FileInputorController(options)
85
+ }
86
+
87
+ export interface SupportSelect<Value> {
88
+ controller?: Select.SelectInputorController<Value> | undefined
89
+ controllerOptions?: Select.SelectInputorControllerOptions<Value> | undefined
90
+ }
91
+ export const select = <Value = unknown>(
92
+ options: Select.SelectInputorControllerOptions<Value>,
93
+ ): Select.SelectInputorController<Value> => {
94
+ return new Select.SelectInputorController(options)
95
+ }
96
+
97
+ export interface SupportMultiSelect<Value> {
98
+ controller?: MultiSelect.MultiSelectInputorController<Value> | undefined
99
+ controllerOptions?: MultiSelect.MultiSelectInputorControllerOptions<Value> | undefined
100
+ }
101
+ export const multiSelect = <Value = unknown>(
102
+ options: MultiSelect.MultiSelectInputorControllerOptions<Value>,
103
+ ): MultiSelect.MultiSelectInputorController<Value> => {
104
+ return new MultiSelect.MultiSelectInputorController(options)
105
+ }
106
+
107
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
+ export interface SupportForm<ExternalValue = any, Items extends Form.FormInputorControllerItems = any> {
109
+ controller?: Form.FormInputorController<ExternalValue, Items> | undefined
110
+ controllerOptions?: Form.FormInputorControllerOptions<ExternalValue, Items> | undefined
111
+ }
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ export const form = <ExternalValue = any, Items extends Form.FormInputorControllerItems = any>(
114
+ options: Form.FormInputorControllerOptions<ExternalValue, Items>,
115
+ ): Form.FormInputorController<ExternalValue, Items> => {
116
+ return new Form.FormInputorController(options)
117
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 关于 Inputor:
3
+ * 1. Inputor 的定位是输入的原子,所有输入都可以由 Inputor 组合而成。
4
+ * 2. 为了方便,Inputor 之间不必互不依赖或互不重合。
5
+ * 3. 可以借助 Inputor 快速实现输入组件,将对应的 Inputor 作为组件的核心逻辑即可。
6
+ */
7
+
8
+ export * from "./base.ts"
9
+ export * from "./boolean.ts"
10
+ export * from "./number.ts"
11
+ export * from "./text.ts"
12
+ export * from "./file.ts"
13
+ export * from "./select.ts"
14
+ export * from "./multi-select.ts"
15
+ export * from "./form.ts"
16
+
17
+ export * from "./helper.ts"
@@ -0,0 +1,99 @@
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 MULTI_SELECT_INPUTOR_TYPE_NAME = "multi-select" as const
7
+ export type MultiSelectInputorTypeName = typeof MULTI_SELECT_INPUTOR_TYPE_NAME
8
+
9
+ export interface MultiSelectOption<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 MultiSelectOptions<Value = any> = Array<MultiSelectOption<Value>>
18
+ export type MultiSelectInputorExternalValue<Value = any> = MultiSelectOptions<Value>
19
+ export type MultiSelectInputorInternalValue<Value = any> = MultiSelectOptions<Value>
20
+ export interface MultiSelectInputorSchema<Value = any> extends BaseInputorSchema<MultiSelectInputorExternalValue<Value>> {
21
+ inputorTypeName: MultiSelectInputorTypeName
22
+ }
23
+ export interface MultiSelectInputorContext<Value = any> extends BaseInputorContext<MultiSelectInputorExternalValue<Value>, MultiSelectInputorInternalValue<Value>> {
24
+ }
25
+
26
+ export interface MultiSelectInputorControllerOptions<Value = any> extends BaseInputorControllerOptions<
27
+ MultiSelectInputorExternalValue<Value>,
28
+ MultiSelectInputorSchema<Value>
29
+ > {
30
+ minSelectCount?: number | undefined
31
+ maxSelectCount?: number | undefined
32
+ }
33
+ export class MultiSelectInputorController<Value = any> extends BaseInputorController<
34
+ MultiSelectInputorExternalValue<Value>,
35
+ MultiSelectInputorInternalValue<Value>,
36
+ MultiSelectInputorSchema<Value>,
37
+ MultiSelectInputorContext<Value>
38
+ > {
39
+ declare schemaType: MultiSelectInputorSchema<Value>
40
+ declare optionsType: MultiSelectInputorControllerOptions<Value>
41
+ declare constructorType: typeof MultiSelectInputorController<Value>
42
+
43
+ static inputorTypeName: MultiSelectInputorTypeName = MULTI_SELECT_INPUTOR_TYPE_NAME
44
+
45
+ inputorTypeName: MultiSelectInputorTypeName = MULTI_SELECT_INPUTOR_TYPE_NAME
46
+ voidExternalValue = [] as MultiSelectInputorExternalValue<Value>
47
+ voidInternalValue = [] as MultiSelectInputorInternalValue<Value>
48
+
49
+ private minSelectCount!: number
50
+ private maxSelectCount!: number
51
+
52
+ constructor(options: MultiSelectInputorControllerOptions<Value>) {
53
+ super(options)
54
+ }
55
+
56
+ protected override async initialize(
57
+ options: MultiSelectInputorControllerOptions<Value>,
58
+ hooks?: InputorControllerInitializeHooks,
59
+ ): Promise<void> {
60
+ await super.initialize(options, {
61
+ ...hooks,
62
+ onSchemaReady: async () => {
63
+ this.minSelectCount = options.minSelectCount ?? 0
64
+ this.maxSelectCount = options.maxSelectCount ?? Infinity
65
+ await hooks?.onSchemaReady?.()
66
+ },
67
+ })
68
+ }
69
+
70
+ async select(name: string): Promise<void> {
71
+ const internalValue = this.getInternalValue()
72
+ const selectedCount = internalValue.filter(option => option.isSelected).length
73
+ const hasReachedMaxSelectCount = selectedCount >= this.maxSelectCount
74
+ const updatedInternalValue = internalValue.map((option) => {
75
+ const { name: optionName, isSelected, isDisabled } = option
76
+
77
+ if (isDisabled === true) {
78
+ return option
79
+ }
80
+
81
+ if (optionName !== name) {
82
+ return option
83
+ }
84
+
85
+ const targetIsSelected = !isSelected
86
+
87
+ if (targetIsSelected === true && hasReachedMaxSelectCount === true) {
88
+ return option
89
+ }
90
+ else {
91
+ return {
92
+ ...option,
93
+ isSelected: targetIsSelected,
94
+ }
95
+ }
96
+ })
97
+ await this.updateInternalValue(updatedInternalValue)
98
+ }
99
+ }
@@ -0,0 +1,116 @@
1
+ import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema, InputorControllerInitializeHooks } from "./base.ts"
2
+ import { BaseInputorController } from "./base.ts"
3
+
4
+ interface InternalNumberConstraints {
5
+ min?: number | undefined
6
+ max?: number | undefined
7
+ step?: number | undefined
8
+ }
9
+ const internalConstrainNumber = (value: number, constraints: InternalNumberConstraints): number => {
10
+ let constrainedValue = value
11
+ if (constraints.step !== undefined) {
12
+ constrainedValue = Math.round(constrainedValue / constraints.step) * constraints.step
13
+ }
14
+ if (constraints.min !== undefined) {
15
+ constrainedValue = Math.max(constraints.min, constrainedValue)
16
+ }
17
+ if (constraints.max !== undefined) {
18
+ constrainedValue = Math.min(constraints.max, constrainedValue)
19
+ }
20
+ return constrainedValue
21
+ }
22
+
23
+ export const NUMBER_INPUTOR_TYPE_NAME = "number" as const
24
+ export type NumberInputorTypeName = typeof NUMBER_INPUTOR_TYPE_NAME
25
+
26
+ export type NumberInputorExternalValue = number | undefined
27
+ export type NumberInputorInternalValue = number | undefined
28
+ export interface NumberInputorSchema extends BaseInputorSchema<NumberInputorExternalValue> {
29
+ inputorTypeName: NumberInputorTypeName
30
+ min?: number | undefined
31
+ max?: number | undefined
32
+ step?: number | undefined
33
+ }
34
+ export interface NumberInputorContext extends BaseInputorContext<NumberInputorExternalValue, NumberInputorInternalValue> {
35
+ }
36
+
37
+ export interface NumberInputorControllerOptions extends BaseInputorControllerOptions<
38
+ NumberInputorExternalValue,
39
+ NumberInputorSchema
40
+ > {
41
+ min?: number | undefined
42
+ max?: number | undefined
43
+ step?: number | undefined
44
+ }
45
+ export class NumberInputorController extends BaseInputorController<
46
+ NumberInputorExternalValue,
47
+ NumberInputorInternalValue,
48
+ NumberInputorSchema,
49
+ NumberInputorContext
50
+ > {
51
+ declare schemaType: NumberInputorSchema
52
+ declare optionsType: NumberInputorControllerOptions
53
+ declare constructorType: typeof NumberInputorController
54
+
55
+ static inputorTypeName: NumberInputorTypeName = NUMBER_INPUTOR_TYPE_NAME
56
+
57
+ inputorTypeName: NumberInputorTypeName = NUMBER_INPUTOR_TYPE_NAME
58
+ voidExternalValue = undefined
59
+ voidInternalValue = undefined
60
+
61
+ private min: number | undefined
62
+ private max: number | undefined
63
+ private step: number | undefined
64
+
65
+ constructor(options: NumberInputorControllerOptions) {
66
+ super(options)
67
+ }
68
+
69
+ protected override async initialize(
70
+ options: NumberInputorControllerOptions,
71
+ hooks?: InputorControllerInitializeHooks,
72
+ ): Promise<void> {
73
+ await super.initialize(options, {
74
+ ...hooks,
75
+ onSchemaReady: async () => {
76
+ this.min = options.min
77
+ this.max = options.max
78
+ this.step = options.step
79
+ await hooks?.onSchemaReady?.()
80
+ },
81
+ })
82
+ }
83
+
84
+ override async getSchema(): Promise<NumberInputorSchema> {
85
+ return {
86
+ ...await super.getSchema(),
87
+ min: this.min,
88
+ max: this.max,
89
+ step: this.step,
90
+ }
91
+ }
92
+
93
+ override async constrainExternalValue(externalValue: NumberInputorExternalValue): Promise<NumberInputorExternalValue> {
94
+ if (externalValue === undefined) {
95
+ return await Promise.resolve(undefined)
96
+ }
97
+ const constrainedValue = internalConstrainNumber(externalValue, {
98
+ min: this.min,
99
+ max: this.max,
100
+ step: this.step,
101
+ })
102
+ return await Promise.resolve(constrainedValue)
103
+ }
104
+
105
+ override async constrainInternalValue(internalValue: NumberInputorInternalValue): Promise<NumberInputorInternalValue> {
106
+ if (internalValue === undefined) {
107
+ return await Promise.resolve(undefined)
108
+ }
109
+ const constrainedValue = internalConstrainNumber(internalValue, {
110
+ min: this.min,
111
+ max: this.max,
112
+ step: this.step,
113
+ })
114
+ return await Promise.resolve(constrainedValue)
115
+ }
116
+ }