@mandujs/core 0.54.32 → 0.55.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/README.md +654 -654
  2. package/package.json +106 -210
  3. package/scripts/postinstall-lock.ts +153 -153
  4. package/src/a11y/__tests__/run-audit.test.ts +333 -333
  5. package/src/a11y/fix-hints.ts +76 -76
  6. package/src/a11y/index.ts +18 -18
  7. package/src/a11y/run-audit.ts +15 -15
  8. package/src/a11y/types.ts +125 -125
  9. package/src/agent/__tests__/apply.test.ts +224 -0
  10. package/src/agent/__tests__/context.test.ts +97 -98
  11. package/src/agent/apply.ts +1031 -0
  12. package/src/agent/context.ts +552 -552
  13. package/src/agent/index.ts +4 -3
  14. package/src/agent/plan.ts +161 -243
  15. package/src/agent/repair.ts +239 -162
  16. package/src/agent/sync.ts +197 -198
  17. package/src/agent/types.ts +242 -94
  18. package/src/agent/verify.ts +55 -55
  19. package/src/auth/__tests__/login.test.ts +1 -1
  20. package/src/auth/__tests__/password.test.ts +15 -5
  21. package/src/auth/__tests__/reset.test.ts +2 -2
  22. package/src/auth/__tests__/tokens.test.ts +274 -274
  23. package/src/auth/__tests__/verification.test.ts +274 -274
  24. package/src/auth/index.ts +76 -76
  25. package/src/auth/login.ts +225 -225
  26. package/src/auth/password.ts +14 -2
  27. package/src/auth/reset.ts +243 -243
  28. package/src/auth/tokens.ts +612 -612
  29. package/src/auth/verification.ts +253 -253
  30. package/src/brain/__tests__/redactor.test.ts +94 -94
  31. package/src/brain/adapters/__tests__/_helpers.ts +83 -83
  32. package/src/brain/adapters/__tests__/anthropic-oauth.test.ts +196 -196
  33. package/src/brain/adapters/__tests__/chatgpt-auth.test.ts +193 -193
  34. package/src/brain/adapters/__tests__/openai-oauth.test.ts +209 -209
  35. package/src/brain/adapters/__tests__/resolver.test.ts +143 -143
  36. package/src/brain/adapters/anthropic-oauth.ts +1 -1
  37. package/src/brain/adapters/chatgpt-auth.ts +300 -300
  38. package/src/brain/adapters/index.ts +319 -319
  39. package/src/brain/adapters/oauth-flow.ts +439 -439
  40. package/src/brain/consent.ts +240 -240
  41. package/src/brain/credentials.ts +396 -396
  42. package/src/brain/doctor/analyzer.ts +7 -7
  43. package/src/bundler/__snapshots__/build.test.ts.snap +5 -5
  44. package/src/bundler/__tests__/build-runner.ts +166 -166
  45. package/src/bundler/__tests__/client-boundary-transform.test.ts +524 -524
  46. package/src/bundler/__tests__/cold-start.test.ts +60 -60
  47. package/src/bundler/__tests__/css.test.ts +49 -20
  48. package/src/bundler/__tests__/dev-reliability.test.ts +619 -619
  49. package/src/bundler/__tests__/extended-watch.test.ts +711 -711
  50. package/src/bundler/__tests__/fast-refresh.test.ts +24 -24
  51. package/src/bundler/__tests__/generation.test.ts +447 -0
  52. package/src/bundler/__tests__/hdr.test.ts +24 -18
  53. package/src/bundler/__tests__/hmr-client.test.ts +62 -24
  54. package/src/bundler/__tests__/jsx-runtime-shim.test.ts +179 -140
  55. package/src/bundler/__tests__/manifest-schema.test.ts +305 -266
  56. package/src/bundler/__tests__/prod-smoke.test.ts +138 -138
  57. package/src/bundler/__tests__/reverse-import-graph.test.ts +42 -42
  58. package/src/bundler/__tests__/slot-dispatch.test.ts +573 -573
  59. package/src/bundler/__tests__/url-cap-and-slot-regex.test.ts +286 -286
  60. package/src/bundler/__tests__/vendor-cache.test.ts +455 -455
  61. package/src/bundler/analyzer.ts +15 -15
  62. package/src/bundler/budget.ts +404 -404
  63. package/src/bundler/build.test.ts +898 -915
  64. package/src/bundler/build.ts +113 -24
  65. package/src/bundler/client-boundary-transform.ts +977 -977
  66. package/src/bundler/css.ts +65 -44
  67. package/src/bundler/dev.ts +105 -73
  68. package/src/bundler/fast-refresh-preamble.ts +47 -47
  69. package/src/bundler/generation.ts +602 -0
  70. package/src/bundler/index.ts +3 -3
  71. package/src/bundler/manifest-schema.ts +55 -40
  72. package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +13 -13
  73. package/src/bundler/plugins/__tests__/react-compiler-config.test.ts +83 -83
  74. package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -110
  75. package/src/bundler/plugins/block-generated-imports.ts +16 -15
  76. package/src/bundler/plugins/index.ts +83 -83
  77. package/src/bundler/plugins/react-compiler-config.ts +108 -108
  78. package/src/bundler/plugins/react-compiler-lint.ts +253 -253
  79. package/src/bundler/plugins/react-compiler.ts +162 -162
  80. package/src/bundler/prerender.ts +29 -9
  81. package/src/bundler/reverse-import-graph.ts +339 -339
  82. package/src/bundler/safe-build.test.ts +1 -1
  83. package/src/bundler/safe-build.ts +103 -103
  84. package/src/bundler/scenario-matrix.ts +229 -229
  85. package/src/bundler/types.ts +58 -56
  86. package/src/bundler/vendor-cache-types.ts +130 -130
  87. package/src/bundler/vendor-cache.ts +526 -526
  88. package/src/change/snapshot.ts +18 -18
  89. package/src/client/Form.tsx +105 -105
  90. package/src/client/Link.tsx +9 -9
  91. package/src/client/__tests__/props-serialization.test.ts +37 -37
  92. package/src/client/__tests__/use-sse.test.ts +153 -153
  93. package/src/client/globals.ts +1 -1
  94. package/src/client/hooks.ts +362 -362
  95. package/src/client/hydrate.ts +2 -2
  96. package/src/client/index.ts +1 -1
  97. package/src/client/island.ts +79 -79
  98. package/src/client/prefetch-helper.ts +55 -55
  99. package/src/client/props-serialization.ts +233 -233
  100. package/src/client/runtime-entry.ts +598 -598
  101. package/src/client/runtime.ts +1 -1
  102. package/src/client/serialize.ts +50 -50
  103. package/src/client/use-fetch.ts +6 -6
  104. package/src/client/use-head.ts +197 -197
  105. package/src/client/use-sse.ts +378 -378
  106. package/src/client/window-state.ts +101 -101
  107. package/src/components/Image-compat.ts +3 -0
  108. package/src/components/Image.tsx +162 -162
  109. package/src/config/validate.ts +1 -1
  110. package/src/config/watcher.ts +311 -311
  111. package/src/constants.ts +40 -40
  112. package/src/content/collection.ts +9 -9
  113. package/src/content/content-layer.ts +7 -7
  114. package/src/content/data-store.ts +245 -245
  115. package/src/content/frontmatter.ts +189 -189
  116. package/src/content/generate-types.ts +1 -1
  117. package/src/content/index.ts +2 -2
  118. package/src/content/loader-context.ts +171 -171
  119. package/src/content/loaders/api.ts +216 -216
  120. package/src/content/loaders/file.ts +172 -172
  121. package/src/content/loaders/glob.ts +253 -253
  122. package/src/content/loaders/index.ts +34 -34
  123. package/src/content/loaders/types.ts +137 -137
  124. package/src/content/meta-store.ts +209 -209
  125. package/src/content/prebuild.test.ts +571 -571
  126. package/src/content/prebuild.ts +636 -636
  127. package/src/content/schema.ts +20 -20
  128. package/src/content/sidebar.ts +630 -630
  129. package/src/content/slug.ts +110 -110
  130. package/src/content/types.ts +282 -282
  131. package/src/content/watcher.ts +135 -135
  132. package/src/contract/client-safe.test.ts +42 -42
  133. package/src/contract/client-safe.ts +114 -114
  134. package/src/contract/define.ts +11 -11
  135. package/src/contract/index.ts +1 -1
  136. package/src/contract/normalize.test.ts +276 -276
  137. package/src/contract/normalize.ts +410 -410
  138. package/src/contract/registry.test.ts +206 -206
  139. package/src/contract/route-helpers.ts +1 -1
  140. package/src/contract/rpc.ts +443 -443
  141. package/src/contract/types.ts +58 -58
  142. package/src/db/__tests__/db.test.ts +9 -9
  143. package/src/db/index.ts +2 -2
  144. package/src/db/migrations/history-table.ts +345 -345
  145. package/src/db/migrations/index.ts +3 -3
  146. package/src/db/migrations/lock.ts +324 -324
  147. package/src/db/migrations/runner.ts +650 -650
  148. package/src/deploy/cache.ts +140 -140
  149. package/src/deploy/compile/vercel.ts +344 -344
  150. package/src/deploy/index.ts +87 -87
  151. package/src/deploy/inference/brain.ts +268 -268
  152. package/src/deploy/inference/context.ts +82 -82
  153. package/src/deploy/inference/filling-extract.ts +245 -245
  154. package/src/deploy/inference/heuristic.ts +182 -182
  155. package/src/deploy/intent.ts +173 -173
  156. package/src/deploy/plan.ts +178 -178
  157. package/src/design/__tests__/agents-link.test.ts +109 -109
  158. package/src/design/__tests__/extract-patch-diff.test.ts +265 -265
  159. package/src/design/__tests__/lint.test.ts +110 -110
  160. package/src/design/__tests__/parser.test.ts +195 -195
  161. package/src/design/__tests__/tailwind-theme.test.ts +229 -229
  162. package/src/design/agents-link.ts +165 -165
  163. package/src/design/diff.ts +138 -138
  164. package/src/design/extract.ts +285 -285
  165. package/src/design/index.ts +102 -102
  166. package/src/design/lint.ts +209 -209
  167. package/src/design/parser.ts +555 -555
  168. package/src/design/patch.ts +241 -241
  169. package/src/design/scaffold.ts +147 -147
  170. package/src/design/tailwind-theme.ts +441 -441
  171. package/src/design/types.ts +210 -210
  172. package/src/desktop/__tests__/smoke.test.ts +2 -2
  173. package/src/desktop/__tests__/webview-fallback.test.ts +12 -32
  174. package/src/desktop/__tests__/window.test.ts +20 -99
  175. package/src/desktop/__tests__/worker.test.ts +266 -266
  176. package/src/desktop/index.ts +43 -43
  177. package/src/desktop/types.ts +158 -158
  178. package/src/desktop/webview-fallback.ts +17 -4
  179. package/src/desktop/window.ts +17 -8
  180. package/src/desktop/worker.ts +180 -180
  181. package/src/dev-error-overlay/__tests__/overlay-injector.test.ts +241 -241
  182. package/src/dev-error-overlay/index.ts +30 -30
  183. package/src/dev-error-overlay/overlay-injector.ts +243 -243
  184. package/src/dev-error-overlay/overlay-styles.ts +52 -52
  185. package/src/dev-error-overlay/types.ts +66 -66
  186. package/src/devtools/ai/context-builder.ts +375 -375
  187. package/src/devtools/ai/index.ts +25 -25
  188. package/src/devtools/ai/mcp-connector.ts +25 -25
  189. package/src/devtools/client/catchers/error-catcher.ts +344 -344
  190. package/src/devtools/client/catchers/index.ts +18 -18
  191. package/src/devtools/client/components/index.ts +39 -39
  192. package/src/devtools/client/components/mandu-character.tsx +331 -331
  193. package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
  194. package/src/devtools/client/components/panel/guard-panel.tsx +30 -30
  195. package/src/devtools/client/components/panel/islands-panel.tsx +16 -16
  196. package/src/devtools/client/components/panel/network-panel.tsx +291 -291
  197. package/src/devtools/client/components/panel/panel-container.tsx +1 -1
  198. package/src/devtools/client/components/panel/preview-panel.tsx +46 -46
  199. package/src/devtools/client/filters/context-filters.ts +282 -282
  200. package/src/devtools/client/filters/index.ts +16 -16
  201. package/src/devtools/client/index.ts +63 -63
  202. package/src/devtools/hook/create-hook.ts +207 -207
  203. package/src/devtools/hook/index.ts +13 -13
  204. package/src/devtools/index.ts +439 -439
  205. package/src/devtools/init.ts +265 -265
  206. package/src/devtools/protocol.ts +237 -237
  207. package/src/devtools/server/index.ts +17 -17
  208. package/src/devtools/types.ts +35 -35
  209. package/src/devtools/worker/index.ts +25 -25
  210. package/src/devtools/worker/redaction-worker.ts +233 -233
  211. package/src/diagnose/__tests__/checks.test.ts +136 -136
  212. package/src/diagnose/checks.ts +185 -185
  213. package/src/diagnose/index.ts +17 -17
  214. package/src/diagnose/run.ts +10 -10
  215. package/src/diagnose/types.ts +53 -53
  216. package/src/email/__tests__/email.test.ts +355 -355
  217. package/src/email/index.ts +282 -282
  218. package/src/email/smtp.ts +64 -64
  219. package/src/error/domains.ts +265 -265
  220. package/src/error/types.ts +6 -6
  221. package/src/errors/extractor.ts +409 -409
  222. package/src/errors/index.ts +19 -19
  223. package/src/filling/__tests__/session-sqlite.test.ts +5 -1
  224. package/src/filling/auth.ts +308 -308
  225. package/src/filling/body-parse.test.ts +60 -60
  226. package/src/filling/cookie-codec.ts +5 -3
  227. package/src/filling/deps.ts +265 -265
  228. package/src/filling/head-method.test.ts +154 -154
  229. package/src/filling/session-sqlite.ts +617 -617
  230. package/src/filling/sse.ts +5 -5
  231. package/src/filling/ws.ts +78 -78
  232. package/src/generator/generate.ts +30 -30
  233. package/src/generator/index.ts +3 -3
  234. package/src/generator/templates.test.ts +48 -48
  235. package/src/generator/templates.ts +219 -219
  236. package/src/guard/__tests__/design-inline-class.test.ts +219 -219
  237. package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -347
  238. package/src/guard/analyzer.ts +360 -360
  239. package/src/guard/auto-correct.ts +1 -1
  240. package/src/guard/check.ts +39 -24
  241. package/src/guard/config-guard.ts +13 -13
  242. package/src/guard/contract-guard.ts +9 -9
  243. package/src/guard/define-rule.ts +243 -243
  244. package/src/guard/design-inline-class.ts +393 -393
  245. package/src/guard/file-type.test.ts +24 -24
  246. package/src/guard/fs-routes-policy.ts +51 -51
  247. package/src/guard/graph.ts +1 -1
  248. package/src/guard/healing.ts +36 -36
  249. package/src/guard/index.ts +11 -11
  250. package/src/guard/presets/atomic.ts +70 -70
  251. package/src/guard/presets/clean.ts +77 -77
  252. package/src/guard/presets/fsd.ts +79 -79
  253. package/src/guard/presets/hexagonal.ts +68 -68
  254. package/src/guard/reporter.ts +442 -442
  255. package/src/guard/rule-presets.ts +379 -379
  256. package/src/guard/semantic-slots.ts +1 -1
  257. package/src/guard/suggestions.ts +358 -358
  258. package/src/guard/tsgolint-bridge.ts +512 -512
  259. package/src/guard/types.ts +348 -348
  260. package/src/guard/watcher.ts +405 -405
  261. package/src/i18n/define.ts +126 -126
  262. package/src/i18n/index.ts +52 -52
  263. package/src/i18n/message-registry.ts +173 -173
  264. package/src/i18n/types.ts +112 -112
  265. package/src/id/__tests__/id.test.ts +3 -3
  266. package/src/id/index.ts +105 -105
  267. package/src/index.ts +9 -48
  268. package/src/internal/client-boundary.ts +266 -266
  269. package/src/internal/index.ts +2 -2
  270. package/src/kitchen/api/agent-devtools-api.ts +779 -779
  271. package/src/kitchen/api/bundle-inspector.ts +179 -0
  272. package/src/kitchen/api/errors-grouping.ts +126 -126
  273. package/src/kitchen/api/file-api.ts +11 -11
  274. package/src/kitchen/kitchen-handler.ts +36 -0
  275. package/src/kitchen/kitchen-ui.ts +456 -0
  276. package/src/logging/index.ts +22 -22
  277. package/src/logging/transports.ts +365 -365
  278. package/src/middleware/bridge.ts +147 -147
  279. package/src/middleware/compose.ts +134 -134
  280. package/src/middleware/compress.ts +62 -62
  281. package/src/middleware/cors.ts +47 -47
  282. package/src/middleware/csrf.ts +328 -328
  283. package/src/middleware/define.ts +132 -132
  284. package/src/middleware/jwt.ts +134 -134
  285. package/src/middleware/logger.ts +58 -58
  286. package/src/middleware/oauth/__tests__/oauth.test.ts +1 -1
  287. package/src/middleware/oauth/index.ts +505 -505
  288. package/src/middleware/oauth/providers.ts +115 -115
  289. package/src/middleware/rate-limit/index.ts +522 -522
  290. package/src/middleware/rate-limit/sqlite-store.ts +382 -382
  291. package/src/middleware/scheduler-cron.ts +96 -96
  292. package/src/middleware/secure/__tests__/secure.test.ts +360 -360
  293. package/src/middleware/secure/csp.ts +193 -193
  294. package/src/middleware/session.ts +174 -174
  295. package/src/middleware/timeout.ts +55 -55
  296. package/src/observability/logger-adapter.ts +36 -36
  297. package/src/observability/sqlite-store.ts +254 -254
  298. package/src/openapi/generator.ts +1 -1
  299. package/src/openapi/openapi.test.ts +43 -43
  300. package/src/perf/__tests__/user-marks.test.ts +354 -354
  301. package/src/perf/index.ts +133 -133
  302. package/src/perf/user-marks.ts +1 -1
  303. package/src/plugins/__tests__/lifecycle-integration.test.ts +272 -272
  304. package/src/plugins/__tests__/runner.test.ts +409 -409
  305. package/src/plugins/define.ts +124 -124
  306. package/src/plugins/examples/dep-check-plugin.ts +80 -80
  307. package/src/plugins/examples/prerender-cache-plugin.ts +111 -111
  308. package/src/plugins/examples/sitemap-plugin.ts +65 -65
  309. package/src/plugins/runner.ts +361 -361
  310. package/src/plugins/types.ts +368 -368
  311. package/src/report/index.ts +1 -1
  312. package/src/resource/__tests__/generator.test.ts +7 -7
  313. package/src/resource/__tests__/schema.test.ts +14 -14
  314. package/src/resource/ddl/__tests__/diff.test.ts +639 -639
  315. package/src/resource/ddl/__tests__/emit.test.ts +165 -165
  316. package/src/resource/ddl/__tests__/snapshot.test.ts +499 -499
  317. package/src/resource/ddl/emit.ts +146 -146
  318. package/src/resource/ddl/persistence-types.ts +218 -218
  319. package/src/resource/ddl/type-map.ts +223 -223
  320. package/src/resource/ddl/types.ts +232 -232
  321. package/src/resource/generator-repo.ts +630 -630
  322. package/src/resource/generator-schema.ts +11 -11
  323. package/src/resource/generators/slot.ts +72 -72
  324. package/src/resource/schema.ts +21 -21
  325. package/src/router/client-entry.test.ts +227 -227
  326. package/src/router/client-entry.ts +218 -218
  327. package/src/router/fs-patterns.test.ts +96 -96
  328. package/src/router/fs-routes.test.ts +532 -532
  329. package/src/router/fs-routes.ts +53 -53
  330. package/src/router/fs-scanner.ts +216 -216
  331. package/src/router/fs-types.ts +19 -19
  332. package/src/router/route-source-analyzer.ts +521 -521
  333. package/src/routes/index.ts +74 -74
  334. package/src/routes/metadata-routes.ts +427 -427
  335. package/src/routes/types.ts +341 -341
  336. package/src/runtime/__tests__/devtools-adapter.test.ts +68 -68
  337. package/src/runtime/__tests__/error-boundary-redaction.test.ts +141 -141
  338. package/src/runtime/__tests__/hdr-client.test.ts +223 -223
  339. package/src/runtime/__tests__/http-errors.test.ts +117 -117
  340. package/src/runtime/__tests__/inline-client-hydration.test.ts +237 -237
  341. package/src/runtime/__tests__/not-found.test.ts +152 -152
  342. package/src/runtime/__tests__/observability-lifecycle.test.ts +103 -103
  343. package/src/runtime/__tests__/page-render-response.test.ts +517 -517
  344. package/src/runtime/__tests__/request-middleware.test.ts +70 -70
  345. package/src/runtime/__tests__/searchparams-page-props.test.ts +81 -81
  346. package/src/runtime/adapter.ts +47 -47
  347. package/src/runtime/boundary.tsx +252 -252
  348. package/src/runtime/cache.ts +494 -494
  349. package/src/runtime/compose.ts +222 -222
  350. package/src/runtime/devtools-adapter.ts +68 -68
  351. package/src/runtime/escape.ts +34 -34
  352. package/src/runtime/fast-refresh-runtime.ts +322 -322
  353. package/src/runtime/fast-refresh-types.ts +1 -1
  354. package/src/runtime/handler.ts +65 -65
  355. package/src/runtime/handlers.ts +30 -11
  356. package/src/runtime/http-errors.ts +113 -113
  357. package/src/runtime/image-handler.ts +1 -1
  358. package/src/runtime/lifecycle.ts +381 -381
  359. package/src/runtime/logger.test.ts +345 -345
  360. package/src/runtime/middleware.ts +264 -264
  361. package/src/runtime/not-found.ts +93 -93
  362. package/src/runtime/observability-lifecycle.ts +290 -290
  363. package/src/runtime/openapi-endpoint.ts +236 -236
  364. package/src/runtime/page-render-response.ts +287 -274
  365. package/src/runtime/ppr.ts +74 -74
  366. package/src/runtime/rate-limit.ts +1 -1
  367. package/src/runtime/redirect.ts +1 -1
  368. package/src/runtime/registry.ts +171 -171
  369. package/src/runtime/request-middleware.ts +31 -31
  370. package/src/runtime/router.test.ts +4 -4
  371. package/src/runtime/router.ts +10 -10
  372. package/src/runtime/server.ts +127 -211
  373. package/src/runtime/shims.ts +48 -48
  374. package/src/runtime/ssr.ts +43 -17
  375. package/src/runtime/static-files.ts +369 -289
  376. package/src/runtime/streaming-ssr.ts +219 -180
  377. package/src/runtime/trace.ts +144 -144
  378. package/src/scheduler/__tests__/scheduler.test.ts +12 -11
  379. package/src/scheduler/index.ts +11 -5
  380. package/src/scheduler/validate.ts +169 -169
  381. package/src/seo/index.ts +219 -219
  382. package/src/seo/integration/ssr.ts +306 -306
  383. package/src/seo/render/basic.ts +435 -435
  384. package/src/seo/render/index.ts +143 -143
  385. package/src/seo/render/jsonld.ts +539 -539
  386. package/src/seo/render/opengraph.ts +197 -197
  387. package/src/seo/render/robots.ts +116 -116
  388. package/src/seo/render/sitemap.ts +137 -137
  389. package/src/seo/render/twitter.ts +127 -127
  390. package/src/seo/resolve/opengraph.ts +143 -143
  391. package/src/seo/resolve/robots.ts +73 -73
  392. package/src/seo/resolve/title.ts +94 -94
  393. package/src/seo/resolve/twitter.ts +73 -73
  394. package/src/seo/resolve/url.ts +104 -104
  395. package/src/seo/routes/index.ts +290 -290
  396. package/src/seo/types.ts +588 -588
  397. package/src/slot/validator.ts +39 -39
  398. package/src/spec/schema.ts +35 -35
  399. package/src/storage/s3/__tests__/s3.test.ts +479 -479
  400. package/src/storage/s3/index.ts +412 -412
  401. package/src/testing/__tests__/assertions.test.ts +632 -632
  402. package/src/testing/__tests__/reporter.test.ts +454 -454
  403. package/src/testing/assertions.ts +986 -986
  404. package/src/testing/db.ts +157 -157
  405. package/src/testing/index.ts +9 -3
  406. package/src/testing/lcov.ts +192 -0
  407. package/src/testing/mocks.ts +203 -203
  408. package/src/testing/session.ts +190 -190
  409. package/src/types/branded.ts +56 -56
  410. package/src/types/index.ts +1 -1
  411. package/src/utils/safe-io.ts +188 -188
  412. package/src/utils/string-safe.ts +298 -298
  413. package/src/watcher/__tests__/watcher.test.ts +59 -59
  414. package/src/watcher/watcher.ts +61 -61
package/src/seo/types.ts CHANGED
@@ -1,588 +1,588 @@
1
- /**
2
- * Mandu SEO - Type Definitions
3
- *
4
- * Next.js Metadata API 패턴 기반
5
- * @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata
6
- */
7
-
8
- // ============================================================================
9
- // Basic Types
10
- // ============================================================================
11
-
12
- export type ReferrerEnum =
13
- | 'no-referrer'
14
- | 'no-referrer-when-downgrade'
15
- | 'origin'
16
- | 'origin-when-cross-origin'
17
- | 'same-origin'
18
- | 'strict-origin'
19
- | 'strict-origin-when-cross-origin'
20
- | 'unsafe-url'
21
-
22
- export type ColorSchemeEnum = 'normal' | 'light' | 'dark' | 'light dark' | 'dark light' | 'only light'
23
-
24
- // ============================================================================
25
- // Title Types
26
- // ============================================================================
27
-
28
- export interface TemplateString {
29
- default: string
30
- template?: string // "%s | My Site" - %s is replaced with page title
31
- absolute?: string // Ignores parent template
32
- }
33
-
34
- /**
35
- * 단축형 absolute 타이틀 (템플릿 무시)
36
- */
37
- export interface AbsoluteString {
38
- absolute: string
39
- template?: string
40
- }
41
-
42
- export type Title = string | TemplateString | AbsoluteString
43
-
44
- export interface AbsoluteTemplateString {
45
- absolute: string
46
- template: string | null
47
- }
48
-
49
- // ============================================================================
50
- // Author & Creator
51
- // ============================================================================
52
-
53
- export interface Author {
54
- name?: string
55
- url?: string | URL
56
- }
57
-
58
- // ============================================================================
59
- // Robots
60
- // ============================================================================
61
-
62
- export interface Robots {
63
- index?: boolean
64
- follow?: boolean
65
- noarchive?: boolean
66
- nosnippet?: boolean
67
- noimageindex?: boolean
68
- nocache?: boolean
69
- notranslate?: boolean
70
- 'max-snippet'?: number
71
- 'max-image-preview'?: 'none' | 'standard' | 'large'
72
- 'max-video-preview'?: number
73
- /** Google 전용 설정 (다르게 적용할 경우) */
74
- googleBot?: Omit<Robots, 'googleBot'>
75
- }
76
-
77
- export interface ResolvedRobots {
78
- basic: string | null
79
- googleBot: string | null
80
- }
81
-
82
- // ============================================================================
83
- // Google SEO Specific
84
- // ============================================================================
85
-
86
- /**
87
- * Google 전용 메타 설정
88
- */
89
- export interface GoogleMeta {
90
- /** Google 사이트링크 검색창 비활성화 */
91
- nositelinkssearchbox?: boolean
92
- /** Google 번역 제안 비활성화 */
93
- notranslate?: boolean
94
- }
95
-
96
- /**
97
- * 전화번호/이메일 자동 감지 설정
98
- */
99
- export interface FormatDetection {
100
- telephone?: boolean
101
- date?: boolean
102
- address?: boolean
103
- email?: boolean
104
- url?: boolean
105
- }
106
-
107
- /**
108
- * 리소스 힌트 (성능 최적화)
109
- */
110
- export interface ResourceHint {
111
- /** preconnect URLs (외부 도메인 미리 연결) */
112
- preconnect?: string[]
113
- /** dns-prefetch URLs (DNS 미리 조회) */
114
- dnsPrefetch?: string[]
115
- /** preload resources */
116
- preload?: Array<{
117
- href: string
118
- as: 'script' | 'style' | 'font' | 'image' | 'fetch'
119
- type?: string
120
- crossOrigin?: 'anonymous' | 'use-credentials'
121
- }>
122
- /** prefetch resources (다음 페이지용) */
123
- prefetch?: string[]
124
- }
125
-
126
- /**
127
- * App 관련 메타 (PWA, iOS)
128
- */
129
- export interface AppLinks {
130
- /** iOS App Store ID */
131
- iosAppStoreId?: string
132
- /** iOS App 이름 */
133
- iosAppName?: string
134
- /** iOS App URL Scheme */
135
- iosUrl?: string
136
- /** Android Package */
137
- androidPackage?: string
138
- /** Android App 이름 */
139
- androidAppName?: string
140
- /** Android URL */
141
- androidUrl?: string
142
- }
143
-
144
- /**
145
- * Theme Color 설정
146
- */
147
- export interface ThemeColor {
148
- color: string
149
- media?: string // e.g., '(prefers-color-scheme: dark)'
150
- }
151
-
152
- // ============================================================================
153
- // Icons
154
- // ============================================================================
155
-
156
- export type IconURL = string | URL
157
-
158
- export interface IconDescriptor {
159
- url: string | URL
160
- type?: string
161
- sizes?: string
162
- color?: string
163
- rel?: string
164
- media?: string
165
- fetchPriority?: 'auto' | 'high' | 'low'
166
- }
167
-
168
- export type Icon = IconURL | IconDescriptor
169
-
170
- export interface Icons {
171
- icon?: Icon | Icon[]
172
- shortcut?: Icon | Icon[]
173
- apple?: Icon | Icon[]
174
- other?: IconDescriptor | IconDescriptor[]
175
- }
176
-
177
- export interface ResolvedIcons {
178
- icon: IconDescriptor[]
179
- apple: IconDescriptor[]
180
- shortcut: IconDescriptor[]
181
- other: IconDescriptor[]
182
- }
183
-
184
- // ============================================================================
185
- // Alternate URLs
186
- // ============================================================================
187
-
188
- export interface Languages<T> {
189
- [locale: string]: T
190
- }
191
-
192
- export interface AlternateURLs {
193
- canonical?: string | URL | null
194
- languages?: Languages<string | URL | null>
195
- media?: Record<string, string | URL>
196
- types?: Record<string, string | URL>
197
- }
198
-
199
- export interface ResolvedAlternateURLs {
200
- canonical: URL | null
201
- languages: Record<string, URL> | null
202
- media: Record<string, URL> | null
203
- types: Record<string, URL> | null
204
- }
205
-
206
- // ============================================================================
207
- // Verification
208
- // ============================================================================
209
-
210
- export interface Verification {
211
- google?: string | string[]
212
- yahoo?: string | string[]
213
- yandex?: string | string[]
214
- me?: string | string[]
215
- other?: Record<string, string | string[]>
216
- }
217
-
218
- export interface ResolvedVerification {
219
- google: string[] | null
220
- yahoo: string[] | null
221
- yandex: string[] | null
222
- me: string[] | null
223
- other: Record<string, string[]> | null
224
- }
225
-
226
- // ============================================================================
227
- // Template Literal Types for Meta Properties
228
- // ============================================================================
229
-
230
- /** OpenGraph meta property name (og:title, og:description, etc.) */
231
- export type OGProperty = `og:${string}`;
232
-
233
- /** Twitter meta property name (twitter:card, twitter:site, etc.) */
234
- export type TwitterProperty = `twitter:${string}`;
235
-
236
- /** Union of well-known meta property prefixes plus arbitrary strings */
237
- export type MetaProperty = OGProperty | TwitterProperty | string;
238
-
239
- // ============================================================================
240
- // Open Graph Types
241
- // ============================================================================
242
-
243
- export interface OpenGraphImage {
244
- url: string | URL
245
- secureUrl?: string | URL
246
- alt?: string
247
- type?: string
248
- width?: string | number
249
- height?: string | number
250
- }
251
-
252
- export interface OpenGraphVideo {
253
- url: string | URL
254
- secureUrl?: string | URL
255
- type?: string
256
- width?: string | number
257
- height?: string | number
258
- }
259
-
260
- export interface OpenGraphAudio {
261
- url: string | URL
262
- secureUrl?: string | URL
263
- type?: string
264
- }
265
-
266
- export interface OpenGraphArticle {
267
- publishedTime?: string
268
- modifiedTime?: string
269
- expirationTime?: string
270
- authors?: string | string[]
271
- section?: string
272
- tags?: string[]
273
- }
274
-
275
- export interface OpenGraphProfile {
276
- firstName?: string
277
- lastName?: string
278
- username?: string
279
- gender?: string
280
- }
281
-
282
- export interface OpenGraphBook {
283
- isbn?: string
284
- releaseDate?: string
285
- authors?: string | string[]
286
- tags?: string[]
287
- }
288
-
289
- export type OpenGraphType =
290
- | 'article'
291
- | 'book'
292
- | 'music.song'
293
- | 'music.album'
294
- | 'music.playlist'
295
- | 'music.radio_station'
296
- | 'profile'
297
- | 'video.movie'
298
- | 'video.episode'
299
- | 'video.tv_show'
300
- | 'video.other'
301
- | 'website'
302
-
303
- export interface OpenGraph {
304
- type?: OpenGraphType
305
- url?: string | URL
306
- title?: string
307
- description?: string
308
- siteName?: string
309
- locale?: string
310
- images?: string | URL | OpenGraphImage | (string | URL | OpenGraphImage)[]
311
- videos?: string | URL | OpenGraphVideo | (string | URL | OpenGraphVideo)[]
312
- audio?: string | URL | OpenGraphAudio | (string | URL | OpenGraphAudio)[]
313
- determiner?: 'a' | 'an' | 'the' | 'auto' | ''
314
- // Type-specific
315
- article?: OpenGraphArticle
316
- profile?: OpenGraphProfile
317
- book?: OpenGraphBook
318
- }
319
-
320
- export interface ResolvedOpenGraph {
321
- type: OpenGraphType
322
- url: URL | null
323
- title: string | null
324
- description: string | null
325
- siteName: string | null
326
- locale: string | null
327
- images: OpenGraphImage[] | null
328
- videos: OpenGraphVideo[] | null
329
- audio: OpenGraphAudio[] | null
330
- determiner: string | null
331
- article: OpenGraphArticle | null
332
- profile: OpenGraphProfile | null
333
- book: OpenGraphBook | null
334
- }
335
-
336
- // ============================================================================
337
- // Twitter Types
338
- // ============================================================================
339
-
340
- export type TwitterCardType = 'summary' | 'summary_large_image' | 'app' | 'player'
341
-
342
- export interface TwitterImage {
343
- url: string | URL
344
- alt?: string
345
- }
346
-
347
- export interface TwitterPlayer {
348
- playerUrl: string | URL
349
- streamUrl?: string | URL
350
- width: number
351
- height: number
352
- }
353
-
354
- export interface TwitterApp {
355
- id: {
356
- iphone?: string | number
357
- ipad?: string | number
358
- googleplay?: string
359
- }
360
- url?: {
361
- iphone?: string | URL
362
- ipad?: string | URL
363
- googleplay?: string | URL
364
- }
365
- name?: string
366
- }
367
-
368
- export interface Twitter {
369
- card?: TwitterCardType
370
- site?: string
371
- siteId?: string
372
- creator?: string
373
- creatorId?: string
374
- title?: string
375
- description?: string
376
- images?: string | URL | TwitterImage | (string | URL | TwitterImage)[]
377
- // Player card
378
- players?: TwitterPlayer | TwitterPlayer[]
379
- // App card
380
- app?: TwitterApp
381
- }
382
-
383
- export interface ResolvedTwitter {
384
- card: TwitterCardType
385
- site: string | null
386
- siteId: string | null
387
- creator: string | null
388
- creatorId: string | null
389
- title: string | null
390
- description: string | null
391
- images: TwitterImage[] | null
392
- players: TwitterPlayer[] | null
393
- app: TwitterApp | null
394
- }
395
-
396
- // ============================================================================
397
- // JSON-LD Types
398
- // ============================================================================
399
-
400
- export type JsonLdType =
401
- | 'Article'
402
- | 'BlogPosting'
403
- | 'NewsArticle'
404
- | 'WebSite'
405
- | 'WebPage'
406
- | 'Organization'
407
- | 'Person'
408
- | 'Product'
409
- | 'BreadcrumbList'
410
- | 'FAQPage'
411
- | 'HowTo'
412
- | 'Recipe'
413
- | 'Event'
414
- | 'LocalBusiness'
415
- | 'SoftwareApplication'
416
-
417
- export interface JsonLd {
418
- '@context'?: string
419
- '@type': JsonLdType | string
420
- [key: string]: unknown
421
- }
422
-
423
- // ============================================================================
424
- // Main Metadata Interface
425
- // ============================================================================
426
-
427
- export interface Metadata {
428
- // Base URL for resolving relative URLs
429
- metadataBase?: string | URL | null
430
-
431
- // Basic
432
- title?: Title | null
433
- description?: string | null
434
- applicationName?: string | null
435
- authors?: Author | Author[] | null
436
- generator?: string | null
437
- keywords?: string | string[] | null
438
- referrer?: ReferrerEnum | null
439
- creator?: string | null
440
- publisher?: string | null
441
- robots?: string | Robots | null
442
-
443
- // Alternate URLs
444
- alternates?: AlternateURLs | null
445
-
446
- // Icons
447
- icons?: IconURL | Icon[] | Icons | null
448
-
449
- // Manifest
450
- manifest?: string | URL | null
451
-
452
- // Open Graph
453
- openGraph?: OpenGraph | null
454
-
455
- // Twitter
456
- twitter?: Twitter | null
457
-
458
- // Verification
459
- verification?: Verification | null
460
-
461
- // Category
462
- category?: string | null
463
- classification?: string | null
464
-
465
- // JSON-LD
466
- jsonLd?: JsonLd | JsonLd[] | null
467
-
468
- // === Google SEO 최적화 ===
469
-
470
- /** Google 전용 메타 설정 */
471
- google?: GoogleMeta | null
472
-
473
- /** 전화번호/이메일 자동 감지 설정 */
474
- formatDetection?: FormatDetection | null
475
-
476
- /** 리소스 힌트 (성능 최적화) */
477
- resourceHints?: ResourceHint | null
478
-
479
- /** Theme Color (브라우저 UI, PWA) */
480
- themeColor?: string | ThemeColor | ThemeColor[] | null
481
-
482
- /** Viewport 설정 (기본값: width=device-width, initial-scale=1) */
483
- viewport?: string | {
484
- width?: string | number
485
- height?: string | number
486
- initialScale?: number
487
- minimumScale?: number
488
- maximumScale?: number
489
- userScalable?: boolean
490
- viewportFit?: 'auto' | 'cover' | 'contain'
491
- } | null
492
-
493
- /** App Links (iOS/Android 앱 연동) */
494
- appLinks?: AppLinks | null
495
-
496
- // Other custom meta tags
497
- other?: Record<string, string | number | (string | number)[]> | null
498
- }
499
-
500
- // ============================================================================
501
- // Resolved Metadata (after processing)
502
- // ============================================================================
503
-
504
- export interface ResolvedMetadata {
505
- metadataBase: URL | null
506
- title: AbsoluteTemplateString | null
507
- description: string | null
508
- applicationName: string | null
509
- authors: Author[] | null
510
- generator: string | null
511
- keywords: string[] | null
512
- referrer: ReferrerEnum | null
513
- creator: string | null
514
- publisher: string | null
515
- robots: ResolvedRobots | null
516
- alternates: ResolvedAlternateURLs | null
517
- icons: ResolvedIcons | null
518
- manifest: URL | null
519
- openGraph: ResolvedOpenGraph | null
520
- twitter: ResolvedTwitter | null
521
- verification: ResolvedVerification | null
522
- category: string | null
523
- classification: string | null
524
- jsonLd: JsonLd[] | null
525
- // Google SEO 최적화
526
- google: GoogleMeta | null
527
- formatDetection: FormatDetection | null
528
- resourceHints: ResourceHint | null
529
- themeColor: ThemeColor[] | null
530
- viewport: string | null
531
- appLinks: AppLinks | null
532
- other: Record<string, string | number | (string | number)[]> | null
533
- }
534
-
535
- // ============================================================================
536
- // Metadata Route Types (sitemap.ts, robots.ts)
537
- // ============================================================================
538
-
539
- export interface SitemapEntry {
540
- url: string
541
- lastModified?: string | Date
542
- changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'
543
- priority?: number
544
- alternates?: {
545
- languages?: Languages<string>
546
- }
547
- images?: string[]
548
- }
549
-
550
- export type Sitemap = SitemapEntry[]
551
-
552
- export interface RobotsRule {
553
- userAgent?: string | string[]
554
- allow?: string | string[]
555
- disallow?: string | string[]
556
- crawlDelay?: number
557
- }
558
-
559
- export interface RobotsFile {
560
- rules: RobotsRule | RobotsRule[]
561
- sitemap?: string | string[]
562
- host?: string
563
- }
564
-
565
- // ============================================================================
566
- // Metadata Route Namespace
567
- // ============================================================================
568
-
569
- export namespace MetadataRoute {
570
- export type Sitemap = SitemapEntry[]
571
- export type Robots = RobotsFile
572
- }
573
-
574
- // ============================================================================
575
- // Generator Function Types
576
- // ============================================================================
577
-
578
- export interface MetadataParams {
579
- params: Record<string, string>
580
- searchParams: Record<string, string>
581
- }
582
-
583
- export type GenerateMetadata = (
584
- props: MetadataParams,
585
- parent: Promise<ResolvedMetadata>
586
- ) => Metadata | Promise<Metadata>
587
-
588
- export type MetadataItem = Metadata | GenerateMetadata | null
1
+ /**
2
+ * Mandu SEO - Type Definitions
3
+ *
4
+ * Next.js Metadata API 패턴 기반
5
+ * @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata
6
+ */
7
+
8
+ // ============================================================================
9
+ // Basic Types
10
+ // ============================================================================
11
+
12
+ export type ReferrerEnum =
13
+ | 'no-referrer'
14
+ | 'no-referrer-when-downgrade'
15
+ | 'origin'
16
+ | 'origin-when-cross-origin'
17
+ | 'same-origin'
18
+ | 'strict-origin'
19
+ | 'strict-origin-when-cross-origin'
20
+ | 'unsafe-url'
21
+
22
+ export type ColorSchemeEnum = 'normal' | 'light' | 'dark' | 'light dark' | 'dark light' | 'only light'
23
+
24
+ // ============================================================================
25
+ // Title Types
26
+ // ============================================================================
27
+
28
+ export interface TemplateString {
29
+ default: string
30
+ template?: string // "%s | My Site" - %s is replaced with page title
31
+ absolute?: string // Ignores parent template
32
+ }
33
+
34
+ /**
35
+ * 단축형 absolute 타이틀 (템플릿 무시)
36
+ */
37
+ export interface AbsoluteString {
38
+ absolute: string
39
+ template?: string
40
+ }
41
+
42
+ export type Title = string | TemplateString | AbsoluteString
43
+
44
+ export interface AbsoluteTemplateString {
45
+ absolute: string
46
+ template: string | null
47
+ }
48
+
49
+ // ============================================================================
50
+ // Author & Creator
51
+ // ============================================================================
52
+
53
+ export interface Author {
54
+ name?: string
55
+ url?: string | URL
56
+ }
57
+
58
+ // ============================================================================
59
+ // Robots
60
+ // ============================================================================
61
+
62
+ export interface Robots {
63
+ index?: boolean
64
+ follow?: boolean
65
+ noarchive?: boolean
66
+ nosnippet?: boolean
67
+ noimageindex?: boolean
68
+ nocache?: boolean
69
+ notranslate?: boolean
70
+ 'max-snippet'?: number
71
+ 'max-image-preview'?: 'none' | 'standard' | 'large'
72
+ 'max-video-preview'?: number
73
+ /** Google 전용 설정 (다르게 적용할 경우) */
74
+ googleBot?: Omit<Robots, 'googleBot'>
75
+ }
76
+
77
+ export interface ResolvedRobots {
78
+ basic: string | null
79
+ googleBot: string | null
80
+ }
81
+
82
+ // ============================================================================
83
+ // Google SEO Specific
84
+ // ============================================================================
85
+
86
+ /**
87
+ * Google 전용 메타 설정
88
+ */
89
+ export interface GoogleMeta {
90
+ /** Google 사이트링크 검색창 비활성화 */
91
+ nositelinkssearchbox?: boolean
92
+ /** Google 번역 제안 비활성화 */
93
+ notranslate?: boolean
94
+ }
95
+
96
+ /**
97
+ * 전화번호/이메일 자동 감지 설정
98
+ */
99
+ export interface FormatDetection {
100
+ telephone?: boolean
101
+ date?: boolean
102
+ address?: boolean
103
+ email?: boolean
104
+ url?: boolean
105
+ }
106
+
107
+ /**
108
+ * 리소스 힌트 (성능 최적화)
109
+ */
110
+ export interface ResourceHint {
111
+ /** preconnect URLs (외부 도메인 미리 연결) */
112
+ preconnect?: string[]
113
+ /** dns-prefetch URLs (DNS 미리 조회) */
114
+ dnsPrefetch?: string[]
115
+ /** preload resources */
116
+ preload?: Array<{
117
+ href: string
118
+ as: 'script' | 'style' | 'font' | 'image' | 'fetch'
119
+ type?: string
120
+ crossOrigin?: 'anonymous' | 'use-credentials'
121
+ }>
122
+ /** prefetch resources (다음 페이지용) */
123
+ prefetch?: string[]
124
+ }
125
+
126
+ /**
127
+ * App 관련 메타 (PWA, iOS)
128
+ */
129
+ export interface AppLinks {
130
+ /** iOS App Store ID */
131
+ iosAppStoreId?: string
132
+ /** iOS App 이름 */
133
+ iosAppName?: string
134
+ /** iOS App URL Scheme */
135
+ iosUrl?: string
136
+ /** Android Package */
137
+ androidPackage?: string
138
+ /** Android App 이름 */
139
+ androidAppName?: string
140
+ /** Android URL */
141
+ androidUrl?: string
142
+ }
143
+
144
+ /**
145
+ * Theme Color 설정
146
+ */
147
+ export interface ThemeColor {
148
+ color: string
149
+ media?: string // e.g., '(prefers-color-scheme: dark)'
150
+ }
151
+
152
+ // ============================================================================
153
+ // Icons
154
+ // ============================================================================
155
+
156
+ export type IconURL = string | URL
157
+
158
+ export interface IconDescriptor {
159
+ url: string | URL
160
+ type?: string
161
+ sizes?: string
162
+ color?: string
163
+ rel?: string
164
+ media?: string
165
+ fetchPriority?: 'auto' | 'high' | 'low'
166
+ }
167
+
168
+ export type Icon = IconURL | IconDescriptor
169
+
170
+ export interface Icons {
171
+ icon?: Icon | Icon[]
172
+ shortcut?: Icon | Icon[]
173
+ apple?: Icon | Icon[]
174
+ other?: IconDescriptor | IconDescriptor[]
175
+ }
176
+
177
+ export interface ResolvedIcons {
178
+ icon: IconDescriptor[]
179
+ apple: IconDescriptor[]
180
+ shortcut: IconDescriptor[]
181
+ other: IconDescriptor[]
182
+ }
183
+
184
+ // ============================================================================
185
+ // Alternate URLs
186
+ // ============================================================================
187
+
188
+ export interface Languages<T> {
189
+ [locale: string]: T
190
+ }
191
+
192
+ export interface AlternateURLs {
193
+ canonical?: string | URL | null
194
+ languages?: Languages<string | URL | null>
195
+ media?: Record<string, string | URL>
196
+ types?: Record<string, string | URL>
197
+ }
198
+
199
+ export interface ResolvedAlternateURLs {
200
+ canonical: URL | null
201
+ languages: Record<string, URL> | null
202
+ media: Record<string, URL> | null
203
+ types: Record<string, URL> | null
204
+ }
205
+
206
+ // ============================================================================
207
+ // Verification
208
+ // ============================================================================
209
+
210
+ export interface Verification {
211
+ google?: string | string[]
212
+ yahoo?: string | string[]
213
+ yandex?: string | string[]
214
+ me?: string | string[]
215
+ other?: Record<string, string | string[]>
216
+ }
217
+
218
+ export interface ResolvedVerification {
219
+ google: string[] | null
220
+ yahoo: string[] | null
221
+ yandex: string[] | null
222
+ me: string[] | null
223
+ other: Record<string, string[]> | null
224
+ }
225
+
226
+ // ============================================================================
227
+ // Template Literal Types for Meta Properties
228
+ // ============================================================================
229
+
230
+ /** OpenGraph meta property name (og:title, og:description, etc.) */
231
+ export type OGProperty = `og:${string}`;
232
+
233
+ /** Twitter meta property name (twitter:card, twitter:site, etc.) */
234
+ export type TwitterProperty = `twitter:${string}`;
235
+
236
+ /** Union of well-known meta property prefixes plus arbitrary strings */
237
+ export type MetaProperty = OGProperty | TwitterProperty | string;
238
+
239
+ // ============================================================================
240
+ // Open Graph Types
241
+ // ============================================================================
242
+
243
+ export interface OpenGraphImage {
244
+ url: string | URL
245
+ secureUrl?: string | URL
246
+ alt?: string
247
+ type?: string
248
+ width?: string | number
249
+ height?: string | number
250
+ }
251
+
252
+ export interface OpenGraphVideo {
253
+ url: string | URL
254
+ secureUrl?: string | URL
255
+ type?: string
256
+ width?: string | number
257
+ height?: string | number
258
+ }
259
+
260
+ export interface OpenGraphAudio {
261
+ url: string | URL
262
+ secureUrl?: string | URL
263
+ type?: string
264
+ }
265
+
266
+ export interface OpenGraphArticle {
267
+ publishedTime?: string
268
+ modifiedTime?: string
269
+ expirationTime?: string
270
+ authors?: string | string[]
271
+ section?: string
272
+ tags?: string[]
273
+ }
274
+
275
+ export interface OpenGraphProfile {
276
+ firstName?: string
277
+ lastName?: string
278
+ username?: string
279
+ gender?: string
280
+ }
281
+
282
+ export interface OpenGraphBook {
283
+ isbn?: string
284
+ releaseDate?: string
285
+ authors?: string | string[]
286
+ tags?: string[]
287
+ }
288
+
289
+ export type OpenGraphType =
290
+ | 'article'
291
+ | 'book'
292
+ | 'music.song'
293
+ | 'music.album'
294
+ | 'music.playlist'
295
+ | 'music.radio_station'
296
+ | 'profile'
297
+ | 'video.movie'
298
+ | 'video.episode'
299
+ | 'video.tv_show'
300
+ | 'video.other'
301
+ | 'website'
302
+
303
+ export interface OpenGraph {
304
+ type?: OpenGraphType
305
+ url?: string | URL
306
+ title?: string
307
+ description?: string
308
+ siteName?: string
309
+ locale?: string
310
+ images?: string | URL | OpenGraphImage | (string | URL | OpenGraphImage)[]
311
+ videos?: string | URL | OpenGraphVideo | (string | URL | OpenGraphVideo)[]
312
+ audio?: string | URL | OpenGraphAudio | (string | URL | OpenGraphAudio)[]
313
+ determiner?: 'a' | 'an' | 'the' | 'auto' | ''
314
+ // Type-specific
315
+ article?: OpenGraphArticle
316
+ profile?: OpenGraphProfile
317
+ book?: OpenGraphBook
318
+ }
319
+
320
+ export interface ResolvedOpenGraph {
321
+ type: OpenGraphType
322
+ url: URL | null
323
+ title: string | null
324
+ description: string | null
325
+ siteName: string | null
326
+ locale: string | null
327
+ images: OpenGraphImage[] | null
328
+ videos: OpenGraphVideo[] | null
329
+ audio: OpenGraphAudio[] | null
330
+ determiner: string | null
331
+ article: OpenGraphArticle | null
332
+ profile: OpenGraphProfile | null
333
+ book: OpenGraphBook | null
334
+ }
335
+
336
+ // ============================================================================
337
+ // Twitter Types
338
+ // ============================================================================
339
+
340
+ export type TwitterCardType = 'summary' | 'summary_large_image' | 'app' | 'player'
341
+
342
+ export interface TwitterImage {
343
+ url: string | URL
344
+ alt?: string
345
+ }
346
+
347
+ export interface TwitterPlayer {
348
+ playerUrl: string | URL
349
+ streamUrl?: string | URL
350
+ width: number
351
+ height: number
352
+ }
353
+
354
+ export interface TwitterApp {
355
+ id: {
356
+ iphone?: string | number
357
+ ipad?: string | number
358
+ googleplay?: string
359
+ }
360
+ url?: {
361
+ iphone?: string | URL
362
+ ipad?: string | URL
363
+ googleplay?: string | URL
364
+ }
365
+ name?: string
366
+ }
367
+
368
+ export interface Twitter {
369
+ card?: TwitterCardType
370
+ site?: string
371
+ siteId?: string
372
+ creator?: string
373
+ creatorId?: string
374
+ title?: string
375
+ description?: string
376
+ images?: string | URL | TwitterImage | (string | URL | TwitterImage)[]
377
+ // Player card
378
+ players?: TwitterPlayer | TwitterPlayer[]
379
+ // App card
380
+ app?: TwitterApp
381
+ }
382
+
383
+ export interface ResolvedTwitter {
384
+ card: TwitterCardType
385
+ site: string | null
386
+ siteId: string | null
387
+ creator: string | null
388
+ creatorId: string | null
389
+ title: string | null
390
+ description: string | null
391
+ images: TwitterImage[] | null
392
+ players: TwitterPlayer[] | null
393
+ app: TwitterApp | null
394
+ }
395
+
396
+ // ============================================================================
397
+ // JSON-LD Types
398
+ // ============================================================================
399
+
400
+ export type JsonLdType =
401
+ | 'Article'
402
+ | 'BlogPosting'
403
+ | 'NewsArticle'
404
+ | 'WebSite'
405
+ | 'WebPage'
406
+ | 'Organization'
407
+ | 'Person'
408
+ | 'Product'
409
+ | 'BreadcrumbList'
410
+ | 'FAQPage'
411
+ | 'HowTo'
412
+ | 'Recipe'
413
+ | 'Event'
414
+ | 'LocalBusiness'
415
+ | 'SoftwareApplication'
416
+
417
+ export interface JsonLd {
418
+ '@context'?: string
419
+ '@type': JsonLdType | string
420
+ [key: string]: unknown
421
+ }
422
+
423
+ // ============================================================================
424
+ // Main Metadata Interface
425
+ // ============================================================================
426
+
427
+ export interface Metadata {
428
+ // Base URL for resolving relative URLs
429
+ metadataBase?: string | URL | null
430
+
431
+ // Basic
432
+ title?: Title | null
433
+ description?: string | null
434
+ applicationName?: string | null
435
+ authors?: Author | Author[] | null
436
+ generator?: string | null
437
+ keywords?: string | string[] | null
438
+ referrer?: ReferrerEnum | null
439
+ creator?: string | null
440
+ publisher?: string | null
441
+ robots?: string | Robots | null
442
+
443
+ // Alternate URLs
444
+ alternates?: AlternateURLs | null
445
+
446
+ // Icons
447
+ icons?: IconURL | Icon[] | Icons | null
448
+
449
+ // Manifest
450
+ manifest?: string | URL | null
451
+
452
+ // Open Graph
453
+ openGraph?: OpenGraph | null
454
+
455
+ // Twitter
456
+ twitter?: Twitter | null
457
+
458
+ // Verification
459
+ verification?: Verification | null
460
+
461
+ // Category
462
+ category?: string | null
463
+ classification?: string | null
464
+
465
+ // JSON-LD
466
+ jsonLd?: JsonLd | JsonLd[] | null
467
+
468
+ // === Google SEO 최적화 ===
469
+
470
+ /** Google 전용 메타 설정 */
471
+ google?: GoogleMeta | null
472
+
473
+ /** 전화번호/이메일 자동 감지 설정 */
474
+ formatDetection?: FormatDetection | null
475
+
476
+ /** 리소스 힌트 (성능 최적화) */
477
+ resourceHints?: ResourceHint | null
478
+
479
+ /** Theme Color (브라우저 UI, PWA) */
480
+ themeColor?: string | ThemeColor | ThemeColor[] | null
481
+
482
+ /** Viewport 설정 (기본값: width=device-width, initial-scale=1) */
483
+ viewport?: string | {
484
+ width?: string | number
485
+ height?: string | number
486
+ initialScale?: number
487
+ minimumScale?: number
488
+ maximumScale?: number
489
+ userScalable?: boolean
490
+ viewportFit?: 'auto' | 'cover' | 'contain'
491
+ } | null
492
+
493
+ /** App Links (iOS/Android 앱 연동) */
494
+ appLinks?: AppLinks | null
495
+
496
+ // Other custom meta tags
497
+ other?: Record<string, string | number | (string | number)[]> | null
498
+ }
499
+
500
+ // ============================================================================
501
+ // Resolved Metadata (after processing)
502
+ // ============================================================================
503
+
504
+ export interface ResolvedMetadata {
505
+ metadataBase: URL | null
506
+ title: AbsoluteTemplateString | null
507
+ description: string | null
508
+ applicationName: string | null
509
+ authors: Author[] | null
510
+ generator: string | null
511
+ keywords: string[] | null
512
+ referrer: ReferrerEnum | null
513
+ creator: string | null
514
+ publisher: string | null
515
+ robots: ResolvedRobots | null
516
+ alternates: ResolvedAlternateURLs | null
517
+ icons: ResolvedIcons | null
518
+ manifest: URL | null
519
+ openGraph: ResolvedOpenGraph | null
520
+ twitter: ResolvedTwitter | null
521
+ verification: ResolvedVerification | null
522
+ category: string | null
523
+ classification: string | null
524
+ jsonLd: JsonLd[] | null
525
+ // Google SEO 최적화
526
+ google: GoogleMeta | null
527
+ formatDetection: FormatDetection | null
528
+ resourceHints: ResourceHint | null
529
+ themeColor: ThemeColor[] | null
530
+ viewport: string | null
531
+ appLinks: AppLinks | null
532
+ other: Record<string, string | number | (string | number)[]> | null
533
+ }
534
+
535
+ // ============================================================================
536
+ // Metadata Route Types (sitemap.ts, robots.ts)
537
+ // ============================================================================
538
+
539
+ export interface SitemapEntry {
540
+ url: string
541
+ lastModified?: string | Date
542
+ changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'
543
+ priority?: number
544
+ alternates?: {
545
+ languages?: Languages<string>
546
+ }
547
+ images?: string[]
548
+ }
549
+
550
+ export type Sitemap = SitemapEntry[]
551
+
552
+ export interface RobotsRule {
553
+ userAgent?: string | string[]
554
+ allow?: string | string[]
555
+ disallow?: string | string[]
556
+ crawlDelay?: number
557
+ }
558
+
559
+ export interface RobotsFile {
560
+ rules: RobotsRule | RobotsRule[]
561
+ sitemap?: string | string[]
562
+ host?: string
563
+ }
564
+
565
+ // ============================================================================
566
+ // Metadata Route Namespace
567
+ // ============================================================================
568
+
569
+ export namespace MetadataRoute {
570
+ export type Sitemap = SitemapEntry[]
571
+ export type Robots = RobotsFile
572
+ }
573
+
574
+ // ============================================================================
575
+ // Generator Function Types
576
+ // ============================================================================
577
+
578
+ export interface MetadataParams {
579
+ params: Record<string, string>
580
+ searchParams: Record<string, string>
581
+ }
582
+
583
+ export type GenerateMetadata = (
584
+ props: MetadataParams,
585
+ parent: Promise<ResolvedMetadata>
586
+ ) => Metadata | Promise<Metadata>
587
+
588
+ export type MetadataItem = Metadata | GenerateMetadata | null