@aotter/mantle-runtime 0.1.0-alpha.1 → 0.1.0-alpha.3

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 (141) hide show
  1. package/dist/domain/model/SeoMeta.d.ts +1 -1
  2. package/dist/domain/model/SeoMeta.d.ts.map +1 -1
  3. package/dist/domain/model/TemplateRegistry.d.ts +3 -4
  4. package/dist/domain/model/TemplateRegistry.d.ts.map +1 -1
  5. package/dist/domain/model/TemplateRegistry.js.map +1 -1
  6. package/dist/domain/port/AssetServer.d.ts +1 -1
  7. package/dist/domain/port/DatabaseDriver.d.ts +1 -1
  8. package/dist/domain/port/EntryReader.d.ts +1 -1
  9. package/dist/domain/port/EntryReader.d.ts.map +1 -1
  10. package/dist/domain/port/EntryRepository.d.ts +19 -4
  11. package/dist/domain/port/EntryRepository.d.ts.map +1 -1
  12. package/dist/domain/port/IdGenerator.d.ts +2 -2
  13. package/dist/domain/port/SiteConfigRepository.d.ts +2 -2
  14. package/dist/domain/service/HtmlRenderer.d.ts +2 -0
  15. package/dist/domain/service/HtmlRenderer.d.ts.map +1 -1
  16. package/dist/domain/service/HtmlRenderer.js +2 -2
  17. package/dist/domain/service/HtmlRenderer.js.map +1 -1
  18. package/dist/domain/service/MarkdownSerializer.d.ts +6 -9
  19. package/dist/domain/service/MarkdownSerializer.d.ts.map +1 -1
  20. package/dist/domain/service/MarkdownSerializer.js +77 -32
  21. package/dist/domain/service/MarkdownSerializer.js.map +1 -1
  22. package/dist/domain/service/SeoMetaComposer.d.ts +13 -0
  23. package/dist/domain/service/SeoMetaComposer.d.ts.map +1 -1
  24. package/dist/domain/service/SeoMetaComposer.js +58 -9
  25. package/dist/domain/service/SeoMetaComposer.js.map +1 -1
  26. package/dist/domain/service/SitemapSerializer.d.ts +1 -1
  27. package/dist/domain/service/SitemapSerializer.d.ts.map +1 -1
  28. package/dist/domain/service/SitemapSerializer.js +1 -1
  29. package/dist/domain/service/SitemapSerializer.js.map +1 -1
  30. package/dist/domain/service/TriggerIndex.d.ts +2 -3
  31. package/dist/domain/service/TriggerIndex.d.ts.map +1 -1
  32. package/dist/domain/service/TriggerIndex.js +2 -3
  33. package/dist/domain/service/TriggerIndex.js.map +1 -1
  34. package/dist/domain/service/ViewParamCoercer.d.ts +1 -1
  35. package/dist/domain/service/ViewParamCoercer.js +1 -1
  36. package/dist/domain/service/ViewSqlCompiler.d.ts.map +1 -1
  37. package/dist/domain/service/ViewSqlCompiler.js +15 -23
  38. package/dist/domain/service/ViewSqlCompiler.js.map +1 -1
  39. package/dist/domain/service/io/EntryDeleteGuard.js +1 -1
  40. package/dist/domain/service/io/EntryDeleteGuard.js.map +1 -1
  41. package/dist/index.d.ts +5 -4
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +4 -3
  44. package/dist/index.js.map +1 -1
  45. package/dist/infrastructure/boot/canonicalMigrations.d.ts.map +1 -1
  46. package/dist/infrastructure/boot/canonicalMigrations.js +1 -26
  47. package/dist/infrastructure/boot/canonicalMigrations.js.map +1 -1
  48. package/dist/infrastructure/mcp/McpJsonRpcDispatcher.d.ts +5 -21
  49. package/dist/infrastructure/mcp/McpJsonRpcDispatcher.d.ts.map +1 -1
  50. package/dist/infrastructure/mcp/McpJsonRpcDispatcher.js +24 -31
  51. package/dist/infrastructure/mcp/McpJsonRpcDispatcher.js.map +1 -1
  52. package/dist/infrastructure/mcp/McpToolCatalog.d.ts.map +1 -1
  53. package/dist/infrastructure/mcp/McpToolCatalog.js +13 -9
  54. package/dist/infrastructure/mcp/McpToolCatalog.js.map +1 -1
  55. package/dist/infrastructure/mcp/index.d.ts +1 -1
  56. package/dist/infrastructure/mcp/index.d.ts.map +1 -1
  57. package/dist/infrastructure/mcp/index.js.map +1 -1
  58. package/dist/infrastructure/persistence/DatabaseEntryRepository.d.ts +3 -7
  59. package/dist/infrastructure/persistence/DatabaseEntryRepository.d.ts.map +1 -1
  60. package/dist/infrastructure/persistence/DatabaseEntryRepository.js +74 -35
  61. package/dist/infrastructure/persistence/DatabaseEntryRepository.js.map +1 -1
  62. package/dist/infrastructure/persistence/DatabaseSiteConfigRepository.d.ts.map +1 -1
  63. package/dist/infrastructure/persistence/DatabaseSiteConfigRepository.js +20 -26
  64. package/dist/infrastructure/persistence/DatabaseSiteConfigRepository.js.map +1 -1
  65. package/dist/infrastructure/persistence/Pagination.d.ts +3 -0
  66. package/dist/infrastructure/persistence/Pagination.d.ts.map +1 -1
  67. package/dist/infrastructure/persistence/Pagination.js +28 -0
  68. package/dist/infrastructure/persistence/Pagination.js.map +1 -1
  69. package/dist/runtime.d.ts +4 -0
  70. package/dist/runtime.d.ts.map +1 -1
  71. package/dist/runtime.js +38 -3
  72. package/dist/runtime.js.map +1 -1
  73. package/dist/usecase/boot/ValidateBootUseCase.d.ts +5 -1
  74. package/dist/usecase/boot/ValidateBootUseCase.d.ts.map +1 -1
  75. package/dist/usecase/boot/ValidateBootUseCase.js +31 -11
  76. package/dist/usecase/boot/ValidateBootUseCase.js.map +1 -1
  77. package/dist/usecase/content/ArchiveUseCase.d.ts +1 -1
  78. package/dist/usecase/content/ArchiveUseCase.js +1 -1
  79. package/dist/usecase/content/CreateDraftUseCase.d.ts +1 -1
  80. package/dist/usecase/content/CreateDraftUseCase.js +5 -5
  81. package/dist/usecase/content/CreateDraftUseCase.js.map +1 -1
  82. package/dist/usecase/content/DeleteEntryUseCase.d.ts +3 -5
  83. package/dist/usecase/content/DeleteEntryUseCase.d.ts.map +1 -1
  84. package/dist/usecase/content/DeleteEntryUseCase.js +3 -5
  85. package/dist/usecase/content/DeleteEntryUseCase.js.map +1 -1
  86. package/dist/usecase/content/ListEntriesUseCase.d.ts.map +1 -1
  87. package/dist/usecase/content/ListEntriesUseCase.js +30 -3
  88. package/dist/usecase/content/ListEntriesUseCase.js.map +1 -1
  89. package/dist/usecase/content/RequestPublishUseCase.d.ts +2 -10
  90. package/dist/usecase/content/RequestPublishUseCase.d.ts.map +1 -1
  91. package/dist/usecase/content/RequestPublishUseCase.js +3 -21
  92. package/dist/usecase/content/RequestPublishUseCase.js.map +1 -1
  93. package/dist/usecase/content/UpdateDraftUseCase.js +4 -4
  94. package/dist/usecase/content/UpdateDraftUseCase.js.map +1 -1
  95. package/dist/usecase/content/diagnostics.d.ts +1 -0
  96. package/dist/usecase/content/diagnostics.d.ts.map +1 -1
  97. package/dist/usecase/content/diagnostics.js +10 -0
  98. package/dist/usecase/content/diagnostics.js.map +1 -1
  99. package/dist/usecase/dto/content/index.d.ts +10 -1
  100. package/dist/usecase/dto/content/index.d.ts.map +1 -1
  101. package/dist/usecase/dto/render/ComposeEntrySeoMetaRequest.d.ts +4 -0
  102. package/dist/usecase/dto/render/ComposeEntrySeoMetaRequest.d.ts.map +1 -1
  103. package/dist/usecase/dto/render/ComposeLlmsTxtRequest.d.ts +6 -1
  104. package/dist/usecase/dto/render/ComposeLlmsTxtRequest.d.ts.map +1 -1
  105. package/dist/usecase/dto/render/ComposeSitemapRequest.d.ts +4 -2
  106. package/dist/usecase/dto/render/ComposeSitemapRequest.d.ts.map +1 -1
  107. package/dist/usecase/dto/render/PreviewEntryRequest.d.ts +5 -0
  108. package/dist/usecase/dto/render/PreviewEntryRequest.d.ts.map +1 -1
  109. package/dist/usecase/dto/render/RenderEntryLiveRequest.d.ts +5 -0
  110. package/dist/usecase/dto/render/RenderEntryLiveRequest.d.ts.map +1 -1
  111. package/dist/usecase/dto/render/RenderListLiveRequest.d.ts +4 -0
  112. package/dist/usecase/dto/render/RenderListLiveRequest.d.ts.map +1 -1
  113. package/dist/usecase/procedure/InvokeBuiltinUseCase.d.ts +1 -1
  114. package/dist/usecase/procedure/InvokeBuiltinUseCase.js +2 -2
  115. package/dist/usecase/procedure/InvokeBuiltinUseCase.js.map +1 -1
  116. package/dist/usecase/render/ComposeEntrySeoMetaUseCase.d.ts +1 -1
  117. package/dist/usecase/render/ComposeEntrySeoMetaUseCase.d.ts.map +1 -1
  118. package/dist/usecase/render/ComposeEntrySeoMetaUseCase.js +13 -6
  119. package/dist/usecase/render/ComposeEntrySeoMetaUseCase.js.map +1 -1
  120. package/dist/usecase/render/ComposeLlmsTxtUseCase.d.ts +4 -2
  121. package/dist/usecase/render/ComposeLlmsTxtUseCase.d.ts.map +1 -1
  122. package/dist/usecase/render/ComposeLlmsTxtUseCase.js +13 -2
  123. package/dist/usecase/render/ComposeLlmsTxtUseCase.js.map +1 -1
  124. package/dist/usecase/render/ComposeSitemapUseCase.d.ts.map +1 -1
  125. package/dist/usecase/render/ComposeSitemapUseCase.js +13 -3
  126. package/dist/usecase/render/ComposeSitemapUseCase.js.map +1 -1
  127. package/dist/usecase/render/PreviewEntryUseCase.js +2 -2
  128. package/dist/usecase/render/PreviewEntryUseCase.js.map +1 -1
  129. package/dist/usecase/render/RenderEntryLiveUseCase.js +2 -2
  130. package/dist/usecase/render/RenderEntryLiveUseCase.js.map +1 -1
  131. package/dist/usecase/render/RenderListLiveUseCase.d.ts.map +1 -1
  132. package/dist/usecase/render/RenderListLiveUseCase.js +2 -1
  133. package/dist/usecase/render/RenderListLiveUseCase.js.map +1 -1
  134. package/dist/usecase/site/UpdateSiteSettingsUseCase.d.ts +3 -2
  135. package/dist/usecase/site/UpdateSiteSettingsUseCase.d.ts.map +1 -1
  136. package/dist/usecase/site/UpdateSiteSettingsUseCase.js +28 -2
  137. package/dist/usecase/site/UpdateSiteSettingsUseCase.js.map +1 -1
  138. package/dist/usecase/view/ExecuteViewUseCase.d.ts.map +1 -1
  139. package/dist/usecase/view/ExecuteViewUseCase.js +4 -1
  140. package/dist/usecase/view/ExecuteViewUseCase.js.map +1 -1
  141. package/package.json +2 -2
@@ -14,7 +14,7 @@ export interface SeoMeta {
14
14
  readonly canonical: string;
15
15
  /** Absolute URL of the markdown mirror — `<link rel="alternate"
16
16
  * type="text/markdown">`. AEO-critical. */
17
- readonly alternateMarkdown: string;
17
+ readonly alternateMarkdown: string | null;
18
18
  /** One per locale this entry has a translation in, plus an
19
19
  * `x-default` row when the site has multiple locales. */
20
20
  readonly hreflangs: ReadonlyArray<{
@@ -1 +1 @@
1
- {"version":3,"file":"SeoMeta.d.ts","sourceRoot":"","sources":["../../../src/domain/model/SeoMeta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO;IACtB,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;gDAC4C;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC;8DAC0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE;QACX,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,qBAAqB,CAAC;QACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;IACF;iCAC6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC"}
1
+ {"version":3,"file":"SeoMeta.d.ts","sourceRoot":"","sources":["../../../src/domain/model/SeoMeta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO;IACtB,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;gDAC4C;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C;8DAC0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE;QACX,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,qBAAqB,CAAC;QACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;IACF;iCAC6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC"}
@@ -10,10 +10,9 @@ import type { MediaAsset } from "../port/MediaStorage.js";
10
10
  * their public surface (Hono + hono/jsx) call their JSX → string
11
11
  * function before the template returns.
12
12
  *
13
- * Schemas without a registered entry/list template still get
14
- * markdown / `llms.txt` mirrors the HTML surfaces are simply
15
- * skipped (per ADR-0009-extended: the SDK ships zero opinionated
16
- * templates).
13
+ * Schemas without a registered entry/list template skip HTML.
14
+ * Their agent mirrors are emitted only when a public path resolves
15
+ * and the entry has serializable content.
17
16
  *
18
17
  * `seo` is populated when the renderer is given a composed SeoMeta
19
18
  * block — templates render `<SeoTags seo={seo} />` (or read fields
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateRegistry.d.ts","sourceRoot":"","sources":["../../../src/domain/model/TemplateRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,MAAM,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;AAExD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEzD,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,GAAG,IAAI;IAIjE,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,IAAI;IAI/D,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI/D,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAG9D"}
1
+ {"version":3,"file":"TemplateRegistry.d.ts","sourceRoot":"","sources":["../../../src/domain/model/TemplateRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,MAAM,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;AAExD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEzD,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,GAAG,IAAI;IAIjE,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,IAAI;IAI/D,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI/D,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAG9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateRegistry.js","sourceRoot":"","sources":["../../../src/domain/model/TemplateRegistry.ts"],"names":[],"mappings":"AA6CA,MAAM,OAAO,gBAAgB;IACV,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC3C,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEzD,qBAAqB,CAAC,UAAkB,EAAE,CAAgB;QACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,oBAAoB,CAAC,UAAkB,EAAE,CAAe;QACtD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,gBAAgB,CAAC,UAAkB;QACjC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;CACF"}
1
+ {"version":3,"file":"TemplateRegistry.js","sourceRoot":"","sources":["../../../src/domain/model/TemplateRegistry.ts"],"names":[],"mappings":"AA4CA,MAAM,OAAO,gBAAgB;IACV,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC3C,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEzD,qBAAqB,CAAC,UAAkB,EAAE,CAAgB;QACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,oBAAoB,CAAC,UAAkB,EAAE,CAAe;QACtD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,gBAAgB,CAAC,UAAkB;QACjC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -7,7 +7,7 @@
7
7
  * returns the response.
8
8
  *
9
9
  * CF adapter: wraps `env.ASSETS.fetch(req)`. Future: filesystem read,
10
- * S3+CDN, Netlify static-publish dir.
10
+ * S3+CDN, or another platform asset service.
11
11
  *
12
12
  * Returning `null` lets the runtime's HTTP layer fall back to the
13
13
  * SPA's `index.html` catchall — the React Router routing model.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `DatabaseDriver` — runtime's adapter-agnostic interface to
3
- * persistent relational state. Entries, revisions, approvals, site config,
3
+ * persistent relational state. Entries, site config,
4
4
  * auth support, and media tables declared by the canonical migrations live
5
5
  * behind this surface; the runtime never sees `D1Database`, `Pool` (postgres),
6
6
  * or any concrete driver.
@@ -17,7 +17,7 @@ export interface ReadEntryByDataFieldArgs {
17
17
  export interface ReadEntriesByDataFieldInArgs {
18
18
  readonly collection: string;
19
19
  readonly field: string;
20
- readonly values: readonly string[];
20
+ readonly values: readonly EntryDataScalar[];
21
21
  readonly locale?: string | null;
22
22
  readonly status?: ContentState;
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EntryReader.d.ts","sourceRoot":"","sources":["../../../src/domain/port/EntryReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC5C,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC7D,eAAe,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACvE,iBAAiB,CAAC,IAAI,EAAE,4BAA4B,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IACjF,aAAa,CAAC,IAAI,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IAC1E,mBAAmB,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;CACtF"}
1
+ {"version":3,"file":"EntryReader.d.ts","sourceRoot":"","sources":["../../../src/domain/port/EntryReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC5C,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC7D,eAAe,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACvE,iBAAiB,CAAC,IAAI,EAAE,4BAA4B,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IACjF,aAAa,CAAC,IAAI,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IAC1E,mBAAmB,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;CACtF"}
@@ -20,7 +20,6 @@ export interface EntryRepository {
20
20
  get(id: string): Promise<EntryRow | null>;
21
21
  /** Throws `EntryVersionConflict` on OCC mismatch. */
22
22
  update(args: UpdateEntryArgs): Promise<EntryRow>;
23
- /** Cascades to revisions + approvals child rows for the entry id. */
24
23
  delete(args: DeleteEntryArgs): Promise<{
25
24
  readonly removed: boolean;
26
25
  }>;
@@ -106,13 +105,29 @@ export interface ListEntriesArgs {
106
105
  /** Opaque continuation token from a prior `ListEntriesResult.nextCursor`.
107
106
  * Caller must round-trip without interpreting; format is impl-defined. */
108
107
  readonly cursor?: string;
109
- /** Free-text filter matched against `id` and the raw `data` JSON
110
- * blob (substring, case-sensitive per SQLite's default `LIKE`).
111
- * Composes with `status` both narrow the same query. */
108
+ /** Fetch the page before `cursor`; default is the page after it. */
109
+ readonly cursorDirection?: "forward" | "backward";
110
+ /** Free-text filter matched against `id` and `searchFields`
111
+ * (substring, case-insensitive for ASCII per SQLite `LIKE`). */
112
112
  readonly search?: string;
113
+ /** Trusted top-level string fields resolved from Schema.searchableFields. */
114
+ readonly searchFields?: readonly string[];
115
+ /** Trusted exact enum filter resolved from the Schema's indexed fields. */
116
+ readonly filter?: {
117
+ readonly field: string;
118
+ readonly value: string;
119
+ };
120
+ /** Native fields or Schema-indexed scalar data fields only. */
121
+ readonly sort?: EntrySort;
122
+ }
123
+ export interface EntrySort {
124
+ readonly field: string;
125
+ readonly direction: "asc" | "desc";
113
126
  }
114
127
  export interface ListEntriesResult {
115
128
  readonly rows: readonly EntryRow[];
129
+ /** Pass back with `cursorDirection: "backward"`. */
130
+ readonly previousCursor?: string;
116
131
  /** Present when there may be more rows beyond this page. Undefined
117
132
  * signals "this is the last page". Pass back as `cursor` to
118
133
  * continue. */
@@ -1 +1 @@
1
- {"version":3,"file":"EntryRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/port/EntryRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntryRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/port/EntryRepository.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
- * `IdGenerator` — abstracted id source for new entries / revisions /
3
- * approvals / lifecycle events / sessions / media bearer tokens / R2
2
+ * `IdGenerator` — abstracted id source for entries / lifecycle events /
3
+ * sessions / media bearer tokens / R2
4
4
  * object keys.
5
5
  *
6
6
  * # Security invariant
@@ -7,7 +7,7 @@ import type { MediaPurposePolicy, SiteConfig, SiteDefaults } from "@aotter/mantl
7
7
  * `siteDefaults`, but treats keys differently depending on ownership:
8
8
  * UI-editable keys (brand/title/description/…) seed once (INSERT …
9
9
  * ON CONFLICT DO NOTHING) so operator edits are preserved; keys with
10
- * no admin-UI edit path (`locales`, `mediaPurposes`) are synced from
10
+ * no admin-UI edit path (`origin`, `locales`, `mediaPurposes`) are synced from
11
11
  * config on every boot (upsert when the value differs) since code is
12
12
  * their only source of truth. See `DatabaseSiteConfigRepository`'s
13
13
  * header comment for the full rationale (#441).
@@ -24,7 +24,7 @@ export interface SiteConfigRepository {
24
24
  load(): Promise<SiteConfig>;
25
25
  /** Persist the operator-owned subset exposed by the Admin settings UI.
26
26
  * Omitted fields are unchanged; an empty string intentionally clears a
27
- * value. Code-canonical locales and media purposes are never writable
27
+ * value. Code-canonical origin, locales, and media purposes are never writable
28
28
  * through this path. Optional during the `CmsRuntime.db` compatibility
29
29
  * window; canonical Mantle runtimes always provide it. */
30
30
  updateEditable?(args: UpdateEditableSiteConfigArgs): Promise<void>;
@@ -33,4 +33,6 @@ export interface RenderListArgs {
33
33
  * registered for `collection`. */
34
34
  export declare function renderListHtml(args: RenderListArgs): string | null;
35
35
  export declare function renderTrackingTagsHtml(site: SiteConfig): string;
36
+ export declare function normalizeGa4MeasurementId(value: string | undefined): string | null;
37
+ export declare function normalizeFacebookPixelId(value: string | undefined): string | null;
36
38
  //# sourceMappingURL=HtmlRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlRenderer.d.ts","sourceRoot":"","sources":["../../../src/domain/service/HtmlRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAW1D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC;mEAC+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD;;;+DAG2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;qDACqD;AACrD,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAepE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;mCACmC;AACnC,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAelE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAa/D"}
1
+ {"version":3,"file":"HtmlRenderer.d.ts","sourceRoot":"","sources":["../../../src/domain/service/HtmlRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAW1D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC;mEAC+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD;;;+DAG2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;qDACqD;AACrD,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAepE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;mCACmC;AACnC,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAelE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAa/D;AAYD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGlF;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGjF"}
@@ -62,11 +62,11 @@ function injectTrackingTags(html, site) {
62
62
  return html.replace(bodyOpen, (match) => `${match}${tags}`);
63
63
  return `${tags}${html}`;
64
64
  }
65
- function normalizeGa4MeasurementId(value) {
65
+ export function normalizeGa4MeasurementId(value) {
66
66
  const trimmed = value?.trim().toUpperCase() ?? "";
67
67
  return /^G-[A-Z0-9]{4,32}$/.test(trimmed) ? trimmed : null;
68
68
  }
69
- function normalizeFacebookPixelId(value) {
69
+ export function normalizeFacebookPixelId(value) {
70
70
  const trimmed = value?.trim() ?? "";
71
71
  return /^[0-9]{5,32}$/.test(trimmed) ? trimmed : null;
72
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlRenderer.js","sourceRoot":"","sources":["../../../src/domain/service/HtmlRenderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HtmlRenderer.js","sourceRoot":"","sources":["../../../src/domain/service/HtmlRenderer.ts"],"names":[],"mappings":"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"}
@@ -19,21 +19,17 @@ import type { Entry, SiteConfig } from "@aotter/mantle-spec";
19
19
  *
20
20
  * <content>
21
21
  *
22
- * Entries without a `content` (or `body`) field skip the `.md`
23
- * mirror — see `getMarkdownBody` below for the dual-field rule.
22
+ * Entries without serializable public content skip the `.md` mirror.
24
23
  *
25
24
  * Pure transformation — no I/O. Lives in `domain/service/`.
26
25
  */
27
26
  /**
28
- * The canonical markdown source field. Spec-preferred name is
29
- * `content`; the reference starter (and likely consumers cribbing
30
- * from it) declares `body`. Both are markdown text under the hood;
31
- * accept either everywhere a markdown payload is read so consumers
32
- * don't have to choose. Single predicate so `serializeEntryAsMarkdown`,
33
- * `serializeLlmsTxt`, and the article-signal heuristic stay in sync.
27
+ * `content`/`body` win, then structured sections, then a non-empty
28
+ * description/summary. One predicate keeps mirrors and metadata in sync.
34
29
  */
35
30
  export declare function getMarkdownBody(entry: Entry): string | null;
36
31
  export declare function hasMarkdownBody(entry: Entry): boolean;
32
+ export declare function getEntryDescription(entry: Entry): string | null;
37
33
  export declare function serializeEntryAsMarkdown(entry: Entry): string | null;
38
34
  /**
39
35
  * Per-locale `/llms.txt` index. One section per collection, one bullet
@@ -44,5 +40,6 @@ export declare function serializeLlmsTxt(args: {
44
40
  readonly site: SiteConfig;
45
41
  readonly locale: string;
46
42
  readonly entriesByCollection: ReadonlyMap<string, readonly Entry[]>;
47
- }): string;
43
+ readonly pathFor: (entry: Entry) => string | null;
44
+ }): string | null;
48
45
  //# sourceMappingURL=MarkdownSerializer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownSerializer.d.ts","sourceRoot":"","sources":["../../../src/domain/service/MarkdownSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAK3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAErD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAsBpE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC;CACrE,GAAG,MAAM,CAsBT"}
1
+ {"version":3,"file":"MarkdownSerializer.d.ts","sourceRoot":"","sources":["../../../src/domain/service/MarkdownSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAS3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAErD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAG/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAuBpE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC;CACnD,GAAG,MAAM,GAAG,IAAI,CAsBhB"}
@@ -19,43 +19,48 @@ import { absoluteUrl, appendMarkdownExt } from "./AbsoluteUrl.js";
19
19
  *
20
20
  * <content>
21
21
  *
22
- * Entries without a `content` (or `body`) field skip the `.md`
23
- * mirror — see `getMarkdownBody` below for the dual-field rule.
22
+ * Entries without serializable public content skip the `.md` mirror.
24
23
  *
25
24
  * Pure transformation — no I/O. Lives in `domain/service/`.
26
25
  */
27
26
  /**
28
- * The canonical markdown source field. Spec-preferred name is
29
- * `content`; the reference starter (and likely consumers cribbing
30
- * from it) declares `body`. Both are markdown text under the hood;
31
- * accept either everywhere a markdown payload is read so consumers
32
- * don't have to choose. Single predicate so `serializeEntryAsMarkdown`,
33
- * `serializeLlmsTxt`, and the article-signal heuristic stay in sync.
27
+ * `content`/`body` win, then structured sections, then a non-empty
28
+ * description/summary. One predicate keeps mirrors and metadata in sync.
34
29
  */
35
30
  export function getMarkdownBody(entry) {
36
31
  const data = entry.data;
37
- if (typeof data["content"] === "string")
38
- return data["content"];
39
- if (typeof data["body"] === "string")
40
- return data["body"];
41
- return null;
32
+ for (const key of ["content", "body"]) {
33
+ const value = nonEmptyString(data[key]);
34
+ if (value)
35
+ return value;
36
+ }
37
+ const sections = serializeSections(data["sections"]);
38
+ if (sections)
39
+ return sections;
40
+ return getEntryDescription(entry);
42
41
  }
43
42
  export function hasMarkdownBody(entry) {
44
43
  return getMarkdownBody(entry) !== null;
45
44
  }
45
+ export function getEntryDescription(entry) {
46
+ return nonEmptyString(entry.data["description"])
47
+ ?? nonEmptyString(entry.data["summary"]);
48
+ }
46
49
  export function serializeEntryAsMarkdown(entry) {
47
50
  const data = entry.data;
48
51
  const content = getMarkdownBody(entry);
49
52
  if (content == null)
50
53
  return null;
51
54
  const fm = [];
52
- for (const k of ["title", "description", "slug", "locale", "publishedAt"]) {
55
+ for (const k of ["title", "slug", "locale", "publishedAt"]) {
53
56
  const v = k === "locale" ? entry.locale : data[k];
54
57
  if (typeof v === "string" && v.length > 0)
55
58
  fm.push([k, v]);
56
59
  }
57
60
  const title = data["title"] ?? entry.id;
58
- const description = data["description"];
61
+ const description = getEntryDescription(entry);
62
+ if (description)
63
+ fm.splice(1, 0, ["description", description]);
59
64
  let out = "---\n";
60
65
  for (const [k, v] of fm)
61
66
  out += `${k}: ${yamlScalar(v)}\n`;
@@ -74,31 +79,71 @@ export function serializeEntryAsMarkdown(entry) {
74
79
  * so agent consumers can rely on a stable structure.
75
80
  */
76
81
  export function serializeLlmsTxt(args) {
77
- const { site, locale, entriesByCollection } = args;
78
- const urlLocale = locale.toLowerCase();
79
- let out = `# ${site.title}\n\n`;
80
- if (site.description)
81
- out += `> ${site.description}\n\n`;
82
- if (locale)
83
- out += `Locale: ${locale}\n\n`;
82
+ const { site, locale, entriesByCollection, pathFor } = args;
83
+ const sections = [];
84
84
  for (const [collection, entries] of entriesByCollection) {
85
- if (entries.length === 0)
86
- continue;
87
- out += `## ${collection}\n\n`;
85
+ const bullets = [];
88
86
  for (const e of entries) {
89
87
  if (!hasMarkdownBody(e))
90
88
  continue;
91
89
  const data = e.data;
92
90
  const title = data["title"] ?? e.id;
93
- const slug = data["slug"] ?? e.id;
94
- const desc = data["description"] ?? "";
95
- const localePrefix = urlLocale ? `/${urlLocale}` : "";
96
- const url = appendMarkdownExt(absoluteUrl(site.origin, `${localePrefix}/${collection}/${slug}`));
97
- out += desc ? `- [${title}](${url}): ${desc}\n` : `- [${title}](${url})\n`;
91
+ const path = pathFor(e);
92
+ if (!path)
93
+ continue;
94
+ const desc = getEntryDescription(e) ?? "";
95
+ const url = appendMarkdownExt(absoluteUrl(site.origin, path));
96
+ bullets.push(desc ? `- [${title}](${url}): ${desc}` : `- [${title}](${url})`);
98
97
  }
99
- out += "\n";
98
+ if (bullets.length > 0)
99
+ sections.push(`## ${collection}\n\n${bullets.join("\n")}`);
100
100
  }
101
- return out;
101
+ if (sections.length === 0)
102
+ return null;
103
+ let out = `# ${site.title}\n\n`;
104
+ if (site.description)
105
+ out += `> ${site.description}\n\n`;
106
+ if (locale)
107
+ out += `Locale: ${locale}\n\n`;
108
+ return `${out}${sections.join("\n\n")}\n`;
109
+ }
110
+ function serializeSections(value) {
111
+ if (!Array.isArray(value))
112
+ return null;
113
+ const sections = value.map(serializeSection).filter((section) => section.length > 0);
114
+ return sections.length > 0 ? sections.join("\n\n") : null;
115
+ }
116
+ function serializeSection(value) {
117
+ if (!isRecord(value))
118
+ return "";
119
+ const heading = nonEmptyString(value["title"]);
120
+ const lines = heading ? [`## ${heading}`] : [];
121
+ for (const key of ["eyebrow", "body", "description", "quote", "value"]) {
122
+ const text = nonEmptyString(value[key]);
123
+ if (text && text !== heading)
124
+ lines.push(text);
125
+ }
126
+ if (Array.isArray(value["items"])) {
127
+ for (const item of value["items"]) {
128
+ if (!isRecord(item))
129
+ continue;
130
+ const title = nonEmptyString(item["title"]);
131
+ const body = nonEmptyString(item["body"])
132
+ ?? nonEmptyString(item["description"])
133
+ ?? nonEmptyString(item["quote"]);
134
+ if (title && body)
135
+ lines.push(`- **${title}:** ${body}`);
136
+ else if (title ?? body)
137
+ lines.push(`- ${title ?? body}`);
138
+ }
139
+ }
140
+ return lines.join("\n\n");
141
+ }
142
+ function nonEmptyString(value) {
143
+ return typeof value === "string" && value.trim() ? value : null;
144
+ }
145
+ function isRecord(value) {
146
+ return typeof value === "object" && value !== null && !Array.isArray(value);
102
147
  }
103
148
  function yamlScalar(s) {
104
149
  if (/^[A-Za-z0-9._/-][\w. /:-]*$/.test(s) && !/^(true|false|null|yes|no|on|off)$/i.test(s)) {
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownSerializer.js","sourceRoot":"","sources":["../../../src/domain/service/MarkdownSerializer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MarkdownSerializer.js","sourceRoot":"","sources":["../../../src/domain/service/MarkdownSerializer.ts"],"names":[],"mappings":"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"}
@@ -33,8 +33,21 @@ export interface ComposeEntrySeoMetaArgs {
33
33
  /** og:type. Defaults to `article` when the entry has a `publishedAt`
34
34
  * (or `updatedAt`) field, `website` otherwise. */
35
35
  readonly type?: "article" | "website";
36
+ /** Public-route locale for non-localized entries mounted under a locale URL. */
37
+ readonly locale?: string;
36
38
  }
37
39
  export declare function composeEntrySeoMeta(args: ComposeEntrySeoMetaArgs): SeoMeta;
40
+ export interface ComposePageSeoMetaArgs {
41
+ readonly site: SiteConfig;
42
+ readonly locale: string;
43
+ readonly publicPath: string;
44
+ readonly title?: string;
45
+ readonly description?: string | null;
46
+ readonly markdown: boolean;
47
+ readonly pathForLocale: (locale: string) => string;
48
+ }
49
+ /** SEO for public home/list pages that are not represented by one Entry. */
50
+ export declare function composePageSeoMeta(args: ComposePageSeoMetaArgs): SeoMeta;
38
51
  /**
39
52
  * Render the SEO meta block as an HTML fragment. Templates embed this
40
53
  * verbatim inside `<head>` via `raw(renderSeoTagsHtml(seo))`.
@@ -1 +1 @@
1
- {"version":3,"file":"SeoMetaComposer.d.ts","sourceRoot":"","sources":["../../../src/domain/service/SeoMetaComposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD;;;;;;;;;;;;;;;GAeG;AACH,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;yDACqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;wEACoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IACtD;uDACmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAiD1E;AAmFD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CA8CvD"}
1
+ {"version":3,"file":"SeoMetaComposer.d.ts","sourceRoot":"","sources":["../../../src/domain/service/SeoMetaComposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD;;;;;;;;;;;;;;;GAeG;AACH,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;yDACqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;wEACoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IACtD;uDACmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAkD1E;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACpD;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAiDxE;AAmFD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAgDvD"}
@@ -1,17 +1,17 @@
1
1
  import { toUrlLocale } from "@aotter/mantle-spec";
2
2
  import { absoluteUrl, appendMarkdownExt } from "./AbsoluteUrl.js";
3
3
  import { escapeHtml as escapeAttr } from "./HtmlEscaping.js";
4
- import { hasMarkdownBody } from "./MarkdownSerializer.js";
4
+ import { getEntryDescription, hasMarkdownBody } from "./MarkdownSerializer.js";
5
5
  export function composeEntrySeoMeta(args) {
6
6
  const { entry, site, publicPath, siblings = [], type } = args;
7
7
  const data = entry.data;
8
8
  const canonical = absoluteUrl(site.origin, publicPath);
9
- const alternateMarkdown = appendMarkdownExt(canonical);
9
+ const alternateMarkdown = hasMarkdownBody(entry) ? appendMarkdownExt(canonical) : null;
10
10
  const title = stringField(data, "title") ?? site.title;
11
- const description = stringField(data, "description") ?? site.description ?? null;
11
+ const description = getEntryDescription(entry) ?? site.description ?? null;
12
12
  const image = stringField(data, "coverUrl") ?? stringField(data, "ogImage") ?? null;
13
13
  const ogType = type ?? (hasArticleSignal(entry) ? "article" : "website");
14
- const entryLocale = entry.locale ?? site.canonicalLocale ?? "en";
14
+ const entryLocale = args.locale ?? entry.locale ?? site.canonicalLocale ?? "en";
15
15
  const hreflangs = buildHreflangs({
16
16
  site,
17
17
  currentLocale: entryLocale,
@@ -46,13 +46,60 @@ export function composeEntrySeoMeta(args) {
46
46
  image,
47
47
  data,
48
48
  site,
49
+ locale: entryLocale,
50
+ }),
51
+ };
52
+ }
53
+ /** SEO for public home/list pages that are not represented by one Entry. */
54
+ export function composePageSeoMeta(args) {
55
+ const { site, locale, publicPath, pathForLocale } = args;
56
+ const canonical = absoluteUrl(site.origin, publicPath);
57
+ const title = args.title ?? site.title;
58
+ const description = args.description ?? site.description ?? null;
59
+ const hreflangs = [
60
+ ...site.locales.map((candidate) => ({
61
+ locale: candidate,
62
+ href: absoluteUrl(site.origin, pathForLocale(candidate)),
63
+ })),
64
+ {
65
+ locale: "x-default",
66
+ href: absoluteUrl(site.origin, pathForLocale(site.canonicalLocale ?? site.locales[0] ?? locale)),
67
+ },
68
+ ];
69
+ return {
70
+ canonical,
71
+ alternateMarkdown: args.markdown ? appendMarkdownExt(canonical) : null,
72
+ hreflangs,
73
+ description,
74
+ og: {
75
+ type: "website",
76
+ url: canonical,
77
+ title,
78
+ siteName: site.title || site.brand,
79
+ description,
80
+ image: null,
81
+ locale,
82
+ },
83
+ twitter: {
84
+ card: "summary",
85
+ title,
86
+ description,
87
+ image: null,
88
+ },
89
+ jsonLd: buildJsonLd({
90
+ ogType: "website",
91
+ title,
92
+ description,
93
+ canonical,
94
+ image: null,
95
+ data: {},
96
+ site,
97
+ locale,
49
98
  }),
50
99
  };
51
100
  }
52
101
  function buildHreflangs(args) {
53
102
  const { site, currentLocale, currentPublicPath, siblings } = args;
54
- if (site.locales.length <= 1)
55
- return [];
56
103
  const out = [];
57
104
  const seen = new Set();
58
105
  const push = (locale, path) => {
@@ -76,7 +123,7 @@ function buildHreflangs(args) {
76
123
  return out;
77
124
  }
78
125
  function buildJsonLd(args) {
79
- const { ogType, title, description, canonical, image, data, site } = args;
126
+ const { ogType, title, description, canonical, image, data, site, locale } = args;
80
127
  const publishedAtMs = numericField(data, "publishedAt");
81
128
  const updatedAtMs = numericField(data, "updatedAt");
82
129
  const base = {
@@ -87,7 +134,7 @@ function buildJsonLd(args) {
87
134
  url: canonical,
88
135
  description: description ?? undefined,
89
136
  image: image ?? undefined,
90
- inLanguage: site.canonicalLocale ?? undefined,
137
+ inLanguage: locale,
91
138
  publisher: site.title || site.brand
92
139
  ? {
93
140
  "@type": "Organization",
@@ -122,7 +169,9 @@ function hasArticleSignal(entry) {
122
169
  export function renderSeoTagsHtml(meta) {
123
170
  const parts = [];
124
171
  parts.push(`<link rel="canonical" href="${escapeAttr(meta.canonical)}">`);
125
- parts.push(`<link rel="alternate" type="text/markdown" href="${escapeAttr(meta.alternateMarkdown)}">`);
172
+ if (meta.alternateMarkdown) {
173
+ parts.push(`<link rel="alternate" type="text/markdown" href="${escapeAttr(meta.alternateMarkdown)}">`);
174
+ }
126
175
  for (const h of meta.hreflangs) {
127
176
  parts.push(`<link rel="alternate" hreflang="${escapeAttr(h.locale)}" href="${escapeAttr(h.href)}">`);
128
177
  }