sonamu 0.12.0 → 0.13.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 (275) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -2
  2. package/dist/ai/agents/agent.js +2 -3
  3. package/dist/ai/agents/index.js +1 -2
  4. package/dist/ai/index.js +1 -2
  5. package/dist/ai/providers/rtzr/api.js +1 -2
  6. package/dist/ai/providers/rtzr/error.js +2 -3
  7. package/dist/ai/providers/rtzr/model.js +1 -2
  8. package/dist/ai/providers/rtzr/options.js +1 -2
  9. package/dist/ai/providers/rtzr/provider.js +1 -2
  10. package/dist/ai/providers/rtzr/utils.js +1 -2
  11. package/dist/api/base-frame.js +4 -4
  12. package/dist/api/caster.d.ts +1 -1
  13. package/dist/api/caster.d.ts.map +1 -1
  14. package/dist/api/caster.js +9 -9
  15. package/dist/api/code-converters.js +6 -5
  16. package/dist/api/config.d.ts +1 -1
  17. package/dist/api/config.d.ts.map +1 -1
  18. package/dist/api/config.js +2 -3
  19. package/dist/api/context.d.ts +2 -3
  20. package/dist/api/context.d.ts.map +1 -1
  21. package/dist/api/context.js +2 -3
  22. package/dist/api/decorators.js +2 -3
  23. package/dist/api/http-validator.js +2 -3
  24. package/dist/api/index.js +8 -3
  25. package/dist/api/secret.js +1 -2
  26. package/dist/api/sonamu.d.ts +3 -5
  27. package/dist/api/sonamu.d.ts.map +1 -1
  28. package/dist/api/sonamu.js +19 -18
  29. package/dist/api/validator.js +1 -2
  30. package/dist/api/websocket-helpers.js +2 -3
  31. package/dist/auth/audit-log/builders.js +1 -2
  32. package/dist/auth/audit-log/client-ip.js +2 -3
  33. package/dist/auth/audit-log/events.js +1 -2
  34. package/dist/auth/audit-log/plugin.d.ts.map +1 -1
  35. package/dist/auth/audit-log/plugin.js +2 -3
  36. package/dist/auth/audit-log-ingestor.js +2 -3
  37. package/dist/auth/auth-generator.js +2 -3
  38. package/dist/auth/better-auth-entities.js +1 -2
  39. package/dist/auth/better-auth-request.js +2 -3
  40. package/dist/auth/index.js +2 -3
  41. package/dist/auth/knex-adapter.js +2 -3
  42. package/dist/auth/plugins/entity-definitions/admin.js +1 -2
  43. package/dist/auth/plugins/entity-definitions/anonymous.js +1 -2
  44. package/dist/auth/plugins/entity-definitions/api-key.js +1 -2
  45. package/dist/auth/plugins/entity-definitions/audit-log.js +1 -2
  46. package/dist/auth/plugins/entity-definitions/index.js +1 -2
  47. package/dist/auth/plugins/entity-definitions/jwt.js +1 -2
  48. package/dist/auth/plugins/entity-definitions/organization.js +1 -2
  49. package/dist/auth/plugins/entity-definitions/passkey.js +1 -2
  50. package/dist/auth/plugins/entity-definitions/phone-number.js +1 -2
  51. package/dist/auth/plugins/entity-definitions/sso.js +1 -2
  52. package/dist/auth/plugins/entity-definitions/two-factor.js +1 -2
  53. package/dist/auth/plugins/entity-definitions/username.js +1 -2
  54. package/dist/auth/plugins/wrappers/admin.d.ts +33 -32
  55. package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
  56. package/dist/auth/plugins/wrappers/admin.js +2 -3
  57. package/dist/auth/plugins/wrappers/anonymous.js +2 -3
  58. package/dist/auth/plugins/wrappers/api-key.js +2 -3
  59. package/dist/auth/plugins/wrappers/jwt.js +2 -3
  60. package/dist/auth/plugins/wrappers/organization.js +2 -3
  61. package/dist/auth/plugins/wrappers/passkey.js +2 -3
  62. package/dist/auth/plugins/wrappers/phone-number.d.ts +43 -1
  63. package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
  64. package/dist/auth/plugins/wrappers/phone-number.js +2 -3
  65. package/dist/auth/plugins/wrappers/sso.d.ts +138 -187
  66. package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -1
  67. package/dist/auth/plugins/wrappers/sso.js +1 -2
  68. package/dist/auth/plugins/wrappers/two-factor.d.ts +51 -10
  69. package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
  70. package/dist/auth/plugins/wrappers/two-factor.js +2 -3
  71. package/dist/auth/plugins/wrappers/username.d.ts +39 -5
  72. package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
  73. package/dist/auth/plugins/wrappers/username.js +2 -3
  74. package/dist/bin/build-config.js +5 -5
  75. package/dist/bin/compiler-policy.js +2 -3
  76. package/dist/bin/fixture.js +7 -5
  77. package/dist/bin/hmr-hook-register.js +1 -2
  78. package/dist/bin/migrate-targets.js +2 -3
  79. package/dist/bin/test-command.js +2 -3
  80. package/dist/bin/ts-loader-register.js +2 -3
  81. package/dist/bin/ts-loader-registration.js +2 -3
  82. package/dist/bin/typecheck-web.js +2 -3
  83. package/dist/cache/cache-manager.js +1 -2
  84. package/dist/cache/decorator.js +2 -3
  85. package/dist/cache/drivers.js +1 -2
  86. package/dist/cache/index.js +2 -3
  87. package/dist/cache-control/cache-control.js +1 -2
  88. package/dist/code-formatting/index.js +2 -3
  89. package/dist/code-formatting/oxfmt.js +2 -3
  90. package/dist/code-formatting/oxlint.js +2 -3
  91. package/dist/compress/compress.js +1 -2
  92. package/dist/compress/index.js +2 -2
  93. package/dist/compress/types.d.ts +1 -1
  94. package/dist/compress/types.d.ts.map +1 -1
  95. package/dist/cone/cone-generator.js +2 -3
  96. package/dist/database/_batch_update.js +1 -2
  97. package/dist/database/base-model.js +4 -4
  98. package/dist/database/db.js +4 -4
  99. package/dist/database/knex.js +2 -3
  100. package/dist/database/puri-wrapper.js +2 -3
  101. package/dist/database/puri.js +23 -22
  102. package/dist/database/puri.types.js +1 -2
  103. package/dist/database/transaction-context.js +1 -2
  104. package/dist/database/upsert-builder.js +2 -3
  105. package/dist/dict/en.js +2 -3
  106. package/dist/dict/index.js +3 -3
  107. package/dist/dict/ko.js +2 -3
  108. package/dist/dict/rc-keys.js +1 -2
  109. package/dist/dict/sd.js +2 -3
  110. package/dist/dict/sonamu-dictionary.js +7 -6
  111. package/dist/dict/utils.js +2 -3
  112. package/dist/entity/entity-manager.d.ts +66 -66
  113. package/dist/entity/entity-manager.js +4 -4
  114. package/dist/entity/entity-template-cone.js +2 -3
  115. package/dist/entity/entity.js +21 -18
  116. package/dist/env.js +1 -2
  117. package/dist/exceptions/error-handler.d.ts.map +1 -1
  118. package/dist/exceptions/error-handler.js +2 -3
  119. package/dist/exceptions/so-exceptions.js +2 -3
  120. package/dist/filter/index.js +3 -2
  121. package/dist/filter/types.js +1 -2
  122. package/dist/filter/utils.js +7 -6
  123. package/dist/index.js +39 -5
  124. package/dist/logger/category.js +2 -3
  125. package/dist/logger/configure.js +5 -5
  126. package/dist/migration/code-generation.js +23 -16
  127. package/dist/migration/index-where-predicate.js +2 -3
  128. package/dist/migration/migration-set.js +2 -3
  129. package/dist/migration/migrator.js +2 -3
  130. package/dist/migration/postgresql-schema-reader.js +6 -9
  131. package/dist/migration/slack-confirm.js +2 -3
  132. package/dist/naite/naite-reporter.js +2 -3
  133. package/dist/naite/naite.js +10 -8
  134. package/dist/runtime-type.js +2 -3
  135. package/dist/ssr/hmr-opt-out.js +1 -2
  136. package/dist/ssr/index.js +7 -4
  137. package/dist/ssr/registry.js +1 -2
  138. package/dist/ssr/renderer.js +2 -3
  139. package/dist/storage/base-file.js +1 -2
  140. package/dist/storage/buffered-file.js +2 -3
  141. package/dist/storage/drivers.js +1 -2
  142. package/dist/storage/index.js +2 -3
  143. package/dist/storage/s3-driver.js +1 -2
  144. package/dist/storage/storage-manager.js +2 -3
  145. package/dist/storage/uploaded-file.js +2 -3
  146. package/dist/stream/__tests__/ws-test-helpers.js +2 -3
  147. package/dist/stream/index.js +11 -2
  148. package/dist/stream/sse.js +1 -2
  149. package/dist/stream/ws-audience-resolver.js +2 -3
  150. package/dist/stream/ws-audience.js +1 -2
  151. package/dist/stream/ws-cluster-bus.js +1 -2
  152. package/dist/stream/ws-delivery.js +2 -3
  153. package/dist/stream/ws-frame.js +1 -2
  154. package/dist/stream/ws-local-connection-store.js +2 -3
  155. package/dist/stream/ws-presence-index.js +1 -2
  156. package/dist/stream/ws-presence-store.js +2 -3
  157. package/dist/stream/ws-registry.js +2 -3
  158. package/dist/stream/ws-session-id.js +1 -2
  159. package/dist/stream/ws-telemetry-memory.js +3 -4
  160. package/dist/stream/ws-telemetry-trace.js +1 -2
  161. package/dist/stream/ws-telemetry.js +2 -3
  162. package/dist/stream/ws.js +2 -3
  163. package/dist/syncer/api-parser.js +2 -3
  164. package/dist/syncer/checksum.js +4 -4
  165. package/dist/syncer/code-generator.js +4 -4
  166. package/dist/syncer/entity-operations.js +2 -3
  167. package/dist/syncer/event-batcher.js +1 -2
  168. package/dist/syncer/file-copy.js +2 -3
  169. package/dist/syncer/file-patterns.js +2 -3
  170. package/dist/syncer/file-tracking.js +2 -3
  171. package/dist/syncer/filesystem-dependencies.js +1 -2
  172. package/dist/syncer/index.js +8 -2
  173. package/dist/syncer/module-loader.js +8 -6
  174. package/dist/syncer/syncer-actions.js +8 -7
  175. package/dist/syncer/syncer.js +13 -8
  176. package/dist/syncer/watcher.js +2 -3
  177. package/dist/tasks/decorator.js +1 -2
  178. package/dist/tasks/step-wrapper.js +2 -3
  179. package/dist/tasks/workflow-manager.js +2 -3
  180. package/dist/template/entity-converter.js +17 -16
  181. package/dist/template/helpers.js +2 -3
  182. package/dist/template/implementations/entity.template.js +2 -3
  183. package/dist/template/implementations/entry-server.template.js +2 -3
  184. package/dist/template/implementations/generated.template.js +2 -3
  185. package/dist/template/implementations/generated_http.template.js +6 -6
  186. package/dist/template/implementations/generated_sso.template.js +2 -3
  187. package/dist/template/implementations/http_validators.template.js +2 -3
  188. package/dist/template/implementations/init_types.template.js +2 -3
  189. package/dist/template/implementations/model.template.js +4 -4
  190. package/dist/template/implementations/model_test.template.js +2 -3
  191. package/dist/template/implementations/queries.template.js +2 -3
  192. package/dist/template/implementations/sd.template.js +2 -3
  193. package/dist/template/implementations/services.template.js +2 -3
  194. package/dist/template/implementations/view_form.template.js +12 -9
  195. package/dist/template/implementations/view_id_all_select.template.js +2 -3
  196. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  197. package/dist/template/implementations/view_list.template.js +19 -17
  198. package/dist/template/implementations/view_search_input.template.js +2 -3
  199. package/dist/template/index.js +9 -3
  200. package/dist/template/template-manager.js +2 -3
  201. package/dist/template/template-types.js +1 -2
  202. package/dist/template/template.js +2 -3
  203. package/dist/template/zod-converter.js +54 -47
  204. package/dist/testing/_relation-graph.js +2 -3
  205. package/dist/testing/bootstrap.js +2 -3
  206. package/dist/testing/data-explorer.js +2 -3
  207. package/dist/testing/dev-test-routes.js +2 -3
  208. package/dist/testing/dev-vitest-manager.js +15 -12
  209. package/dist/testing/faker-mappings.js +1 -2
  210. package/dist/testing/filesystem.js +2 -3
  211. package/dist/testing/fixture-generator.js +2 -3
  212. package/dist/testing/fixture-loader.js +1 -2
  213. package/dist/testing/fixture-manager.js +12 -9
  214. package/dist/testing/global-setup.js +5 -5
  215. package/dist/testing/index.js +6 -3
  216. package/dist/testing/naite-vitest-reporter.js +1 -2
  217. package/dist/testing/parallel-db-manager.js +2 -3
  218. package/dist/testing/vitest-helpers.js +2 -3
  219. package/dist/tooling/__tests__/helpers/sonamu-test-root.js +2 -3
  220. package/dist/tooling/cdd-service.js +1 -2
  221. package/dist/tooling/cli-tooling.js +1 -2
  222. package/dist/tooling/fixture-service.js +1 -2
  223. package/dist/tooling/index.js +1 -2
  224. package/dist/tooling/test-run-client.js +2 -3
  225. package/dist/tsdown.api.config.js +1 -2
  226. package/dist/types/types.js +2 -3
  227. package/dist/ui/ai-api.d.ts.map +1 -1
  228. package/dist/ui/ai-api.js +4 -5
  229. package/dist/ui/ai-client.d.ts +2 -2
  230. package/dist/ui/ai-client.d.ts.map +1 -1
  231. package/dist/ui/ai-client.js +9 -8
  232. package/dist/ui/api.d.ts.map +1 -1
  233. package/dist/ui/api.js +11 -8
  234. package/dist/ui/async-route.js +1 -2
  235. package/dist/ui/cdd-service.js +22 -21
  236. package/dist/ui/migrations-api.js +6 -5
  237. package/dist/ui-web/assets/index-QDMyy31K.js +180 -0
  238. package/dist/ui-web/assets/index-dV7akMFB.css +1 -0
  239. package/dist/ui-web/index.html +2 -2
  240. package/dist/utils/async-utils.js +1 -2
  241. package/dist/utils/class-name.js +1 -2
  242. package/dist/utils/console-util.js +1 -2
  243. package/dist/utils/controller.js +2 -3
  244. package/dist/utils/esm-utils.js +1 -2
  245. package/dist/utils/fs-utils.js +2 -3
  246. package/dist/utils/lodash-able.js +1 -2
  247. package/dist/utils/model.js +1 -2
  248. package/dist/utils/object-utils.js +2 -3
  249. package/dist/utils/path-utils.js +2 -3
  250. package/dist/utils/process-utils.js +2 -3
  251. package/dist/utils/runtime-value.js +1 -2
  252. package/dist/utils/sql-parser.js +2 -3
  253. package/dist/utils/type-utils.js +8 -8
  254. package/dist/utils/utils.js +2 -3
  255. package/dist/utils/zod-error.js +2 -3
  256. package/dist/vector/chunking.js +1 -2
  257. package/dist/vector/config.js +1 -2
  258. package/dist/vector/embedding.js +4 -4
  259. package/package.json +63 -63
  260. package/src/ai/agents/agent.ts +1 -1
  261. package/src/api/__tests__/sonamu.plugins.test.ts +11 -1
  262. package/src/api/__tests__/sonamu.websocket.test.ts +6 -10
  263. package/src/api/config.ts +1 -1
  264. package/src/api/context.ts +2 -8
  265. package/src/api/sonamu.ts +26 -21
  266. package/src/auth/audit-log/plugin.ts +2 -0
  267. package/src/compress/types.ts +1 -1
  268. package/src/exceptions/error-handler.ts +3 -2
  269. package/src/template/implementations/model.template.ts +3 -3
  270. package/src/template/implementations/view_list.template.ts +12 -13
  271. package/src/ui/ai-api.ts +4 -2
  272. package/src/ui/ai-client.ts +2 -2
  273. package/src/ui/api.ts +58 -62
  274. package/dist/ui-web/assets/index-BMdIyKXS.css +0 -1
  275. package/dist/ui-web/assets/index-LpE8u19O.js +0 -178
@@ -111,10 +111,7 @@ describe("Sonamu websocket context scoping", () => {
111
111
  Reflect.set(Sonamu, "syncerValue", { types: {} });
112
112
 
113
113
  await Sonamu.createWebSocketHandlerForTesting(api, config)(
114
- {
115
- socket:
116
- /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ {} as WebSocket,
117
- },
114
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ {} as WebSocket,
118
115
  request,
119
116
  );
120
117
 
@@ -369,12 +366,11 @@ describe("Sonamu websocket context scoping", () => {
369
366
  Reflect.set(Sonamu, "syncerValue", { types: {} });
370
367
 
371
368
  let handlerDone = false;
372
- const handling = Sonamu.createWebSocketHandlerForTesting(api, config)(
373
- { socket },
374
- request,
375
- ).then(() => {
376
- handlerDone = true;
377
- });
369
+ const handling = Sonamu.createWebSocketHandlerForTesting(api, config)(socket, request).then(
370
+ () => {
371
+ handlerDone = true;
372
+ },
373
+ );
378
374
  await new Promise<void>((resolve) => setImmediate(resolve));
379
375
 
380
376
  // 등록이 끝나기 전에는 context를 만들지 않는다
package/src/api/config.ts CHANGED
@@ -201,7 +201,7 @@ export type SonamuServerOptions = {
201
201
  // 프로젝트 외부에서 접근할 수 있는 URL. 기본값은 {server.listen.host}:{server.listen.port} 입니다.
202
202
  baseUrl?: string;
203
203
 
204
- fastify?: Omit<FastifyServerOptions, "logger">;
204
+ fastify?: Omit<FastifyServerOptions, "logger" | "loggerInstance">;
205
205
 
206
206
  listen?: {
207
207
  port: number;
@@ -1,13 +1,7 @@
1
- import {
2
- type IncomingHttpHeaders,
3
- type IncomingMessage,
4
- type Server,
5
- type ServerResponse,
6
- } from "http";
1
+ import { type IncomingHttpHeaders } from "http";
7
2
 
8
3
  import { type Session, type User } from "better-auth";
9
4
  import { type FastifyReply, type FastifyRequest } from "fastify";
10
- import { type RouteGenericInterface } from "fastify/types/route";
11
5
  import { type ZodObject } from "zod";
12
6
 
13
7
  import { type NaiteStore } from "../naite/naite";
@@ -32,7 +26,7 @@ type BaseContext = {
32
26
 
33
27
  export type Context = BaseContext & {
34
28
  transport: "http";
35
- reply: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface>;
29
+ reply: FastifyReply;
36
30
  createSSE: <T extends ZodObject>(events: T) => ReturnType<typeof createSSEFactory<T>>;
37
31
  /** buffer 모드에서 업로드된 파일 */
38
32
  bufferedFiles?: BufferedFile[];
package/src/api/sonamu.ts CHANGED
@@ -9,7 +9,12 @@ import { dispose as logtapeDispose } from "@logtape/logtape";
9
9
  import { type Auth, type BetterAuthOptions } from "better-auth";
10
10
  import chalk from "chalk";
11
11
  import { type FSWatcher } from "chokidar";
12
- import { type FastifyInstance, type FastifyReply, type FastifyRequest } from "fastify";
12
+ import {
13
+ type FastifyBaseLogger,
14
+ type FastifyInstance,
15
+ type FastifyReply,
16
+ type FastifyRequest,
17
+ } from "fastify";
13
18
  import mime, { lookup as mimeLookup } from "mime-types";
14
19
  import { type WebSocket } from "ws";
15
20
  import { type ZodObject } from "zod";
@@ -470,14 +475,17 @@ class SonamuClass {
470
475
  const options = this.config.server;
471
476
  const { default: fastify } = await import("fastify");
472
477
  const { getLogTapeFastifyLogger } = await import("@logtape/fastify");
478
+ // Fastify 5는 logger 옵션에 설정 객체만 받고, 로거 인스턴스는 loggerInstance로 넘겨야 한다
479
+ // SAFETY: LogTape 어댑터는 pino 호환 메서드 집합(trace~fatal, silent, child)을 제공하며 Fastify 4에서도 같은 객체를 logger로 넘겨 동작했다.
480
+ const loggerInstance: FastifyBaseLogger | undefined =
481
+ this.config.logging !== false
482
+ ? (getLogTapeFastifyLogger({
483
+ category: this.config.logging?.fastifyCategory ?? ["fastify"],
484
+ }) as FastifyBaseLogger)
485
+ : undefined;
473
486
  const server = fastify({
474
487
  ...options.fastify,
475
- logger:
476
- this.config.logging !== false
477
- ? getLogTapeFastifyLogger({
478
- category: this.config.logging?.fastifyCategory ?? ["fastify"],
479
- })
480
- : undefined,
488
+ loggerInstance,
481
489
  });
482
490
  this.server = server;
483
491
  this.websocketRuntime = new WebSocketRuntime(options.websocket);
@@ -714,13 +722,14 @@ class SonamuClass {
714
722
  // 등록된 API와 일치하지 않는 요청에 대한 fallback입니다.
715
723
  throw new NotFoundException(SD("error.api.notFound"));
716
724
  },
717
- wsHandler: async (connection, request) => {
718
- await this.handleDevWebSocketRequest(connection.socket, request, config);
725
+ wsHandler: async (socket, request) => {
726
+ await this.handleDevWebSocketRequest(socket, request, config);
719
727
  },
720
728
  });
721
729
 
730
+ // HEAD는 위 GET catch-all이 exposeHeadRoutes로 자동 노출하므로 중복 선언하면 Fastify 5가 FST_ERR_DUPLICATED_ROUTE를 던진다
722
731
  server.route({
723
- method: ["HEAD", "POST", "PUT", "DELETE", "PATCH"],
732
+ method: ["POST", "PUT", "DELETE", "PATCH"],
724
733
  url: `${this.config.api.route.prefix}/*`,
725
734
  handler: async (request, reply) => {
726
735
  const handler = await this.handleDevApiRequest(request, config);
@@ -784,13 +793,14 @@ class SonamuClass {
784
793
  }
785
794
  throw new NotFoundException(SD("error.api.notFound"));
786
795
  },
787
- wsHandler: async (connection, request) => {
788
- await this.handleDevWebSocketRequest(connection.socket, request, config);
796
+ wsHandler: async (socket, request) => {
797
+ await this.handleDevWebSocketRequest(socket, request, config);
789
798
  },
790
799
  });
791
800
 
801
+ // HEAD는 위 GET catch-all이 exposeHeadRoutes로 자동 노출하므로 중복 선언하면 Fastify 5가 FST_ERR_DUPLICATED_ROUTE를 던진다
792
802
  server.route({
793
- method: ["HEAD", "POST", "PUT", "DELETE", "PATCH"],
803
+ method: ["POST", "PUT", "DELETE", "PATCH"],
794
804
  url: `${this.config.api.route.prefix}/*`,
795
805
  handler: async (request, reply) => {
796
806
  const result = await this.handleDevApiRequest(request, config);
@@ -1380,7 +1390,7 @@ class SonamuClass {
1380
1390
  }
1381
1391
 
1382
1392
  const handler = this.createWebSocketHandler(matchedApi, config);
1383
- await handler({ socket }, request);
1393
+ await handler(socket, request);
1384
1394
  }
1385
1395
 
1386
1396
  // WS route 핸들러의 실행 순서를 고정함:
@@ -1393,13 +1403,8 @@ class SonamuClass {
1393
1403
  }
1394
1404
 
1395
1405
  private createWebSocketHandler(api: ExtendedApi, config: SonamuFastifyConfig) {
1396
- return async (
1397
- connection: {
1398
- socket: WebSocket;
1399
- },
1400
- request: FastifyRequest,
1401
- ): Promise<void> => {
1402
- const socket = connection.socket;
1406
+ // @fastify/websocket 11부터 wsHandler는 connection 래퍼 대신 ws.WebSocket을 직접 전달한다
1407
+ return async (socket: WebSocket, request: FastifyRequest): Promise<void> => {
1403
1408
  let wsContext: WebSocketContext<object, object> | null = null;
1404
1409
  let rawWs: Awaited<ReturnType<WebSocketRuntime["registerConnection"]>> | null = null;
1405
1410
  let preRegisterPhase: "guard" | "query" | "register" | "handler" = "guard";
@@ -85,6 +85,8 @@ const getOrganizationTriggerInfo = (user: { id?: string } | null | undefined): B
85
85
  type BetterAuthRequestCtx = GenericEndpointContext & {
86
86
  context: GenericEndpointContext["context"] & {
87
87
  location?: BuilderLocation | null;
88
+ // after hook에서 dispatch가 채우는 응답값. better-auth 1.6.2x부터 GenericEndpointContext 타입에서 빠졌지만 HookEndpointContext에는 남아 있다.
89
+ returned?: unknown;
88
90
  };
89
91
  };
90
92
 
@@ -14,7 +14,7 @@ export type CompressOptions = {
14
14
  /** 압축을 적용할 최소 바이트 크기 (기본값: 1024) */
15
15
  threshold?: number;
16
16
  /** 사용할 인코딩 우선순위 (기본값: ["br", "gzip", "deflate"]) */
17
- encodings?: ("br" | "gzip" | "deflate" | "identity")[];
17
+ encodings?: ("zstd" | "br" | "gzip" | "deflate" | "identity")[];
18
18
  /** 압축할 Content-Type 필터 */
19
19
  customTypes?: RegExp | ((contentType: string) => boolean);
20
20
  };
@@ -1,4 +1,4 @@
1
- import { type FastifyInstance } from "fastify";
1
+ import { type FastifyError, type FastifyInstance } from "fastify";
2
2
  import type z from "zod";
3
3
 
4
4
  import { isObjectValue, isStringValue } from "../utils/runtime-value";
@@ -19,7 +19,8 @@ function isZodIssuePayload<Value>(payload: Value): payload is Value & z.core.$Zo
19
19
  }
20
20
 
21
21
  export function setupErrorHandler(server: FastifyInstance) {
22
- server.setErrorHandler((error, request, reply) => {
22
+ // Fastify 5는 error 타입 기본값이 unknown이므로 기존 FastifyError 계약을 명시한다
23
+ server.setErrorHandler<FastifyError>((error, request, reply) => {
23
24
  error.statusCode ??= 400;
24
25
 
25
26
  if (isSoException(error) && isZodIssuePayload(error.payload)) {
@@ -33,9 +33,9 @@ export class Template__model extends Template {
33
33
  const listParamsNode = zodTypeToRenderingNode(listParamsZodType);
34
34
 
35
35
  const subsetKeyZodType = await getZodTypeById(`${entityId}SubsetKey`);
36
- const subsetKeys =
37
- /* SAFETY: 생성된 *SubsetKey 타입은 enum 스키마로 등록된다. */ (subsetKeyZodType as z.ZodEnum)
38
- .enum;
36
+ const subsetKeys = /* SAFETY: 생성된 *SubsetKey 타입은 enum 스키마로 등록된다. */ (
37
+ subsetKeyZodType as z.ZodEnum
38
+ ).enum;
39
39
 
40
40
  const names = EntityManager.getNamesFromId(entityId);
41
41
  const entity = EntityManager.get(entityId);
@@ -305,20 +305,19 @@ export class Template__view_list extends Template {
305
305
  });
306
306
 
307
307
  // 필터 컬럼
308
- const filterColumns =
309
- /* SAFETY: ListParams 렌더링 노드의 자식은 모두 필터 컬럼 노드다. */ (
310
- listParamsNode.children as RenderingNode[]
308
+ const filterColumns = /* SAFETY: ListParams 렌더링 노드의 자식은 모두 필터 컬럼 노드다. */ (
309
+ listParamsNode.children as RenderingNode[]
310
+ )
311
+ .filter(
312
+ (col) =>
313
+ col.name !== "id" &&
314
+ col.name !== "queryMode" &&
315
+ ["enums", "number-id", "number-fk_id", "string-fk_id"].includes(col.renderType),
311
316
  )
312
- .filter(
313
- (col) =>
314
- col.name !== "id" &&
315
- col.name !== "queryMode" &&
316
- ["enums", "number-id", "number-fk_id", "string-fk_id"].includes(col.renderType),
317
- )
318
- // orderBy가 가장 뒤로 오게 순서 조정
319
- .toSorted((a) => {
320
- return a.name === "orderBy" ? 1 : -1;
321
- });
317
+ // orderBy가 가장 뒤로 오게 순서 조정
318
+ .toSorted((a) => {
319
+ return a.name === "orderBy" ? 1 : -1;
320
+ });
322
321
 
323
322
  // 필터 컬럼을 프리 템플릿으로 설정
324
323
  const preTemplates: RenderedTemplate["preTemplates"] = [];
package/src/ui/ai-api.ts CHANGED
@@ -24,7 +24,8 @@ export async function setAiApi(server: FastifyInstance) {
24
24
  const result = aiClient.handleFixture(await convertToModelMessages(messages), fixtureRecords);
25
25
  const response = result.toUIMessageStreamResponse();
26
26
 
27
- reply.raw.writeHead(response.status, Object.fromEntries(Object.entries(response.headers)));
27
+ // ai 7의 Response.headers는 Headers 인스턴스라 entries()로 풀어야 Node 응답 헤더로 전달된다
28
+ reply.raw.writeHead(response.status, Object.fromEntries(response.headers.entries()));
28
29
 
29
30
  if (response.body) {
30
31
  const reader = response.body.getReader();
@@ -49,7 +50,8 @@ export async function setAiApi(server: FastifyInstance) {
49
50
  const result = aiClient.handleEntity(await convertToModelMessages(messages));
50
51
  const response = result.toUIMessageStreamResponse();
51
52
 
52
- reply.raw.writeHead(response.status, Object.fromEntries(Object.entries(response.headers)));
53
+ // ai 7의 Response.headers는 Headers 인스턴스라 entries()로 풀어야 Node 응답 헤더로 전달된다
54
+ reply.raw.writeHead(response.status, Object.fromEntries(response.headers.entries()));
53
55
 
54
56
  if (response.body) {
55
57
  const reader = response.body.getReader();
@@ -52,7 +52,7 @@ class AIClient {
52
52
  handleFixture(
53
53
  messages: ModelMessage[],
54
54
  fixtureRecords: FixtureRecord[],
55
- ): StreamTextResult<any, any> {
55
+ ): StreamTextResult<any, any, any> {
56
56
  if (!this.aiSdk || !this.model) {
57
57
  throw new Error("AI SDK not initialized. Call init() first.");
58
58
  }
@@ -253,7 +253,7 @@ class AIClient {
253
253
  });
254
254
  }
255
255
 
256
- handleEntity(messages: ModelMessage[]): StreamTextResult<any, any> {
256
+ handleEntity(messages: ModelMessage[]): StreamTextResult<any, any, any> {
257
257
  if (!this.aiSdk || !this.model) {
258
258
  throw new Error("AI SDK not initialized. Call init() first.");
259
259
  }
package/src/ui/api.ts CHANGED
@@ -323,54 +323,52 @@ export async function sonamuUIApiPlugin(fastify: FastifyInstance) {
323
323
  filter?: "enums" | "types";
324
324
  reload?: "1";
325
325
  };
326
- }>(
327
- "/api/entity/typeIds",
328
- (request): Promise<{ typeIds: string[] }> =>
329
- forwardAsyncErrors(async () => {
330
- const { filter, reload } = request.query;
331
-
332
- if (reload === "1") {
333
- await Sonamu.syncer.autoloadTypes();
334
- }
326
+ }>("/api/entity/typeIds", (request): Promise<{ typeIds: string[] }> =>
327
+ forwardAsyncErrors(async () => {
328
+ const { filter, reload } = request.query;
335
329
 
336
- const typeIds = (() => {
337
- // 프로젝트에서 정의한 타입들
338
- const projectTypeIds = Object.entries(Sonamu.syncer.types)
339
- .filter(([_typeId, zodType]) => {
340
- const { _zod: zodMetadata } = zodType;
341
- return (
342
- /* SAFETY: UI 도구의 Zod 입력 스키마가 이 값의 타입을 보장한다. */ (zodMetadata
343
- .def.type as string) !== "enum"
344
- );
345
- })
346
- .map(([typeId, _zodType]) => typeId);
347
-
348
- // 내장 타입들 (sonamu 코어에서 제공)
349
- const builtInTypeIds = [...BUILT_IN_TYPE_IDS];
350
-
351
- // 모든 타입 병합
352
- const allTypeIds = [...builtInTypeIds, ...projectTypeIds];
353
-
354
- if (filter === "types") {
355
- return allTypeIds;
356
- }
330
+ if (reload === "1") {
331
+ await Sonamu.syncer.autoloadTypes();
332
+ }
357
333
 
358
- const enumIds = EntityManager.getAllIds().flatMap((entityId) => {
359
- const entity = EntityManager.get(entityId);
360
- return Object.keys(entity.enumLabels);
361
- });
334
+ const typeIds = (() => {
335
+ // 프로젝트에서 정의한 타입들
336
+ const projectTypeIds = Object.entries(Sonamu.syncer.types)
337
+ .filter(([_typeId, zodType]) => {
338
+ const { _zod: zodMetadata } = zodType;
339
+ return (
340
+ /* SAFETY: UI 도구의 Zod 입력 스키마가 이 값의 타입을 보장한다. */ (zodMetadata
341
+ .def.type as string) !== "enum"
342
+ );
343
+ })
344
+ .map(([typeId, _zodType]) => typeId);
362
345
 
363
- if (filter === "enums") {
364
- return enumIds;
365
- } else {
366
- return [...allTypeIds, ...enumIds];
367
- }
368
- })();
346
+ // 내장 타입들 (sonamu 코어에서 제공)
347
+ const builtInTypeIds = [...BUILT_IN_TYPE_IDS];
369
348
 
370
- return {
371
- typeIds,
372
- };
373
- }),
349
+ // 모든 타입 병합
350
+ const allTypeIds = [...builtInTypeIds, ...projectTypeIds];
351
+
352
+ if (filter === "types") {
353
+ return allTypeIds;
354
+ }
355
+
356
+ const enumIds = EntityManager.getAllIds().flatMap((entityId) => {
357
+ const entity = EntityManager.get(entityId);
358
+ return Object.keys(entity.enumLabels);
359
+ });
360
+
361
+ if (filter === "enums") {
362
+ return enumIds;
363
+ } else {
364
+ return [...allTypeIds, ...enumIds];
365
+ }
366
+ })();
367
+
368
+ return {
369
+ typeIds,
370
+ };
371
+ }),
374
372
  );
375
373
 
376
374
  server.post<{
@@ -902,25 +900,23 @@ export async function sonamuUIApiPlugin(fastify: FastifyInstance) {
902
900
  enumId?: string;
903
901
  };
904
902
  };
905
- }>(
906
- "/api/scaffolding/preview",
907
- (request): Promise<{ pathAndCodes: PathAndCode[] }> =>
908
- forwardAsyncErrors(async () => {
909
- const { option } = request.body;
910
-
911
- try {
912
- const { templateKey, ...templateOptions } = option;
913
- const pathAndCodes = await Sonamu.syncer.renderTemplate(
914
- /* SAFETY: UI 도구의 Zod 입력 스키마가 이 값의 타입을 보장한다. */ templateKey as TemplateKey,
915
- templateOptions,
916
- );
903
+ }>("/api/scaffolding/preview", (request): Promise<{ pathAndCodes: PathAndCode[] }> =>
904
+ forwardAsyncErrors(async () => {
905
+ const { option } = request.body;
917
906
 
918
- return { pathAndCodes };
919
- } catch (e) {
920
- console.error(e);
921
- throw e;
922
- }
923
- }),
907
+ try {
908
+ const { templateKey, ...templateOptions } = option;
909
+ const pathAndCodes = await Sonamu.syncer.renderTemplate(
910
+ /* SAFETY: UI 도구의 Zod 입력 스키마가 이 값의 타입을 보장한다. */ templateKey as TemplateKey,
911
+ templateOptions,
912
+ );
913
+
914
+ return { pathAndCodes };
915
+ } catch (e) {
916
+ console.error(e);
917
+ throw e;
918
+ }
919
+ }),
924
920
  );
925
921
 
926
922
  server.post("/api/fixture", (request) =>