@geekity/cms 0.3.0 → 0.5.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.
- package/README.md +2217 -214
- package/admin/components/fields.njk +165 -0
- package/admin/layouts/base.njk +1 -1
- package/admin/layouts/settings-page.njk +26 -0
- package/admin/layouts/shell.njk +17 -3
- package/admin/pages/account/forgot.njk +47 -0
- package/admin/pages/account/login.njk +26 -0
- package/admin/pages/account/reset.njk +38 -0
- package/admin/pages/account/setup.njk +28 -0
- package/admin/pages/appearance/themes.njk +69 -0
- package/admin/pages/comments/all.njk +133 -0
- package/admin/{layouts/dashboard.njk → pages/dashboard/home.njk} +8 -15
- package/admin/{layouts/document-conflict.njk → pages/documents/conflict.njk} +1 -0
- package/admin/{layouts/document-editor.njk → pages/documents/editor.njk} +75 -59
- package/admin/{layouts/document-list.njk → pages/documents/list.njk} +19 -2
- package/admin/pages/documents/taxonomy.njk +95 -0
- package/admin/pages/federation/followers.njk +238 -0
- package/admin/pages/federation/settings.njk +77 -0
- package/admin/pages/media/library.njk +160 -0
- package/admin/pages/messages/all.njk +110 -0
- package/admin/pages/navigation/menus.njk +129 -0
- package/admin/{layouts → pages}/placeholder.njk +5 -1
- package/admin/pages/settings/discussion.njk +99 -0
- package/admin/pages/settings/email.njk +203 -0
- package/admin/pages/settings/general.njk +29 -0
- package/admin/pages/settings/permalinks.njk +50 -0
- package/admin/pages/settings/reading.njk +64 -0
- package/admin/pages/tools/content-index.njk +89 -0
- package/admin/pages/users/edit.njk +239 -0
- package/admin/pages/users/list.njk +51 -0
- package/admin/pages/users/new.njk +41 -0
- package/admin/static/admin.css +558 -3
- package/admin/static/copy.js +52 -0
- package/admin/static/editor.js +16 -16
- package/admin/static/slug.js +61 -0
- package/dist/access-log.d.ts +44 -0
- package/dist/access-log.d.ts.map +1 -0
- package/dist/access-log.js +71 -0
- package/dist/access-log.js.map +1 -0
- package/dist/admin/accounts.d.ts +413 -0
- package/dist/admin/accounts.d.ts.map +1 -0
- package/dist/admin/accounts.js +680 -0
- package/dist/admin/accounts.js.map +1 -0
- package/dist/admin/appearance.d.ts +80 -0
- package/dist/admin/appearance.d.ts.map +1 -0
- package/dist/admin/appearance.js +136 -0
- package/dist/admin/appearance.js.map +1 -0
- package/dist/admin/comments.d.ts +90 -0
- package/dist/admin/comments.d.ts.map +1 -0
- package/dist/admin/comments.js +244 -0
- package/dist/admin/comments.js.map +1 -0
- package/dist/admin/credentials.d.ts +26 -2
- package/dist/admin/credentials.d.ts.map +1 -1
- package/dist/admin/credentials.js +35 -2
- package/dist/admin/credentials.js.map +1 -1
- package/dist/admin/documents.d.ts +117 -10
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +328 -41
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/federation.d.ts +161 -50
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +235 -93
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/formatting.d.ts +20 -0
- package/dist/admin/formatting.d.ts.map +1 -0
- package/dist/admin/formatting.js +72 -0
- package/dist/admin/formatting.js.map +1 -0
- package/dist/admin/headers.d.ts +65 -0
- package/dist/admin/headers.d.ts.map +1 -0
- package/dist/admin/headers.js +104 -0
- package/dist/admin/headers.js.map +1 -0
- package/dist/admin/index.d.ts +38 -12
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +25 -7
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/media.d.ts +168 -0
- package/dist/admin/media.d.ts.map +1 -0
- package/dist/admin/media.js +295 -0
- package/dist/admin/media.js.map +1 -0
- package/dist/admin/menu.d.ts +79 -0
- package/dist/admin/menu.d.ts.map +1 -0
- package/dist/admin/menu.js +143 -0
- package/dist/admin/menu.js.map +1 -0
- package/dist/admin/messages.d.ts +80 -0
- package/dist/admin/messages.d.ts.map +1 -0
- package/dist/admin/messages.js +152 -0
- package/dist/admin/messages.js.map +1 -0
- package/dist/admin/navigation.d.ts +155 -0
- package/dist/admin/navigation.d.ts.map +1 -0
- package/dist/admin/navigation.js +292 -0
- package/dist/admin/navigation.js.map +1 -0
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +31 -7
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/recovery.d.ts +92 -0
- package/dist/admin/recovery.d.ts.map +1 -0
- package/dist/admin/recovery.js +229 -0
- package/dist/admin/recovery.js.map +1 -0
- package/dist/admin/routes.d.ts +0 -20
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +164 -105
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/session.d.ts +17 -3
- package/dist/admin/session.d.ts.map +1 -1
- package/dist/admin/session.js +19 -5
- package/dist/admin/session.js.map +1 -1
- package/dist/admin/settings-discussion.d.ts +37 -0
- package/dist/admin/settings-discussion.d.ts.map +1 -0
- package/dist/admin/settings-discussion.js +117 -0
- package/dist/admin/settings-discussion.js.map +1 -0
- package/dist/admin/settings-email.d.ts +54 -0
- package/dist/admin/settings-email.d.ts.map +1 -0
- package/dist/admin/settings-email.js +189 -0
- package/dist/admin/settings-email.js.map +1 -0
- package/dist/admin/settings-federation.d.ts +48 -0
- package/dist/admin/settings-federation.d.ts.map +1 -0
- package/dist/admin/settings-federation.js +123 -0
- package/dist/admin/settings-federation.js.map +1 -0
- package/dist/admin/settings-general.d.ts +12 -0
- package/dist/admin/settings-general.d.ts.map +1 -0
- package/dist/admin/settings-general.js +48 -0
- package/dist/admin/settings-general.js.map +1 -0
- package/dist/admin/settings-page.d.ts +119 -0
- package/dist/admin/settings-page.d.ts.map +1 -0
- package/dist/admin/settings-page.js +132 -0
- package/dist/admin/settings-page.js.map +1 -0
- package/dist/admin/settings-pages.d.ts +30 -0
- package/dist/admin/settings-pages.d.ts.map +1 -0
- package/dist/admin/settings-pages.js +43 -0
- package/dist/admin/settings-pages.js.map +1 -0
- package/dist/admin/settings-permalinks.d.ts +16 -0
- package/dist/admin/settings-permalinks.d.ts.map +1 -0
- package/dist/admin/settings-permalinks.js +32 -0
- package/dist/admin/settings-permalinks.js.map +1 -0
- package/dist/admin/settings-reading.d.ts +34 -0
- package/dist/admin/settings-reading.d.ts.map +1 -0
- package/dist/admin/settings-reading.js +49 -0
- package/dist/admin/settings-reading.js.map +1 -0
- package/dist/admin/settings.d.ts +339 -96
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +600 -308
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/store.d.ts +606 -152
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +863 -268
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/taxonomy.d.ts +114 -0
- package/dist/admin/taxonomy.d.ts.map +1 -0
- package/dist/admin/taxonomy.js +289 -0
- package/dist/admin/taxonomy.js.map +1 -0
- package/dist/admin/templates.d.ts +46 -14
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +46 -14
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/throttle.d.ts +84 -0
- package/dist/admin/throttle.d.ts.map +1 -0
- package/dist/admin/throttle.js +143 -0
- package/dist/admin/throttle.js.map +1 -0
- package/dist/admin/tools.d.ts +111 -0
- package/dist/admin/tools.d.ts.map +1 -0
- package/dist/admin/tools.js +182 -0
- package/dist/admin/tools.js.map +1 -0
- package/dist/admin/uploads.d.ts +28 -2
- package/dist/admin/uploads.d.ts.map +1 -1
- package/dist/admin/uploads.js +43 -4
- package/dist/admin/uploads.js.map +1 -1
- package/dist/admin/users.d.ts +100 -13
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +412 -39
- package/dist/admin/users.js.map +1 -1
- package/dist/cache.d.ts +141 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +207 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +429 -21
- package/dist/cli.js.map +1 -1
- package/dist/comments/akismet.d.ts +130 -0
- package/dist/comments/akismet.d.ts.map +1 -0
- package/dist/comments/akismet.js +274 -0
- package/dist/comments/akismet.js.map +1 -0
- package/dist/comments/conversation.d.ts +29 -0
- package/dist/comments/conversation.d.ts.map +1 -0
- package/dist/comments/conversation.js +60 -0
- package/dist/comments/conversation.js.map +1 -0
- package/dist/comments/form.d.ts +123 -0
- package/dist/comments/form.d.ts.map +1 -0
- package/dist/comments/form.js +79 -0
- package/dist/comments/form.js.map +1 -0
- package/dist/comments/index.d.ts +16 -0
- package/dist/comments/index.d.ts.map +1 -0
- package/dist/comments/index.js +10 -0
- package/dist/comments/index.js.map +1 -0
- package/dist/comments/markdown.d.ts +8 -0
- package/dist/comments/markdown.d.ts.map +1 -0
- package/dist/comments/markdown.js +85 -0
- package/dist/comments/markdown.js.map +1 -0
- package/dist/comments/moderate.d.ts +71 -0
- package/dist/comments/moderate.d.ts.map +1 -0
- package/dist/comments/moderate.js +88 -0
- package/dist/comments/moderate.js.map +1 -0
- package/dist/comments/policy.d.ts +57 -0
- package/dist/comments/policy.d.ts.map +1 -0
- package/dist/comments/policy.js +80 -0
- package/dist/comments/policy.js.map +1 -0
- package/dist/comments/records.d.ts +266 -0
- package/dist/comments/records.d.ts.map +1 -0
- package/dist/comments/records.js +487 -0
- package/dist/comments/records.js.map +1 -0
- package/dist/comments/routes.d.ts +60 -0
- package/dist/comments/routes.d.ts.map +1 -0
- package/dist/comments/routes.js +212 -0
- package/dist/comments/routes.js.map +1 -0
- package/dist/comments/submission.d.ts +297 -0
- package/dist/comments/submission.d.ts.map +1 -0
- package/dist/comments/submission.js +280 -0
- package/dist/comments/submission.js.map +1 -0
- package/dist/comments/viewer.d.ts +21 -0
- package/dist/comments/viewer.d.ts.map +1 -0
- package/dist/comments/viewer.js +45 -0
- package/dist/comments/viewer.js.map +1 -0
- package/dist/config.d.ts +225 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +121 -6
- package/dist/config.js.map +1 -1
- package/dist/contact/delivery.d.ts +60 -0
- package/dist/contact/delivery.d.ts.map +1 -0
- package/dist/contact/delivery.js +87 -0
- package/dist/contact/delivery.js.map +1 -0
- package/dist/contact/form.d.ts +130 -0
- package/dist/contact/form.d.ts.map +1 -0
- package/dist/contact/form.js +163 -0
- package/dist/contact/form.js.map +1 -0
- package/dist/contact/index.d.ts +17 -0
- package/dist/contact/index.d.ts.map +1 -0
- package/dist/contact/index.js +13 -0
- package/dist/contact/index.js.map +1 -0
- package/dist/contact/records.d.ts +124 -0
- package/dist/contact/records.d.ts.map +1 -0
- package/dist/contact/records.js +218 -0
- package/dist/contact/records.js.map +1 -0
- package/dist/contact/routes.d.ts +17 -0
- package/dist/contact/routes.d.ts.map +1 -0
- package/dist/contact/routes.js +127 -0
- package/dist/contact/routes.js.map +1 -0
- package/dist/contact/submission.d.ts +103 -0
- package/dist/contact/submission.d.ts.map +1 -0
- package/dist/contact/submission.js +166 -0
- package/dist/contact/submission.js.map +1 -0
- package/dist/content/document.d.ts +7 -2
- package/dist/content/document.d.ts.map +1 -1
- package/dist/content/document.js +1 -0
- package/dist/content/document.js.map +1 -1
- package/dist/content/index.d.ts +7 -2
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +4 -1
- package/dist/content/index.js.map +1 -1
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +24 -2
- package/dist/content/markdown.js.map +1 -1
- package/dist/content/parser.d.ts.map +1 -1
- package/dist/content/parser.js +11 -4
- package/dist/content/parser.js.map +1 -1
- package/dist/content/save.d.ts +5 -0
- package/dist/content/save.d.ts.map +1 -1
- package/dist/content/save.js +44 -1
- package/dist/content/save.js.map +1 -1
- package/dist/content/schedule.d.ts +125 -0
- package/dist/content/schedule.d.ts.map +1 -0
- package/dist/content/schedule.js +207 -0
- package/dist/content/schedule.js.map +1 -0
- package/dist/content/search.d.ts +64 -0
- package/dist/content/search.d.ts.map +1 -0
- package/dist/content/search.js +136 -0
- package/dist/content/search.js.map +1 -0
- package/dist/content/store.d.ts +220 -7
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +392 -67
- package/dist/content/store.js.map +1 -1
- package/dist/content/sync.d.ts +7 -1
- package/dist/content/sync.d.ts.map +1 -1
- package/dist/content/sync.js +18 -10
- package/dist/content/sync.js.map +1 -1
- package/dist/content/time.d.ts +56 -0
- package/dist/content/time.d.ts.map +1 -0
- package/dist/content/time.js +141 -0
- package/dist/content/time.js.map +1 -0
- package/dist/content/writer.d.ts.map +1 -1
- package/dist/content/writer.js +3 -0
- package/dist/content/writer.js.map +1 -1
- package/dist/env.d.ts +70 -5
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/actor.d.ts +95 -41
- package/dist/federation/actor.d.ts.map +1 -1
- package/dist/federation/actor.js +180 -53
- package/dist/federation/actor.js.map +1 -1
- package/dist/federation/article.d.ts +44 -17
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +98 -46
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/delivery.d.ts +63 -15
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +154 -80
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts +22 -17
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +98 -77
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/followers.d.ts +3 -2
- package/dist/federation/followers.d.ts.map +1 -1
- package/dist/federation/followers.js +6 -5
- package/dist/federation/followers.js.map +1 -1
- package/dist/federation/import-wordpress.d.ts +128 -0
- package/dist/federation/import-wordpress.d.ts.map +1 -0
- package/dist/federation/import-wordpress.js +426 -0
- package/dist/federation/import-wordpress.js.map +1 -0
- package/dist/federation/inbox.d.ts +36 -13
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +120 -49
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +22 -10
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +13 -8
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/keys.d.ts +98 -20
- package/dist/federation/keys.d.ts.map +1 -1
- package/dist/federation/keys.js +269 -39
- package/dist/federation/keys.js.map +1 -1
- package/dist/federation/mount.d.ts +46 -10
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +300 -28
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/paths.d.ts +23 -35
- package/dist/federation/paths.d.ts.map +1 -1
- package/dist/federation/paths.js +26 -39
- package/dist/federation/paths.js.map +1 -1
- package/dist/federation/records.d.ts +223 -0
- package/dist/federation/records.d.ts.map +1 -0
- package/dist/federation/records.js +506 -0
- package/dist/federation/records.js.map +1 -0
- package/dist/federation/relays.d.ts +114 -0
- package/dist/federation/relays.d.ts.map +1 -0
- package/dist/federation/relays.js +290 -0
- package/dist/federation/relays.js.map +1 -0
- package/dist/federation/replies.d.ts +80 -0
- package/dist/federation/replies.d.ts.map +1 -0
- package/dist/federation/replies.js +166 -0
- package/dist/federation/replies.js.map +1 -0
- package/dist/federation/wordpress.d.ts +131 -0
- package/dist/federation/wordpress.d.ts.map +1 -0
- package/dist/federation/wordpress.js +341 -0
- package/dist/federation/wordpress.js.map +1 -0
- package/dist/files/atomic.d.ts +103 -0
- package/dist/files/atomic.d.ts.map +1 -0
- package/dist/files/atomic.js +150 -0
- package/dist/files/atomic.js.map +1 -0
- package/dist/files/index.d.ts +3 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +2 -0
- package/dist/files/index.js.map +1 -0
- package/dist/forms/protection.d.ts +85 -0
- package/dist/forms/protection.d.ts.map +1 -0
- package/dist/forms/protection.js +116 -0
- package/dist/forms/protection.js.map +1 -0
- package/dist/images/icons.d.ts +59 -0
- package/dist/images/icons.d.ts.map +1 -0
- package/dist/images/icons.js +131 -0
- package/dist/images/icons.js.map +1 -0
- package/dist/images/index.d.ts +7 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +4 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/markup.d.ts +47 -0
- package/dist/images/markup.d.ts.map +1 -0
- package/dist/images/markup.js +175 -0
- package/dist/images/markup.js.map +1 -0
- package/dist/images/paths.d.ts +34 -0
- package/dist/images/paths.d.ts.map +1 -0
- package/dist/images/paths.js +41 -0
- package/dist/images/paths.js.map +1 -0
- package/dist/images/variants.d.ts +104 -0
- package/dist/images/variants.d.ts.map +1 -0
- package/dist/images/variants.js +320 -0
- package/dist/images/variants.js.map +1 -0
- package/dist/index.d.ts +123 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +344 -25
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +18 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +34 -3
- package/dist/init.js.map +1 -1
- package/dist/mail/brevo.d.ts +35 -0
- package/dist/mail/brevo.d.ts.map +1 -0
- package/dist/mail/brevo.js +85 -0
- package/dist/mail/brevo.js.map +1 -0
- package/dist/mail/credentials.d.ts +62 -0
- package/dist/mail/credentials.d.ts.map +1 -0
- package/dist/mail/credentials.js +86 -0
- package/dist/mail/credentials.js.map +1 -0
- package/dist/mail/index.d.ts +15 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +8 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/memory.d.ts +35 -0
- package/dist/mail/memory.d.ts.map +1 -0
- package/dist/mail/memory.js +29 -0
- package/dist/mail/memory.js.map +1 -0
- package/dist/mail/provider.d.ts +80 -0
- package/dist/mail/provider.d.ts.map +1 -0
- package/dist/mail/provider.js +23 -0
- package/dist/mail/provider.js.map +1 -0
- package/dist/mail/service.d.ts +156 -0
- package/dist/mail/service.d.ts.map +1 -0
- package/dist/mail/service.js +265 -0
- package/dist/mail/service.js.map +1 -0
- package/dist/mail/smtp.d.ts +39 -0
- package/dist/mail/smtp.d.ts.map +1 -0
- package/dist/mail/smtp.js +58 -0
- package/dist/mail/smtp.js.map +1 -0
- package/dist/mail/templates.d.ts +91 -0
- package/dist/mail/templates.d.ts.map +1 -0
- package/dist/mail/templates.js +69 -0
- package/dist/mail/templates.js.map +1 -0
- package/dist/notifications/comments.d.ts +66 -0
- package/dist/notifications/comments.d.ts.map +1 -0
- package/dist/notifications/comments.js +151 -0
- package/dist/notifications/comments.js.map +1 -0
- package/dist/notifications/digest.d.ts +135 -0
- package/dist/notifications/digest.d.ts.map +1 -0
- package/dist/notifications/digest.js +287 -0
- package/dist/notifications/digest.js.map +1 -0
- package/dist/notifications/index.d.ts +13 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +8 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/links.d.ts +60 -0
- package/dist/notifications/links.d.ts.map +1 -0
- package/dist/notifications/links.js +63 -0
- package/dist/notifications/links.js.map +1 -0
- package/dist/notifications/optouts.d.ts +48 -0
- package/dist/notifications/optouts.d.ts.map +1 -0
- package/dist/notifications/optouts.js +93 -0
- package/dist/notifications/optouts.js.map +1 -0
- package/dist/notifications/preferences.d.ts +158 -0
- package/dist/notifications/preferences.d.ts.map +1 -0
- package/dist/notifications/preferences.js +195 -0
- package/dist/notifications/preferences.js.map +1 -0
- package/dist/notifications/routes.d.ts +28 -0
- package/dist/notifications/routes.d.ts.map +1 -0
- package/dist/notifications/routes.js +184 -0
- package/dist/notifications/routes.js.map +1 -0
- package/dist/notifications/tokens.d.ts +60 -0
- package/dist/notifications/tokens.d.ts.map +1 -0
- package/dist/notifications/tokens.js +125 -0
- package/dist/notifications/tokens.js.map +1 -0
- package/dist/notify.d.ts +84 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +149 -0
- package/dist/notify.js.map +1 -0
- package/dist/web/archive.d.ts +49 -0
- package/dist/web/archive.d.ts.map +1 -0
- package/dist/web/archive.js +59 -0
- package/dist/web/archive.js.map +1 -0
- package/dist/web/assets.d.ts +6 -5
- package/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +5 -7
- package/dist/web/assets.js.map +1 -1
- package/dist/web/authors.d.ts +143 -0
- package/dist/web/authors.d.ts.map +1 -0
- package/dist/web/authors.js +178 -0
- package/dist/web/authors.js.map +1 -0
- package/dist/web/comments.d.ts +60 -0
- package/dist/web/comments.d.ts.map +1 -0
- package/dist/web/comments.js +207 -0
- package/dist/web/comments.js.map +1 -0
- package/dist/web/context.d.ts +162 -28
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +123 -26
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts +209 -0
- package/dist/web/conversation.d.ts.map +1 -0
- package/dist/web/conversation.js +557 -0
- package/dist/web/conversation.js.map +1 -0
- package/dist/web/documents.d.ts +36 -6
- package/dist/web/documents.d.ts.map +1 -1
- package/dist/web/documents.js +52 -10
- package/dist/web/documents.js.map +1 -1
- package/dist/web/feed-atom.d.ts +22 -0
- package/dist/web/feed-atom.d.ts.map +1 -0
- package/dist/web/feed-atom.js +83 -0
- package/dist/web/feed-atom.js.map +1 -0
- package/dist/web/feed-item.d.ts +145 -0
- package/dist/web/feed-item.d.ts.map +1 -0
- package/dist/web/feed-item.js +120 -0
- package/dist/web/feed-item.js.map +1 -0
- package/dist/web/feed-json.d.ts +79 -0
- package/dist/web/feed-json.d.ts.map +1 -0
- package/dist/web/feed-json.js +53 -0
- package/dist/web/feed-json.js.map +1 -0
- package/dist/web/feed-rss.d.ts +26 -0
- package/dist/web/feed-rss.d.ts.map +1 -0
- package/dist/web/feed-rss.js +203 -0
- package/dist/web/feed-rss.js.map +1 -0
- package/dist/web/feed-source.d.ts +244 -0
- package/dist/web/feed-source.d.ts.map +1 -0
- package/dist/web/feed-source.js +201 -0
- package/dist/web/feed-source.js.map +1 -0
- package/dist/web/feed-xml.d.ts +63 -0
- package/dist/web/feed-xml.d.ts.map +1 -0
- package/dist/web/feed-xml.js +116 -0
- package/dist/web/feed-xml.js.map +1 -0
- package/dist/web/feeds.d.ts +31 -96
- package/dist/web/feeds.d.ts.map +1 -1
- package/dist/web/feeds.js +94 -198
- package/dist/web/feeds.js.map +1 -1
- package/dist/web/health.d.ts +31 -0
- package/dist/web/health.d.ts.map +1 -0
- package/dist/web/health.js +44 -0
- package/dist/web/health.js.map +1 -0
- package/dist/web/index.d.ts +30 -10
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +18 -7
- package/dist/web/index.js.map +1 -1
- package/dist/web/navigation.d.ts +195 -0
- package/dist/web/navigation.d.ts.map +1 -0
- package/dist/web/navigation.js +300 -0
- package/dist/web/navigation.js.map +1 -0
- package/dist/web/negotiate.d.ts +31 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +31 -11
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/recent.d.ts +43 -0
- package/dist/web/recent.d.ts.map +1 -0
- package/dist/web/recent.js +37 -0
- package/dist/web/recent.js.map +1 -0
- package/dist/web/render.d.ts +203 -9
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +341 -17
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts +25 -8
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +854 -93
- package/dist/web/routes.js.map +1 -1
- package/dist/web/sanitize.d.ts +19 -0
- package/dist/web/sanitize.d.ts.map +1 -0
- package/dist/web/sanitize.js +272 -0
- package/dist/web/sanitize.js.map +1 -0
- package/dist/web/search.d.ts +79 -0
- package/dist/web/search.d.ts.map +1 -0
- package/dist/web/search.js +94 -0
- package/dist/web/search.js.map +1 -0
- package/dist/web/sitemap.d.ts +120 -0
- package/dist/web/sitemap.d.ts.map +1 -0
- package/dist/web/sitemap.js +199 -0
- package/dist/web/sitemap.js.map +1 -0
- package/dist/web/taxonomy.d.ts +152 -0
- package/dist/web/taxonomy.d.ts.map +1 -0
- package/dist/web/taxonomy.js +237 -0
- package/dist/web/taxonomy.js.map +1 -0
- package/dist/web/templates.d.ts +54 -16
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +109 -28
- package/dist/web/templates.js.map +1 -1
- package/dist/web/themes.d.ts +226 -0
- package/dist/web/themes.d.ts.map +1 -0
- package/dist/web/themes.js +314 -0
- package/dist/web/themes.js.map +1 -0
- package/dist/webmention/discovery.d.ts +51 -0
- package/dist/webmention/discovery.d.ts.map +1 -0
- package/dist/webmention/discovery.js +176 -0
- package/dist/webmention/discovery.js.map +1 -0
- package/dist/webmention/html.d.ts +71 -0
- package/dist/webmention/html.d.ts.map +1 -0
- package/dist/webmention/html.js +285 -0
- package/dist/webmention/html.js.map +1 -0
- package/dist/webmention/index.d.ts +12 -0
- package/dist/webmention/index.d.ts.map +1 -0
- package/dist/webmention/index.js +8 -0
- package/dist/webmention/index.js.map +1 -0
- package/dist/webmention/links.d.ts +18 -0
- package/dist/webmention/links.d.ts.map +1 -0
- package/dist/webmention/links.js +64 -0
- package/dist/webmention/links.js.map +1 -0
- package/dist/webmention/microformats.d.ts +93 -0
- package/dist/webmention/microformats.d.ts.map +1 -0
- package/dist/webmention/microformats.js +376 -0
- package/dist/webmention/microformats.js.map +1 -0
- package/dist/webmention/receive.d.ts +141 -0
- package/dist/webmention/receive.d.ts.map +1 -0
- package/dist/webmention/receive.js +264 -0
- package/dist/webmention/receive.js.map +1 -0
- package/dist/webmention/routes.d.ts +37 -0
- package/dist/webmention/routes.d.ts.map +1 -0
- package/dist/webmention/routes.js +75 -0
- package/dist/webmention/routes.js.map +1 -0
- package/dist/webmention/service.d.ts +94 -0
- package/dist/webmention/service.d.ts.map +1 -0
- package/dist/webmention/service.js +207 -0
- package/dist/webmention/service.js.map +1 -0
- package/package.json +11 -6
- package/templates/site/content/_data/site.json +8 -0
- package/templates/site/content/pages/about.md +7 -0
- package/templates/site/content/posts/2026-01-01-hello-world.md +5 -3
- package/templates/site/geekity.config.ts +11 -1
- package/templates/site/tsconfig.json +1 -1
- package/themes/default/README.md +1216 -50
- package/themes/default/layouts/404.njk +2 -3
- package/themes/default/layouts/author.njk +36 -0
- package/themes/default/layouts/base.njk +161 -31
- package/themes/default/layouts/category.njk +27 -0
- package/themes/default/layouts/front-page.njk +56 -0
- package/themes/default/layouts/home.njk +17 -1
- package/themes/default/layouts/page.njk +57 -5
- package/themes/default/layouts/post.njk +78 -19
- package/themes/default/layouts/search.njk +57 -0
- package/themes/default/layouts/tag.njk +3 -6
- package/themes/default/mail/comment-digest.html.njk +37 -0
- package/themes/default/mail/comment-digest.subject.njk +3 -0
- package/themes/default/mail/comment-digest.txt.njk +40 -0
- package/themes/default/mail/comment-pending.html.njk +27 -0
- package/themes/default/mail/comment-pending.subject.njk +2 -0
- package/themes/default/mail/comment-pending.txt.njk +24 -0
- package/themes/default/mail/comment-reply.html.njk +21 -0
- package/themes/default/mail/comment-reply.subject.njk +2 -0
- package/themes/default/mail/comment-reply.txt.njk +22 -0
- package/themes/default/mail/contact-message.html.njk +24 -0
- package/themes/default/mail/contact-message.subject.njk +5 -0
- package/themes/default/mail/contact-message.txt.njk +20 -0
- package/themes/default/mail/password-changed.html.njk +18 -0
- package/themes/default/mail/password-changed.subject.njk +2 -0
- package/themes/default/mail/password-changed.txt.njk +17 -0
- package/themes/default/mail/password-reset.html.njk +22 -0
- package/themes/default/mail/password-reset.subject.njk +2 -0
- package/themes/default/mail/password-reset.txt.njk +18 -0
- package/themes/default/mail/test.html.njk +14 -0
- package/themes/default/mail/test.subject.njk +2 -0
- package/themes/default/mail/test.txt.njk +12 -0
- package/themes/default/partials/archive.njk +27 -0
- package/themes/default/partials/bio.njk +71 -0
- package/themes/default/partials/comment-form.njk +137 -0
- package/themes/default/partials/contact-form.njk +88 -0
- package/themes/default/partials/conversation.njk +139 -0
- package/themes/default/partials/feeds.njk +26 -0
- package/themes/default/partials/jsonld.njk +120 -0
- package/themes/default/partials/menu.njk +32 -0
- package/themes/default/partials/pagination.njk +12 -6
- package/themes/default/partials/post-list.njk +51 -18
- package/themes/default/partials/search-form.njk +22 -0
- package/themes/default/partials/tags.njk +26 -5
- package/themes/default/static/highlight.js +4 -0
- package/themes/default/static/style.css +1142 -194
- package/themes/default/theme.json +9 -0
- package/admin/layouts/federation.njk +0 -145
- package/admin/layouts/login.njk +0 -23
- package/admin/layouts/settings.njk +0 -116
- package/admin/layouts/setup.njk +0 -27
- package/admin/layouts/users.njk +0 -91
- /package/admin/{layouts/_flash.njk → components/flash.njk} +0 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
import { readdirSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFileIfPresentSync, withFileLock, writeFileAtomicallySync } from '../files/atomic.js';
|
|
4
|
+
import { uriOf } from './replies.js';
|
|
5
|
+
/**
|
|
6
|
+
* The two things an ActivityPub site cannot regenerate, as files it publishes.
|
|
7
|
+
*
|
|
8
|
+
* decision-9 makes the filesystem the source of truth for everything durable,
|
|
9
|
+
* and for federation that is the followers and the log of what the inbox was
|
|
10
|
+
* told. Both live under `content/_data/federation/`, which puts them in git
|
|
11
|
+
* beside the posts, hands them to an Eleventy build of the same directory as
|
|
12
|
+
* `federation.followers` and `federation.inbox`, and leaves SQLite holding
|
|
13
|
+
* nothing but an index of them — one that is rebuilt from these files on every
|
|
14
|
+
* boot and may be deleted at rest.
|
|
15
|
+
*
|
|
16
|
+
* Two rules make that safe, and both live here so no handler has to remember
|
|
17
|
+
* them:
|
|
18
|
+
*
|
|
19
|
+
* - **The file first, the index inside the same step.** Every writer takes
|
|
20
|
+
* {@link withFileLock} over the file it is about to change and writes the
|
|
21
|
+
* index before it lets go, so a follow and an unfollow arriving together
|
|
22
|
+
* cannot leave the index saying something the file does not. SQLite's
|
|
23
|
+
* transactions used to cover this and cover nothing here any more.
|
|
24
|
+
* - **The index is derived, never told.** A row is built from a line of the
|
|
25
|
+
* log by {@link inboxRowFrom} whether it is being written for the first time
|
|
26
|
+
* or rebuilt at boot, so a rebuilt index cannot differ from the live one.
|
|
27
|
+
*/
|
|
28
|
+
/** Where the federation files live, relative to the content directory. */
|
|
29
|
+
export const FEDERATION_DATA_DIRECTORY = '_data/federation';
|
|
30
|
+
/** What a user's followers file is called, inside their own directory. */
|
|
31
|
+
export const FOLLOWERS_FILE = 'followers.json';
|
|
32
|
+
/** The directory of monthly inbox logs, relative to the content directory. */
|
|
33
|
+
export const INBOX_DIRECTORY = `${FEDERATION_DATA_DIRECTORY}/inbox`;
|
|
34
|
+
/**
|
|
35
|
+
* The directory one user's federation files live in, relative to the content
|
|
36
|
+
* directory: `_data/federation/{username}`.
|
|
37
|
+
*
|
|
38
|
+
* decision-14 makes every user an actor, and an actor's followers are its own
|
|
39
|
+
* — an actor that was followed and forgotten simply stops hearing from the
|
|
40
|
+
* site — so the one file doc-4 had becomes one per user. The name is the
|
|
41
|
+
* username verbatim, because it is also the name in the actor's id and in the
|
|
42
|
+
* key files, and a directory nobody can match to a person would be worse than
|
|
43
|
+
* one with an unusual name in it.
|
|
44
|
+
*
|
|
45
|
+
* `inbox` is not a username: it is where the shared log lives, and
|
|
46
|
+
* `web/authors.ts` reserves the path for exactly that reason. A name that
|
|
47
|
+
* could climb out of the directory is refused rather than sanitised, because
|
|
48
|
+
* sanitising two different usernames into one directory would merge two
|
|
49
|
+
* people's followers.
|
|
50
|
+
*/
|
|
51
|
+
export function userDirectory(username) {
|
|
52
|
+
if (username === '' || username === '.' || username === '..' || /[/\\]/.test(username)) {
|
|
53
|
+
throw new Error(`"${username}" cannot name a federation directory.`);
|
|
54
|
+
}
|
|
55
|
+
return `${FEDERATION_DATA_DIRECTORY}/${username}`;
|
|
56
|
+
}
|
|
57
|
+
/** The absolute path of one user's `content/_data/federation/{username}/followers.json`. */
|
|
58
|
+
export function followersFile(contentDir, username) {
|
|
59
|
+
return path.join(contentDir, ...userDirectory(username).split('/'), FOLLOWERS_FILE);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Every user the content directory holds federation files for, sorted.
|
|
63
|
+
*
|
|
64
|
+
* Read from the directory rather than from `data/users.json`, because
|
|
65
|
+
* decision-9 makes the files the truth: a rebuilt database has to put back
|
|
66
|
+
* exactly what is on disk, including the followers of a user whose account was
|
|
67
|
+
* removed — deleting the account is not the same act as unfollowing everybody
|
|
68
|
+
* on their behalf, and only one of the two can be taken back.
|
|
69
|
+
*/
|
|
70
|
+
export function federatedUsernames(contentDir) {
|
|
71
|
+
let entries;
|
|
72
|
+
try {
|
|
73
|
+
entries = readdirSync(path.join(contentDir, ...FEDERATION_DATA_DIRECTORY.split('/')), {
|
|
74
|
+
withFileTypes: true,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// No directory is a site nobody has federated with yet.
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return entries
|
|
82
|
+
.filter((entry) => entry.isDirectory() && entry.name !== 'inbox')
|
|
83
|
+
.map((entry) => entry.name)
|
|
84
|
+
.sort();
|
|
85
|
+
}
|
|
86
|
+
/** The absolute path of one site's `content/_data/federation/inbox`. */
|
|
87
|
+
export function inboxDirectory(contentDir) {
|
|
88
|
+
return path.join(contentDir, ...INBOX_DIRECTORY.split('/'));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The month an instant falls in, `yyyy-mm`, in UTC.
|
|
92
|
+
*
|
|
93
|
+
* UTC rather than the site's zone because the log is a record of what a server
|
|
94
|
+
* was told, not of a site's day: the name of a file that has been written must
|
|
95
|
+
* not move when somebody changes the `timezone` setting.
|
|
96
|
+
*/
|
|
97
|
+
export function inboxMonth(instant) {
|
|
98
|
+
const at = new Date(instant);
|
|
99
|
+
if (Number.isNaN(at.getTime()))
|
|
100
|
+
return instant.slice(0, 7);
|
|
101
|
+
return `${String(at.getUTCFullYear()).padStart(4, '0')}-${String(at.getUTCMonth() + 1).padStart(2, '0')}`;
|
|
102
|
+
}
|
|
103
|
+
/** The log file an activity that arrived at this instant belongs in. */
|
|
104
|
+
export function inboxFile(contentDir, instant) {
|
|
105
|
+
return path.join(inboxDirectory(contentDir), `${inboxMonth(instant)}.jsonl`);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* One user's followers, as their `followers.json` says them, oldest follow
|
|
109
|
+
* first.
|
|
110
|
+
*
|
|
111
|
+
* A missing file is an empty list, which is what a site nobody has followed
|
|
112
|
+
* yet has. Anything else that is not a list of deliverable followers throws,
|
|
113
|
+
* naming the file: this is read at boot to build the index, and a damaged file
|
|
114
|
+
* read as "no followers" would quietly unfollow everybody — the one thing
|
|
115
|
+
* doc-4 says an ActivityPub site can never take back.
|
|
116
|
+
*/
|
|
117
|
+
export function readFollowers(contentDir, username) {
|
|
118
|
+
const file = followersFile(contentDir, username);
|
|
119
|
+
const source = readFileIfPresentSync(file);
|
|
120
|
+
if (source === undefined)
|
|
121
|
+
return [];
|
|
122
|
+
return parseFollowers(source, file, username);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Record a follow of one user: append the follower to that user's file, or
|
|
126
|
+
* refresh the profile of one already there, and put the same thing in the
|
|
127
|
+
* index.
|
|
128
|
+
*
|
|
129
|
+
* Following twice is not two followers. The file is keyed by actor id exactly
|
|
130
|
+
* as the index is, and an actor already in it keeps its place and its original
|
|
131
|
+
* follow time — a repeated or redelivered `Follow` refreshes the name and the
|
|
132
|
+
* avatar and nothing else.
|
|
133
|
+
*/
|
|
134
|
+
export async function addFollower(records, username, follower) {
|
|
135
|
+
const { admin, contentDir } = records;
|
|
136
|
+
const file = followersFile(contentDir, username);
|
|
137
|
+
return await withFileLock(file, () => {
|
|
138
|
+
const held = readFollowers(contentDir, username);
|
|
139
|
+
const existing = held.find((entry) => entry.actorId === follower.actorId);
|
|
140
|
+
const stored = {
|
|
141
|
+
username,
|
|
142
|
+
actorId: follower.actorId,
|
|
143
|
+
inboxId: follower.inboxId,
|
|
144
|
+
sharedInboxId: follower.sharedInboxId,
|
|
145
|
+
handle: follower.handle,
|
|
146
|
+
name: follower.name,
|
|
147
|
+
iconUrl: follower.iconUrl,
|
|
148
|
+
url: follower.url,
|
|
149
|
+
// The file remembers when the follow began, so a profile refresh cannot
|
|
150
|
+
// move an actor to the top of the list it has been on for a year.
|
|
151
|
+
followedAt: existing?.followedAt ?? follower.followedAt ?? new Date().toISOString(),
|
|
152
|
+
};
|
|
153
|
+
const next = existing === undefined
|
|
154
|
+
? [...held, stored]
|
|
155
|
+
: held.map((entry) => (entry.actorId === stored.actorId ? stored : entry));
|
|
156
|
+
writeFileAtomicallySync(file, followersJson(next));
|
|
157
|
+
admin.putFollower(stored);
|
|
158
|
+
return stored;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Forget one of a user's followers: an `Undo(Follow)`, or an actor deleting
|
|
163
|
+
* itself.
|
|
164
|
+
*
|
|
165
|
+
* Returns whether anything was there to forget. The index is emptied of the
|
|
166
|
+
* actor whether or not the file held it, so a row left over from a file that
|
|
167
|
+
* was edited by hand cannot go on being delivered to.
|
|
168
|
+
*/
|
|
169
|
+
export async function removeFollower(records, username, actorId) {
|
|
170
|
+
const { admin, contentDir } = records;
|
|
171
|
+
const file = followersFile(contentDir, username);
|
|
172
|
+
return await withFileLock(file, () => {
|
|
173
|
+
const held = readFollowers(contentDir, username);
|
|
174
|
+
const next = held.filter((entry) => entry.actorId !== actorId);
|
|
175
|
+
if (next.length !== held.length)
|
|
176
|
+
writeFileAtomicallySync(file, followersJson(next));
|
|
177
|
+
const indexed = admin.deleteFollower(username, actorId);
|
|
178
|
+
return next.length !== held.length || indexed;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The whole inbox log, oldest month first and, within a month, in the order
|
|
183
|
+
* the activities arrived.
|
|
184
|
+
*
|
|
185
|
+
* Every month file under `content/_data/federation/inbox` is read; a file or a
|
|
186
|
+
* line that will not parse throws, naming the file. Fedify answers a throwing
|
|
187
|
+
* dispatcher by swallowing the throw, so a log this cannot read has to stop
|
|
188
|
+
* the boot rather than wait to be noticed through a request.
|
|
189
|
+
*/
|
|
190
|
+
export function readInboxLog(contentDir) {
|
|
191
|
+
const lines = [];
|
|
192
|
+
for (const file of inboxFiles(contentDir))
|
|
193
|
+
lines.push(...readInboxFile(file));
|
|
194
|
+
return lines;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Record one inbound activity: append it to the month's log and index it.
|
|
198
|
+
*
|
|
199
|
+
* `json` is the activity as compacted JSON-LD, which is what the handler has
|
|
200
|
+
* and what doc-4 says to keep whole — nothing is picked out of it here beyond
|
|
201
|
+
* the columns the index pages and counts by, because what a later phase will
|
|
202
|
+
* want out of an activity is not knowable from here.
|
|
203
|
+
*
|
|
204
|
+
* An activity with no actor is dropped and nothing is written: Fedify has
|
|
205
|
+
* already refused anything whose signature does not match its actor, so one
|
|
206
|
+
* without an actor is malformed rather than anonymous. A redelivery of an
|
|
207
|
+
* activity the month already holds replaces its line where it stands, which is
|
|
208
|
+
* what the index's unique key on the activity id does to the row.
|
|
209
|
+
*/
|
|
210
|
+
export async function appendInboxActivity(records, json, options = {}) {
|
|
211
|
+
const { admin, contentDir } = records;
|
|
212
|
+
const receivedAt = options.receivedAt ?? new Date().toISOString();
|
|
213
|
+
const line = { receivedAt, recipient: options.recipient ?? null, json };
|
|
214
|
+
const row = inboxRowFrom(line);
|
|
215
|
+
if (row === undefined)
|
|
216
|
+
return undefined;
|
|
217
|
+
const file = inboxFile(contentDir, receivedAt);
|
|
218
|
+
return await withFileLock(file, () => {
|
|
219
|
+
const held = readInboxFile(file);
|
|
220
|
+
const at = row.activityId === null ? -1 : held.findIndex(sameActivity(row.activityId));
|
|
221
|
+
const next = at === -1 ? [...held, line] : held.with(at, line);
|
|
222
|
+
writeFileAtomicallySync(file, inboxJsonl(next));
|
|
223
|
+
return admin.logInboxActivity(row);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* One line of the log as the index row it makes, or `undefined` when it is not
|
|
228
|
+
* an activity the log keeps.
|
|
229
|
+
*
|
|
230
|
+
* This is the only place a row is derived, and the live append and the boot
|
|
231
|
+
* rebuild both go through it, so a row rebuilt from the log cannot say
|
|
232
|
+
* something different from the row the activity made when it arrived. Every
|
|
233
|
+
* column is read out of the JSON, so the file really is the whole story;
|
|
234
|
+
* `inReplyTo` is the one the store derives for itself, from this same JSON and
|
|
235
|
+
* by the same rule.
|
|
236
|
+
*/
|
|
237
|
+
export function inboxRowFrom(line) {
|
|
238
|
+
let parsed;
|
|
239
|
+
try {
|
|
240
|
+
parsed = JSON.parse(line.json);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
if (!isRecord(parsed))
|
|
246
|
+
return undefined;
|
|
247
|
+
const actorId = uriOf(parsed['actor']);
|
|
248
|
+
if (actorId === null)
|
|
249
|
+
return undefined;
|
|
250
|
+
return {
|
|
251
|
+
activityId: uriOf(parsed['id']),
|
|
252
|
+
activityType: activityTypeOf(parsed['type']),
|
|
253
|
+
actorId,
|
|
254
|
+
objectId: uriOf(parsed['object']),
|
|
255
|
+
recipient: line.recipient,
|
|
256
|
+
receivedAt: line.receivedAt,
|
|
257
|
+
json: line.json,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Rebuild the followers and inbox indexes from the files.
|
|
262
|
+
*
|
|
263
|
+
* This is what makes `data/geekity.db` disposable for federation (decision-9):
|
|
264
|
+
* the two tables hold nothing but what these files say, so every boot throws
|
|
265
|
+
* away what they hold and reads them again. That is also what makes editing
|
|
266
|
+
* `followers.json` by hand and restarting a supported thing to do, and why a
|
|
267
|
+
* database deleted at rest costs a site nothing.
|
|
268
|
+
*
|
|
269
|
+
* Exported so `geekity rebuild` can call the very function boot calls. It is
|
|
270
|
+
* synchronous because both callers are, and it reads before it writes: a file
|
|
271
|
+
* that will not parse throws with the file named and leaves the index exactly
|
|
272
|
+
* as it was, rather than emptying it and then failing.
|
|
273
|
+
*/
|
|
274
|
+
export function rebuildFederationIndexes(records) {
|
|
275
|
+
const { admin, contentDir } = records;
|
|
276
|
+
const followers = federatedUsernames(contentDir).flatMap((username) => readFollowers(contentDir, username));
|
|
277
|
+
const activities = [];
|
|
278
|
+
for (const line of readInboxLog(contentDir)) {
|
|
279
|
+
const row = inboxRowFrom(line);
|
|
280
|
+
if (row !== undefined)
|
|
281
|
+
activities.push(row);
|
|
282
|
+
}
|
|
283
|
+
admin.replaceFollowers(followers);
|
|
284
|
+
admin.replaceInboxActivities(activities);
|
|
285
|
+
return { followers: followers.length, activities: activities.length };
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Write an older site's inbox rows out as files, once.
|
|
289
|
+
*
|
|
290
|
+
* Before decision-9 the table was the source rather than an index of one, so a
|
|
291
|
+
* site upgrading has rows that no file carries. The rule is the simple one the
|
|
292
|
+
* other decision-9 migrations use, and it is simple here because the log did
|
|
293
|
+
* not exist as a file at all before: a log that is already there wins outright
|
|
294
|
+
* and is not touched, and rows are written out only where there is none. The
|
|
295
|
+
* lines it writes name no recipient, because the site they came from had one
|
|
296
|
+
* actor and it is gone (decision-14).
|
|
297
|
+
*
|
|
298
|
+
* The site actor's followers are **not** migrated. decision-14 replaces one
|
|
299
|
+
* site actor with one actor per user, and there is no honest answer to which
|
|
300
|
+
* user inherited the followers of an account that no longer exists: a follow
|
|
301
|
+
* is an agreement with somebody, and handing it to whoever happens to have the
|
|
302
|
+
* lowest user id would be answering it for them. A site that federated as the
|
|
303
|
+
* site actor starts again as its users, and the old
|
|
304
|
+
* `content/_data/federation/followers.json` is left exactly where it is for an
|
|
305
|
+
* operator who wants to move rows into a user's file by hand.
|
|
306
|
+
*
|
|
307
|
+
* The table is not dropped, unlike `settings`, `actor_keys` and `users`: it
|
|
308
|
+
* stays as the index the rest of the CMS reads. {@link rebuildFederationIndexes}
|
|
309
|
+
* is what runs next and puts the files back into it.
|
|
310
|
+
*/
|
|
311
|
+
export function migrateFederationToFiles(records) {
|
|
312
|
+
const { admin, contentDir } = records;
|
|
313
|
+
if (inboxFiles(contentDir).length === 0) {
|
|
314
|
+
const byMonth = new Map();
|
|
315
|
+
for (const activity of [...admin.listInboxActivities()].reverse()) {
|
|
316
|
+
const line = {
|
|
317
|
+
receivedAt: activity.receivedAt,
|
|
318
|
+
recipient: activity.recipient,
|
|
319
|
+
json: activity.json,
|
|
320
|
+
};
|
|
321
|
+
const month = inboxFile(contentDir, activity.receivedAt);
|
|
322
|
+
byMonth.set(month, [...(byMonth.get(month) ?? []), line]);
|
|
323
|
+
}
|
|
324
|
+
for (const [month, lines] of byMonth)
|
|
325
|
+
writeFileAtomicallySync(month, inboxJsonl(lines));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* One user's followers as their file spells them: an array, indented, newline
|
|
330
|
+
* ended.
|
|
331
|
+
*
|
|
332
|
+
* The username is not written into the entries. It is the name of the
|
|
333
|
+
* directory the file is in, and saying it again once per follower would be a
|
|
334
|
+
* second place for it to be wrong.
|
|
335
|
+
*/
|
|
336
|
+
function followersJson(followers) {
|
|
337
|
+
const entries = followers.map(({ username: _username, ...rest }) => rest);
|
|
338
|
+
return `${JSON.stringify(entries, null, 2)}\n`;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* `followers.json` as the followers it names, or a thrown error naming it.
|
|
342
|
+
*
|
|
343
|
+
* An entry with no actor id or no inbox is refused rather than dropped. Those
|
|
344
|
+
* two are the whole of what a follower is for — something to deliver to, and a
|
|
345
|
+
* name to key it by — and skipping such an entry would leave the file and the
|
|
346
|
+
* index quietly disagreeing about who follows the site.
|
|
347
|
+
*/
|
|
348
|
+
function parseFollowers(source, file, username) {
|
|
349
|
+
let parsed;
|
|
350
|
+
try {
|
|
351
|
+
parsed = JSON.parse(source);
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
throw new Error(`${file} could not be read as JSON: ${messageOf(error)}`, { cause: error });
|
|
355
|
+
}
|
|
356
|
+
if (!Array.isArray(parsed)) {
|
|
357
|
+
throw new Error(`${file} should be a list of followers, one object per follower.`);
|
|
358
|
+
}
|
|
359
|
+
return parsed.map((entry, index) => {
|
|
360
|
+
if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {
|
|
361
|
+
throw new Error(`${file}: entry ${String(index + 1)} is not a follower object.`);
|
|
362
|
+
}
|
|
363
|
+
const follower = entry;
|
|
364
|
+
const actorId = follower['actorId'];
|
|
365
|
+
const inboxId = follower['inboxId'];
|
|
366
|
+
if (typeof actorId !== 'string' || actorId === '') {
|
|
367
|
+
throw new Error(`${file}: entry ${String(index + 1)} has no actorId.`);
|
|
368
|
+
}
|
|
369
|
+
if (typeof inboxId !== 'string' || inboxId === '') {
|
|
370
|
+
throw new Error(`${file}: the follower "${actorId}" has no inboxId to deliver to.`);
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
username,
|
|
374
|
+
actorId,
|
|
375
|
+
inboxId,
|
|
376
|
+
sharedInboxId: optionalText(follower['sharedInboxId']),
|
|
377
|
+
handle: optionalText(follower['handle']),
|
|
378
|
+
name: optionalText(follower['name']),
|
|
379
|
+
iconUrl: optionalText(follower['iconUrl']),
|
|
380
|
+
url: optionalText(follower['url']),
|
|
381
|
+
followedAt: typeof follower['followedAt'] === 'string' ? follower['followedAt'] : '',
|
|
382
|
+
};
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
/** A value the file may have left out, as the text it holds or `null`. */
|
|
386
|
+
function optionalText(value) {
|
|
387
|
+
return typeof value === 'string' && value !== '' ? value : null;
|
|
388
|
+
}
|
|
389
|
+
/** Every month log a site has, oldest first. */
|
|
390
|
+
function inboxFiles(contentDir) {
|
|
391
|
+
const directory = inboxDirectory(contentDir);
|
|
392
|
+
let entries;
|
|
393
|
+
try {
|
|
394
|
+
entries = readdirSync(directory);
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
// No directory is no log, which is what a site nobody has interacted with
|
|
398
|
+
// has. Every other way this can fail fails again on the next boot.
|
|
399
|
+
return [];
|
|
400
|
+
}
|
|
401
|
+
// The names are `yyyy-mm`, so sorting them as text sorts them by month, and
|
|
402
|
+
// reading them in that order is what makes the row ids the arrival order.
|
|
403
|
+
return entries
|
|
404
|
+
.filter((name) => name.endsWith('.jsonl'))
|
|
405
|
+
.sort()
|
|
406
|
+
.map((name) => path.join(directory, name));
|
|
407
|
+
}
|
|
408
|
+
/** One month's log as its lines, or a thrown error naming the file. */
|
|
409
|
+
function readInboxFile(file) {
|
|
410
|
+
const source = readFileIfPresentSync(file);
|
|
411
|
+
if (source === undefined)
|
|
412
|
+
return [];
|
|
413
|
+
const lines = [];
|
|
414
|
+
const rows = source.split('\n');
|
|
415
|
+
for (const [index, row] of rows.entries()) {
|
|
416
|
+
if (row.trim() === '')
|
|
417
|
+
continue;
|
|
418
|
+
let parsed;
|
|
419
|
+
try {
|
|
420
|
+
parsed = JSON.parse(row);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
throw new Error(`${file}: line ${String(index + 1)} is not JSON: ${messageOf(error)}`, {
|
|
424
|
+
cause: error,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
if (!isRecord(parsed)) {
|
|
428
|
+
throw new Error(`${file}: line ${String(index + 1)} is not an activity.`);
|
|
429
|
+
}
|
|
430
|
+
// `receivedAt` and `recipient` are the log's own words and everything else
|
|
431
|
+
// is the activity, so taking them off leaves exactly what the peer
|
|
432
|
+
// delivered.
|
|
433
|
+
const { receivedAt, recipient, ...activity } = parsed;
|
|
434
|
+
lines.push({
|
|
435
|
+
receivedAt: typeof receivedAt === 'string' ? receivedAt : '',
|
|
436
|
+
recipient: typeof recipient === 'string' && recipient !== '' ? recipient : null,
|
|
437
|
+
json: JSON.stringify(activity),
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
return lines;
|
|
441
|
+
}
|
|
442
|
+
/** The lines as the file spells them: one compact JSON object each. */
|
|
443
|
+
function inboxJsonl(lines) {
|
|
444
|
+
return lines
|
|
445
|
+
.map((line) => `${JSON.stringify({
|
|
446
|
+
receivedAt: line.receivedAt,
|
|
447
|
+
// Absent rather than null for a shared-inbox delivery that named
|
|
448
|
+
// nobody, so a log written before decision-14 and one written after
|
|
449
|
+
// it read the same.
|
|
450
|
+
...(line.recipient === null ? {} : { recipient: line.recipient }),
|
|
451
|
+
...JSON.parse(line.json),
|
|
452
|
+
})}\n`)
|
|
453
|
+
.join('');
|
|
454
|
+
}
|
|
455
|
+
/** Whether a line carries this activity id, for the redelivery that replaces it. */
|
|
456
|
+
function sameActivity(activityId) {
|
|
457
|
+
return (line) => {
|
|
458
|
+
const parsed = JSON.parse(line.json);
|
|
459
|
+
return isRecord(parsed) && uriOf(parsed['id']) === activityId;
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* The short ActivityStreams type name an activity carries: `Like`, `Announce`,
|
|
464
|
+
* `Create`.
|
|
465
|
+
*
|
|
466
|
+
* A compacted document usually spells it as that word, which is what the
|
|
467
|
+
* `INBOX_INTERACTIONS` table on the federation screen keys on. Anything else
|
|
468
|
+
* is reduced the way the type IRI is: the fragment, else the last path
|
|
469
|
+
* segment, so an activity outside the core vocabulary still has a name rather
|
|
470
|
+
* than a URL. An activity with several types is filed under the first, and one
|
|
471
|
+
* with none is `Activity`, which is what it is.
|
|
472
|
+
*/
|
|
473
|
+
function activityTypeOf(value) {
|
|
474
|
+
if (Array.isArray(value)) {
|
|
475
|
+
for (const item of value) {
|
|
476
|
+
const found = activityTypeOf(item);
|
|
477
|
+
if (found !== 'Activity')
|
|
478
|
+
return found;
|
|
479
|
+
}
|
|
480
|
+
return 'Activity';
|
|
481
|
+
}
|
|
482
|
+
if (typeof value !== 'string' || value === '')
|
|
483
|
+
return 'Activity';
|
|
484
|
+
if (!value.includes(':'))
|
|
485
|
+
return value;
|
|
486
|
+
try {
|
|
487
|
+
const url = new URL(value);
|
|
488
|
+
if (url.hash !== '')
|
|
489
|
+
return url.hash.slice(1);
|
|
490
|
+
const last = url.pathname
|
|
491
|
+
.split('/')
|
|
492
|
+
.filter((segment) => segment !== '')
|
|
493
|
+
.pop();
|
|
494
|
+
return last ?? value;
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
return value;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function isRecord(value) {
|
|
501
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
502
|
+
}
|
|
503
|
+
function messageOf(error) {
|
|
504
|
+
return error instanceof Error ? error.message : String(error);
|
|
505
|
+
}
|
|
506
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/federation/records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Accept, Reject } from '@fedify/vocab';
|
|
2
|
+
import type { Recipient } from '@fedify/vocab';
|
|
3
|
+
import type { AdminStore, Relay } from '../admin/store.ts';
|
|
4
|
+
import type { ResolvedConfig } from '../config.ts';
|
|
5
|
+
import type { ContentStore } from '../content/store.ts';
|
|
6
|
+
import type { SiteFederation } from './federation.ts';
|
|
7
|
+
/** Where a relay reports what it could not do. `console` will do. */
|
|
8
|
+
export interface RelayLogger {
|
|
9
|
+
warn(message: string): void;
|
|
10
|
+
}
|
|
11
|
+
/** What {@link createRelayService} needs. */
|
|
12
|
+
export interface CreateRelayServiceOptions {
|
|
13
|
+
/** The site's federation object, which mints the ids and signs the requests. */
|
|
14
|
+
federation: SiteFederation;
|
|
15
|
+
/** The settings, which hold the relay list, and the subscription records. */
|
|
16
|
+
admin: AdminStore;
|
|
17
|
+
/** The content index, which the dispatchers read through the context. */
|
|
18
|
+
store: ContentStore;
|
|
19
|
+
/** Config after defaults and environment overrides. */
|
|
20
|
+
config: ResolvedConfig;
|
|
21
|
+
/** Where failures are reported. Defaults to `console`. */
|
|
22
|
+
logger?: RelayLogger | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** What one call to {@link RelayService.sync} did. */
|
|
25
|
+
export interface RelaySyncReport {
|
|
26
|
+
/** The relays newly followed, because the list named them and nothing knew them. */
|
|
27
|
+
readonly followed: readonly string[];
|
|
28
|
+
/** The relays unfollowed, because the list stopped naming them. */
|
|
29
|
+
readonly unfollowed: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The site's half of the Mastodon relay protocol (FEP-ae0c).
|
|
33
|
+
*
|
|
34
|
+
* A relay is not a follower and is not stored as one: it is followed rather
|
|
35
|
+
* than following, its subscription can be refused, and it has no profile worth
|
|
36
|
+
* showing. What it shares with a follower is the only thing that matters to
|
|
37
|
+
* the rest of the system — an inbox every public activity is delivered to —
|
|
38
|
+
* and {@link relayRecipient} is where that likeness is spelled out.
|
|
39
|
+
*/
|
|
40
|
+
export interface RelayService {
|
|
41
|
+
/**
|
|
42
|
+
* Bring the subscriptions in line with the relay list in the settings: a
|
|
43
|
+
* listed relay with no record is followed, a record no longer listed is
|
|
44
|
+
* undone. Called at boot and after every save of the settings.
|
|
45
|
+
*
|
|
46
|
+
* A listed relay whose record was lost — a rebuilt database, a restored
|
|
47
|
+
* content directory — is followed again, which is what makes the file the
|
|
48
|
+
* source and the records derivable from it.
|
|
49
|
+
*/
|
|
50
|
+
sync(): RelaySyncReport;
|
|
51
|
+
/**
|
|
52
|
+
* Send the `Follow` again for one relay, under a fresh id, and put its
|
|
53
|
+
* record back to pending. This is the Retry on the federation screen: a
|
|
54
|
+
* relay may have been down, or may have lost the subscription.
|
|
55
|
+
*/
|
|
56
|
+
retry(inboxId: string): Promise<Relay | undefined>;
|
|
57
|
+
/** Resolve once every queued `Follow` and `Undo` has finished, however it finished. */
|
|
58
|
+
settled(): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* One relay as the {@link Recipient} Fedify delivers to.
|
|
62
|
+
*
|
|
63
|
+
* The inbox stands in for the id until the relay has answered, because the
|
|
64
|
+
* `Follow` goes out before the site knows what to call it: Fedify drops a
|
|
65
|
+
* recipient with no id, so `null` would silently send nothing. The id is only
|
|
66
|
+
* ever used to key the inbox and to build a collection synchronisation header
|
|
67
|
+
* for a shared inbox, and a relay publishes no shared inbox — a relay *is* one
|
|
68
|
+
* — so standing the inbox in for it costs the relay nothing.
|
|
69
|
+
*/
|
|
70
|
+
export declare function relayRecipient(relay: Relay): Recipient;
|
|
71
|
+
/**
|
|
72
|
+
* The relays a public activity is delivered to: the accepted ones, and only
|
|
73
|
+
* those.
|
|
74
|
+
*
|
|
75
|
+
* A pending subscription has not been agreed to and a rejected one has been
|
|
76
|
+
* refused; delivering to either would be posting into an inbox that has not
|
|
77
|
+
* said it wants this, which is what the handshake exists to establish.
|
|
78
|
+
*/
|
|
79
|
+
export declare function acceptedRelays(admin: AdminStore): Relay[];
|
|
80
|
+
/**
|
|
81
|
+
* Build the relay service for one site.
|
|
82
|
+
*
|
|
83
|
+
* FEP-ae0c is the whole of the protocol: a `Follow` whose object is the
|
|
84
|
+
* literal Public collection, sent to the relay's inbox and signed the way any
|
|
85
|
+
* other activity is; an `Accept` or a `Reject` back, which may take days
|
|
86
|
+
* because a relay is allowed to hold a subscription for a human to approve;
|
|
87
|
+
* and an `Undo` of that same `Follow` to leave.
|
|
88
|
+
*/
|
|
89
|
+
export declare function createRelayService(options: CreateRelayServiceOptions): RelayService;
|
|
90
|
+
/**
|
|
91
|
+
* Mark the subscription an `Accept` answers as accepted, and record who the
|
|
92
|
+
* relay turned out to be. `undefined` when it answers no follow this site
|
|
93
|
+
* sent — the site follows nothing but relays (doc-4), so that is a stray.
|
|
94
|
+
*
|
|
95
|
+
* A free function over the store rather than a method on the service: nothing
|
|
96
|
+
* about it is queued or sent, and the inbox listener that calls it has the
|
|
97
|
+
* store on its context and no service.
|
|
98
|
+
*/
|
|
99
|
+
export declare function acceptRelay(admin: AdminStore, activity: Accept): Relay | undefined;
|
|
100
|
+
/** The same for a `Reject`, which marks the relay rejected with its reason. */
|
|
101
|
+
export declare function rejectRelay(admin: AdminStore, activity: Reject): Relay | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Match an `Accept` or a `Reject` to the subscription it answers.
|
|
104
|
+
*
|
|
105
|
+
* The follow id is what FEP-ae0c says the answer names, so it is tried first.
|
|
106
|
+
* A relay that has answered before is then recognised by its actor id, which
|
|
107
|
+
* covers a re-follow whose answer echoes a stale id. Last, a single pending
|
|
108
|
+
* subscription on the answering relay's own origin is taken as the one meant:
|
|
109
|
+
* a relay answering from the host its inbox is on is answering about that
|
|
110
|
+
* inbox, and there is nothing else it could be about. Two pending
|
|
111
|
+
* subscriptions on one host are left alone rather than guessed between.
|
|
112
|
+
*/
|
|
113
|
+
export declare function relayAnswering(admin: AdminStore, activity: Accept | Reject): Relay | undefined;
|
|
114
|
+
//# sourceMappingURL=relays.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relays.d.ts","sourceRoot":"","sources":["../../src/federation/relays.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAA6B,MAAM,EAAQ,MAAM,eAAe,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAK/C,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAyB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE7E,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,6CAA6C;AAC7C,MAAM,WAAW,yBAAyB;IACxC,gFAAgF;IAChF,UAAU,EAAE,cAAc,CAAC;IAC3B,6EAA6E;IAC7E,KAAK,EAAE,UAAU,CAAC;IAClB,yEAAyE;IACzE,KAAK,EAAE,YAAY,CAAC;IACpB,uDAAuD;IACvD,MAAM,EAAE,cAAc,CAAC;IACvB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;OAQG;IACH,IAAI,IAAI,eAAe,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IACnD,uFAAuF;IACvF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAKtD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,EAAE,CAEzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,YAAY,CAyMnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CASlF;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CASlF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAoB9F"}
|