emdash 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/dist/{adapters-DoNJiveC.d.mts → adapters-BktHA7EO.d.mts} +1 -1
  2. package/dist/{adapters-DoNJiveC.d.mts.map → adapters-BktHA7EO.d.mts.map} +1 -1
  3. package/dist/{apply-BzltprvY.mjs → apply-Ded_1vng.mjs} +167 -254
  4. package/dist/apply-Ded_1vng.mjs.map +1 -0
  5. package/dist/astro/index.d.mts +6 -6
  6. package/dist/astro/index.mjs +10 -2
  7. package/dist/astro/index.mjs.map +1 -1
  8. package/dist/astro/middleware/auth.d.mts +5 -5
  9. package/dist/astro/middleware/auth.mjs +5 -5
  10. package/dist/astro/middleware/redirect.mjs +5 -5
  11. package/dist/astro/middleware/request-context.mjs +4 -4
  12. package/dist/astro/middleware/setup.mjs +1 -1
  13. package/dist/astro/middleware.d.mts.map +1 -1
  14. package/dist/astro/middleware.mjs +94 -43
  15. package/dist/astro/middleware.mjs.map +1 -1
  16. package/dist/astro/types.d.mts +12 -11
  17. package/dist/astro/types.d.mts.map +1 -1
  18. package/dist/{base64-BRICGH2l.mjs → base64-MBPo9ozB.mjs} +1 -1
  19. package/dist/{base64-BRICGH2l.mjs.map → base64-MBPo9ozB.mjs.map} +1 -1
  20. package/dist/{byline-BSaNL1w7.mjs → byline-gFn1r0vA.mjs} +4 -4
  21. package/dist/{byline-BSaNL1w7.mjs.map → byline-gFn1r0vA.mjs.map} +1 -1
  22. package/dist/{bylines-CvJ3PYz2.mjs → bylines-DTFI8nDM.mjs} +5 -5
  23. package/dist/{bylines-CvJ3PYz2.mjs.map → bylines-DTFI8nDM.mjs.map} +1 -1
  24. package/dist/{cache-C6N_hhN7.mjs → cache-BAJbeoZ8.mjs} +3 -3
  25. package/dist/{cache-C6N_hhN7.mjs.map → cache-BAJbeoZ8.mjs.map} +1 -1
  26. package/dist/{chunks-NBQVDOci.mjs → chunks-BK1oZS-l.mjs} +2 -2
  27. package/dist/{chunks-NBQVDOci.mjs.map → chunks-BK1oZS-l.mjs.map} +1 -1
  28. package/dist/cli/index.mjs +342 -95
  29. package/dist/cli/index.mjs.map +1 -1
  30. package/dist/client/cf-access.d.mts +1 -1
  31. package/dist/client/index.d.mts +1 -1
  32. package/dist/client/index.mjs +1 -1
  33. package/dist/{config-BI0V3ICQ.mjs → config-CVssduLe.mjs} +1 -1
  34. package/dist/{config-BI0V3ICQ.mjs.map → config-CVssduLe.mjs.map} +1 -1
  35. package/dist/{content-8lOYF0pr.mjs → content-CERxPUN0.mjs} +14 -3
  36. package/dist/content-CERxPUN0.mjs.map +1 -0
  37. package/dist/database/instrumentation.d.mts +6 -4
  38. package/dist/database/instrumentation.d.mts.map +1 -1
  39. package/dist/database/instrumentation.mjs +19 -7
  40. package/dist/database/instrumentation.mjs.map +1 -1
  41. package/dist/db/index.d.mts +3 -3
  42. package/dist/db/index.mjs +1 -1
  43. package/dist/db/libsql.d.mts +1 -1
  44. package/dist/db/postgres.d.mts +1 -1
  45. package/dist/db/sqlite.d.mts +1 -1
  46. package/dist/{db-errors-WRezodiz.mjs → db-errors-B7P2pSCn.mjs} +1 -1
  47. package/dist/{db-errors-WRezodiz.mjs.map → db-errors-B7P2pSCn.mjs.map} +1 -1
  48. package/dist/{default-D8ksjWhO.mjs → default-pHuz9WF6.mjs} +1 -1
  49. package/dist/{default-D8ksjWhO.mjs.map → default-pHuz9WF6.mjs.map} +1 -1
  50. package/dist/{error-D_-tqP-I.mjs → error-DqnRMM5z.mjs} +1 -1
  51. package/dist/{error-D_-tqP-I.mjs.map → error-DqnRMM5z.mjs.map} +1 -1
  52. package/dist/{index-BFRaVcD6.d.mts → index-Cg-rC4Gj.d.mts} +110 -87
  53. package/dist/index-Cg-rC4Gj.d.mts.map +1 -0
  54. package/dist/index.d.mts +11 -11
  55. package/dist/index.mjs +29 -28
  56. package/dist/{load-DDqMMvZL.mjs → load-DR1VwFXR.mjs} +2 -2
  57. package/dist/{load-DDqMMvZL.mjs.map → load-DR1VwFXR.mjs.map} +1 -1
  58. package/dist/{loader-CKLbBnhK.mjs → loader-ou_PXAjg.mjs} +31 -6
  59. package/dist/loader-ou_PXAjg.mjs.map +1 -0
  60. package/dist/{manifest-schema-DqWNC3lM.mjs → manifest-schema-CXAbd1vH.mjs} +1 -1
  61. package/dist/{manifest-schema-DqWNC3lM.mjs.map → manifest-schema-CXAbd1vH.mjs.map} +1 -1
  62. package/dist/media/index.d.mts +1 -1
  63. package/dist/media/index.mjs +1 -1
  64. package/dist/media/local-runtime.d.mts +7 -7
  65. package/dist/media/local-runtime.mjs +3 -3
  66. package/dist/{media-BW32b4gi.mjs → media-1fFhub9c.mjs} +22 -10
  67. package/dist/media-1fFhub9c.mjs.map +1 -0
  68. package/dist/{mode-ier8jbBk.mjs → mode-YhqNVef_.mjs} +1 -1
  69. package/dist/{mode-ier8jbBk.mjs.map → mode-YhqNVef_.mjs.map} +1 -1
  70. package/dist/{options-BVp3UsTS.mjs → options-nPxWnrya.mjs} +1 -1
  71. package/dist/{options-BVp3UsTS.mjs.map → options-nPxWnrya.mjs.map} +1 -1
  72. package/dist/page/index.d.mts +2 -2
  73. package/dist/{patterns-CrCYkMBb.mjs → patterns-DsUZ4uxI.mjs} +1 -1
  74. package/dist/{patterns-CrCYkMBb.mjs.map → patterns-DsUZ4uxI.mjs.map} +1 -1
  75. package/dist/{placeholder-BE4o_2dc.d.mts → placeholder-CDPtkelt.d.mts} +1 -1
  76. package/dist/{placeholder-BE4o_2dc.d.mts.map → placeholder-CDPtkelt.d.mts.map} +1 -1
  77. package/dist/{placeholder-CIJejMlK.mjs → placeholder-Ci0RLeCk.mjs} +1 -1
  78. package/dist/{placeholder-CIJejMlK.mjs.map → placeholder-Ci0RLeCk.mjs.map} +1 -1
  79. package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
  80. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  81. package/dist/{public-url-DByxYjUw.mjs → public-url-B1AxbbbQ.mjs} +1 -1
  82. package/dist/{public-url-DByxYjUw.mjs.map → public-url-B1AxbbbQ.mjs.map} +1 -1
  83. package/dist/{query-Cg9ZKRQ0.mjs → query-8c_meo_K.mjs} +13 -13
  84. package/dist/{query-Cg9ZKRQ0.mjs.map → query-8c_meo_K.mjs.map} +1 -1
  85. package/dist/{redirect-BhUBKRc1.mjs → redirect-C5H7VGIX.mjs} +3 -3
  86. package/dist/{redirect-BhUBKRc1.mjs.map → redirect-C5H7VGIX.mjs.map} +1 -1
  87. package/dist/{registry-Dw70ChxB.mjs → registry-Do34mz_P.mjs} +7 -6
  88. package/dist/registry-Do34mz_P.mjs.map +1 -0
  89. package/dist/{request-cache-B-bmkipQ.mjs → request-cache-D4I69LeL.mjs} +6 -2
  90. package/dist/request-cache-D4I69LeL.mjs.map +1 -0
  91. package/dist/request-context.d.mts +27 -1
  92. package/dist/request-context.d.mts.map +1 -1
  93. package/dist/request-context.mjs +16 -3
  94. package/dist/request-context.mjs.map +1 -1
  95. package/dist/{runner-C7ADox5q.mjs → runner-DIcU2UCC.mjs} +465 -148
  96. package/dist/runner-DIcU2UCC.mjs.map +1 -0
  97. package/dist/{runner-Bnoj7vjK.d.mts → runner-Iu3IZSDM.d.mts} +2 -2
  98. package/dist/{runner-Bnoj7vjK.d.mts.map → runner-Iu3IZSDM.d.mts.map} +1 -1
  99. package/dist/runtime.d.mts +6 -6
  100. package/dist/runtime.mjs +3 -3
  101. package/dist/{search-dOGEccMa.mjs → search-DuWhx4NG.mjs} +322 -108
  102. package/dist/search-DuWhx4NG.mjs.map +1 -0
  103. package/dist/{secrets-CW3reAnU.mjs → secrets-CZ8rxLX3.mjs} +3 -3
  104. package/dist/{secrets-CW3reAnU.mjs.map → secrets-CZ8rxLX3.mjs.map} +1 -1
  105. package/dist/seed/index.d.mts +2 -2
  106. package/dist/seed/index.mjs +15 -14
  107. package/dist/seo/index.d.mts +1 -1
  108. package/dist/storage/local.d.mts +1 -1
  109. package/dist/storage/local.mjs +1 -1
  110. package/dist/storage/s3.d.mts +1 -1
  111. package/dist/storage/s3.mjs +1 -1
  112. package/dist/taxonomies-Bw76xAxo.mjs +407 -0
  113. package/dist/taxonomies-Bw76xAxo.mjs.map +1 -0
  114. package/dist/taxonomy-D6NvlKo8.mjs +218 -0
  115. package/dist/taxonomy-D6NvlKo8.mjs.map +1 -0
  116. package/dist/{tokens-D7zMmWi2.mjs → tokens-CyRDPVW2.mjs} +2 -2
  117. package/dist/{tokens-D7zMmWi2.mjs.map → tokens-CyRDPVW2.mjs.map} +1 -1
  118. package/dist/{transaction-Cn2rjY78.mjs → transaction-D44LBXvU.mjs} +1 -1
  119. package/dist/{transaction-Cn2rjY78.mjs.map → transaction-D44LBXvU.mjs.map} +1 -1
  120. package/dist/{transport-DNEfeMaU.d.mts → transport-DX_5rpsq.d.mts} +1 -1
  121. package/dist/{transport-DNEfeMaU.d.mts.map → transport-DX_5rpsq.d.mts.map} +1 -1
  122. package/dist/{transport-BeMCmin1.mjs → transport-xpzIjCIB.mjs} +1 -1
  123. package/dist/{transport-BeMCmin1.mjs.map → transport-xpzIjCIB.mjs.map} +1 -1
  124. package/dist/{types-CIOg5AR8.mjs → types-56BKbld_.mjs} +1 -1
  125. package/dist/types-56BKbld_.mjs.map +1 -0
  126. package/dist/{types-CRxNbK-Z.mjs → types-BIgulNsW.mjs} +2 -2
  127. package/dist/{types-CRxNbK-Z.mjs.map → types-BIgulNsW.mjs.map} +1 -1
  128. package/dist/{types-CrtWgIvl.d.mts → types-BQx6ZXpR.d.mts} +10 -1
  129. package/dist/types-BQx6ZXpR.d.mts.map +1 -0
  130. package/dist/{types-CJsYGpco.d.mts → types-B_CXXnzh.d.mts} +1 -1
  131. package/dist/{types-CJsYGpco.d.mts.map → types-B_CXXnzh.d.mts.map} +1 -1
  132. package/dist/{types-M78DQ1lx.d.mts → types-C-aFbqmA.d.mts} +1 -1
  133. package/dist/{types-M78DQ1lx.d.mts.map → types-C-aFbqmA.d.mts.map} +1 -1
  134. package/dist/types-DiI8NOG_.mjs +16 -0
  135. package/dist/types-DiI8NOG_.mjs.map +1 -0
  136. package/dist/{types-BuBIptGk.d.mts → types-IN5z_S3P.d.mts} +158 -92
  137. package/dist/types-IN5z_S3P.d.mts.map +1 -0
  138. package/dist/{types-BSyXeCFW.d.mts → types-IZSZfEwv.d.mts} +4 -3
  139. package/dist/types-IZSZfEwv.d.mts.map +1 -0
  140. package/dist/{types-CDbKp7ND.mjs → types-K-EkEQCI.mjs} +1 -1
  141. package/dist/{types-CDbKp7ND.mjs.map → types-K-EkEQCI.mjs.map} +1 -1
  142. package/dist/{validate-BfQh_C_y.d.mts → validate-CO3JjFV5.d.mts} +22 -5
  143. package/dist/validate-CO3JjFV5.d.mts.map +1 -0
  144. package/dist/{validate-Baqf0slj.mjs → validate-UK4Ja1uo.mjs} +14 -10
  145. package/dist/validate-UK4Ja1uo.mjs.map +1 -0
  146. package/dist/{validation-BfEI7tNe.mjs → validation-Vc5DQkJa.mjs} +5 -5
  147. package/dist/{validation-BfEI7tNe.mjs.map → validation-Vc5DQkJa.mjs.map} +1 -1
  148. package/dist/version-Bg31I_Ff.mjs +7 -0
  149. package/dist/{version-DoxrVdYf.mjs.map → version-Bg31I_Ff.mjs.map} +1 -1
  150. package/dist/{zod-generator-CC0xNe_K.mjs → zod-generator-CHnJUP2l.mjs} +8 -3
  151. package/dist/zod-generator-CHnJUP2l.mjs.map +1 -0
  152. package/package.json +9 -8
  153. package/src/api/errors.ts +5 -0
  154. package/src/api/handlers/content.ts +20 -0
  155. package/src/api/handlers/dashboard.ts +29 -36
  156. package/src/api/handlers/media-allowlist.ts +40 -0
  157. package/src/api/handlers/media.ts +1 -1
  158. package/src/api/handlers/menus.ts +400 -89
  159. package/src/api/handlers/taxonomies.ts +273 -97
  160. package/src/api/handlers/validate-media-fields.ts +125 -0
  161. package/src/api/schemas/common.ts +7 -0
  162. package/src/api/schemas/media.ts +23 -3
  163. package/src/api/schemas/menus.ts +23 -0
  164. package/src/api/schemas/schema.ts +11 -2
  165. package/src/api/schemas/taxonomies.ts +39 -0
  166. package/src/astro/integration/routes.ts +10 -0
  167. package/src/astro/middleware.ts +46 -11
  168. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +1 -1
  169. package/src/astro/routes/api/import/wordpress/rewrite-url-helpers.ts +196 -0
  170. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +9 -177
  171. package/src/astro/routes/api/media/upload-url.ts +10 -4
  172. package/src/astro/routes/api/media.ts +12 -4
  173. package/src/astro/routes/api/menus/[name]/items.ts +16 -6
  174. package/src/astro/routes/api/menus/[name]/reorder.ts +8 -3
  175. package/src/astro/routes/api/menus/[name]/translations.ts +82 -0
  176. package/src/astro/routes/api/menus/[name].ts +19 -10
  177. package/src/astro/routes/api/menus/index.ts +9 -6
  178. package/src/astro/routes/api/taxonomies/[name]/terms/[slug]/translations.ts +89 -0
  179. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +22 -22
  180. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +11 -14
  181. package/src/astro/routes/api/taxonomies/index.ts +9 -6
  182. package/src/astro/types.ts +5 -1
  183. package/src/auth/rate-limit.ts +3 -3
  184. package/src/cli/commands/bundle-utils.ts +81 -6
  185. package/src/cli/commands/bundle.ts +18 -15
  186. package/src/cli/commands/export-seed.ts +139 -24
  187. package/src/cli/commands/plugin-init.ts +216 -90
  188. package/src/database/instrumentation.ts +22 -8
  189. package/src/database/migrations/016_api_tokens.ts +18 -3
  190. package/src/database/migrations/036_i18n_menus_and_taxonomies.ts +477 -0
  191. package/src/database/migrations/037_credential_algorithm.ts +18 -0
  192. package/src/database/migrations/runner.ts +4 -0
  193. package/src/database/repositories/content.ts +11 -0
  194. package/src/database/repositories/media.ts +40 -10
  195. package/src/database/repositories/taxonomy.ts +193 -89
  196. package/src/database/types.ts +12 -3
  197. package/src/emdash-runtime.ts +16 -3
  198. package/src/fields/file.ts +7 -6
  199. package/src/fields/image.ts +12 -11
  200. package/src/fields/types.ts +3 -0
  201. package/src/i18n/resolve.ts +37 -0
  202. package/src/index.ts +1 -1
  203. package/src/loader.ts +49 -2
  204. package/src/mcp/server.ts +114 -26
  205. package/src/media/mime.ts +75 -0
  206. package/src/menus/index.ts +143 -124
  207. package/src/menus/types.ts +15 -1
  208. package/src/plugins/types.ts +81 -191
  209. package/src/request-cache.ts +6 -2
  210. package/src/request-context.ts +42 -2
  211. package/src/schema/registry.ts +5 -5
  212. package/src/schema/types.ts +3 -2
  213. package/src/schema/zod-generator.ts +12 -2
  214. package/src/seed/apply.ts +157 -54
  215. package/src/seed/types.ts +18 -1
  216. package/src/seed/validate.ts +27 -13
  217. package/src/taxonomies/index.ts +230 -213
  218. package/src/taxonomies/types.ts +10 -0
  219. package/dist/apply-BzltprvY.mjs.map +0 -1
  220. package/dist/content-8lOYF0pr.mjs.map +0 -1
  221. package/dist/index-BFRaVcD6.d.mts.map +0 -1
  222. package/dist/loader-CKLbBnhK.mjs.map +0 -1
  223. package/dist/media-BW32b4gi.mjs.map +0 -1
  224. package/dist/registry-Dw70ChxB.mjs.map +0 -1
  225. package/dist/request-cache-B-bmkipQ.mjs.map +0 -1
  226. package/dist/runner-C7ADox5q.mjs.map +0 -1
  227. package/dist/search-dOGEccMa.mjs.map +0 -1
  228. package/dist/taxonomies-ZlRtD6AG.mjs +0 -315
  229. package/dist/taxonomies-ZlRtD6AG.mjs.map +0 -1
  230. package/dist/types-4fVtCIm0.mjs +0 -68
  231. package/dist/types-4fVtCIm0.mjs.map +0 -1
  232. package/dist/types-BSyXeCFW.d.mts.map +0 -1
  233. package/dist/types-BuBIptGk.d.mts.map +0 -1
  234. package/dist/types-CIOg5AR8.mjs.map +0 -1
  235. package/dist/types-CrtWgIvl.d.mts.map +0 -1
  236. package/dist/validate-Baqf0slj.mjs.map +0 -1
  237. package/dist/validate-BfQh_C_y.d.mts.map +0 -1
  238. package/dist/version-DoxrVdYf.mjs +0 -7
  239. package/dist/zod-generator-CC0xNe_K.mjs.map +0 -1
@@ -118,4 +118,4 @@ interface PostgresConfig {
118
118
  declare function postgres(config: PostgresConfig): DatabaseDescriptor;
119
119
  //#endregion
120
120
  export { SqliteConfig as a, sqlite as c, PostgresConfig as i, DatabaseDialectType as n, libsql as o, LibsqlConfig as r, postgres as s, DatabaseDescriptor as t };
121
- //# sourceMappingURL=adapters-DoNJiveC.d.mts.map
121
+ //# sourceMappingURL=adapters-BktHA7EO.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapters-DoNJiveC.d.mts","names":[],"sources":["../src/db/adapters.ts"],"mappings":";;AA0BA;;;;;AAKA;;;;;;;;;;;AAqBA;;;;;AAOA;;;KAjCY,mBAAA;;AAsDZ;;UAjDiB,kBAAA;EAChB,UAAA;EACA,MAAA;EACA,IAAA,EAAM,mBAAA;EA8CuC;;;AAqB9C;;;;;;;;;AAWA;;EA/DC,oBAAA;AAAA;AAAA,UAGgB,YAAA;EA8DhB;;;EA1DA,GAAA;AAAA;AAAA,UAGgB,YAAA;EA6DhB;;;EAzDA,GAAA;EAyD0B;AAa3B;;EAlEC,SAAA;AAAA;;;;;;;;;;;iBAae,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,kBAAA;;;;;;;;;;;;;;iBAqB9B,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,kBAAA;;;;UAW7B,cAAA;EAChB,gBAAA;EACA,IAAA;EACA,IAAA;EACA,QAAA;EACA,IAAA;EACA,QAAA;EACA,GAAA;EACA,IAAA;IAAS,GAAA;IAAc,GAAA;EAAA;AAAA;;;;;;;;;;;iBAaR,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,kBAAA"}
1
+ {"version":3,"file":"adapters-BktHA7EO.d.mts","names":[],"sources":["../src/db/adapters.ts"],"mappings":";;AA0BA;;;;;AAKA;;;;;;;;;;;AAqBA;;;;;AAOA;;;KAjCY,mBAAA;;AAsDZ;;UAjDiB,kBAAA;EAChB,UAAA;EACA,MAAA;EACA,IAAA,EAAM,mBAAA;EA8CuC;;;AAqB9C;;;;;;;;;AAWA;;EA/DC,oBAAA;AAAA;AAAA,UAGgB,YAAA;EA8DhB;;;EA1DA,GAAA;AAAA;AAAA,UAGgB,YAAA;EA6DhB;;;EAzDA,GAAA;EAyD0B;AAa3B;;EAlEC,SAAA;AAAA;;;;;;;;;;;iBAae,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,kBAAA;;;;;;;;;;;;;;iBAqB9B,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,kBAAA;;;;UAW7B,cAAA;EAChB,gBAAA;EACA,IAAA;EACA,IAAA;EACA,QAAA;EACA,IAAA;EACA,QAAA;EACA,GAAA;EACA,IAAA;IAAS,GAAA;IAAc,GAAA;EAAA;AAAA;;;;;;;;;;;iBAaR,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,kBAAA"}
@@ -1,183 +1,20 @@
1
- import { i as __exportAll } from "./runner-C7ADox5q.mjs";
2
- import { r as RevisionRepository, t as ContentRepository } from "./content-8lOYF0pr.mjs";
3
- import { t as MediaRepository } from "./media-BW32b4gi.mjs";
4
- import { t as OptionsRepository } from "./options-BVp3UsTS.mjs";
5
- import { t as withTransaction } from "./transaction-Cn2rjY78.mjs";
6
- import { t as RedirectRepository } from "./redirect-BhUBKRc1.mjs";
7
- import { t as BylineRepository } from "./byline-BSaNL1w7.mjs";
8
- import { i as FTSManager, n as SchemaRegistry } from "./registry-Dw70ChxB.mjs";
9
- import { r as getDb } from "./loader-CKLbBnhK.mjs";
10
- import { n as requestCached, t as peekRequestCache } from "./request-cache-B-bmkipQ.mjs";
11
- import { t as validateSeed } from "./validate-Baqf0slj.mjs";
1
+ import { i as __exportAll } from "./runner-DIcU2UCC.mjs";
2
+ import { n as getI18nConfig } from "./config-CVssduLe.mjs";
3
+ import { r as RevisionRepository, t as ContentRepository } from "./content-CERxPUN0.mjs";
4
+ import { t as MediaRepository } from "./media-1fFhub9c.mjs";
5
+ import { t as TaxonomyRepository } from "./taxonomy-D6NvlKo8.mjs";
6
+ import { t as OptionsRepository } from "./options-nPxWnrya.mjs";
7
+ import { t as withTransaction } from "./transaction-D44LBXvU.mjs";
8
+ import { t as RedirectRepository } from "./redirect-C5H7VGIX.mjs";
9
+ import { t as BylineRepository } from "./byline-gFn1r0vA.mjs";
10
+ import { n as requestCached, t as peekRequestCache } from "./request-cache-D4I69LeL.mjs";
11
+ import { i as FTSManager, n as SchemaRegistry } from "./registry-Do34mz_P.mjs";
12
+ import { r as getDb } from "./loader-ou_PXAjg.mjs";
13
+ import { t as validateSeed } from "./validate-UK4Ja1uo.mjs";
12
14
  import { ulid } from "ulidx";
13
15
  import { imageSize } from "image-size";
14
16
  import mime from "mime/lite";
15
17
 
16
- //#region src/database/repositories/taxonomy.ts
17
- /**
18
- * Taxonomy repository for categories, tags, and other classification
19
- *
20
- * Taxonomies are hierarchical (via parentId) and can be attached to content entries.
21
- */
22
- var TaxonomyRepository = class {
23
- constructor(db) {
24
- this.db = db;
25
- }
26
- /**
27
- * Create a new taxonomy term
28
- */
29
- async create(input) {
30
- const id = ulid();
31
- const parentId = input.parentId === void 0 || input.parentId === "" ? null : input.parentId;
32
- const row = {
33
- id,
34
- name: input.name,
35
- slug: input.slug,
36
- label: input.label,
37
- parent_id: parentId,
38
- data: input.data ? JSON.stringify(input.data) : null
39
- };
40
- await this.db.insertInto("taxonomies").values(row).execute();
41
- const taxonomy = await this.findById(id);
42
- if (!taxonomy) throw new Error("Failed to create taxonomy");
43
- return taxonomy;
44
- }
45
- /**
46
- * Find taxonomy by ID
47
- */
48
- async findById(id) {
49
- const row = await this.db.selectFrom("taxonomies").selectAll().where("id", "=", id).executeTakeFirst();
50
- return row ? this.rowToTaxonomy(row) : null;
51
- }
52
- /**
53
- * Find taxonomy by name and slug (unique constraint)
54
- */
55
- async findBySlug(name, slug) {
56
- const row = await this.db.selectFrom("taxonomies").selectAll().where("name", "=", name).where("slug", "=", slug).executeTakeFirst();
57
- return row ? this.rowToTaxonomy(row) : null;
58
- }
59
- /**
60
- * Get all terms for a taxonomy (e.g., all categories)
61
- */
62
- async findByName(name, options = {}) {
63
- let query = this.db.selectFrom("taxonomies").selectAll().where("name", "=", name).orderBy("label", "asc").orderBy("id", "asc");
64
- if (options.parentId !== void 0) if (options.parentId === null) query = query.where("parent_id", "is", null);
65
- else query = query.where("parent_id", "=", options.parentId);
66
- return (await query.execute()).map((row) => this.rowToTaxonomy(row));
67
- }
68
- /**
69
- * Get children of a taxonomy term
70
- */
71
- async findChildren(parentId) {
72
- return (await this.db.selectFrom("taxonomies").selectAll().where("parent_id", "=", parentId).orderBy("label", "asc").orderBy("id", "asc").execute()).map((row) => this.rowToTaxonomy(row));
73
- }
74
- /**
75
- * Update a taxonomy term
76
- */
77
- async update(id, input) {
78
- if (!await this.findById(id)) return null;
79
- const updates = {};
80
- if (input.slug !== void 0) updates.slug = input.slug;
81
- if (input.label !== void 0) updates.label = input.label;
82
- if (input.parentId !== void 0) updates.parent_id = input.parentId === "" ? null : input.parentId;
83
- if (input.data !== void 0) updates.data = JSON.stringify(input.data);
84
- if (Object.keys(updates).length > 0) await this.db.updateTable("taxonomies").set(updates).where("id", "=", id).execute();
85
- return this.findById(id);
86
- }
87
- /**
88
- * Delete a taxonomy term
89
- */
90
- async delete(id) {
91
- await this.db.deleteFrom("content_taxonomies").where("taxonomy_id", "=", id).execute();
92
- return ((await this.db.deleteFrom("taxonomies").where("id", "=", id).executeTakeFirst()).numDeletedRows ?? 0) > 0;
93
- }
94
- /**
95
- * Attach a taxonomy term to a content entry
96
- */
97
- async attachToEntry(collection, entryId, taxonomyId) {
98
- const row = {
99
- collection,
100
- entry_id: entryId,
101
- taxonomy_id: taxonomyId
102
- };
103
- await this.db.insertInto("content_taxonomies").values(row).onConflict((oc) => oc.doNothing()).execute();
104
- }
105
- /**
106
- * Detach a taxonomy term from a content entry
107
- */
108
- async detachFromEntry(collection, entryId, taxonomyId) {
109
- await this.db.deleteFrom("content_taxonomies").where("collection", "=", collection).where("entry_id", "=", entryId).where("taxonomy_id", "=", taxonomyId).execute();
110
- }
111
- /**
112
- * Get all taxonomy terms for a content entry
113
- */
114
- async getTermsForEntry(collection, entryId, taxonomyName) {
115
- let query = this.db.selectFrom("content_taxonomies").innerJoin("taxonomies", "taxonomies.id", "content_taxonomies.taxonomy_id").selectAll("taxonomies").where("content_taxonomies.collection", "=", collection).where("content_taxonomies.entry_id", "=", entryId);
116
- if (taxonomyName) query = query.where("taxonomies.name", "=", taxonomyName);
117
- return (await query.execute()).map((row) => this.rowToTaxonomy(row));
118
- }
119
- /**
120
- * Set all taxonomy terms for a content entry (replaces existing)
121
- * Uses batch operations to avoid N+1 queries.
122
- */
123
- async setTermsForEntry(collection, entryId, taxonomyName, taxonomyIds) {
124
- const current = await this.getTermsForEntry(collection, entryId, taxonomyName);
125
- const currentIds = new Set(current.map((t) => t.id));
126
- const newIds = new Set(taxonomyIds);
127
- const toRemove = current.filter((t) => !newIds.has(t.id)).map((t) => t.id);
128
- if (toRemove.length > 0) await this.db.deleteFrom("content_taxonomies").where("collection", "=", collection).where("entry_id", "=", entryId).where("taxonomy_id", "in", toRemove).execute();
129
- const toAdd = taxonomyIds.filter((id) => !currentIds.has(id));
130
- if (toAdd.length > 0) await this.db.insertInto("content_taxonomies").values(toAdd.map((taxonomy_id) => ({
131
- collection,
132
- entry_id: entryId,
133
- taxonomy_id
134
- }))).onConflict((oc) => oc.doNothing()).execute();
135
- }
136
- /**
137
- * Remove all taxonomy associations for an entry (use when entry is deleted)
138
- */
139
- async clearEntryTerms(collection, entryId) {
140
- const result = await this.db.deleteFrom("content_taxonomies").where("collection", "=", collection).where("entry_id", "=", entryId).executeTakeFirst();
141
- return Number(result.numDeletedRows ?? 0);
142
- }
143
- /**
144
- * Count entries that have a specific taxonomy term
145
- */
146
- async countEntriesWithTerm(taxonomyId) {
147
- const result = await this.db.selectFrom("content_taxonomies").select((eb) => eb.fn.count("entry_id").as("count")).where("taxonomy_id", "=", taxonomyId).executeTakeFirst();
148
- return Number(result?.count || 0);
149
- }
150
- /**
151
- * Batch count entries for multiple taxonomy term IDs.
152
- * Chunks the query at SQL_BATCH_SIZE to stay below D1's bind-parameter limit.
153
- * Returns a Map from term ID to count.
154
- */
155
- async countEntriesForTerms(termIds) {
156
- if (termIds.length === 0) return /* @__PURE__ */ new Map();
157
- const { chunks, SQL_BATCH_SIZE } = await import("./chunks-NBQVDOci.mjs").then((n) => n.r);
158
- const counts = /* @__PURE__ */ new Map();
159
- for (const chunk of chunks(termIds, SQL_BATCH_SIZE)) {
160
- const rows = await this.db.selectFrom("content_taxonomies").select(["taxonomy_id", (eb) => eb.fn.count("entry_id").as("count")]).where("taxonomy_id", "in", chunk).groupBy("taxonomy_id").execute();
161
- for (const row of rows) counts.set(row.taxonomy_id, Number(row.count || 0));
162
- }
163
- return counts;
164
- }
165
- /**
166
- * Convert database row to Taxonomy object
167
- */
168
- rowToTaxonomy(row) {
169
- return {
170
- id: row.id,
171
- name: row.name,
172
- slug: row.slug,
173
- label: row.label,
174
- parentId: row.parent_id,
175
- data: row.data ? JSON.parse(row.data) : null
176
- };
177
- }
178
- };
179
-
180
- //#endregion
181
18
  //#region src/settings/index.ts
182
19
  /** Prefix for site settings in the options table */
183
20
  const SETTINGS_PREFIX = "site:";
@@ -895,49 +732,78 @@ async function applySeed(db, seed, options = {}) {
895
732
  }
896
733
  }
897
734
  }
898
- if (seed.taxonomies) for (const taxonomy of seed.taxonomies) {
899
- const existingDef = await db.selectFrom("_emdash_taxonomy_defs").selectAll().where("name", "=", taxonomy.name).executeTakeFirst();
900
- if (existingDef) {
901
- if (onConflict === "error") throw new Error(`Conflict: taxonomy "${taxonomy.name}" already exists`);
902
- if (onConflict === "update") await db.updateTable("_emdash_taxonomy_defs").set({
903
- label: taxonomy.label,
904
- label_singular: taxonomy.labelSingular ?? null,
905
- hierarchical: taxonomy.hierarchical ? 1 : 0,
906
- collections: JSON.stringify(taxonomy.collections)
907
- }).where("id", "=", existingDef.id).execute();
908
- } else {
909
- await db.insertInto("_emdash_taxonomy_defs").values({
910
- id: ulid(),
911
- name: taxonomy.name,
912
- label: taxonomy.label,
913
- label_singular: taxonomy.labelSingular ?? null,
914
- hierarchical: taxonomy.hierarchical ? 1 : 0,
915
- collections: JSON.stringify(taxonomy.collections)
916
- }).execute();
917
- result.taxonomies.created++;
918
- }
919
- if (taxonomy.terms && taxonomy.terms.length > 0) {
920
- const termRepo = new TaxonomyRepository(db);
921
- if (taxonomy.hierarchical) await applyHierarchicalTerms(termRepo, taxonomy.name, taxonomy.terms, result, onConflict);
922
- else for (const term of taxonomy.terms) {
923
- const existing = await termRepo.findBySlug(taxonomy.name, term.slug);
924
- if (existing) {
925
- if (onConflict === "error") throw new Error(`Conflict: taxonomy term "${term.slug}" in "${taxonomy.name}" already exists`);
926
- if (onConflict === "update") {
927
- await termRepo.update(existing.id, {
735
+ if (seed.taxonomies) {
736
+ const defSeedIdMap = /* @__PURE__ */ new Map();
737
+ const termSeedIdMap = /* @__PURE__ */ new Map();
738
+ const fallbackLocale = getI18nConfig()?.defaultLocale ?? "en";
739
+ for (const taxonomy of seed.taxonomies) {
740
+ const defLocale = taxonomy.locale ?? fallbackLocale;
741
+ const existingDef = await db.selectFrom("_emdash_taxonomy_defs").selectAll().where("name", "=", taxonomy.name).where("locale", "=", defLocale).executeTakeFirst();
742
+ let defId;
743
+ let defTranslationGroup;
744
+ if (existingDef) {
745
+ defId = existingDef.id;
746
+ defTranslationGroup = existingDef.translation_group ?? existingDef.id;
747
+ if (onConflict === "error") throw new Error(`Conflict: taxonomy "${taxonomy.name}" (${defLocale}) already exists`);
748
+ if (onConflict === "update") await db.updateTable("_emdash_taxonomy_defs").set({
749
+ label: taxonomy.label,
750
+ label_singular: taxonomy.labelSingular ?? null,
751
+ hierarchical: taxonomy.hierarchical ? 1 : 0,
752
+ collections: JSON.stringify(taxonomy.collections)
753
+ }).where("id", "=", existingDef.id).execute();
754
+ } else {
755
+ defId = ulid();
756
+ defTranslationGroup = defId;
757
+ if (taxonomy.translationOf) {
758
+ const source = defSeedIdMap.get(taxonomy.translationOf);
759
+ if (source) defTranslationGroup = source.translationGroup;
760
+ else console.warn(`taxonomy "${taxonomy.name}" (${defLocale}): translationOf "${taxonomy.translationOf}" not found yet; minting a fresh group.`);
761
+ }
762
+ await db.insertInto("_emdash_taxonomy_defs").values({
763
+ id: defId,
764
+ name: taxonomy.name,
765
+ label: taxonomy.label,
766
+ label_singular: taxonomy.labelSingular ?? null,
767
+ hierarchical: taxonomy.hierarchical ? 1 : 0,
768
+ collections: JSON.stringify(taxonomy.collections),
769
+ locale: defLocale,
770
+ translation_group: defTranslationGroup
771
+ }).execute();
772
+ result.taxonomies.created++;
773
+ }
774
+ if (taxonomy.id) defSeedIdMap.set(taxonomy.id, {
775
+ id: defId,
776
+ translationGroup: defTranslationGroup
777
+ });
778
+ if (taxonomy.terms && taxonomy.terms.length > 0) {
779
+ const termRepo = new TaxonomyRepository(db);
780
+ if (taxonomy.hierarchical) await applyHierarchicalTerms(termRepo, taxonomy.name, defLocale, taxonomy.terms, termSeedIdMap, result, onConflict);
781
+ else for (const term of taxonomy.terms) {
782
+ const termLocale = term.locale ?? defLocale;
783
+ const existing = await termRepo.findBySlug(taxonomy.name, term.slug, termLocale);
784
+ if (existing) {
785
+ if (onConflict === "error") throw new Error(`Conflict: taxonomy term "${term.slug}" in "${taxonomy.name}" (${termLocale}) already exists`);
786
+ if (onConflict === "update") {
787
+ await termRepo.update(existing.id, {
788
+ label: term.label,
789
+ data: term.description ? { description: term.description } : {}
790
+ });
791
+ result.taxonomies.terms++;
792
+ }
793
+ if (term.id) termSeedIdMap.set(term.id, existing.id);
794
+ } else {
795
+ const translationOf = term.translationOf ? termSeedIdMap.get(term.translationOf) : void 0;
796
+ const created = await termRepo.create({
797
+ name: taxonomy.name,
798
+ slug: term.slug,
928
799
  label: term.label,
929
- data: term.description ? { description: term.description } : {}
800
+ data: term.description ? { description: term.description } : void 0,
801
+ locale: termLocale,
802
+ translationOf
930
803
  });
804
+ if (term.id) termSeedIdMap.set(term.id, created.id);
931
805
  result.taxonomies.terms++;
932
806
  }
933
- } else {
934
- await termRepo.create({
935
- name: taxonomy.name,
936
- slug: term.slug,
937
- label: term.label,
938
- data: term.description ? { description: term.description } : void 0
939
- });
940
- result.taxonomies.terms++;
941
807
  }
942
808
  }
943
809
  }
@@ -1040,25 +906,45 @@ async function applySeed(db, seed, options = {}) {
1040
906
  result.content.created++;
1041
907
  }
1042
908
  }
1043
- if (seed.menus) for (const menu of seed.menus) {
1044
- const existingMenu = await db.selectFrom("_emdash_menus").selectAll().where("name", "=", menu.name).executeTakeFirst();
1045
- let menuId;
1046
- if (existingMenu) {
1047
- menuId = existingMenu.id;
1048
- await db.deleteFrom("_emdash_menu_items").where("menu_id", "=", menuId).execute();
1049
- } else {
1050
- menuId = ulid();
1051
- await db.insertInto("_emdash_menus").values({
909
+ if (seed.menus) {
910
+ const menuSeedIdMap = /* @__PURE__ */ new Map();
911
+ const itemSeedIdMap = /* @__PURE__ */ new Map();
912
+ const fallbackLocale = getI18nConfig()?.defaultLocale ?? "en";
913
+ for (const menu of seed.menus) {
914
+ const locale = menu.locale ?? fallbackLocale;
915
+ const existingMenu = await db.selectFrom("_emdash_menus").selectAll().where("name", "=", menu.name).where("locale", "=", locale).executeTakeFirst();
916
+ let menuId;
917
+ let translationGroup;
918
+ if (existingMenu) {
919
+ menuId = existingMenu.id;
920
+ translationGroup = existingMenu.translation_group ?? existingMenu.id;
921
+ await db.deleteFrom("_emdash_menu_items").where("menu_id", "=", menuId).execute();
922
+ } else {
923
+ menuId = ulid();
924
+ translationGroup = menuId;
925
+ if (menu.translationOf) {
926
+ const source = menuSeedIdMap.get(menu.translationOf);
927
+ if (source) translationGroup = source.translationGroup;
928
+ else console.warn(`menu "${menu.name}" (${locale}): translationOf "${menu.translationOf}" not found yet; minting a fresh group.`);
929
+ }
930
+ await db.insertInto("_emdash_menus").values({
931
+ id: menuId,
932
+ name: menu.name,
933
+ label: menu.label,
934
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
935
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
936
+ locale,
937
+ translation_group: translationGroup
938
+ }).execute();
939
+ result.menus.created++;
940
+ }
941
+ if (menu.id) menuSeedIdMap.set(menu.id, {
1052
942
  id: menuId,
1053
- name: menu.name,
1054
- label: menu.label,
1055
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
1056
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1057
- }).execute();
1058
- result.menus.created++;
943
+ translationGroup
944
+ });
945
+ const itemCount = await applyMenuItems(db, menuId, locale, menu.items, null, 0, seedIdMap, itemSeedIdMap);
946
+ result.menus.items += itemCount;
1059
947
  }
1060
- const itemCount = await applyMenuItems(db, menuId, menu.items, null, 0, seedIdMap);
1061
- result.menus.items += itemCount;
1062
948
  }
1063
949
  if (seed.redirects) {
1064
950
  const redirectRepo = new RedirectRepository(db);
@@ -1157,9 +1043,9 @@ async function applySeed(db, seed, options = {}) {
1157
1043
  }
1158
1044
  }
1159
1045
  }
1160
- const { invalidateBylineCache } = await import("./bylines-CvJ3PYz2.mjs").then((n) => n.t);
1161
- const { invalidateRedirectCache } = await import("./cache-C6N_hhN7.mjs").then((n) => n.t);
1162
- const { invalidateUrlPatternCache } = await import("./query-Cg9ZKRQ0.mjs").then((n) => n.o);
1046
+ const { invalidateBylineCache } = await import("./bylines-DTFI8nDM.mjs").then((n) => n.t);
1047
+ const { invalidateRedirectCache } = await import("./cache-BAJbeoZ8.mjs").then((n) => n.t);
1048
+ const { invalidateUrlPatternCache } = await import("./query-8c_meo_K.mjs").then((n) => n.o);
1163
1049
  invalidateBylineCache();
1164
1050
  invalidateRedirectCache();
1165
1051
  invalidateUrlPatternCache();
@@ -1168,17 +1054,22 @@ async function applySeed(db, seed, options = {}) {
1168
1054
  /**
1169
1055
  * Apply hierarchical taxonomy terms (parents before children)
1170
1056
  */
1171
- async function applyHierarchicalTerms(termRepo, taxonomyName, terms, result, onConflict = "skip") {
1057
+ async function applyHierarchicalTerms(termRepo, taxonomyName, defLocale, terms, termSeedIdMap, result, onConflict = "skip") {
1172
1058
  const slugToId = /* @__PURE__ */ new Map();
1173
1059
  let remaining = [...terms];
1174
1060
  let maxPasses = 10;
1175
1061
  while (remaining.length > 0 && maxPasses > 0) {
1176
1062
  const processedThisPass = [];
1177
- for (const term of remaining) if (!term.parent || slugToId.has(term.parent)) {
1178
- const parentId = term.parent ? slugToId.get(term.parent) : void 0;
1179
- const existing = await termRepo.findBySlug(taxonomyName, term.slug);
1063
+ for (const term of remaining) {
1064
+ const termLocale = term.locale ?? defLocale;
1065
+ const parentReady = !term.parent || slugToId.has(`${termLocale}::${term.parent}`);
1066
+ const translationReady = !term.translationOf || termSeedIdMap.has(term.translationOf);
1067
+ if (!parentReady || !translationReady) continue;
1068
+ const parentId = term.parent ? slugToId.get(`${termLocale}::${term.parent}`) : void 0;
1069
+ const translationOf = term.translationOf ? termSeedIdMap.get(term.translationOf) : void 0;
1070
+ const existing = await termRepo.findBySlug(taxonomyName, term.slug, termLocale);
1180
1071
  if (existing) {
1181
- if (onConflict === "error") throw new Error(`Conflict: taxonomy term "${term.slug}" in "${taxonomyName}" already exists`);
1072
+ if (onConflict === "error") throw new Error(`Conflict: taxonomy term "${term.slug}" in "${taxonomyName}" (${termLocale}) already exists`);
1182
1073
  if (onConflict === "update") {
1183
1074
  await termRepo.update(existing.id, {
1184
1075
  label: term.label,
@@ -1187,24 +1078,28 @@ async function applyHierarchicalTerms(termRepo, taxonomyName, terms, result, onC
1187
1078
  });
1188
1079
  result.taxonomies.terms++;
1189
1080
  }
1190
- slugToId.set(term.slug, existing.id);
1081
+ slugToId.set(`${termLocale}::${term.slug}`, existing.id);
1082
+ if (term.id) termSeedIdMap.set(term.id, existing.id);
1191
1083
  } else {
1192
1084
  const created = await termRepo.create({
1193
1085
  name: taxonomyName,
1194
1086
  slug: term.slug,
1195
1087
  label: term.label,
1196
1088
  parentId,
1197
- data: term.description ? { description: term.description } : void 0
1089
+ data: term.description ? { description: term.description } : void 0,
1090
+ locale: termLocale,
1091
+ translationOf
1198
1092
  });
1199
- slugToId.set(term.slug, created.id);
1093
+ slugToId.set(`${termLocale}::${term.slug}`, created.id);
1094
+ if (term.id) termSeedIdMap.set(term.id, created.id);
1200
1095
  result.taxonomies.terms++;
1201
1096
  }
1202
- processedThisPass.push(term.slug);
1097
+ processedThisPass.push(term.slug + "::" + termLocale);
1203
1098
  }
1204
- remaining = remaining.filter((t) => !processedThisPass.includes(t.slug));
1099
+ remaining = remaining.filter((t) => !processedThisPass.includes(t.slug + "::" + (t.locale ?? defLocale)));
1205
1100
  maxPasses--;
1206
1101
  }
1207
- if (remaining.length > 0) console.warn(`Could not process ${remaining.length} terms due to missing parents`);
1102
+ if (remaining.length > 0) console.warn(`Could not process ${remaining.length} terms due to missing parents/translations`);
1208
1103
  }
1209
1104
  /**
1210
1105
  * Apply byline credits to a content entry.
@@ -1234,7 +1129,7 @@ async function applyContentTaxonomies(db, collectionSlug, contentId, entry, isUp
1234
1129
  if (isUpdate) await db.deleteFrom("content_taxonomies").where("collection", "=", collectionSlug).where("entry_id", "=", contentId).execute();
1235
1130
  if (!entry.taxonomies) {
1236
1131
  if (isUpdate) {
1237
- const { invalidateTermCache } = await import("./taxonomies-ZlRtD6AG.mjs").then((n) => n.u);
1132
+ const { invalidateTermCache } = await import("./taxonomies-Bw76xAxo.mjs").then((n) => n.u);
1238
1133
  invalidateTermCache();
1239
1134
  }
1240
1135
  return;
@@ -1246,17 +1141,23 @@ async function applyContentTaxonomies(db, collectionSlug, contentId, entry, isUp
1246
1141
  if (term) await termRepo.attachToEntry(collectionSlug, contentId, term.id);
1247
1142
  }
1248
1143
  }
1249
- const { invalidateTermCache } = await import("./taxonomies-ZlRtD6AG.mjs").then((n) => n.u);
1144
+ const { invalidateTermCache } = await import("./taxonomies-Bw76xAxo.mjs").then((n) => n.u);
1250
1145
  invalidateTermCache();
1251
1146
  }
1252
1147
  /**
1253
- * Apply menu items recursively
1148
+ * Apply menu items recursively.
1149
+ *
1150
+ * When a `SeedMenuItem` carries `id`/`translationOf`, the import resolves the
1151
+ * source item's `translation_group` so cross-locale "same nav entry" links
1152
+ * survive export → apply. Items without `translationOf` get a fresh group
1153
+ * (= their own id).
1254
1154
  */
1255
- async function applyMenuItems(db, menuId, items, parentId, startOrder, seedIdMap) {
1155
+ async function applyMenuItems(db, menuId, locale, items, parentId, startOrder, seedIdMap, itemSeedIdMap) {
1256
1156
  let count = 0;
1257
1157
  let order = startOrder;
1258
1158
  for (const item of items) {
1259
1159
  const itemId = ulid();
1160
+ const itemLocale = item.locale ?? locale;
1260
1161
  let referenceId = null;
1261
1162
  let referenceCollection = null;
1262
1163
  if (item.type === "page" || item.type === "post") {
@@ -1265,6 +1166,12 @@ async function applyMenuItems(db, menuId, items, parentId, startOrder, seedIdMap
1265
1166
  referenceCollection = item.collection || `${item.type}s`;
1266
1167
  }
1267
1168
  }
1169
+ let translationGroup = itemId;
1170
+ if (item.translationOf) {
1171
+ const source = itemSeedIdMap.get(item.translationOf);
1172
+ if (source) translationGroup = source.translationGroup;
1173
+ else console.warn(`menu item "${item.label ?? item.url ?? item.ref ?? "(unlabeled)"}" (${itemLocale}): translationOf "${item.translationOf}" not found yet; minting a fresh group.`);
1174
+ }
1268
1175
  await db.insertInto("_emdash_menu_items").values({
1269
1176
  id: itemId,
1270
1177
  menu_id: menuId,
@@ -1278,12 +1185,18 @@ async function applyMenuItems(db, menuId, items, parentId, startOrder, seedIdMap
1278
1185
  title_attr: item.titleAttr ?? null,
1279
1186
  target: item.target ?? null,
1280
1187
  css_classes: item.cssClasses ?? null,
1281
- created_at: (/* @__PURE__ */ new Date()).toISOString()
1188
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
1189
+ locale: itemLocale,
1190
+ translation_group: translationGroup
1282
1191
  }).execute();
1192
+ if (item.id) itemSeedIdMap.set(item.id, {
1193
+ id: itemId,
1194
+ translationGroup
1195
+ });
1283
1196
  count++;
1284
1197
  order++;
1285
1198
  if (item.children && item.children.length > 0) {
1286
- const childCount = await applyMenuItems(db, menuId, item.children, itemId, 0, seedIdMap);
1199
+ const childCount = await applyMenuItems(db, menuId, itemLocale, item.children, itemId, 0, seedIdMap, itemSeedIdMap);
1287
1200
  count += childCount;
1288
1201
  }
1289
1202
  }
@@ -1474,5 +1387,5 @@ function getImageDimensions(buffer) {
1474
1387
  }
1475
1388
 
1476
1389
  //#endregion
1477
- export { ssrfSafeFetch as a, getPluginSetting as c, getSiteSettings as d, setSiteSettings as f, resolveAndValidateExternalUrl as i, getPluginSettings as l, apply_exports as n, stripCredentialHeaders as o, TaxonomyRepository as p, SsrfError as r, validateExternalUrl as s, applySeed as t, getSiteSetting as u };
1478
- //# sourceMappingURL=apply-BzltprvY.mjs.map
1390
+ export { ssrfSafeFetch as a, getPluginSetting as c, getSiteSettings as d, setSiteSettings as f, resolveAndValidateExternalUrl as i, getPluginSettings as l, apply_exports as n, stripCredentialHeaders as o, SsrfError as r, validateExternalUrl as s, applySeed as t, getSiteSetting as u };
1391
+ //# sourceMappingURL=apply-Ded_1vng.mjs.map