hexok 1.0.1 → 2.0.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 (251) hide show
  1. package/README.md +4 -26
  2. package/dist/adapter.d.ts +18 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/adapter.js +21 -0
  5. package/dist/adapter.js.map +1 -0
  6. package/dist/catalog.d.ts +88 -0
  7. package/dist/catalog.d.ts.map +1 -0
  8. package/dist/catalog.js +79 -0
  9. package/dist/catalog.js.map +1 -0
  10. package/dist/{core/coded-error.d.ts → coded-error.d.ts} +9 -4
  11. package/dist/coded-error.d.ts.map +1 -0
  12. package/dist/{core/coded-error.js → coded-error.js} +9 -4
  13. package/dist/coded-error.js.map +1 -0
  14. package/dist/cow-draft.d.ts.map +1 -0
  15. package/dist/cow-draft.js.map +1 -0
  16. package/dist/entity.d.ts +63 -0
  17. package/dist/entity.d.ts.map +1 -0
  18. package/dist/{domain/entity.js → entity.js} +52 -80
  19. package/dist/entity.js.map +1 -0
  20. package/dist/error-map.d.ts +22 -0
  21. package/dist/error-map.d.ts.map +1 -0
  22. package/dist/error-map.js +2 -0
  23. package/dist/error-map.js.map +1 -0
  24. package/dist/errors.d.ts +85 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +85 -0
  27. package/dist/errors.js.map +1 -0
  28. package/dist/event-handler.d.ts +31 -0
  29. package/dist/event-handler.d.ts.map +1 -0
  30. package/dist/event-handler.js +28 -0
  31. package/dist/event-handler.js.map +1 -0
  32. package/dist/event.d.ts +37 -0
  33. package/dist/event.d.ts.map +1 -0
  34. package/dist/event.js +44 -0
  35. package/dist/event.js.map +1 -0
  36. package/dist/index.d.ts +16 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +14 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/mapper.d.ts +100 -0
  41. package/dist/mapper.d.ts.map +1 -0
  42. package/dist/mapper.js +167 -0
  43. package/dist/mapper.js.map +1 -0
  44. package/dist/port.d.ts +20 -0
  45. package/dist/port.d.ts.map +1 -0
  46. package/dist/port.js +25 -0
  47. package/dist/port.js.map +1 -0
  48. package/dist/result.d.ts.map +1 -0
  49. package/dist/result.js.map +1 -0
  50. package/dist/schema.d.ts +37 -0
  51. package/dist/schema.d.ts.map +1 -0
  52. package/dist/schema.js +50 -0
  53. package/dist/schema.js.map +1 -0
  54. package/dist/{core/standard-schema.d.ts → standard-schema.d.ts} +1 -1
  55. package/dist/standard-schema.d.ts.map +1 -0
  56. package/dist/standard-schema.js.map +1 -0
  57. package/dist/use-case.d.ts +183 -0
  58. package/dist/use-case.d.ts.map +1 -0
  59. package/dist/use-case.js +221 -0
  60. package/dist/use-case.js.map +1 -0
  61. package/dist/{core/schema.d.ts → validate.d.ts} +1 -1
  62. package/dist/validate.d.ts.map +1 -0
  63. package/dist/{core/schema.js → validate.js} +1 -1
  64. package/dist/validate.js.map +1 -0
  65. package/package.json +5 -25
  66. package/dist/app/callable-use-case.d.ts +0 -34
  67. package/dist/app/callable-use-case.d.ts.map +0 -1
  68. package/dist/app/callable-use-case.js +0 -41
  69. package/dist/app/callable-use-case.js.map +0 -1
  70. package/dist/app/contract.d.ts +0 -46
  71. package/dist/app/contract.d.ts.map +0 -1
  72. package/dist/app/contract.js +0 -28
  73. package/dist/app/contract.js.map +0 -1
  74. package/dist/app/error-factory.d.ts +0 -9
  75. package/dist/app/error-factory.d.ts.map +0 -1
  76. package/dist/app/error-factory.js +0 -30
  77. package/dist/app/error-factory.js.map +0 -1
  78. package/dist/app/event-channel.d.ts +0 -133
  79. package/dist/app/event-channel.d.ts.map +0 -1
  80. package/dist/app/event-channel.js +0 -49
  81. package/dist/app/event-channel.js.map +0 -1
  82. package/dist/app/event-use-case.d.ts +0 -47
  83. package/dist/app/event-use-case.d.ts.map +0 -1
  84. package/dist/app/event-use-case.js +0 -54
  85. package/dist/app/event-use-case.js.map +0 -1
  86. package/dist/app/execute-ctx.d.ts +0 -92
  87. package/dist/app/execute-ctx.d.ts.map +0 -1
  88. package/dist/app/execute-ctx.js +0 -2
  89. package/dist/app/execute-ctx.js.map +0 -1
  90. package/dist/app/external-use-case.d.ts +0 -25
  91. package/dist/app/external-use-case.d.ts.map +0 -1
  92. package/dist/app/external-use-case.js +0 -25
  93. package/dist/app/external-use-case.js.map +0 -1
  94. package/dist/app/index.d.ts +0 -9
  95. package/dist/app/index.d.ts.map +0 -1
  96. package/dist/app/index.js +0 -8
  97. package/dist/app/index.js.map +0 -1
  98. package/dist/app/internal-use-case.d.ts +0 -26
  99. package/dist/app/internal-use-case.d.ts.map +0 -1
  100. package/dist/app/internal-use-case.js +0 -26
  101. package/dist/app/internal-use-case.js.map +0 -1
  102. package/dist/app/nest.d.ts +0 -9
  103. package/dist/app/nest.d.ts.map +0 -1
  104. package/dist/app/nest.js +0 -28
  105. package/dist/app/nest.js.map +0 -1
  106. package/dist/app/types.d.ts +0 -153
  107. package/dist/app/types.d.ts.map +0 -1
  108. package/dist/app/types.js +0 -17
  109. package/dist/app/types.js.map +0 -1
  110. package/dist/core/coded-error.d.ts.map +0 -1
  111. package/dist/core/coded-error.js.map +0 -1
  112. package/dist/core/error-map.d.ts +0 -21
  113. package/dist/core/error-map.d.ts.map +0 -1
  114. package/dist/core/error-map.js +0 -5
  115. package/dist/core/error-map.js.map +0 -1
  116. package/dist/core/index.d.ts +0 -6
  117. package/dist/core/index.d.ts.map +0 -1
  118. package/dist/core/index.js +0 -5
  119. package/dist/core/index.js.map +0 -1
  120. package/dist/core/result.d.ts.map +0 -1
  121. package/dist/core/result.js.map +0 -1
  122. package/dist/core/schema.d.ts.map +0 -1
  123. package/dist/core/schema.js.map +0 -1
  124. package/dist/core/standard-schema.d.ts.map +0 -1
  125. package/dist/core/standard-schema.js.map +0 -1
  126. package/dist/domain/capabilities.d.ts +0 -42
  127. package/dist/domain/capabilities.d.ts.map +0 -1
  128. package/dist/domain/capabilities.js +0 -2
  129. package/dist/domain/capabilities.js.map +0 -1
  130. package/dist/domain/catalog.d.ts +0 -46
  131. package/dist/domain/catalog.d.ts.map +0 -1
  132. package/dist/domain/catalog.js +0 -114
  133. package/dist/domain/catalog.js.map +0 -1
  134. package/dist/domain/channel.d.ts +0 -36
  135. package/dist/domain/channel.d.ts.map +0 -1
  136. package/dist/domain/channel.js +0 -2
  137. package/dist/domain/channel.js.map +0 -1
  138. package/dist/domain/cow-draft.d.ts.map +0 -1
  139. package/dist/domain/cow-draft.js.map +0 -1
  140. package/dist/domain/entity.d.ts +0 -120
  141. package/dist/domain/entity.d.ts.map +0 -1
  142. package/dist/domain/entity.js.map +0 -1
  143. package/dist/domain/envelope.d.ts +0 -59
  144. package/dist/domain/envelope.d.ts.map +0 -1
  145. package/dist/domain/envelope.js +0 -2
  146. package/dist/domain/envelope.js.map +0 -1
  147. package/dist/domain/event.d.ts +0 -44
  148. package/dist/domain/event.d.ts.map +0 -1
  149. package/dist/domain/event.js +0 -21
  150. package/dist/domain/event.js.map +0 -1
  151. package/dist/domain/index.d.ts +0 -8
  152. package/dist/domain/index.d.ts.map +0 -1
  153. package/dist/domain/index.js +0 -5
  154. package/dist/domain/index.js.map +0 -1
  155. package/dist/domain/port.d.ts +0 -45
  156. package/dist/domain/port.d.ts.map +0 -1
  157. package/dist/domain/port.js +0 -41
  158. package/dist/domain/port.js.map +0 -1
  159. package/dist/infra/adapter.d.ts +0 -22
  160. package/dist/infra/adapter.d.ts.map +0 -1
  161. package/dist/infra/adapter.js +0 -18
  162. package/dist/infra/adapter.js.map +0 -1
  163. package/dist/infra/index.d.ts +0 -3
  164. package/dist/infra/index.d.ts.map +0 -1
  165. package/dist/infra/index.js +0 -3
  166. package/dist/infra/index.js.map +0 -1
  167. package/dist/infra/mapper.d.ts +0 -48
  168. package/dist/infra/mapper.d.ts.map +0 -1
  169. package/dist/infra/mapper.js +0 -77
  170. package/dist/infra/mapper.js.map +0 -1
  171. package/dist/runtime/app.d.ts +0 -100
  172. package/dist/runtime/app.d.ts.map +0 -1
  173. package/dist/runtime/app.js +0 -292
  174. package/dist/runtime/app.js.map +0 -1
  175. package/dist/runtime/channel.d.ts +0 -34
  176. package/dist/runtime/channel.d.ts.map +0 -1
  177. package/dist/runtime/channel.js +0 -110
  178. package/dist/runtime/channel.js.map +0 -1
  179. package/dist/runtime/client.d.ts +0 -21
  180. package/dist/runtime/client.d.ts.map +0 -1
  181. package/dist/runtime/client.js +0 -2
  182. package/dist/runtime/client.js.map +0 -1
  183. package/dist/runtime/completeness.d.ts +0 -89
  184. package/dist/runtime/completeness.d.ts.map +0 -1
  185. package/dist/runtime/completeness.js +0 -2
  186. package/dist/runtime/completeness.js.map +0 -1
  187. package/dist/runtime/envelope.d.ts +0 -7
  188. package/dist/runtime/envelope.d.ts.map +0 -1
  189. package/dist/runtime/envelope.js +0 -69
  190. package/dist/runtime/envelope.js.map +0 -1
  191. package/dist/runtime/events.d.ts +0 -6
  192. package/dist/runtime/events.d.ts.map +0 -1
  193. package/dist/runtime/events.js +0 -48
  194. package/dist/runtime/events.js.map +0 -1
  195. package/dist/runtime/http-status.d.ts +0 -3
  196. package/dist/runtime/http-status.d.ts.map +0 -1
  197. package/dist/runtime/http-status.js +0 -11
  198. package/dist/runtime/http-status.js.map +0 -1
  199. package/dist/runtime/http.d.ts +0 -4
  200. package/dist/runtime/http.d.ts.map +0 -1
  201. package/dist/runtime/http.js +0 -58
  202. package/dist/runtime/http.js.map +0 -1
  203. package/dist/runtime/index.d.ts +0 -10
  204. package/dist/runtime/index.d.ts.map +0 -1
  205. package/dist/runtime/index.js +0 -6
  206. package/dist/runtime/index.js.map +0 -1
  207. package/dist/runtime/interceptor.d.ts +0 -61
  208. package/dist/runtime/interceptor.d.ts.map +0 -1
  209. package/dist/runtime/interceptor.js +0 -7
  210. package/dist/runtime/interceptor.js.map +0 -1
  211. package/dist/runtime/invoke.d.ts +0 -34
  212. package/dist/runtime/invoke.d.ts.map +0 -1
  213. package/dist/runtime/invoke.js +0 -235
  214. package/dist/runtime/invoke.js.map +0 -1
  215. package/dist/runtime/middleware.d.ts +0 -20
  216. package/dist/runtime/middleware.d.ts.map +0 -1
  217. package/dist/runtime/middleware.js +0 -2
  218. package/dist/runtime/middleware.js.map +0 -1
  219. package/dist/runtime/rpc.d.ts +0 -24
  220. package/dist/runtime/rpc.d.ts.map +0 -1
  221. package/dist/runtime/rpc.js +0 -16
  222. package/dist/runtime/rpc.js.map +0 -1
  223. package/dist/testing/app-test.d.ts +0 -77
  224. package/dist/testing/app-test.d.ts.map +0 -1
  225. package/dist/testing/app-test.js +0 -109
  226. package/dist/testing/app-test.js.map +0 -1
  227. package/dist/testing/in-memory-bus.d.ts +0 -19
  228. package/dist/testing/in-memory-bus.d.ts.map +0 -1
  229. package/dist/testing/in-memory-bus.js +0 -31
  230. package/dist/testing/in-memory-bus.js.map +0 -1
  231. package/dist/testing/in-memory-channel.d.ts +0 -32
  232. package/dist/testing/in-memory-channel.d.ts.map +0 -1
  233. package/dist/testing/in-memory-channel.js +0 -65
  234. package/dist/testing/in-memory-channel.js.map +0 -1
  235. package/dist/testing/in-memory-queue.d.ts +0 -24
  236. package/dist/testing/in-memory-queue.d.ts.map +0 -1
  237. package/dist/testing/in-memory-queue.js +0 -66
  238. package/dist/testing/in-memory-queue.js.map +0 -1
  239. package/dist/testing/in-memory-repository.d.ts +0 -44
  240. package/dist/testing/in-memory-repository.d.ts.map +0 -1
  241. package/dist/testing/in-memory-repository.js +0 -60
  242. package/dist/testing/in-memory-repository.js.map +0 -1
  243. package/dist/testing/index.d.ts +0 -6
  244. package/dist/testing/index.d.ts.map +0 -1
  245. package/dist/testing/index.js +0 -6
  246. package/dist/testing/index.js.map +0 -1
  247. /package/dist/{domain/cow-draft.d.ts → cow-draft.d.ts} +0 -0
  248. /package/dist/{domain/cow-draft.js → cow-draft.js} +0 -0
  249. /package/dist/{core/result.d.ts → result.d.ts} +0 -0
  250. /package/dist/{core/result.js → result.js} +0 -0
  251. /package/dist/{core/standard-schema.js → standard-schema.js} +0 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Application service. Pass ports through the constructor.
3
+ * `execute` is required; the compiler errors on the class when it is missing.
4
+ * Declare the input and output on `execute` — those are the types callers see.
5
+ * A refusal throws an {@link Errors} catalog member. The application catches it.
6
+ *
7
+ * ```ts
8
+ * class CreateUser extends UseCase('user.create') {
9
+ * constructor(private readonly users: UserRepository) { super() }
10
+ * async execute(input: { email: string }): Promise<{ id: string }> {
11
+ * return { id: input.email }
12
+ * }
13
+ * }
14
+ * ```
15
+ */
16
+ export declare function UseCase<const Token extends string>(token: Token): (abstract new () => {
17
+ /** Nominal marker. Each `UseCase(...)` call is a distinct class. */
18
+ readonly "__#private@#brand": true;
19
+ /**
20
+ * Required. Annotate `input` and the return type on the subclass;
21
+ * callers of the subclass see those types.
22
+ */
23
+ execute(input: unknown): Promise<unknown>;
24
+ }) & {
25
+ /** Use-case name. Literal type of the string passed to {@link UseCase}. */
26
+ readonly token: Token;
27
+ };
28
+ type ReservedKey = 'token' | 'prototype' | 'name' | 'length';
29
+ /** A bag that uses a reserved class static fails on that property. */
30
+ type ReservedOk<S> = {
31
+ [K in keyof S]: K extends ReservedKey ? never : S[K];
32
+ };
33
+ type NoStatics = Record<never, never>;
34
+ /** Static bag minus names that would overwrite the class constructor. */
35
+ type Statics<S> = Omit<S, ReservedKey>;
36
+ /**
37
+ * Family of use cases that receive a caller context on `execute`.
38
+ * Returns a factory: a token, or a token and statics when `Spec` has keys.
39
+ * `execute` is required; annotate it on the subclass — callers see those types.
40
+ * A guard and hooks, when set, run around that method.
41
+ * Statics are application data copied onto the class. The application validates `input`.
42
+ * {@link UseCase.GuardParameters} reads the guard's call off the factory.
43
+ * {@link UseCase.Ctx} reads that call's context type.
44
+ * {@link context} returns that factory. {@link ContextFactory.guard} and
45
+ * {@link ContextFactory.hooks} return it again.
46
+ *
47
+ * ```ts
48
+ * const ApiUseCase = UseCase.context<
49
+ * ApiContext,
50
+ * { input: StandardSchemaV1; permission: string }
51
+ * >()
52
+ * .guard((call) => {
53
+ * if (call.ctx.sessionId.length < 1 || call.spec.permission.length < 1) {
54
+ * throw new Error('unauthorized')
55
+ * }
56
+ * })
57
+ * .hooks({
58
+ * preExecute: () => ({ started: Date.now() }),
59
+ * postExecute(_call, state) {
60
+ * void state.started
61
+ * },
62
+ * })
63
+ *
64
+ * class FindUsers extends ApiUseCase('user.find', {
65
+ * input: z.object({ query: z.string() }),
66
+ * permission: 'users.read',
67
+ * }) {
68
+ * constructor(private readonly users: UserRepository) { super() }
69
+ * async execute(
70
+ * ctx: UseCase.Ctx<typeof ApiUseCase>,
71
+ * input: { query: string },
72
+ * ): Promise<User[]> {
73
+ * return this.users.search(input.query)
74
+ * }
75
+ * }
76
+ * ```
77
+ */
78
+ export declare namespace UseCase {
79
+ /**
80
+ * Call passed to a {@link context} guard.
81
+ * `ctx` is the per-call context. `spec` is the static contract.
82
+ * `token` is the use-case name. `input` is the argument passed to `execute`.
83
+ *
84
+ * ```ts
85
+ * type Call = UseCase.GuardParameters<typeof ApiUseCase>
86
+ * ```
87
+ */
88
+ type GuardParameters<Factory> = Factory extends GuardParametersSlot<infer Ctx, infer Spec> ? Call<Ctx, Spec> : never;
89
+ /**
90
+ * Context type of a {@link context} factory.
91
+ * Pass the factory. A subclass, and a plain {@link UseCase} class, are `never`.
92
+ *
93
+ * ```ts
94
+ * async execute(
95
+ * ctx: UseCase.Ctx<typeof ApiUseCase>,
96
+ * input: { query: string },
97
+ * ): Promise<User[]> {}
98
+ * ```
99
+ */
100
+ type Ctx<Factory> = GuardParameters<Factory>['ctx'];
101
+ /**
102
+ * Factory returned by {@link context}.
103
+ * An exported const infers this type.
104
+ * `guard` and `hooks` return the same factory.
105
+ */
106
+ interface ContextFactory<Ctx, Spec = NoStatics> extends ReturnType<typeof buildContext<Ctx, Spec>> {
107
+ /**
108
+ * Runs after guards already registered, and before `execute`.
109
+ * Returns the same factory.
110
+ */
111
+ guard(guard: (call: Call<Ctx, Spec>) => void | Promise<void>): ContextFactory<Ctx, Spec>;
112
+ /**
113
+ * Lifecycle around `execute`. The value returned from `preExecute` is the
114
+ * `state` argument of `postExecute`, `onCatch`, and `onFinally`.
115
+ * A second call throws when this factory already has hooks.
116
+ */
117
+ hooks<State = void>(definition: HookDefinition<Ctx, Spec, State>): ContextFactory<Ctx, Spec>;
118
+ }
119
+ /**
120
+ * Family factory. Pass the context type.
121
+ * The argument is a settings object with no keys yet.
122
+ */
123
+ function context<Ctx, Spec = NoStatics>(config?: ContextConfig): unknown extends Ctx ? 'Pass a type argument: UseCase.context<Ctx>()' : ContextFactory<Ctx, Spec>;
124
+ }
125
+ /** Values a guard and the hooks share for one invocation. */
126
+ type Call<Ctx, Spec> = {
127
+ readonly ctx: Ctx;
128
+ readonly spec: Spec;
129
+ readonly token: string;
130
+ /** The `input` argument the caller passed to `execute`. */
131
+ readonly input: unknown;
132
+ };
133
+ type Performed<Ctx, Spec> = Call<Ctx, Spec> & {
134
+ readonly result: unknown;
135
+ };
136
+ type Caught<Ctx, Spec> = Call<Ctx, Spec> & {
137
+ readonly error: unknown;
138
+ };
139
+ type Settled<Ctx, Spec> = (Call<Ctx, Spec> & {
140
+ readonly status: 'success';
141
+ readonly result: unknown;
142
+ }) | (Call<Ctx, Spec> & {
143
+ readonly status: 'failure';
144
+ readonly error: unknown;
145
+ });
146
+ /** Settings for {@link UseCase.context}. There are none yet. */
147
+ type ContextConfig = Record<string, never>;
148
+ type ContextGuard<Ctx, Spec> = (call: Call<Ctx, Spec>) => void | Promise<void>;
149
+ type HookDefinition<Ctx, Spec, State> = {
150
+ preExecute?: (call: Call<Ctx, Spec>) => State | Promise<State>;
151
+ postExecute?: (call: Performed<Ctx, Spec>, state: Awaited<State>) => void | Promise<void>;
152
+ onCatch?: (call: Caught<Ctx, Spec>, state: Awaited<State> | undefined) => void | Promise<void>;
153
+ onFinally?: (call: Settled<Ctx, Spec>, state: Awaited<State> | undefined) => void | Promise<void>;
154
+ };
155
+ /** Hooks stored on one factory. State is erased after `.hooks()` checks it. */
156
+ type StoredHooks<Ctx, Spec> = {
157
+ preExecute?: (call: Call<Ctx, Spec>) => unknown;
158
+ postExecute?: (call: Performed<Ctx, Spec>, state: unknown) => void | Promise<void>;
159
+ onCatch?: (call: Caught<Ctx, Spec>, state: unknown) => void | Promise<void>;
160
+ onFinally?: (call: Settled<Ctx, Spec>, state: unknown) => void | Promise<void>;
161
+ };
162
+ /** Type-only mark. Absent at runtime. Same symbol in {@link UseCase.GuardParameters}. */
163
+ declare const guardParameters: unique symbol;
164
+ type GuardParametersSlot<Ctx, Spec> = {
165
+ readonly [guardParameters]?: (call: Call<Ctx, Spec>) => void;
166
+ };
167
+ declare function buildContext<Ctx, Spec = NoStatics>(options?: {
168
+ guard?: ContextGuard<Ctx, Spec>;
169
+ hooks?: StoredHooks<Ctx, Spec>;
170
+ }): (<const Token extends string, const S extends [keyof Spec] extends [never] ? NoStatics : Spec>(token: Token, ...args: [keyof Spec] extends [never] ? [] : [statics: ReservedOk<S> & Spec]) => ((abstract new () => {
171
+ /** Nominal marker. Each factory call is a distinct class. */
172
+ readonly "__#private@#brand": true;
173
+ /**
174
+ * Required. Annotate `ctx`, `input`, and the return type on the subclass.
175
+ * A guard and hooks run around this method when set.
176
+ */
177
+ execute(ctx: Ctx, input: unknown): Promise<unknown>;
178
+ }) & {
179
+ /** Use-case name. Literal type of the string passed to the factory. */
180
+ readonly token: Token;
181
+ }) & ([keyof Spec] extends [never] ? NoStatics : Statics<S>)) & GuardParametersSlot<Ctx, Spec>;
182
+ export {};
183
+ //# sourceMappingURL=use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-case.d.ts","sourceRoot":"","sources":["../src/use-case.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Application service. Pass ports through the constructor.
3
+ * `execute` is required; the compiler errors on the class when it is missing.
4
+ * Declare the input and output on `execute` — those are the types callers see.
5
+ * A refusal throws an {@link Errors} catalog member. The application catches it.
6
+ *
7
+ * ```ts
8
+ * class CreateUser extends UseCase('user.create') {
9
+ * constructor(private readonly users: UserRepository) { super() }
10
+ * async execute(input: { email: string }): Promise<{ id: string }> {
11
+ * return { id: input.email }
12
+ * }
13
+ * }
14
+ * ```
15
+ */
16
+ export function UseCase(token) {
17
+ class UseCaseClass {
18
+ /** Use-case name. Literal type of the string passed to {@link UseCase}. */
19
+ static token = token;
20
+ /** Nominal marker. Each `UseCase(...)` call is a distinct class. */
21
+ #brand = true;
22
+ constructor() {
23
+ void this.#brand;
24
+ }
25
+ }
26
+ return UseCaseClass;
27
+ }
28
+ const RESERVED_STATICS = new Set([
29
+ 'token',
30
+ 'prototype',
31
+ 'name',
32
+ 'length',
33
+ ]);
34
+ /**
35
+ * Family of use cases that receive a caller context on `execute`.
36
+ * Returns a factory: a token, or a token and statics when `Spec` has keys.
37
+ * `execute` is required; annotate it on the subclass — callers see those types.
38
+ * A guard and hooks, when set, run around that method.
39
+ * Statics are application data copied onto the class. The application validates `input`.
40
+ * {@link UseCase.GuardParameters} reads the guard's call off the factory.
41
+ * {@link UseCase.Ctx} reads that call's context type.
42
+ * {@link context} returns that factory. {@link ContextFactory.guard} and
43
+ * {@link ContextFactory.hooks} return it again.
44
+ *
45
+ * ```ts
46
+ * const ApiUseCase = UseCase.context<
47
+ * ApiContext,
48
+ * { input: StandardSchemaV1; permission: string }
49
+ * >()
50
+ * .guard((call) => {
51
+ * if (call.ctx.sessionId.length < 1 || call.spec.permission.length < 1) {
52
+ * throw new Error('unauthorized')
53
+ * }
54
+ * })
55
+ * .hooks({
56
+ * preExecute: () => ({ started: Date.now() }),
57
+ * postExecute(_call, state) {
58
+ * void state.started
59
+ * },
60
+ * })
61
+ *
62
+ * class FindUsers extends ApiUseCase('user.find', {
63
+ * input: z.object({ query: z.string() }),
64
+ * permission: 'users.read',
65
+ * }) {
66
+ * constructor(private readonly users: UserRepository) { super() }
67
+ * async execute(
68
+ * ctx: UseCase.Ctx<typeof ApiUseCase>,
69
+ * input: { query: string },
70
+ * ): Promise<User[]> {
71
+ * return this.users.search(input.query)
72
+ * }
73
+ * }
74
+ * ```
75
+ */
76
+ (function (UseCase) {
77
+ /**
78
+ * Family factory. Pass the context type.
79
+ * The argument is a settings object with no keys yet.
80
+ */
81
+ function context(config) {
82
+ void config;
83
+ return bindFactory({});
84
+ }
85
+ UseCase.context = context;
86
+ })(UseCase || (UseCase = {}));
87
+ function storedHooks(definition) {
88
+ if (definition.preExecute === undefined &&
89
+ definition.postExecute === undefined &&
90
+ definition.onCatch === undefined &&
91
+ definition.onFinally === undefined) {
92
+ return undefined;
93
+ }
94
+ return definition;
95
+ }
96
+ function composeGuard(current, next) {
97
+ if (current === undefined)
98
+ return next;
99
+ return async (call) => {
100
+ await current(call);
101
+ await next(call);
102
+ };
103
+ }
104
+ function bindFactory(slots) {
105
+ const factory = buildContext(slots);
106
+ Object.defineProperty(factory, 'guard', {
107
+ configurable: true,
108
+ enumerable: false,
109
+ writable: true,
110
+ value: (guard) => bindFactory({
111
+ ...slots,
112
+ guard: composeGuard(slots.guard, guard),
113
+ }),
114
+ });
115
+ Object.defineProperty(factory, 'hooks', {
116
+ configurable: true,
117
+ enumerable: false,
118
+ writable: true,
119
+ value: (definition) => {
120
+ const hooks = storedHooks(definition);
121
+ if (slots.hooks !== undefined && hooks !== undefined) {
122
+ throw new Error('hexok: UseCase hooks are already set');
123
+ }
124
+ return bindFactory({
125
+ ...slots,
126
+ ...(hooks !== undefined ? { hooks } : {}),
127
+ });
128
+ },
129
+ });
130
+ return factory;
131
+ }
132
+ function buildContext(options) {
133
+ const guard = options?.guard;
134
+ const hooks = options?.hooks;
135
+ const factory = function family(token, ...args) {
136
+ // Conditional rest tuple: index 0 is the statics bag, or absent.
137
+ const statics = bagOf(args);
138
+ const spec = (statics ?? {});
139
+ class Runtime {
140
+ /** Use-case name. Literal type of the string passed to the factory. */
141
+ static token = token;
142
+ /** Nominal marker. Each factory call is a distinct class. */
143
+ #brand = true;
144
+ constructor() {
145
+ void this.#brand;
146
+ if (guard === undefined && hooks === undefined)
147
+ return;
148
+ installExecute(this, token, guard, hooks, spec);
149
+ }
150
+ }
151
+ if (statics !== undefined)
152
+ assignStatics(Runtime, statics);
153
+ return Runtime;
154
+ };
155
+ return factory;
156
+ }
157
+ function bagOf(args) {
158
+ const value = args[0];
159
+ if (typeof value !== 'object' || value === null)
160
+ return undefined;
161
+ return value;
162
+ }
163
+ function assignStatics(target, statics) {
164
+ const copy = {};
165
+ const record = statics;
166
+ for (const key of Object.keys(statics)) {
167
+ if (RESERVED_STATICS.has(key))
168
+ continue;
169
+ copy[key] = record[key];
170
+ }
171
+ Object.assign(target, copy);
172
+ }
173
+ function installExecute(instance, token, guard, hooks, spec) {
174
+ const prototype = Object.getPrototypeOf(instance);
175
+ // Own property would shadow this and recurse.
176
+ const execute = prototype.execute;
177
+ Object.defineProperty(instance, 'execute', {
178
+ configurable: true,
179
+ writable: true,
180
+ value: async (ctx, input) => {
181
+ const call = { ctx, spec, token, input };
182
+ if (guard !== undefined)
183
+ await guard(call);
184
+ // Local to this invocation. Overlapping execute calls must not share it.
185
+ let state;
186
+ let succeeded = false;
187
+ let result;
188
+ let caught;
189
+ let failed = false;
190
+ try {
191
+ if (hooks?.preExecute !== undefined) {
192
+ state = await hooks.preExecute(call);
193
+ }
194
+ result = await execute.call(instance, ctx, input);
195
+ if (hooks?.postExecute !== undefined) {
196
+ await hooks.postExecute({ ...call, result }, state);
197
+ }
198
+ succeeded = true;
199
+ return result;
200
+ }
201
+ catch (error) {
202
+ failed = true;
203
+ caught = error;
204
+ if (hooks?.onCatch !== undefined) {
205
+ await hooks.onCatch({ ...call, error }, state);
206
+ }
207
+ throw error;
208
+ }
209
+ finally {
210
+ if (hooks?.onFinally !== undefined) {
211
+ const settled = succeeded
212
+ ? { ...call, status: 'success', result }
213
+ : { ...call, status: 'failure', error: caught };
214
+ if (failed || succeeded)
215
+ await hooks.onFinally(settled, state);
216
+ }
217
+ }
218
+ },
219
+ });
220
+ }
221
+ //# sourceMappingURL=use-case.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-case.js","sourceRoot":"","sources":["../src/use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,OAAO,CAA6B,KAAY;IAC9D,MAAe,YAAY;QACzB,2EAA2E;QAC3E,MAAM,CAAU,KAAK,GAAU,KAAK,CAAC;QACrC,oEAAoE;QAC3D,MAAM,GAAG,IAAI,CAAC;QAEvB;YACE,KAAK,IAAI,CAAC,MAAM,CAAC;QACnB,CAAC;;IASH,OAAO,YAAY,CAAC;AACtB,CAAC;AAcD,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IACpD,OAAO;IACP,WAAW;IACX,MAAM;IACN,QAAQ;CACT,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,WAAiB,OAAO;IAoDtB;;;OAGG;IACH,SAAgB,OAAO,CACrB,MAAsB;QAItB,KAAK,MAAM,CAAC;QACZ,OAAO,WAAW,CAAY,EAAE,CAEH,CAAC;IAChC,CAAC;IATe,eAAO,UAStB,CAAA;AACH,CAAC,EAlEgB,OAAO,KAAP,OAAO,QAkEvB;AA4ED,SAAS,WAAW,CAClB,UAA4C;IAE5C,IACE,UAAU,CAAC,UAAU,KAAK,SAAS;QACnC,UAAU,CAAC,WAAW,KAAK,SAAS;QACpC,UAAU,CAAC,OAAO,KAAK,SAAS;QAChC,UAAU,CAAC,SAAS,KAAK,SAAS,EAClC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,UAA+C,CAAC;AACzD,CAAC;AAED,SAAS,YAAY,CACnB,OAA4C,EAC5C,IAA6B;IAE7B,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,KAAK,EAAE,IAAI,EAAE,EAAE;QACpB,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,KAAuB;IAEvB,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAsC,CAAC;IACzE,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE;QACtC,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,KAA8B,EAAE,EAAE,CACxC,WAAW,CAAC;YACV,GAAG,KAAK;YACR,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC;SACxC,CAAC;KACL,CAAC,CAAC;IACH,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE;QACtC,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAQ,UAA4C,EAAE,EAAE;YAC7D,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;YACtC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACrD,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,WAAW,CAAC;gBACjB,GAAG,KAAK;gBACR,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1C,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAwB,OAG5C;IACC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,CAAC;IAE7B,MAAM,OAAO,GAAG,SAAS,MAAM,CAI7B,KAAY,EACZ,GAAG,IAAyE;QAE5E,iEAAiE;QACjE,MAAM,OAAO,GAAG,KAAK,CAAC,IAA0B,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAS,CAAC;QAErC,MAAe,OAAO;YACpB,uEAAuE;YACvE,MAAM,CAAU,KAAK,GAAU,KAAK,CAAC;YACrC,6DAA6D;YACpD,MAAM,GAAG,IAAI,CAAC;YAEvB;gBACE,KAAK,IAAI,CAAC,MAAM,CAAC;gBACjB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;oBAAE,OAAO;gBACvD,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YAClD,CAAC;;QASH,IAAI,OAAO,KAAK,SAAS;YAAE,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,OACkD,CAAC;IAC5D,CAAC,CAAC;IAEF,OAAO,OAA0D,CAAC;AACpE,CAAC;AAED,SAAS,KAAK,CAAC,IAAwB;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,OAAe;IACpD,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,OAAkC,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,cAAc,CACrB,QAAgB,EAChB,KAAa,EACb,KAA0C,EAC1C,KAAyC,EACzC,IAAU;IAEV,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAE/C,CAAC;IACF,8CAA8C;IAC9C,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;IAElC,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE;QACzC,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,KAAK,EAAE,GAAQ,EAAE,KAAc,EAAoB,EAAE;YAC1D,MAAM,IAAI,GAAoB,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC1D,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3C,yEAAyE;YACzE,IAAI,KAAc,CAAC;YACnB,IAAI,SAAS,GAAG,KAAK,CAAC;YACtB,IAAI,MAAe,CAAC;YACpB,IAAI,MAAe,CAAC;YACpB,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;oBACpC,KAAK,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBACvC,CAAC;gBACD,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;gBAClD,IAAI,KAAK,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;oBACrC,MAAM,KAAK,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;gBACtD,CAAC;gBACD,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM,GAAG,KAAK,CAAC;gBACf,IAAI,KAAK,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;oBACjC,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;gBACjD,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;oBAAS,CAAC;gBACT,IAAI,KAAK,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;oBACnC,MAAM,OAAO,GAAuB,SAAS;wBAC3C,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;wBACxC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;oBAClD,IAAI,MAAM,IAAI,SAAS;wBAAE,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -16,4 +16,4 @@ export type Infer<S extends StandardSchemaV1> = NonNullable<S['~standard']['type
16
16
  * ```
17
17
  */
18
18
  export declare function validate<S extends StandardSchemaV1>(schema: S, value: unknown): Result<Infer<S>, 'VALIDATION'>;
19
- //# sourceMappingURL=schema.d.ts.map
19
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,kDAAkD;AAClD,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,gBAAgB,IAAI,WAAW,CACzD,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CACxB,CAAC,QAAQ,CAAC,CAAC;AAEZ;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,gBAAgB,EACjD,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,OAAO,GACb,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAShC"}
@@ -25,4 +25,4 @@ export function validate(schema, value) {
25
25
  function isPromise(value) {
26
26
  return typeof value.then === 'function';
27
27
  }
28
- //# sourceMappingURL=schema.js.map
28
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,EAAE,EAAe,MAAM,aAAa,CAAC;AAQpD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAS,EACT,KAAc;IAEd,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,EAAE,CAAC,MAAM,CAAC,KAAiB,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,SAAS,CAChB,KAE6C;IAE7C,OAAO,OAAQ,KAA0B,CAAC,IAAI,KAAK,UAAU,CAAC;AAChE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hexok",
3
- "version": "1.0.1",
4
- "description": "A TypeScript kit for writing a clean-architecture backend as ordinary classes.",
3
+ "version": "2.0.0",
4
+ "description": "TypeScript primitives for hexagonal software: Schema, Entity, UseCase, Port, Adapter, Mapper, Event, EventCatalog, EventHandler, and Errors.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,
@@ -28,29 +28,9 @@
28
28
  "access": "public"
29
29
  },
30
30
  "exports": {
31
- "./core": {
32
- "types": "./dist/core/index.d.ts",
33
- "import": "./dist/core/index.js"
34
- },
35
- "./domain": {
36
- "types": "./dist/domain/index.d.ts",
37
- "import": "./dist/domain/index.js"
38
- },
39
- "./app": {
40
- "types": "./dist/app/index.d.ts",
41
- "import": "./dist/app/index.js"
42
- },
43
- "./infra": {
44
- "types": "./dist/infra/index.d.ts",
45
- "import": "./dist/infra/index.js"
46
- },
47
- "./runtime": {
48
- "types": "./dist/runtime/index.d.ts",
49
- "import": "./dist/runtime/index.js"
50
- },
51
- "./testing": {
52
- "types": "./dist/testing/index.d.ts",
53
- "import": "./dist/testing/index.js"
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
54
34
  },
55
35
  "./package.json": "./package.json"
56
36
  },
@@ -1,34 +0,0 @@
1
- import { type ErrorMap, type Result } from '../core/index.js';
2
- import type { AnyEventCatalog, PortToken } from '../domain/index.js';
3
- import type { EventChannelCtor } from './types.js';
4
- /**
5
- * Request/response base for ExternalUseCase and InternalUseCase.
6
- * Do not declare `trigger` here — each sibling sets a distinct literal.
7
- * Not re-exported from hexok/app; application authors extend ExternalUseCase
8
- * or InternalUseCase.
9
- */
10
- export declare abstract class CallableUseCase {
11
- /** Use-case id (`incident.close`). Unique among the callable family. */
12
- static readonly key: string;
13
- /** Request Standard Schema. Validated before `execute`. */
14
- static readonly input: unknown;
15
- /** Success Standard Schema. Types `execute`, `run`, and the contract. */
16
- static readonly output: unknown;
17
- /** Declared refusals. Keys become `errors.CODE()` factories on `ExecuteCtx`. */
18
- static readonly errors: ErrorMap;
19
- /** Port tokens keyed by the alias used in `execute`. Required by `App.from`. */
20
- static readonly ports?: Record<string, PortToken<unknown>>;
21
- /** `static publishes = [DomainEvents] as const` — without `as const`, Events widens to EventClass. */
22
- static readonly publishes?: readonly AnyEventCatalog[];
23
- /** `static channels = [ClientChannel] as const` — without `as const`, catalog keys widen. */
24
- static readonly channels?: readonly EventChannelCtor[];
25
- protected constructor();
26
- /** Typed `never` so subclasses may take `ExecuteCtx` (tighter `publish`). */
27
- abstract execute(ctx: never): Promise<unknown>;
28
- /**
29
- * Same one-liner as `if (!result.ok) throw new CodedError({ code: result.code })`.
30
- * For `validate` / custom Results. Entity methods throw themselves.
31
- */
32
- unwrap<T, E extends string>(result: Result<T, E>): T;
33
- }
34
- //# sourceMappingURL=callable-use-case.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"callable-use-case.d.ts","sourceRoot":"","sources":["../../src/app/callable-use-case.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;GAKG;AACH,8BAAsB,eAAe;IACnC,wEAAwE;IACxE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC5B,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAC/B,yEAAyE;IACzE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAM;IACtC,gFAAgF;IAChF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,sGAAsG;IACtG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACvD,6FAA6F;IAC7F,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAEvD,SAAS;IAET,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;IAE9C;;;OAGG;IACH,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC;CAYrD"}
@@ -1,41 +0,0 @@
1
- import { CodedError } from '../core/index.js';
2
- /**
3
- * Request/response base for ExternalUseCase and InternalUseCase.
4
- * Do not declare `trigger` here — each sibling sets a distinct literal.
5
- * Not re-exported from hexok/app; application authors extend ExternalUseCase
6
- * or InternalUseCase.
7
- */
8
- export class CallableUseCase {
9
- /** Use-case id (`incident.close`). Unique among the callable family. */
10
- static key;
11
- /** Request Standard Schema. Validated before `execute`. */
12
- static input;
13
- /** Success Standard Schema. Types `execute`, `run`, and the contract. */
14
- static output;
15
- /** Declared refusals. Keys become `errors.CODE()` factories on `ExecuteCtx`. */
16
- static errors = {};
17
- /** Port tokens keyed by the alias used in `execute`. Required by `App.from`. */
18
- static ports;
19
- /** `static publishes = [DomainEvents] as const` — without `as const`, Events widens to EventClass. */
20
- static publishes;
21
- /** `static channels = [ClientChannel] as const` — without `as const`, catalog keys widen. */
22
- static channels;
23
- constructor() { }
24
- /**
25
- * Same one-liner as `if (!result.ok) throw new CodedError({ code: result.code })`.
26
- * For `validate` / custom Results. Entity methods throw themselves.
27
- */
28
- unwrap(result) {
29
- if (!result.ok) {
30
- throw new CodedError({
31
- code: result.code,
32
- message: result.code,
33
- ...(result.issues !== undefined
34
- ? { data: { issues: result.issues } }
35
- : {}),
36
- });
37
- }
38
- return result.value;
39
- }
40
- }
41
- //# sourceMappingURL=callable-use-case.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"callable-use-case.js","sourceRoot":"","sources":["../../src/app/callable-use-case.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,MAAM,kBAAkB,CAAC;AAI1E;;;;;GAKG;AACH,MAAM,OAAgB,eAAe;IACnC,wEAAwE;IACxE,MAAM,CAAU,GAAG,CAAS;IAC5B,2DAA2D;IAC3D,MAAM,CAAU,KAAK,CAAU;IAC/B,yEAAyE;IACzE,MAAM,CAAU,MAAM,CAAU;IAChC,gFAAgF;IAChF,MAAM,CAAU,MAAM,GAAa,EAAE,CAAC;IACtC,gFAAgF;IAChF,MAAM,CAAU,KAAK,CAAsC;IAC3D,sGAAsG;IACtG,MAAM,CAAU,SAAS,CAA8B;IACvD,6FAA6F;IAC7F,MAAM,CAAU,QAAQ,CAA+B;IAEvD,gBAAyB,CAAC;IAK1B;;;OAGG;IACH,MAAM,CAAsB,MAAoB;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,UAAU,CAAC;gBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE,MAAM,CAAC,IAAI;gBACpB,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;oBAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE;oBACrC,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC"}
@@ -1,46 +0,0 @@
1
- import type { ErrorMap, StandardSchemaV1 } from '../core/index.js';
2
- import type { PathTo, UnionToIntersection } from './nest.js';
3
- import { type ExternalKeysOf, type UseCaseBag } from './types.js';
4
- /** One external use case in the runtime catalog. Transport-neutral, wide. */
5
- export type CatalogEntry = {
6
- /** Use-case `key` (`incident.close`). */
7
- key: string;
8
- /** Request schema. */
9
- input: StandardSchemaV1;
10
- /** Success schema. */
11
- output: StandardSchemaV1;
12
- /** Declared error map. */
13
- errors: ErrorMap;
14
- };
15
- /** Flat catalog from `deriveContract`. Event and internal use cases are omitted. */
16
- export type UseCaseContract = {
17
- /** Entries keyed by use-case `key`. */
18
- entries: Record<string, CatalogEntry>;
19
- };
20
- type UseCaseWithKey<Bag, Key> = Extract<Bag[keyof Bag], {
21
- trigger: 'external';
22
- key: Key;
23
- }>;
24
- type RouteView<C> = C extends {
25
- key: infer Key extends string;
26
- input: infer Input;
27
- output: infer Output;
28
- errors: infer Errors;
29
- } ? {
30
- readonly key: Key;
31
- readonly input: Input;
32
- readonly output: Output;
33
- readonly errors: Errors;
34
- } : never;
35
- /**
36
- * Nested by use-case `key` (`incident.close` → `{ incident: { close } }`).
37
- * Event and internal use cases are omitted.
38
- */
39
- export type DerivedContract<Bag> = UnionToIntersection<ExternalKeysOf<Bag> extends infer Key ? Key extends string ? PathTo<Key, RouteView<UseCaseWithKey<Bag, Key>>> : never : never>;
40
- /**
41
- * Build a transport-neutral catalog from a use-case class list.
42
- * Duplicate `key` throws. Event use cases and InternalUseCase are skipped.
43
- */
44
- export declare function deriveContract(useCases: UseCaseBag): UseCaseContract;
45
- export { nestByKey } from './nest.js';
46
- //# sourceMappingURL=contract.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/app/contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EACL,KAAK,cAAc,EAGnB,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAEpB,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG;IACzB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,sBAAsB;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,sBAAsB;IACtB,MAAM,EAAE,gBAAgB,CAAC;IACzB,0BAA0B;IAC1B,MAAM,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,eAAe,GAAG;IAC5B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACvC,CAAC;AAEF,KAAK,cAAc,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CACrC,GAAG,CAAC,MAAM,GAAG,CAAC,EACd;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAClC,CAAC;AAEF,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,KAAK,CAAC;IACnB,MAAM,EAAE,MAAM,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,MAAM,CAAC;CACtB,GACG;IACE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD,KAAK,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,GAAG,IAAI,mBAAmB,CACpD,cAAc,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,GACjC,GAAG,SAAS,MAAM,GAChB,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAChD,KAAK,GACP,KAAK,CACV,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,CAkBpE;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -1,28 +0,0 @@
1
- import { isCallableUseCase, isExternalUseCase, } from './types.js';
2
- /**
3
- * Build a transport-neutral catalog from a use-case class list.
4
- * Duplicate `key` throws. Event use cases and InternalUseCase are skipped.
5
- */
6
- export function deriveContract(useCases) {
7
- const entries = {};
8
- const seen = new Set();
9
- for (const ctor of Object.values(useCases)) {
10
- if (!isCallableUseCase(ctor))
11
- continue;
12
- if (seen.has(ctor.key)) {
13
- throw new Error(`hexok: duplicate use-case key "${ctor.key}"`);
14
- }
15
- seen.add(ctor.key);
16
- if (!isExternalUseCase(ctor))
17
- continue;
18
- entries[ctor.key] = {
19
- key: ctor.key,
20
- input: ctor.input,
21
- output: ctor.output,
22
- errors: ctor.errors,
23
- };
24
- }
25
- return { entries };
26
- }
27
- export { nestByKey } from './nest.js';
28
- //# sourceMappingURL=contract.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/app/contract.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,iBAAiB,EACjB,iBAAiB,GAGlB,MAAM,YAAY,CAAC;AAmDpB;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAoB;IACjD,MAAM,OAAO,GAAiC,EAAE,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAmB,EAAE,CAAC;QAC7D,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAAE,SAAS;QACvC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAAE,SAAS;QACvC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG;YAClB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}