@planet-matrix/mobius-model 0.9.0 → 0.10.1

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 (63) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/oxlint.config.ts +1 -2
  3. package/package.json +5 -5
  4. package/scripts/build.ts +2 -52
  5. package/src/basic/promise.ts +141 -71
  6. package/src/drizzle/pagination.ts +0 -2
  7. package/src/event/class-event-proxy.ts +0 -2
  8. package/src/event/instance-event-proxy.ts +0 -2
  9. package/src/exception/README.md +28 -19
  10. package/src/exception/error/error.ts +123 -0
  11. package/src/exception/error/index.ts +2 -0
  12. package/src/exception/error/match.ts +38 -0
  13. package/src/exception/error/must-fix.ts +17 -0
  14. package/src/exception/index.ts +2 -0
  15. package/src/file-system/find.ts +53 -0
  16. package/src/file-system/index.ts +2 -0
  17. package/src/file-system/path.ts +76 -0
  18. package/src/file-system/resolve.ts +22 -0
  19. package/src/form/inputor-controller/base.ts +0 -13
  20. package/src/form/inputor-controller/form.ts +0 -2
  21. package/src/http/api/api-type.ts +0 -3
  22. package/src/http/api-adapter/api-result-arktype.ts +0 -3
  23. package/src/index.ts +2 -0
  24. package/src/openai/openai.ts +0 -1
  25. package/src/request/fetch/browser.ts +0 -5
  26. package/src/request/fetch/nodejs.ts +0 -5
  27. package/src/request/request/base.ts +0 -4
  28. package/src/request/request/general.ts +0 -1
  29. package/src/result/controller.ts +11 -7
  30. package/src/result/either.ts +230 -60
  31. package/src/result/generator.ts +168 -0
  32. package/src/result/index.ts +1 -0
  33. package/src/route/router/router.ts +0 -1
  34. package/src/route/uri/hash.ts +0 -1
  35. package/src/route/uri/search.ts +0 -1
  36. package/src/service/README.md +1 -0
  37. package/src/service/index.ts +1 -0
  38. package/src/service/service.ts +110 -0
  39. package/src/socket/client/socket-unit.ts +0 -2
  40. package/src/socket/server/socket-unit.ts +0 -1
  41. package/src/tube/helper.ts +0 -1
  42. package/src/weixin/official-account/authorization.ts +0 -2
  43. package/src/weixin/official-account/js-api.ts +0 -2
  44. package/src/weixin/open/oauth2.ts +0 -2
  45. package/tests/unit/aio/json.spec.ts +0 -1
  46. package/tests/unit/basic/promise.spec.ts +158 -50
  47. package/tests/unit/credential/api-key.spec.ts +0 -1
  48. package/tests/unit/credential/password.spec.ts +0 -1
  49. package/tests/unit/exception/error/error.spec.ts +83 -0
  50. package/tests/unit/exception/error/match.spec.ts +81 -0
  51. package/tests/unit/http/api-adapter/node-http.spec.ts +0 -4
  52. package/tests/unit/identifier/uuid.spec.ts +0 -1
  53. package/tests/unit/request/request/base.spec.ts +0 -3
  54. package/tests/unit/request/request/general.spec.ts +0 -1
  55. package/tests/unit/result/controller.spec.ts +82 -0
  56. package/tests/unit/result/either.spec.ts +377 -0
  57. package/tests/unit/result/generator.spec.ts +273 -0
  58. package/tests/unit/route/router/route.spec.ts +0 -1
  59. package/tests/unit/route/uri/pathname.spec.ts +0 -1
  60. package/tests/unit/socket/server.spec.ts +0 -2
  61. package/vite.config.ts +2 -1
  62. package/dist/index.js +0 -720
  63. package/dist/index.js.map +0 -1005
@@ -0,0 +1,168 @@
1
+ import { mustFixError } from "#Source/exception/error/must-fix.ts"
2
+
3
+ import type { AnyEither, GetLeft, GetRight } from "./either.ts"
4
+ import { Either } from "./either.ts"
5
+
6
+ export type EitherSyncGenerator<Yield extends AnyEither, Return extends AnyEither>
7
+ = Generator<Yield, Return, unknown>
8
+ export type EitherAsyncGenerator<Yield extends AnyEither, Return extends AnyEither>
9
+ = AsyncGenerator<Yield, Return, unknown>
10
+
11
+ export type GetEitherGeneratorResult<Yield extends AnyEither, Return extends AnyEither> = Either<
12
+ GetLeft<Yield> | GetLeft<Return>,
13
+ GetRight<Return>
14
+ >
15
+
16
+ export const runSyncGenerator = <Yield extends AnyEither, Return extends AnyEither>(
17
+ generator: EitherSyncGenerator<Yield, Return>,
18
+ ): GetEitherGeneratorResult<Yield, Return> => {
19
+ let iteratorResult: IteratorResult<Yield, Return>
20
+ try {
21
+ iteratorResult = generator.next()
22
+ } catch (exception) {
23
+ throw mustFixError("Generator threw an exception", { cause: exception })
24
+ }
25
+
26
+ if (Either.isEither(iteratorResult.value) === false) {
27
+ throw mustFixError("Generator yielded a non-Either value", { cause: iteratorResult.value })
28
+ }
29
+
30
+ if (iteratorResult.done === false) {
31
+ try {
32
+ generator.return?.(undefined as never)
33
+ } catch (exception) {
34
+ throw mustFixError("Generator threw an exception during cleanup", { cause: exception })
35
+ }
36
+ }
37
+
38
+ return iteratorResult.value
39
+ }
40
+
41
+ export const runAsyncGenerator = async <Yield extends AnyEither, Return extends AnyEither>(
42
+ generator: EitherAsyncGenerator<Yield, Return>,
43
+ ): Promise<GetEitherGeneratorResult<Yield, Return>> => {
44
+ let iteratorResult: IteratorResult<Yield, Return>
45
+ try {
46
+ iteratorResult = await generator.next()
47
+ } catch (exception) {
48
+ throw mustFixError("Generator threw an exception", { cause: exception })
49
+ }
50
+
51
+ if (Either.isEither(iteratorResult.value) === false) {
52
+ throw mustFixError("Generator yielded a non-Either value", { cause: iteratorResult.value })
53
+ }
54
+
55
+ if (iteratorResult.done === false) {
56
+ try {
57
+ await generator.return?.(undefined as never)
58
+ } catch (exception) {
59
+ throw mustFixError("Generator threw an exception during cleanup", { cause: exception })
60
+ }
61
+ }
62
+
63
+ return iteratorResult.value
64
+ }
65
+
66
+ export interface GenSync {
67
+ <Yield extends AnyEither, Return extends AnyEither>(
68
+ generatorFunction: () => EitherSyncGenerator<Yield, Return>,
69
+ ): GetEitherGeneratorResult<Yield, Return>
70
+ <Yield extends AnyEither, Return extends AnyEither, This>(
71
+ generatorFunction: (this: This) => EitherSyncGenerator<Yield, Return>,
72
+ thisArg: This,
73
+ ): GetEitherGeneratorResult<Yield, Return>
74
+ }
75
+ export const genSync: GenSync = <Yield extends AnyEither, Return extends AnyEither, This>(
76
+ generatorFunction:
77
+ | (() => EitherSyncGenerator<Yield, Return>)
78
+ | ((this: This) => EitherSyncGenerator<Yield, Return>),
79
+ thisArg?:
80
+ | This
81
+ | undefined,
82
+ ): GetEitherGeneratorResult<Yield, Return> => {
83
+ let generator: EitherSyncGenerator<Yield, Return>
84
+ if (thisArg !== undefined) {
85
+ generator = (
86
+ generatorFunction as ((this: This) => EitherSyncGenerator<Yield, Return>)
87
+ ).call(thisArg)
88
+ } else {
89
+ generator = (
90
+ generatorFunction as (() => EitherSyncGenerator<Yield, Return>)
91
+ )()
92
+ }
93
+ const result = runSyncGenerator(generator)
94
+ return result
95
+ }
96
+
97
+ export interface GenAsync {
98
+ <Yield extends AnyEither, Return extends AnyEither>(
99
+ generatorFunction: () => EitherAsyncGenerator<Yield, Return>,
100
+ ): Promise<GetEitherGeneratorResult<Yield, Return>>
101
+ <Yield extends AnyEither, Return extends AnyEither, This>(
102
+ generatorFunction: (this: This) => EitherAsyncGenerator<Yield, Return>,
103
+ thisArg: This,
104
+ ): Promise<GetEitherGeneratorResult<Yield, Return>>
105
+ }
106
+ export const genAsync: GenAsync = async <Yield extends AnyEither, Return extends AnyEither, This>(
107
+ generatorFunction:
108
+ | (() => EitherAsyncGenerator<Yield, Return>)
109
+ | ((this: This) => EitherAsyncGenerator<Yield, Return>),
110
+ thisArg?:
111
+ | This
112
+ | undefined,
113
+ ): Promise<GetEitherGeneratorResult<Yield, Return>> => {
114
+ let generator: EitherAsyncGenerator<Yield, Return>
115
+ if (thisArg !== undefined) {
116
+ generator = (
117
+ generatorFunction as ((this: This) => EitherAsyncGenerator<Yield, Return>)
118
+ ).call(thisArg)
119
+ } else {
120
+ generator = (
121
+ generatorFunction as (() => EitherAsyncGenerator<Yield, Return>)
122
+ )()
123
+ }
124
+ const result = await runAsyncGenerator(generator)
125
+ return result
126
+ }
127
+
128
+ export interface Gen extends GenSync, GenAsync {
129
+ }
130
+ export const gen = (<Yield extends AnyEither, Return extends AnyEither, This>(
131
+ generatorFunction:
132
+ | (() => EitherSyncGenerator<Yield, Return>)
133
+ | ((thisArg: This) => EitherSyncGenerator<Yield, Return>)
134
+ | (() => EitherAsyncGenerator<Yield, Return>)
135
+ | ((thisArg: This) => EitherAsyncGenerator<Yield, Return>),
136
+ thisArg?:
137
+ | This
138
+ | undefined,
139
+ ): (
140
+ | GetEitherGeneratorResult<Yield, Return>
141
+ | Promise<GetEitherGeneratorResult<Yield, Return>>
142
+ ) => {
143
+ let generator: EitherSyncGenerator<Yield, Return> | EitherAsyncGenerator<Yield, Return>
144
+ if (thisArg !== undefined) {
145
+ generator = (generatorFunction as (
146
+ (this: This) => EitherSyncGenerator<Yield, Return> | EitherAsyncGenerator<Yield, Return>
147
+ )).call(thisArg)
148
+ } else {
149
+ generator = (generatorFunction as (
150
+ () => EitherSyncGenerator<Yield, Return> | EitherAsyncGenerator<Yield, Return>
151
+ ))()
152
+ }
153
+ if (Symbol.asyncIterator in generator) {
154
+ return runAsyncGenerator(generator)
155
+ }
156
+ if (Symbol.iterator in generator) {
157
+ return runSyncGenerator(generator)
158
+ }
159
+ throw new TypeError("Invalid generator function")
160
+ }) as Gen
161
+
162
+ export const genAwait = async function* <Left, Right>(
163
+ promise: Promise<Either<Left, Right>>
164
+ ): AsyncGenerator<Either<Left, Right>, Right, unknown> {
165
+ const either = await promise
166
+ const result = yield* either
167
+ return result
168
+ }
@@ -1,2 +1,3 @@
1
1
  export * from "./either.ts"
2
+ export * from "./generator.ts"
2
3
  export * from "./controller.ts"
@@ -481,7 +481,6 @@ const internalCloneRouteHistoryEntry = (historyEntry: RouteHistoryEntry): RouteH
481
481
  return cachedRouteHistoryEntry
482
482
  }
483
483
 
484
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
485
484
  const clonedRouteHistoryEntry = {
486
485
  id: sourceHistoryEntry.id,
487
486
  from: internalCloneRouteEntry(sourceHistoryEntry.from),
@@ -106,7 +106,6 @@ export type HashUnion = HashStringLoose | HashStringStrict | HashObject
106
106
  * ```
107
107
  */
108
108
  export const neatenHash = (target: string): HashStringStrict => {
109
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
110
109
  return target.startsWith("#") ? (target as HashStringStrict) : `#${target}`
111
110
  }
112
111
 
@@ -119,7 +119,6 @@ export type SearchUnion = QueryString | QueryObject | SearchStringLoose | Search
119
119
  * ```
120
120
  */
121
121
  export const neatenSearch = (target: string): SearchStringStrict => {
122
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
123
122
  return target.startsWith("?") ? (target as SearchStringStrict) : `?${target}`
124
123
  }
125
124
 
@@ -0,0 +1 @@
1
+ # Service
@@ -0,0 +1 @@
1
+ export * from "./service.ts"
@@ -0,0 +1,110 @@
1
+ import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts"
2
+ import { Logger } from "#Source/log/index.ts"
3
+ import type {
4
+ Controller,
5
+ Either,
6
+ EitherAsyncGenerator,
7
+ EitherSyncGenerator,
8
+ GetEitherGeneratorResult,
9
+ TupleOfEither,
10
+ } from "#Source/result/index.ts"
11
+ import { controllerFromEitherType, eitherToTuple, gen } from "#Source/result/index.ts"
12
+
13
+ export interface BaseServiceOptions extends LoggerFriendlyOptions { }
14
+ /**
15
+ * 通过继承此基类实现业务逻辑,与使用函数实现业务逻辑相比,具有以下优势:
16
+ *
17
+ * 1. 依赖管理:统一注入所有通用依赖,如 logger 等,避免在每个函数实现中重复声明。
18
+ * 2. 暂时想不到了。
19
+ */
20
+ export abstract class BaseService<Options, Left, Right> implements LoggerFriendly {
21
+ readonly logger: Logger
22
+ protected controller: Controller<Left, Right>
23
+
24
+ constructor(options: BaseServiceOptions) {
25
+ this.logger = Logger.fromOptions(options).setDefaultName("BaseService")
26
+ this.controller = controllerFromEitherType<Either<Left, Right>>()
27
+ }
28
+
29
+ protected gen<Yield extends Either<Left, unknown>, Return extends Either<Left, Right>>(
30
+ generatorFunction:
31
+ | ((this: this) => EitherSyncGenerator<Yield, Return>),
32
+ ): GetEitherGeneratorResult<Yield, Return>
33
+ protected gen<Yield extends Either<Left, unknown>, Return extends Either<Left, Right>>(
34
+ generatorFunction:
35
+ | ((this: this) => EitherAsyncGenerator<Yield, Return>),
36
+ ): Promise<GetEitherGeneratorResult<Yield, Return>>
37
+ protected gen<Yield extends Either<Left, unknown>, Return extends Either<Left, Right>>(
38
+ generatorFunction:
39
+ | ((this: this) => EitherSyncGenerator<Yield, Return>)
40
+ | ((this: this) => EitherAsyncGenerator<Yield, Return>),
41
+ ): (
42
+ | GetEitherGeneratorResult<Yield, Return>
43
+ | Promise<GetEitherGeneratorResult<Yield, Return>>
44
+ ) {
45
+ return gen(generatorFunction as never, this)
46
+ }
47
+
48
+ protected abstract implement(options: Options): Promise<Either<Left, Right>>
49
+
50
+ async runToEither(options: Options): Promise<Either<Left, Right>> {
51
+ return await this.implement(options)
52
+ }
53
+
54
+ async runToTuple(options: Options): Promise<TupleOfEither<Left, Right>> {
55
+ const result = await this.implement(options)
56
+ return eitherToTuple(result)
57
+ }
58
+ }
59
+
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ export type AnyServiceInstance = BaseService<any, any, any>
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ export type AnyServiceConstructor = new (...args: any[]) => AnyServiceInstance
64
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ export type GetServiceInstance<T extends AnyServiceConstructor> = T extends new (...args: any[]) => infer Instance ? Instance : never
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ export type GetServiceConstructorOptions<T extends AnyServiceConstructor> = T extends new (options: infer Options, ...args: any[]) => any ? Options : never
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ export type GetServiceInstanceOptions<T extends AnyServiceConstructor> = GetServiceInstance<T> extends BaseService<infer Options, any, any> ? Options : never
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ export type GetServiceInstanceLeft<T extends AnyServiceConstructor> = GetServiceInstance<T> extends BaseService<any, infer Left, any> ? Left : never
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ export type GetServiceInstanceRight<T extends AnyServiceConstructor> = GetServiceInstance<T> extends BaseService<any, any, infer Right> ? Right : never
74
+
75
+ export const newService = <ServiceConstructor extends AnyServiceConstructor>(
76
+ ServiceConstructor: ServiceConstructor,
77
+ constructorOptions: GetServiceConstructorOptions<ServiceConstructor>,
78
+ ): GetServiceInstance<ServiceConstructor> => {
79
+ return new ServiceConstructor(constructorOptions) as GetServiceInstance<ServiceConstructor>
80
+ }
81
+
82
+ export type RunToEither<ServiceConstructor extends AnyServiceConstructor> = (
83
+ options: GetServiceInstanceOptions<ServiceConstructor>,
84
+ ) => Promise<Either<GetServiceInstanceLeft<ServiceConstructor>, GetServiceInstanceRight<ServiceConstructor>>>
85
+ export const newServiceAndRunToEither = <ServiceConstructor extends AnyServiceConstructor>(
86
+ ServiceConstructor: ServiceConstructor,
87
+ constructorOptions: GetServiceConstructorOptions<ServiceConstructor>,
88
+ ): RunToEither<ServiceConstructor> => {
89
+ const service = newService(ServiceConstructor, constructorOptions)
90
+ const run: RunToEither<ServiceConstructor> = async (options) => {
91
+ const result = await service.runToEither(options)
92
+ return result
93
+ }
94
+ return run
95
+ }
96
+
97
+ export type RunToTuple<ServiceConstructor extends AnyServiceConstructor> = (
98
+ options: GetServiceInstanceOptions<ServiceConstructor>,
99
+ ) => Promise<TupleOfEither<GetServiceInstanceLeft<ServiceConstructor>, GetServiceInstanceRight<ServiceConstructor>>>
100
+ export const newServiceAndRunToTuple = <ServiceConstructor extends AnyServiceConstructor>(
101
+ ServiceConstructor: ServiceConstructor,
102
+ constructorOptions: GetServiceConstructorOptions<ServiceConstructor>,
103
+ ): RunToTuple<ServiceConstructor> => {
104
+ const service = newService(ServiceConstructor, constructorOptions)
105
+ const run: RunToTuple<ServiceConstructor> = async (options) => {
106
+ const result = await service.runToTuple(options)
107
+ return result
108
+ }
109
+ return run
110
+ }
@@ -415,9 +415,7 @@ export class SocketUnit<Message> implements LoggerFriendly {
415
415
 
416
416
  protected parseMessage(event: MessageEvent): Message | undefined {
417
417
  try {
418
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
419
418
  const messageString = event.data as string
420
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
421
419
  const parsedMessage = JSON.parse(messageString) as Message
422
420
  return parsedMessage
423
421
  }
@@ -337,7 +337,6 @@ export class SocketUnit<Message> implements LoggerFriendly {
337
337
  protected parseMessage(data: RawData): Message | undefined {
338
338
  try {
339
339
  const messageString = data.toString()
340
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
341
340
  const parsedMessage = JSON.parse(messageString) as Message
342
341
  return parsedMessage
343
342
  }
@@ -130,7 +130,6 @@ export const readableStreamToTube = <D, E = Error>(
130
130
  readableStream,
131
131
  onValue: async chunk => await tube.pushData(chunk),
132
132
  onDone: async () => await tube.close(),
133
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
134
133
  onError: async error => await tube.pushError(error as E),
135
134
  })
136
135
 
@@ -43,7 +43,6 @@ export const getAuthAccessToken = async (
43
43
  },
44
44
  )
45
45
 
46
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
47
46
  const json = await result.json() as AccessTokenSuccessResponse | AccessTokenErrorResponse
48
47
 
49
48
  if ("errcode" in json) {
@@ -111,7 +110,6 @@ export const getUserInfo = async (
111
110
  },
112
111
  )
113
112
 
114
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
115
113
  const json = await result.json() as UserInfoSuccessResponse | UserInfoErrorResponse
116
114
 
117
115
  if ("errcode" in json) {
@@ -41,7 +41,6 @@ export const getJsApiAccessToken = async (
41
41
  },
42
42
  )
43
43
 
44
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
45
44
  const json = await result.json() as StableTokenResponse
46
45
 
47
46
  return {
@@ -88,7 +87,6 @@ export const getJsApiTicket = async (
88
87
  },
89
88
  )
90
89
 
91
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
92
90
  const json = await result.json() as JsApiTicketResponse
93
91
 
94
92
  return {
@@ -63,7 +63,6 @@ export class WeixinOauth2 {
63
63
  },
64
64
  )
65
65
 
66
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
67
66
  const json = await result.json() as AccessTokenSuccessResponse | AccessTokenErrorResponse
68
67
 
69
68
  if ("errcode" in json) {
@@ -117,7 +116,6 @@ export class WeixinOauth2 {
117
116
  },
118
117
  )
119
118
 
120
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
121
119
  const json = await result.json() as UserInfoSuccessResponse | UserInfoErrorResponse
122
120
 
123
121
  if ("errcode" in json) {
@@ -32,7 +32,6 @@ const createSyncSchema = (
32
32
  }
33
33
  }
34
34
 
35
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
36
35
  const record = value as Record<string, unknown>
37
36
  if (typeof record["value"] !== "number") {
38
37
  return {