sonamu 0.10.11 → 0.10.13

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 (519) hide show
  1. package/dist/ai/agents/agent.d.ts +1 -1
  2. package/dist/ai/agents/agent.d.ts.map +1 -1
  3. package/dist/ai/agents/agent.js +5 -6
  4. package/dist/ai/agents/types.d.ts +1 -1
  5. package/dist/ai/agents/types.d.ts.map +1 -1
  6. package/dist/ai/providers/rtzr/api.js +18 -18
  7. package/dist/ai/providers/rtzr/error.d.ts.map +1 -1
  8. package/dist/ai/providers/rtzr/error.js +17 -15
  9. package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
  10. package/dist/ai/providers/rtzr/model.js +3 -2
  11. package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
  12. package/dist/ai/providers/rtzr/options.js +16 -16
  13. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
  14. package/dist/ai/providers/rtzr/provider.js +9 -9
  15. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
  16. package/dist/ai/providers/rtzr/utils.js +1 -1
  17. package/dist/api/caster.d.ts.map +1 -1
  18. package/dist/api/caster.js +17 -17
  19. package/dist/api/code-converters.d.ts +4 -2
  20. package/dist/api/code-converters.d.ts.map +1 -1
  21. package/dist/api/code-converters.js +100 -19
  22. package/dist/api/config.d.ts +16 -1
  23. package/dist/api/config.d.ts.map +1 -1
  24. package/dist/api/config.js +28 -21
  25. package/dist/api/context.d.ts +2 -2
  26. package/dist/api/context.d.ts.map +1 -1
  27. package/dist/api/context.js +1 -1
  28. package/dist/api/decorators.d.ts.map +1 -1
  29. package/dist/api/decorators.js +18 -11
  30. package/dist/api/http-validator.d.ts +36 -0
  31. package/dist/api/http-validator.d.ts.map +1 -0
  32. package/dist/api/http-validator.js +72 -0
  33. package/dist/api/index.js +6 -4
  34. package/dist/api/sonamu.d.ts +59 -20
  35. package/dist/api/sonamu.d.ts.map +1 -1
  36. package/dist/api/sonamu.js +250 -106
  37. package/dist/api/websocket-helpers.d.ts +7 -5
  38. package/dist/api/websocket-helpers.d.ts.map +1 -1
  39. package/dist/api/websocket-helpers.js +6 -6
  40. package/dist/auth/audit-log/builders.d.ts.map +1 -1
  41. package/dist/auth/audit-log/builders.js +1 -1
  42. package/dist/auth/audit-log/client-ip.d.ts +1 -1
  43. package/dist/auth/audit-log/client-ip.d.ts.map +1 -1
  44. package/dist/auth/audit-log/client-ip.js +4 -2
  45. package/dist/auth/audit-log/events.d.ts +5 -1
  46. package/dist/auth/audit-log/events.d.ts.map +1 -1
  47. package/dist/auth/audit-log/events.js +1 -1
  48. package/dist/auth/audit-log/plugin.d.ts +0 -8
  49. package/dist/auth/audit-log/plugin.d.ts.map +1 -1
  50. package/dist/auth/audit-log/plugin.js +48 -52
  51. package/dist/auth/audit-log-ingestor.d.ts.map +1 -1
  52. package/dist/auth/audit-log-ingestor.js +16 -12
  53. package/dist/auth/auth-generator.d.ts.map +1 -1
  54. package/dist/auth/auth-generator.js +1 -1
  55. package/dist/auth/better-auth-request.d.ts.map +1 -1
  56. package/dist/auth/better-auth-request.js +6 -5
  57. package/dist/auth/knex-adapter.js +1 -1
  58. package/dist/auth/plugins/entity-definitions/index.d.ts +13 -1
  59. package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
  60. package/dist/auth/plugins/entity-definitions/index.js +1 -1
  61. package/dist/auth/plugins/wrappers/admin.d.ts +1 -1
  62. package/dist/bin/build-config.d.ts +25 -0
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +105 -2
  65. package/dist/bin/cli.js +133 -29
  66. package/dist/bin/compiler-policy.d.ts +3 -0
  67. package/dist/bin/compiler-policy.d.ts.map +1 -0
  68. package/dist/bin/compiler-policy.js +24 -0
  69. package/dist/bin/fixture.d.ts.map +1 -1
  70. package/dist/bin/fixture.js +5 -3
  71. package/dist/bin/test-command.d.ts +22 -1
  72. package/dist/bin/test-command.d.ts.map +1 -1
  73. package/dist/bin/test-command.js +18 -10
  74. package/dist/bin/ts-loader-registration.d.ts +7 -1
  75. package/dist/bin/ts-loader-registration.d.ts.map +1 -1
  76. package/dist/bin/ts-loader-registration.js +13 -4
  77. package/dist/cache/decorator.d.ts.map +1 -1
  78. package/dist/cache/decorator.js +11 -4
  79. package/dist/compress/compress.d.ts.map +1 -1
  80. package/dist/compress/compress.js +1 -1
  81. package/dist/cone/cone-generator.d.ts +14 -1
  82. package/dist/cone/cone-generator.d.ts.map +1 -1
  83. package/dist/cone/cone-generator.js +13 -9
  84. package/dist/database/_batch_update.js +1 -1
  85. package/dist/database/base-model.d.ts +22 -10
  86. package/dist/database/base-model.d.ts.map +1 -1
  87. package/dist/database/base-model.js +26 -16
  88. package/dist/database/base-model.types.d.ts +15 -3
  89. package/dist/database/base-model.types.d.ts.map +1 -1
  90. package/dist/database/db.d.ts +12 -2
  91. package/dist/database/db.d.ts.map +1 -1
  92. package/dist/database/db.js +10 -7
  93. package/dist/database/knex.d.ts.map +1 -1
  94. package/dist/database/knex.js +17 -14
  95. package/dist/database/puri.d.ts +11 -9
  96. package/dist/database/puri.d.ts.map +1 -1
  97. package/dist/database/puri.js +93 -79
  98. package/dist/database/puri.types.d.ts +21 -21
  99. package/dist/database/puri.types.d.ts.map +1 -1
  100. package/dist/database/puri.types.js +1 -1
  101. package/dist/database/upsert-builder.d.ts +12 -10
  102. package/dist/database/upsert-builder.d.ts.map +1 -1
  103. package/dist/database/upsert-builder.js +20 -12
  104. package/dist/dict/sd.d.ts.map +1 -1
  105. package/dist/dict/sd.js +1 -1
  106. package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
  107. package/dist/dict/sonamu-dictionary.js +1 -1
  108. package/dist/dict/utils.d.ts.map +1 -1
  109. package/dist/dict/utils.js +7 -2
  110. package/dist/entity/entity-manager.d.ts +13 -4
  111. package/dist/entity/entity-manager.d.ts.map +1 -1
  112. package/dist/entity/entity-manager.js +19 -11
  113. package/dist/entity/entity-template-cone.d.ts +73 -5
  114. package/dist/entity/entity-template-cone.d.ts.map +1 -1
  115. package/dist/entity/entity-template-cone.js +4 -2
  116. package/dist/entity/entity.d.ts +6 -2
  117. package/dist/entity/entity.d.ts.map +1 -1
  118. package/dist/entity/entity.js +30 -28
  119. package/dist/env.d.ts +3 -1
  120. package/dist/env.d.ts.map +1 -1
  121. package/dist/env.js +1 -1
  122. package/dist/exceptions/error-handler.d.ts.map +1 -1
  123. package/dist/exceptions/error-handler.js +7 -2
  124. package/dist/exceptions/so-exceptions.d.ts +24 -20
  125. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  126. package/dist/exceptions/so-exceptions.js +4 -2
  127. package/dist/filter/utils.d.ts +7 -2
  128. package/dist/filter/utils.d.ts.map +1 -1
  129. package/dist/filter/utils.js +8 -6
  130. package/dist/index.d.ts +3 -0
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +13 -7
  133. package/dist/logger/configure.d.ts.map +1 -1
  134. package/dist/logger/configure.js +10 -10
  135. package/dist/migration/code-generation.d.ts.map +1 -1
  136. package/dist/migration/code-generation.js +50 -46
  137. package/dist/migration/index-where-predicate.d.ts.map +1 -1
  138. package/dist/migration/index-where-predicate.js +22 -8
  139. package/dist/migration/migration-set.d.ts.map +1 -1
  140. package/dist/migration/migration-set.js +1 -1
  141. package/dist/migration/migrator.d.ts +61 -36
  142. package/dist/migration/migrator.d.ts.map +1 -1
  143. package/dist/migration/migrator.js +276 -167
  144. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  145. package/dist/migration/postgresql-schema-reader.js +51 -36
  146. package/dist/migration/slack-confirm.d.ts.map +1 -1
  147. package/dist/migration/slack-confirm.js +1 -1
  148. package/dist/migration/types.d.ts +54 -0
  149. package/dist/migration/types.d.ts.map +1 -1
  150. package/dist/naite/naite-reporter.js +2 -2
  151. package/dist/naite/naite.d.ts +74 -15
  152. package/dist/naite/naite.d.ts.map +1 -1
  153. package/dist/naite/naite.js +5 -19
  154. package/dist/runtime-type.d.ts +6 -0
  155. package/dist/runtime-type.d.ts.map +1 -0
  156. package/dist/runtime-type.js +26 -0
  157. package/dist/ssr/hmr-opt-out.d.ts +26 -0
  158. package/dist/ssr/hmr-opt-out.d.ts.map +1 -0
  159. package/dist/ssr/hmr-opt-out.js +59 -0
  160. package/dist/ssr/renderer.d.ts.map +1 -1
  161. package/dist/ssr/renderer.js +4 -1
  162. package/dist/storage/base-file.js +14 -14
  163. package/dist/storage/buffered-file.d.ts +2 -2
  164. package/dist/storage/buffered-file.d.ts.map +1 -1
  165. package/dist/storage/buffered-file.js +12 -12
  166. package/dist/storage/s3-driver.d.ts.map +1 -1
  167. package/dist/storage/s3-driver.js +1 -1
  168. package/dist/storage/uploaded-file.d.ts +2 -2
  169. package/dist/storage/uploaded-file.d.ts.map +1 -1
  170. package/dist/storage/uploaded-file.js +8 -8
  171. package/dist/stream/sse.js +11 -11
  172. package/dist/stream/ws-core.d.ts +1 -1
  173. package/dist/stream/ws-core.d.ts.map +1 -1
  174. package/dist/stream/ws-delivery.d.ts +1 -1
  175. package/dist/stream/ws-delivery.d.ts.map +1 -1
  176. package/dist/stream/ws-delivery.js +6 -4
  177. package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
  178. package/dist/stream/ws-local-connection-store.js +4 -2
  179. package/dist/stream/ws-presence-store.js +1 -1
  180. package/dist/stream/ws-registry.d.ts +4 -4
  181. package/dist/stream/ws-registry.d.ts.map +1 -1
  182. package/dist/stream/ws-registry.js +4 -2
  183. package/dist/stream/ws-telemetry.d.ts +16 -12
  184. package/dist/stream/ws-telemetry.d.ts.map +1 -1
  185. package/dist/stream/ws-telemetry.js +22 -18
  186. package/dist/stream/ws.d.ts +18 -12
  187. package/dist/stream/ws.d.ts.map +1 -1
  188. package/dist/stream/ws.js +26 -22
  189. package/dist/syncer/api-parser.js +1 -1
  190. package/dist/syncer/checksum.d.ts.map +1 -1
  191. package/dist/syncer/checksum.js +7 -8
  192. package/dist/syncer/code-generator.d.ts.map +1 -1
  193. package/dist/syncer/code-generator.js +13 -14
  194. package/dist/syncer/entity-operations.d.ts.map +1 -1
  195. package/dist/syncer/entity-operations.js +5 -6
  196. package/dist/syncer/file-copy.d.ts +5 -0
  197. package/dist/syncer/file-copy.d.ts.map +1 -0
  198. package/dist/syncer/file-copy.js +36 -0
  199. package/dist/syncer/file-patterns.d.ts +1 -0
  200. package/dist/syncer/file-patterns.d.ts.map +1 -1
  201. package/dist/syncer/file-patterns.js +5 -2
  202. package/dist/syncer/file-tracking.d.ts.map +1 -1
  203. package/dist/syncer/file-tracking.js +5 -4
  204. package/dist/syncer/filesystem-dependencies.d.ts +15 -0
  205. package/dist/syncer/filesystem-dependencies.d.ts.map +1 -0
  206. package/dist/syncer/filesystem-dependencies.js +53 -0
  207. package/dist/syncer/module-loader.d.ts +1 -1
  208. package/dist/syncer/module-loader.d.ts.map +1 -1
  209. package/dist/syncer/module-loader.js +6 -4
  210. package/dist/syncer/syncer-actions.d.ts +4 -0
  211. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  212. package/dist/syncer/syncer-actions.js +34 -17
  213. package/dist/syncer/syncer.d.ts +17 -6
  214. package/dist/syncer/syncer.d.ts.map +1 -1
  215. package/dist/syncer/syncer.js +71 -29
  216. package/dist/syncer/watcher.d.ts.map +1 -1
  217. package/dist/syncer/watcher.js +3 -3
  218. package/dist/tasks/decorator.d.ts +6 -6
  219. package/dist/tasks/decorator.d.ts.map +1 -1
  220. package/dist/tasks/decorator.js +4 -4
  221. package/dist/tasks/step-wrapper.d.ts +6 -4
  222. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  223. package/dist/tasks/step-wrapper.js +5 -5
  224. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  225. package/dist/tasks/workflow-manager.js +13 -7
  226. package/dist/template/entity-converter.d.ts +1 -1
  227. package/dist/template/entity-converter.d.ts.map +1 -1
  228. package/dist/template/entity-converter.js +2 -2
  229. package/dist/template/helpers.d.ts +8 -6
  230. package/dist/template/helpers.d.ts.map +1 -1
  231. package/dist/template/helpers.js +1 -1
  232. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  233. package/dist/template/implementations/generated.template.js +4 -4
  234. package/dist/template/implementations/generated_http.template.d.ts +7 -4
  235. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  236. package/dist/template/implementations/generated_http.template.js +21 -21
  237. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  238. package/dist/template/implementations/generated_sso.template.js +6 -3
  239. package/dist/template/implementations/http_validators.template.d.ts +18 -0
  240. package/dist/template/implementations/http_validators.template.d.ts.map +1 -0
  241. package/dist/template/implementations/http_validators.template.js +127 -0
  242. package/dist/template/implementations/model.template.d.ts.map +1 -1
  243. package/dist/template/implementations/model.template.js +1 -1
  244. package/dist/template/implementations/queries.template.js +1 -1
  245. package/dist/template/implementations/sd.template.d.ts.map +1 -1
  246. package/dist/template/implementations/sd.template.js +79 -39
  247. package/dist/template/implementations/services.template.d.ts.map +1 -1
  248. package/dist/template/implementations/services.template.js +6 -4
  249. package/dist/template/implementations/view_form.template.d.ts +6 -1
  250. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  251. package/dist/template/implementations/view_form.template.js +23 -15
  252. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  253. package/dist/template/implementations/view_list.template.js +11 -6
  254. package/dist/template/template-manager.d.ts.map +1 -1
  255. package/dist/template/template-manager.js +9 -7
  256. package/dist/template/template-types.d.ts +12 -5
  257. package/dist/template/template-types.d.ts.map +1 -1
  258. package/dist/template/template-types.js +1 -1
  259. package/dist/template/template.d.ts +2 -2
  260. package/dist/template/template.d.ts.map +1 -1
  261. package/dist/template/template.js +6 -4
  262. package/dist/template/zod-converter.d.ts +0 -19
  263. package/dist/template/zod-converter.d.ts.map +1 -1
  264. package/dist/template/zod-converter.js +100 -84
  265. package/dist/testing/_relation-graph.d.ts.map +1 -1
  266. package/dist/testing/_relation-graph.js +2 -1
  267. package/dist/testing/bootstrap.d.ts.map +1 -1
  268. package/dist/testing/bootstrap.js +9 -6
  269. package/dist/testing/data-explorer.d.ts +32 -7
  270. package/dist/testing/data-explorer.d.ts.map +1 -1
  271. package/dist/testing/data-explorer.js +77 -31
  272. package/dist/testing/dev-test-routes.d.ts +8 -1
  273. package/dist/testing/dev-test-routes.d.ts.map +1 -1
  274. package/dist/testing/dev-test-routes.js +125 -108
  275. package/dist/testing/dev-vitest-manager.d.ts +54 -8
  276. package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
  277. package/dist/testing/dev-vitest-manager.js +24 -9
  278. package/dist/testing/faker-mappings.d.ts +412 -1
  279. package/dist/testing/faker-mappings.d.ts.map +1 -1
  280. package/dist/testing/faker-mappings.js +1 -1
  281. package/dist/testing/filesystem.d.ts +2 -0
  282. package/dist/testing/filesystem.d.ts.map +1 -0
  283. package/dist/testing/filesystem.js +7 -0
  284. package/dist/testing/fixture-generator.d.ts +25 -8
  285. package/dist/testing/fixture-generator.d.ts.map +1 -1
  286. package/dist/testing/fixture-generator.js +132 -73
  287. package/dist/testing/fixture-loader.d.ts +3 -1
  288. package/dist/testing/fixture-loader.d.ts.map +1 -1
  289. package/dist/testing/fixture-loader.js +1 -20
  290. package/dist/testing/fixture-manager.d.ts +8 -7
  291. package/dist/testing/fixture-manager.d.ts.map +1 -1
  292. package/dist/testing/fixture-manager.js +91 -59
  293. package/dist/testing/global-setup.d.ts.map +1 -1
  294. package/dist/testing/global-setup.js +5 -2
  295. package/dist/testing/index.d.ts +2 -0
  296. package/dist/testing/index.d.ts.map +1 -1
  297. package/dist/testing/index.js +6 -3
  298. package/dist/types/types.d.ts +101 -99
  299. package/dist/types/types.d.ts.map +1 -1
  300. package/dist/types/types.js +234 -225
  301. package/dist/ui/ai-api.d.ts.map +1 -1
  302. package/dist/ui/ai-api.js +1 -1
  303. package/dist/ui/ai-client.d.ts.map +1 -1
  304. package/dist/ui/ai-client.js +28 -18
  305. package/dist/ui/api.d.ts.map +1 -1
  306. package/dist/ui/api.js +146 -210
  307. package/dist/ui/async-route.d.ts +3 -0
  308. package/dist/ui/async-route.d.ts.map +1 -0
  309. package/dist/ui/async-route.js +12 -0
  310. package/dist/ui/cdd-service.d.ts +9 -7
  311. package/dist/ui/cdd-service.d.ts.map +1 -1
  312. package/dist/ui/cdd-service.js +7 -5
  313. package/dist/ui/migrations-api.d.ts +3 -0
  314. package/dist/ui/migrations-api.d.ts.map +1 -0
  315. package/dist/ui/migrations-api.js +215 -0
  316. package/dist/ui-web/assets/index-D3QNH-Dv.css +1 -0
  317. package/dist/ui-web/assets/index-DV1AAq6W.js +178 -0
  318. package/dist/ui-web/index.html +2 -2
  319. package/dist/utils/formatter.d.ts.map +1 -1
  320. package/dist/utils/formatter.js +7 -5
  321. package/dist/utils/fs-utils.d.ts +3 -3
  322. package/dist/utils/fs-utils.d.ts.map +1 -1
  323. package/dist/utils/fs-utils.js +6 -6
  324. package/dist/utils/model.d.ts +3 -5
  325. package/dist/utils/model.d.ts.map +1 -1
  326. package/dist/utils/model.js +1 -1
  327. package/dist/utils/object-utils.d.ts +1 -1
  328. package/dist/utils/object-utils.d.ts.map +1 -1
  329. package/dist/utils/object-utils.js +17 -16
  330. package/dist/utils/process-utils.d.ts.map +1 -1
  331. package/dist/utils/process-utils.js +4 -2
  332. package/dist/utils/runtime-value.d.ts +13 -0
  333. package/dist/utils/runtime-value.d.ts.map +1 -0
  334. package/dist/utils/runtime-value.js +40 -0
  335. package/dist/utils/sql-parser.d.ts +8 -1
  336. package/dist/utils/sql-parser.d.ts.map +1 -1
  337. package/dist/utils/sql-parser.js +6 -3
  338. package/dist/utils/type-utils.d.ts.map +1 -1
  339. package/dist/utils/type-utils.js +10 -8
  340. package/dist/utils/utils.d.ts +2 -2
  341. package/dist/utils/utils.d.ts.map +1 -1
  342. package/dist/utils/utils.js +11 -8
  343. package/dist/utils/zod-error.d.ts.map +1 -1
  344. package/dist/utils/zod-error.js +7 -4
  345. package/dist/vector/chunking.d.ts.map +1 -1
  346. package/dist/vector/chunking.js +1 -1
  347. package/dist/vector/embedding.d.ts.map +1 -1
  348. package/dist/vector/embedding.js +1 -1
  349. package/dist/vector/types.d.ts +3 -2
  350. package/dist/vector/types.d.ts.map +1 -1
  351. package/package.json +11 -7
  352. package/src/ai/agents/agent.ts +5 -5
  353. package/src/ai/agents/types.ts +1 -1
  354. package/src/ai/providers/rtzr/__tests__/model.test.ts +2 -2
  355. package/src/ai/providers/rtzr/error.ts +5 -3
  356. package/src/ai/providers/rtzr/model.ts +3 -2
  357. package/src/ai/providers/rtzr/options.ts +10 -5
  358. package/src/ai/providers/rtzr/provider.ts +10 -10
  359. package/src/ai/providers/rtzr/utils.ts +3 -1
  360. package/src/api/__tests__/config.test.ts +11 -21
  361. package/src/api/__tests__/sonamu.http-validator.test.ts +512 -0
  362. package/src/api/__tests__/sonamu.websocket.test.ts +51 -41
  363. package/src/api/__tests__/zod-compiler-policy.test.ts +95 -0
  364. package/src/api/caster.ts +6 -8
  365. package/src/api/code-converters.ts +136 -36
  366. package/src/api/config.ts +62 -4
  367. package/src/api/context.ts +3 -3
  368. package/src/api/decorators.ts +28 -17
  369. package/src/api/http-validator.ts +149 -0
  370. package/src/api/sonamu.ts +459 -152
  371. package/src/api/websocket-helpers.ts +24 -17
  372. package/src/auth/audit-log/builders.ts +3 -2
  373. package/src/auth/audit-log/client-ip.ts +4 -2
  374. package/src/auth/audit-log/events.ts +15 -1
  375. package/src/auth/audit-log/plugin.ts +129 -200
  376. package/src/auth/audit-log-ingestor.ts +19 -15
  377. package/src/auth/auth-generator.ts +10 -5
  378. package/src/auth/better-auth-request.ts +4 -3
  379. package/src/auth/knex-adapter.ts +8 -2
  380. package/src/auth/plugins/entity-definitions/index.ts +6 -5
  381. package/src/bin/__tests__/http-validator-benchmark.test.ts +94 -0
  382. package/src/bin/__tests__/test-command.test.ts +9 -15
  383. package/src/bin/__tests__/ts-loader-register.test.ts +15 -17
  384. package/src/bin/__tests__/zod-compiler-build.test.ts +307 -0
  385. package/src/bin/build-config.ts +167 -0
  386. package/src/bin/cli.ts +155 -38
  387. package/src/bin/compiler-policy.ts +35 -0
  388. package/src/bin/fixture.ts +14 -3
  389. package/src/bin/test-command.ts +74 -29
  390. package/src/bin/ts-loader-registration.ts +22 -4
  391. package/src/cache/decorator.ts +10 -3
  392. package/src/compress/compress.ts +17 -4
  393. package/src/cone/cone-generator.ts +34 -6
  394. package/src/database/__tests__/db.test.ts +1 -0
  395. package/src/database/__tests__/puri.test.ts +16 -15
  396. package/src/database/__tests__/transaction-scope.test.ts +5 -0
  397. package/src/database/_batch_update.ts +1 -0
  398. package/src/database/base-model.ts +81 -50
  399. package/src/database/base-model.types.ts +6 -6
  400. package/src/database/db.ts +29 -19
  401. package/src/database/knex.ts +30 -17
  402. package/src/database/puri-subset.test-d.ts +17 -0
  403. package/src/database/puri.ts +181 -143
  404. package/src/database/puri.types.test-d.ts +31 -1
  405. package/src/database/puri.types.ts +23 -21
  406. package/src/database/upsert-builder.ts +75 -53
  407. package/src/dict/sd.ts +15 -5
  408. package/src/dict/sonamu-dictionary.ts +6 -6
  409. package/src/dict/utils.ts +9 -1
  410. package/src/entity/entity-manager.ts +26 -9
  411. package/src/entity/entity-template-cone.ts +5 -10
  412. package/src/entity/entity.ts +50 -34
  413. package/src/env.ts +7 -3
  414. package/src/exceptions/error-handler.ts +17 -2
  415. package/src/exceptions/so-exceptions.ts +26 -20
  416. package/src/filter/utils.ts +21 -11
  417. package/src/index.ts +3 -0
  418. package/src/logger/configure.ts +26 -18
  419. package/src/migration/__tests__/migrator.test.ts +50 -57
  420. package/src/migration/code-generation.ts +132 -104
  421. package/src/migration/index-where-predicate.ts +51 -24
  422. package/src/migration/migration-set.ts +11 -5
  423. package/src/migration/migrator.ts +392 -244
  424. package/src/migration/postgresql-schema-reader.ts +52 -47
  425. package/src/migration/slack-confirm.ts +17 -15
  426. package/src/migration/types.ts +57 -0
  427. package/src/naite/naite-reporter.ts +1 -1
  428. package/src/naite/naite.ts +97 -24
  429. package/src/runtime-type.ts +34 -0
  430. package/src/ssr/hmr-opt-out.ts +78 -0
  431. package/src/ssr/renderer.ts +6 -0
  432. package/src/storage/base-file.ts +13 -13
  433. package/src/storage/buffered-file.ts +11 -11
  434. package/src/storage/s3-driver.ts +4 -1
  435. package/src/storage/uploaded-file.ts +8 -8
  436. package/src/stream/__tests__/ws-contracts.test.ts +4 -2
  437. package/src/stream/__tests__/ws-telemetry.test.ts +1 -1
  438. package/src/stream/__tests__/ws.test.ts +30 -6
  439. package/src/stream/sse.ts +12 -11
  440. package/src/stream/ws-core.ts +1 -1
  441. package/src/stream/ws-delivery.ts +16 -7
  442. package/src/stream/ws-local-connection-store.ts +2 -3
  443. package/src/stream/ws-presence-store.ts +6 -1
  444. package/src/stream/ws-registry.ts +16 -7
  445. package/src/stream/ws-telemetry.ts +66 -43
  446. package/src/stream/ws.ts +73 -39
  447. package/src/syncer/__tests__/api-parser.websocket-type-ref.test.ts +3 -2
  448. package/src/syncer/__tests__/http-validator-registry.test.ts +137 -0
  449. package/src/syncer/api-parser.ts +67 -27
  450. package/src/syncer/checksum.ts +17 -11
  451. package/src/syncer/code-generator.ts +25 -17
  452. package/src/syncer/entity-operations.ts +3 -5
  453. package/src/syncer/file-copy.ts +46 -0
  454. package/src/syncer/file-patterns.ts +11 -8
  455. package/src/syncer/file-tracking.ts +3 -4
  456. package/src/syncer/filesystem-dependencies.ts +73 -0
  457. package/src/syncer/module-loader.ts +8 -4
  458. package/src/syncer/syncer-actions.ts +56 -18
  459. package/src/syncer/syncer.ts +116 -43
  460. package/src/syncer/watcher.ts +8 -4
  461. package/src/tasks/decorator.ts +20 -12
  462. package/src/tasks/step-wrapper.ts +19 -9
  463. package/src/tasks/workflow-manager.ts +15 -9
  464. package/src/template/__tests__/http_validators.template.test.ts +160 -0
  465. package/src/template/__tests__/services.template.mutation.test.ts +24 -23
  466. package/src/template/__tests__/services.template.websocket.test.ts +21 -25
  467. package/src/template/entity-converter.ts +5 -2
  468. package/src/template/helpers.ts +8 -9
  469. package/src/template/implementations/generated.template.ts +5 -4
  470. package/src/template/implementations/generated_http.template.ts +61 -15
  471. package/src/template/implementations/generated_sso.template.ts +15 -4
  472. package/src/template/implementations/http_validators.template.ts +175 -0
  473. package/src/template/implementations/model.template.ts +3 -1
  474. package/src/template/implementations/sd.template.ts +81 -41
  475. package/src/template/implementations/services.template.ts +2 -2
  476. package/src/template/implementations/view_form.template.ts +56 -39
  477. package/src/template/implementations/view_list.template.ts +31 -23
  478. package/src/template/template-manager.ts +15 -13
  479. package/src/template/template-types.ts +13 -5
  480. package/src/template/template.ts +4 -3
  481. package/src/template/zod-converter.ts +206 -91
  482. package/src/testing/__tests__/dev-test-routes.test.ts +85 -25
  483. package/src/testing/__tests__/dev-vitest-manager.test.ts +15 -15
  484. package/src/testing/_relation-graph.ts +4 -1
  485. package/src/testing/bootstrap.ts +12 -5
  486. package/src/testing/data-explorer.ts +102 -53
  487. package/src/testing/dev-test-routes.ts +87 -50
  488. package/src/testing/dev-vitest-manager.ts +88 -32
  489. package/src/testing/faker-mappings.ts +2 -2
  490. package/src/testing/filesystem.ts +1 -0
  491. package/src/testing/fixture-generator.ts +191 -131
  492. package/src/testing/fixture-loader.ts +5 -1
  493. package/src/testing/fixture-manager.ts +129 -90
  494. package/src/testing/global-setup.ts +7 -3
  495. package/src/testing/index.ts +5 -0
  496. package/src/types/__tests__/entity-json-schema-search-text.test.ts +9 -3
  497. package/src/types/types.ts +184 -158
  498. package/src/ui/ai-api.ts +9 -7
  499. package/src/ui/ai-client.ts +61 -56
  500. package/src/ui/api.ts +726 -770
  501. package/src/ui/async-route.ts +4 -0
  502. package/src/ui/cdd-service.ts +35 -12
  503. package/src/ui/migrations-api.ts +381 -0
  504. package/src/utils/formatter.ts +7 -3
  505. package/src/utils/fs-utils.ts +5 -5
  506. package/src/utils/model.ts +4 -5
  507. package/src/utils/object-utils.ts +32 -22
  508. package/src/utils/process-utils.ts +4 -1
  509. package/src/utils/runtime-value.ts +43 -0
  510. package/src/utils/sql-parser.ts +13 -6
  511. package/src/utils/type-utils.ts +9 -7
  512. package/src/utils/utils.ts +19 -21
  513. package/src/utils/zod-error.ts +4 -2
  514. package/src/vector/chunking.ts +6 -1
  515. package/src/vector/embedding.ts +2 -1
  516. package/src/vector/types.ts +4 -2
  517. package/tsdown.api.config.ts +5 -2
  518. package/dist/ui-web/assets/index-CJf8uJYf.js +0 -176
  519. package/dist/ui-web/assets/index-GMMIVGja.css +0 -1
@@ -164,7 +164,8 @@ class PostgreSQLSchemaReaderClass {
164
164
  );
165
165
 
166
166
  // indexes 처리
167
- const indexes: MigrationIndex[] = Object.keys(dbIndexesGroup).map((indexName) => {
167
+ const indexes: MigrationIndex[] = [];
168
+ for (const indexName of Object.keys(dbIndexesGroup)) {
168
169
  const currentIndexes = dbIndexesGroup[indexName]?.toSorted(
169
170
  (left, right) => left.column_order - right.column_order,
170
171
  );
@@ -180,34 +181,42 @@ class PostgreSQLSchemaReaderClass {
180
181
  parsedIndexDefinition.accessMethod ?? firstIndex.index_type,
181
182
  );
182
183
 
183
- return {
184
+ const indexColumns: MigrationIndex["columns"] = [];
185
+ for (const currentIndex of currentIndexes) {
186
+ const opclass = this.extractIndexColumnOpclass(
187
+ parsedIndexDefinition.columnDefinitions[currentIndex.column_order - 1],
188
+ );
189
+ const column: MigrationIndex["columns"][number] = {
190
+ name: currentIndex.column_name,
191
+ };
192
+ if (opclass) {
193
+ Object.assign(column, { opclass });
194
+ }
195
+ switch (using) {
196
+ case "btree":
197
+ Object.assign(column, {
198
+ sortOrder: currentIndex.sort_order,
199
+ nullsFirst: currentIndex.nulls_first,
200
+ });
201
+ break;
202
+ }
203
+ indexColumns.push(column);
204
+ }
205
+ const index: MigrationIndex = {
184
206
  type: restoredIndexType,
185
207
  name: indexName,
186
- columns: currentIndexes.map((idx) => ({
187
- name: idx.column_name,
188
- ...(this.extractIndexColumnOpclass(
189
- parsedIndexDefinition.columnDefinitions[idx.column_order - 1],
190
- )
191
- ? {
192
- opclass: this.extractIndexColumnOpclass(
193
- parsedIndexDefinition.columnDefinitions[idx.column_order - 1],
194
- ),
195
- }
196
- : {}),
197
- ...(using === "btree"
198
- ? {
199
- sortOrder: idx.sort_order,
200
- nullsFirst: idx.nulls_first,
201
- }
202
- : {}),
203
- })),
204
-
208
+ columns: indexColumns,
205
209
  nullsNotDistinct: firstIndex.nulls_not_distinct,
206
- ...(firstIndex.predicate ? { where: firstIndex.predicate } : {}),
207
- ...(using ? { using } : {}),
208
210
  ...this.parseVectorIndexOptions(restoredIndexType, parsedIndexDefinition.withOptions),
209
211
  };
210
- });
212
+ if (firstIndex.predicate) {
213
+ index.where = firstIndex.predicate;
214
+ }
215
+ if (using) {
216
+ index.using = using;
217
+ }
218
+ indexes.push(index);
219
+ }
211
220
 
212
221
  // foreigns 처리
213
222
  const foreigns: MigrationForeign[] = dbForeigns.map((dbForeign) => {
@@ -231,14 +240,14 @@ class PostgreSQLSchemaReaderClass {
231
240
  * PostgreSQL의 constraint action을 Knex 형식으로 변환
232
241
  */
233
242
  private mapConstraintAction(action: string): RelationOn {
234
- const actionMap: Record<string, RelationOn> = {
235
- "NO ACTION": "NO ACTION",
236
- RESTRICT: "RESTRICT",
237
- CASCADE: "CASCADE",
238
- "SET NULL": "SET NULL",
239
- "SET DEFAULT": "SET DEFAULT",
240
- };
241
- return actionMap[action] ?? "NO ACTION";
243
+ const actionMap = new Map<string, RelationOn>([
244
+ ["NO ACTION", "NO ACTION"],
245
+ ["RESTRICT", "RESTRICT"],
246
+ ["CASCADE", "CASCADE"],
247
+ ["SET NULL", "SET NULL"],
248
+ ["SET DEFAULT", "SET DEFAULT"],
249
+ ]);
250
+ return actionMap.get(action) ?? "NO ACTION";
242
251
  }
243
252
 
244
253
  /**
@@ -277,7 +286,9 @@ class PostgreSQLSchemaReaderClass {
277
286
  AND c.table_schema = 'public'
278
287
  ORDER BY c.ordinal_position
279
288
  `;
280
- const columns = (await compareDB.raw(columnsQuery, [tableName])).rows as PgColumn[];
289
+ const columns = /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (
290
+ await compareDB.raw(columnsQuery, [tableName])
291
+ ).rows as PgColumn[];
281
292
  if (columns.length === 0) {
282
293
  throw new Error(`Table not found: ${tableName}`);
283
294
  }
@@ -398,7 +409,7 @@ class PostgreSQLSchemaReaderClass {
398
409
  return undefined;
399
410
  }
400
411
 
401
- return normalized as MigrationIndex["using"];
412
+ return /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ normalized as MigrationIndex["using"];
402
413
  }
403
414
 
404
415
  private parseVectorIndexOptions(
@@ -406,14 +417,12 @@ class PostgreSQLSchemaReaderClass {
406
417
  withOptions: Record<string, string>,
407
418
  ): Pick<MigrationIndex, "m" | "efConstruction" | "lists"> {
408
419
  if (type === "hnsw") {
409
- return {
410
- ...(this.parseIntegerOption(withOptions.m) !== undefined
411
- ? { m: this.parseIntegerOption(withOptions.m) }
412
- : {}),
413
- ...(this.parseIntegerOption(withOptions.ef_construction) !== undefined
414
- ? { efConstruction: this.parseIntegerOption(withOptions.ef_construction) }
415
- : {}),
416
- };
420
+ const options: Pick<MigrationIndex, "m" | "efConstruction"> = {};
421
+ const m = this.parseIntegerOption(withOptions.m);
422
+ const efConstruction = this.parseIntegerOption(withOptions.ef_construction);
423
+ if (m !== undefined) options.m = m;
424
+ if (efConstruction !== undefined) options.efConstruction = efConstruction;
425
+ return options;
417
426
  }
418
427
 
419
428
  if (type === "ivfflat") {
@@ -456,11 +465,7 @@ class PostgreSQLSchemaReaderClass {
456
465
  return tokens.at(-1);
457
466
  }
458
467
 
459
- private parseIndexDefinition(indexDefinition: string): {
460
- accessMethod?: string;
461
- columnDefinitions: string[];
462
- withOptions: Record<string, string>;
463
- } {
468
+ private parseIndexDefinition(indexDefinition: string) {
464
469
  const accessMethod = indexDefinition.match(/\bUSING\s+([a-z_][\w]*)/i)?.[1]?.toLowerCase();
465
470
  const usingMatchIndex = indexDefinition.search(/\bUSING\b/i);
466
471
  const columnsStart = usingMatchIndex >= 0 ? indexDefinition.indexOf("(", usingMatchIndex) : -1;
@@ -138,12 +138,13 @@ export class SlackConfirm {
138
138
  throw new Error(`Slack API HTTP error: ${response.status}`);
139
139
  }
140
140
 
141
- const data = (await response.json()) as {
142
- ok: boolean;
143
- error?: string;
144
- channel: string;
145
- ts: string;
146
- };
141
+ const data =
142
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (await response.json()) as {
143
+ ok: boolean;
144
+ error?: string;
145
+ channel: string;
146
+ ts: string;
147
+ };
147
148
  if (!data.ok) {
148
149
  throw new Error(`Slack API error: ${data.error}`);
149
150
  }
@@ -202,16 +203,17 @@ ${migrationsText}`;
202
203
  throw new Error(`Slack API HTTP error: ${response.status}`);
203
204
  }
204
205
 
205
- const data = (await response.json()) as {
206
- ok: boolean;
207
- error?: string;
208
- message?: {
209
- reactions?: Array<{
210
- name: string;
211
- users?: string[];
212
- }>;
206
+ const data =
207
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (await response.json()) as {
208
+ ok: boolean;
209
+ error?: string;
210
+ message?: {
211
+ reactions?: Array<{
212
+ name: string;
213
+ users?: string[];
214
+ }>;
215
+ };
213
216
  };
214
- };
215
217
  if (!data.ok) {
216
218
  throw new Error(`Slack API error: ${data.error}`);
217
219
  }
@@ -5,6 +5,63 @@ export type MigrationCode = {
5
5
  name: string;
6
6
  path: string;
7
7
  };
8
+ export type MigrationTarget = keyof SonamuDBConfig;
9
+ export type MigrationConnectionMeta = {
10
+ connKey: MigrationTarget;
11
+ name: string;
12
+ host: string;
13
+ port: number;
14
+ database: string;
15
+ remote: boolean;
16
+ requiresApproval: boolean;
17
+ };
18
+ export type MigrationConnectionStatus = {
19
+ connKey: MigrationTarget;
20
+ currentVersion: string | "none" | "error";
21
+ status: number | "error";
22
+ pending: string[];
23
+ latencyMs: number;
24
+ error?: string;
25
+ };
26
+ export type MigrationAction = "shadow" | "apply" | "rollback";
27
+ export type MigrationProgressEvent =
28
+ | {
29
+ type: "target-start";
30
+ action: MigrationAction;
31
+ connKey: MigrationTarget | "shadow";
32
+ files: string[];
33
+ }
34
+ | {
35
+ type: "file-start" | "file-executed";
36
+ action: MigrationAction;
37
+ connKey: MigrationTarget | "shadow";
38
+ file: string;
39
+ index: number;
40
+ total: number;
41
+ }
42
+ | {
43
+ type: "target-complete";
44
+ action: MigrationAction;
45
+ connKey: MigrationTarget | "shadow";
46
+ batchNo: number;
47
+ files: string[];
48
+ };
49
+ export type MigrationRunOptions = {
50
+ /** 트랜잭션과 migration lock을 연장하지 않는 동기 observer입니다. */
51
+ onProgress?: (event: MigrationProgressEvent) => void;
52
+ };
53
+ export type MigrationStreamEvent =
54
+ | MigrationProgressEvent
55
+ | { type: "complete"; result: import("./migrator").MigrationResult }
56
+ | {
57
+ type: "error";
58
+ action: MigrationAction;
59
+ message: string;
60
+ connKey?: MigrationTarget | "shadow";
61
+ file?: string;
62
+ completedTargets: MigrationTarget[];
63
+ pendingTargets: MigrationTarget[];
64
+ };
8
65
  export type ConnString = `${"pg"}://${string}@${string}:${number}/${string}`; // pg://account@host:port/database
9
66
  export type MigrationStatus = {
10
67
  codes: MigrationCode[];
@@ -103,7 +103,7 @@ class NaiteReporterClass {
103
103
  private async send(data: NaiteMessagingTypes.NaiteMessage): Promise<void> {
104
104
  const msg = `${JSON.stringify(data)}\n`;
105
105
 
106
- await this.ensureConnection().catch((_) => {});
106
+ await this.ensureConnection().catch(() => {});
107
107
 
108
108
  if (this.connected && this.socket) {
109
109
  this.socket.write(msg);
@@ -1,5 +1,3 @@
1
- /* oxlint-disable @typescript-eslint/no-explicit-any */ // Naite는 expect와 호응하도록 any를 허용함
2
-
3
1
  import { getLogger } from "@logtape/logtape";
4
2
  import { get } from "radashi";
5
3
 
@@ -7,6 +5,7 @@ import { Sonamu } from "../api/sonamu";
7
5
  import { type ComparisonOperator } from "../database/puri.types";
8
6
  import { convertNaiteKeyToCategory } from "../logger/category";
9
7
  import { isSerializable } from "../utils/object-utils";
8
+ import { isNumberValue, isStringValue } from "../utils/runtime-value";
10
9
 
11
10
  // StackFrame 타입
12
11
  interface StackFrame {
@@ -18,11 +17,78 @@ interface StackFrame {
18
17
  // NaiteTrace 타입
19
18
  interface NaiteTrace {
20
19
  key: string;
21
- data: any;
20
+ data: NaiteData;
22
21
  stack: StackFrame[]; // 콜스택 정보
23
22
  at: Date;
24
23
  }
25
24
 
25
+ // Naite는 직렬화 가능성 검사를 내보내기 시점에 수행하므로 모든 JavaScript 값을 기록할 수 있습니다.
26
+ export type NaiteData = null | undefined | bigint | boolean | number | object | string | symbol;
27
+
28
+ export interface NaiteEventRegistry {
29
+ actionGenerateServices: readonly object[];
30
+ "fs/promises:rm": {
31
+ path: string;
32
+ options?: object;
33
+ };
34
+ "fs/promises:writeFile": {
35
+ path: string;
36
+ data: string;
37
+ };
38
+ "puri:executed-query": string;
39
+ "puri:ub-batch-updated": {
40
+ tableName: string;
41
+ rowCount: number;
42
+ whereColumns: string[];
43
+ };
44
+ "puri:ub-clean-orphans": {
45
+ tableName: string;
46
+ cleanOrphans: string[];
47
+ deletedCount: number;
48
+ };
49
+ "puri:ub-inherit": {
50
+ tableName: string;
51
+ inheritColumns: string[];
52
+ excludedFromUpdate: string[];
53
+ };
54
+ "puri:ub-ref-resolved": {
55
+ tableName: string;
56
+ field: string;
57
+ from: UBReference;
58
+ to: NaiteData;
59
+ };
60
+ "puri:ub-register": {
61
+ tableName: string;
62
+ uuid: string;
63
+ isUuidReused: boolean;
64
+ row: object & { user_id: UBReference };
65
+ };
66
+ "puri:ub-upserted": {
67
+ tableName: string;
68
+ mode: "insert" | "upsert";
69
+ rowCount: number;
70
+ returnedIds: Array<number | string>;
71
+ };
72
+ }
73
+
74
+ interface UBReference {
75
+ uuid: string;
76
+ of: string;
77
+ use?: string;
78
+ }
79
+
80
+ export interface NaiteResult<Payload> extends Array<Payload> {
81
+ 0: Payload;
82
+ 1: Payload;
83
+ [index: number]: Payload;
84
+ find<Match extends Payload>(
85
+ predicate: (value: Payload, index: number, values: Payload[]) => value is Match,
86
+ ): Match;
87
+ find(predicate: (value: Payload, index: number, values: Payload[]) => boolean): Payload;
88
+ }
89
+
90
+ type NaiteValuesByKey = Record<string, NaiteTrace[] | Array<NaiteTrace["data"]>>;
91
+
26
92
  // Naite.t가 저장되는 타입 (항상 배열로 통일)
27
93
  export type NaiteStore = Map<string, NaiteTrace[]>;
28
94
 
@@ -30,7 +96,7 @@ export type NaiteStore = Map<string, NaiteTrace[]>;
30
96
  // bootstrap.ts의 TaskMeta augmentation, dev-vitest-manager.ts에서도 이 타입을 공유합니다.
31
97
  export type SerializedTrace = {
32
98
  key: string;
33
- value: any;
99
+ value: unknown;
34
100
  filePath: string;
35
101
  lineNumber: number;
36
102
  at: string;
@@ -140,22 +206,22 @@ function matchesPattern(key: string, pattern: string): boolean {
140
206
  * NaiteQuery 클래스
141
207
  * 체이닝을 통한 trace 필터링 및 조회
142
208
  */
143
- export class NaiteQuery {
209
+ export class NaiteQuery<Payload extends NaiteData = NaiteData> {
144
210
  constructor(private traces: NaiteTrace[]) {}
145
211
 
146
- private isComparableValue(value: unknown): value is number | string {
147
- return typeof value === "number" || typeof value === "string";
212
+ private isComparableValue<Value>(value: Value): value is Value & (number | string) {
213
+ return isNumberValue(value) || isStringValue(value);
148
214
  }
149
215
 
150
216
  /**
151
217
  * 파일명으로 필터링
152
218
  * @param fileName 파일명 (예: "syncer.test.ts")
153
219
  */
154
- fromFile(fileName: string): NaiteQuery {
220
+ fromFile(fileName: string): NaiteQuery<Payload> {
155
221
  const filtered = this.traces.filter((t) =>
156
222
  t.stack.some((frame) => frame.filePath.endsWith(`/${fileName}`)),
157
223
  );
158
- return new NaiteQuery(filtered);
224
+ return new NaiteQuery<Payload>(filtered);
159
225
  }
160
226
 
161
227
  /**
@@ -166,7 +232,7 @@ export class NaiteQuery {
166
232
  fromFunction(
167
233
  funcName: string,
168
234
  options: { from: "direct" | "indirect" | "both" } = { from: "both" },
169
- ): NaiteQuery {
235
+ ): NaiteQuery<Payload> {
170
236
  const filtered = this.traces.filter((t) => {
171
237
  if (options.from === "direct") {
172
238
  // stack[0]만 확인 (직접 호출)
@@ -179,7 +245,7 @@ export class NaiteQuery {
179
245
  // 전체 스택에서 확인
180
246
  return t.stack.some((f) => f.functionName?.includes(funcName));
181
247
  });
182
- return new NaiteQuery(filtered);
248
+ return new NaiteQuery<Payload>(filtered);
183
249
  }
184
250
 
185
251
  /**
@@ -188,7 +254,11 @@ export class NaiteQuery {
188
254
  * @param operator 비교 연산자
189
255
  * @param value 비교값
190
256
  */
191
- where(path: string, operator: ComparisonOperator | "includes", value: any): NaiteQuery {
257
+ where<Value extends NaiteData>(
258
+ path: string,
259
+ operator: ComparisonOperator | "includes",
260
+ value: Value,
261
+ ): NaiteQuery<Payload> {
192
262
  const filtered = this.traces.filter((trace) => {
193
263
  const actual = get(trace, path);
194
264
 
@@ -206,39 +276,43 @@ export class NaiteQuery {
206
276
  case "!=":
207
277
  return actual !== value;
208
278
  case "includes":
209
- return typeof actual === "string" && actual.includes(value);
279
+ return isStringValue(actual) && isStringValue(value) && actual.includes(value);
210
280
  default:
211
281
  return false;
212
282
  }
213
283
  });
214
- return new NaiteQuery(filtered);
284
+ return new NaiteQuery<Payload>(filtered);
215
285
  }
216
286
 
217
287
  /**
218
288
  * 전체 데이터 배열 반환
219
289
  */
220
- result(): any[] {
290
+ result(): NaiteResult<Payload>;
291
+ result(): NaiteData[] {
221
292
  return this.traces.map((t) => t.data);
222
293
  }
223
294
 
224
295
  /**
225
296
  * 첫 번째 데이터 반환
226
297
  */
227
- first(): any | undefined {
298
+ first(): Payload;
299
+ first(): NaiteData {
228
300
  return this.traces[0]?.data;
229
301
  }
230
302
 
231
303
  /**
232
304
  * 마지막 데이터 반환
233
305
  */
234
- last(): any | undefined {
306
+ last(): Payload;
307
+ last(): NaiteData {
235
308
  return this.traces[this.traces.length - 1]?.data;
236
309
  }
237
310
 
238
311
  /**
239
312
  * n번째 데이터 반환
240
313
  */
241
- at(index: number): any | undefined {
314
+ at(index: number): Payload;
315
+ at(index: number): NaiteData {
242
316
  return this.traces[index]?.data;
243
317
  }
244
318
 
@@ -253,10 +327,7 @@ export class NaiteQuery {
253
327
  // Naite 싱글턴 객체 (추후 logger 연결 등의 상태 관리 필요성 고려)
254
328
  export class NaiteClass {
255
329
  // 테스트 로그 기록
256
- t(
257
- name: string,
258
- value: any /*이렇게 받은 값이 NaiteTrace로 저장되어 있다가 추후에 vitest에게 meta를 통해 넘겨져 프로세스간 통신을 통해 직렬화되어야 하는 점을 고려하였을 때 여기에 Serializable을 써서 제한을 둘 수도 있지만, 사용상의 편의를 생각하여 any로 받습니다.*/,
259
- ) {
330
+ t<Value extends NaiteData>(name: string, value: Value) {
260
331
  // 이 t 함수는 테스트 환경에서만 작동해야 합니다.
261
332
  // 그리고 테스트 환경 판단에 왜 isTest() 함수를 사용하지 않았냐면요,,
262
333
  // 이렇게 하는게 유틸 함수 불러와서 사용하는 것보다 조금이나마 빠를 것 같았기 때문입니다.
@@ -302,6 +373,8 @@ export class NaiteClass {
302
373
  * key 또는 wildcard 패턴으로 trace 조회
303
374
  * 항상 NaiteQuery 반환하여 체이닝 가능
304
375
  */
376
+ get<Key extends keyof NaiteEventRegistry>(keyPattern: Key): NaiteQuery<NaiteEventRegistry[Key]>;
377
+ get(keyPattern: string): NaiteQuery;
305
378
  get(keyPattern: string): NaiteQuery {
306
379
  const context = Sonamu.getContext();
307
380
  const store = context?.naiteStore;
@@ -328,13 +401,13 @@ export class NaiteClass {
328
401
  }
329
402
 
330
403
  // 전체 리스트 가져오기
331
- getAll(): { [key: string]: any } {
404
+ getAll() {
332
405
  const context = Sonamu.getContext();
333
406
  if (!context?.naiteStore) {
334
407
  return {};
335
408
  }
336
409
  // NaiteTrace 배열을 data만 추출하여 반환
337
- const result: { [key: string]: any } = {};
410
+ const result: NaiteValuesByKey = {};
338
411
  for (const [key, traces] of context.naiteStore.entries()) {
339
412
  if (key.startsWith("mock:")) {
340
413
  // Mock 설정은 그대로 반환
@@ -0,0 +1,34 @@
1
+ import {
2
+ isBigIntValue,
3
+ isFunctionValue,
4
+ isNumberValue,
5
+ isStringValue,
6
+ isSymbolValue,
7
+ } from "./utils/runtime-value";
8
+
9
+ export type RuntimeType =
10
+ | "bigint"
11
+ | "boolean"
12
+ | "function"
13
+ | "number"
14
+ | "object"
15
+ | "string"
16
+ | "symbol"
17
+ | "undefined";
18
+
19
+ /** 런타임 값이 불리언인지 판별합니다. */
20
+ export function isBooleanValue<Value>(value: Value): value is Value & boolean {
21
+ return value === true || value === false;
22
+ }
23
+
24
+ /** JavaScript의 typeof 결과를 단항 연산자 없이 동일하게 계산합니다. */
25
+ export function runtimeTypeOf<Value>(value: Value): RuntimeType {
26
+ if (value === undefined) return "undefined";
27
+ if (isStringValue(value)) return "string";
28
+ if (isNumberValue(value)) return "number";
29
+ if (isBooleanValue(value)) return "boolean";
30
+ if (isBigIntValue(value)) return "bigint";
31
+ if (isSymbolValue(value)) return "symbol";
32
+ if (isFunctionValue(value)) return "function";
33
+ return "object";
34
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * 페이지 단위 HMR 비활성화(`?hmr=false`).
3
+ *
4
+ * 에이전트가 코드를 고치는 동안 사람이 보고 있는 탭이 계속 새로고침되는 것을 막기 위해,
5
+ * 해당 URL로 연 페이지에서만 Vite HMR을 끊는다.
6
+ *
7
+ * Vite는 페이지 단위 HMR 토글을 제공하지 않는다. `server.hmr: false`는 서버 전체에 적용되고,
8
+ * HTML에서 `/@vite/client` 스크립트 태그만 제거하는 방식도 통하지 않는다.
9
+ * 변환된 모듈마다 `import { createHotContext } from "/@vite/client"`가 들어가기 때문이다.
10
+ *
11
+ * 그래서 HMR 웹소켓 자체를 막는다. Vite HMR 소켓은 서브프로토콜로 구분되므로
12
+ * (`vite-hmr`, 재연결 확인은 `vite-ping`), 앱이 같은 포트에서 쓰는 웹소켓
13
+ * (Sonamu telemetry, ctx.ws 등)은 그대로 두고 HMR만 골라낼 수 있다.
14
+ *
15
+ * 연결 실패로 처리하지 않고 "영원히 연결 중"인 더미 소켓을 돌려주는 이유는,
16
+ * Vite 클라이언트가 소켓이 닫히면 재연결을 폴링하다가 성공 시 `location.reload()`를
17
+ * 호출하기 때문이다. close/error 이벤트를 아예 발생시키지 않아야 새로고침되지 않는다.
18
+ */
19
+
20
+ const HMR_OPT_OUT_QUERY = "hmr";
21
+
22
+ /** 요청 URL에 `?hmr=false`가 있는지 확인한다. */
23
+ export function isHmrDisabledByQuery(url: string): boolean {
24
+ const queryIndex = url.indexOf("?");
25
+ if (queryIndex === -1) {
26
+ return false;
27
+ }
28
+
29
+ const params = new URLSearchParams(url.slice(queryIndex + 1));
30
+ const value = params.get(HMR_OPT_OUT_QUERY);
31
+ return value === "false" || value === "0";
32
+ }
33
+
34
+ /**
35
+ * HMR 웹소켓만 무력화하는 인라인 스크립트.
36
+ * 모듈 스크립트(`type="module"`)는 지연 실행되므로, 이 classic 스크립트가 항상 먼저 실행된다.
37
+ */
38
+ export const HMR_OPT_OUT_SCRIPT = `<script>
39
+ (() => {
40
+ var NativeWebSocket = window.WebSocket;
41
+ if (!NativeWebSocket) return;
42
+ var HMR_PROTOCOLS = ["vite-hmr", "vite-ping"];
43
+
44
+ function createIdleSocket(url) {
45
+ // 열리지도 닫히지도 않는 더미. close/error를 발생시키면 Vite가 재연결 후 새로고침한다.
46
+ return {
47
+ url: String(url),
48
+ readyState: 0,
49
+ protocol: "",
50
+ bufferedAmount: 0,
51
+ extensions: "",
52
+ binaryType: "blob",
53
+ onopen: null, onclose: null, onerror: null, onmessage: null,
54
+ addEventListener: function () {},
55
+ removeEventListener: function () {},
56
+ dispatchEvent: function () { return false; },
57
+ send: function () {},
58
+ close: function () {},
59
+ CONNECTING: 0, OPEN: 1, CLOSING: 2, CLOSED: 3,
60
+ };
61
+ }
62
+
63
+ window.WebSocket = new Proxy(NativeWebSocket, {
64
+ construct: function (Target, args) {
65
+ var requested = args[1];
66
+ var protocols = Array.isArray(requested) ? requested : requested ? [requested] : [];
67
+ var isHmr = protocols.some(function (protocol) {
68
+ return HMR_PROTOCOLS.indexOf(protocol) !== -1;
69
+ });
70
+ if (isHmr) {
71
+ console.info("[sonamu] hmr=false: 이 페이지의 Vite HMR 연결을 막았습니다. 변경 사항은 반영되지 않습니다.");
72
+ return createIdleSocket(args[0]);
73
+ }
74
+ return new Target(...args);
75
+ },
76
+ });
77
+ })();
78
+ </script>`;
@@ -6,6 +6,7 @@ import { type ViteDevServer } from "vite";
6
6
  import { applyCacheHeaders } from "../cache-control/cache-control";
7
7
  import { type CacheControlRequest } from "../cache-control/types";
8
8
  import { type SonamuFastifyConfig } from "../types/types";
9
+ import { HMR_OPT_OUT_SCRIPT, isHmrDisabledByQuery } from "./hmr-opt-out";
9
10
  import { type PreloadedData, type SSRRoute } from "./types";
10
11
 
11
12
  export async function renderSSR(
@@ -61,6 +62,11 @@ export async function renderSSR(
61
62
  // Vite가 주입한 스크립트 추출
62
63
  viteScripts = extractScriptTags(transformedHtml);
63
64
 
65
+ // ?hmr=false로 연 페이지는 HMR 웹소켓만 끊어 새로고침되지 않게 한다.
66
+ if (isHmrDisabledByQuery(url)) {
67
+ viteScripts = `${HMR_OPT_OUT_SCRIPT}\n${viteScripts}`;
68
+ }
69
+
64
70
  const entryModule = await vite.ssrLoadModule("/src/entry-server.generated.tsx");
65
71
  render = entryModule.render;
66
72
  } else {