@geekity/cms 0.29.0 → 0.31.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 +26 -4214
- package/admin/pages/settings/privacy.njk +1 -1
- package/dist/access-log.d.ts +2 -10
- package/dist/access-log.d.ts.map +1 -1
- package/dist/access-log.js +1 -1
- package/dist/access-log.js.map +1 -1
- package/dist/{web → admin}/admin-bar.d.ts +3 -2
- package/dist/admin/admin-bar.d.ts.map +1 -0
- package/dist/{web → admin}/admin-bar.js +20 -17
- package/dist/admin/admin-bar.js.map +1 -0
- package/dist/{indieauth → admin}/app-activity.d.ts +2 -2
- package/dist/admin/app-activity.d.ts.map +1 -0
- package/dist/{indieauth → admin}/app-activity.js +5 -5
- package/dist/admin/app-activity.js.map +1 -0
- package/dist/admin/appearance.d.ts +3 -3
- package/dist/admin/appearance.d.ts.map +1 -1
- package/dist/admin/appearance.js +12 -6
- package/dist/admin/appearance.js.map +1 -1
- package/dist/admin/assets.d.ts +1 -8
- package/dist/admin/assets.d.ts.map +1 -1
- package/dist/admin/assets.js +2 -9
- package/dist/admin/assets.js.map +1 -1
- package/dist/admin/comments.d.ts +2 -2
- package/dist/admin/comments.d.ts.map +1 -1
- package/dist/admin/comments.js +16 -17
- package/dist/admin/comments.js.map +1 -1
- package/dist/{indieauth → admin}/connected-apps.d.ts +2 -2
- package/dist/admin/connected-apps.d.ts.map +1 -0
- package/dist/{indieauth → admin}/connected-apps.js +18 -19
- package/dist/admin/connected-apps.js.map +1 -0
- package/dist/admin/credentials.js +1 -1
- package/dist/admin/credentials.js.map +1 -1
- package/dist/admin/dev-mode.d.ts +1 -1
- package/dist/admin/dev-mode.d.ts.map +1 -1
- package/dist/admin/documents.d.ts +16 -301
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +74 -1032
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/editor-actions.d.ts +3 -2
- package/dist/admin/editor-actions.d.ts.map +1 -1
- package/dist/admin/editor-actions.js +8 -8
- package/dist/admin/editor-actions.js.map +1 -1
- package/dist/admin/editor-fields.d.ts +45 -0
- package/dist/admin/editor-fields.d.ts.map +1 -0
- package/dist/admin/editor-fields.js +71 -0
- package/dist/admin/editor-fields.js.map +1 -0
- package/dist/admin/editor-layout.d.ts +2 -10
- package/dist/admin/editor-layout.d.ts.map +1 -1
- package/dist/admin/editor-layout.js +1 -1
- package/dist/admin/editor-layout.js.map +1 -1
- package/dist/admin/federation.d.ts +5 -5
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +16 -18
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/flash.d.ts +2 -2
- package/dist/admin/flash.d.ts.map +1 -1
- package/dist/admin/headers.d.ts +1 -1
- package/dist/admin/headers.d.ts.map +1 -1
- package/dist/admin/headers.js +1 -1
- package/dist/admin/headers.js.map +1 -1
- package/dist/admin/index.d.ts +38 -20
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +27 -13
- package/dist/admin/index.js.map +1 -1
- package/dist/{indieauth/consent.d.ts → admin/indieauth-consent.d.ts} +4 -4
- package/dist/admin/indieauth-consent.d.ts.map +1 -0
- package/dist/{indieauth/consent.js → admin/indieauth-consent.js} +17 -18
- package/dist/admin/indieauth-consent.js.map +1 -0
- package/dist/admin/legacy-migrations.d.ts +131 -0
- package/dist/admin/legacy-migrations.d.ts.map +1 -0
- package/dist/admin/legacy-migrations.js +235 -0
- package/dist/admin/legacy-migrations.js.map +1 -0
- package/dist/admin/media.d.ts +4 -108
- package/dist/admin/media.d.ts.map +1 -1
- package/dist/admin/media.js +19 -187
- package/dist/admin/media.js.map +1 -1
- package/dist/admin/menu.d.ts.map +1 -1
- package/dist/admin/menu.js +7 -7
- package/dist/admin/menu.js.map +1 -1
- package/dist/admin/messages.d.ts +1 -1
- package/dist/admin/messages.d.ts.map +1 -1
- package/dist/admin/messages.js +10 -12
- package/dist/admin/messages.js.map +1 -1
- package/dist/admin/navigation.d.ts +3 -3
- package/dist/admin/navigation.d.ts.map +1 -1
- package/dist/admin/navigation.js +9 -12
- package/dist/admin/navigation.js.map +1 -1
- package/dist/admin/personal-data.d.ts +1 -1
- package/dist/admin/personal-data.d.ts.map +1 -1
- package/dist/admin/personal-data.js +3 -6
- package/dist/admin/personal-data.js.map +1 -1
- package/dist/admin/plugins.d.ts +1 -1
- package/dist/admin/plugins.d.ts.map +1 -1
- package/dist/admin/plugins.js +11 -15
- package/dist/admin/plugins.js.map +1 -1
- package/dist/admin/preview.d.ts +2 -1
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +28 -32
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/recovery.d.ts +3 -3
- package/dist/admin/recovery.d.ts.map +1 -1
- package/dist/admin/recovery.js +10 -12
- package/dist/admin/recovery.js.map +1 -1
- package/dist/admin/routes.d.ts +1 -3
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +28 -26
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/settings-discussion.d.ts.map +1 -1
- package/dist/admin/settings-discussion.js +7 -4
- package/dist/admin/settings-discussion.js.map +1 -1
- package/dist/admin/settings-email.d.ts +1 -1
- package/dist/admin/settings-email.d.ts.map +1 -1
- package/dist/admin/settings-email.js +13 -10
- package/dist/admin/settings-email.js.map +1 -1
- package/dist/admin/settings-general.d.ts.map +1 -1
- package/dist/admin/settings-general.js +10 -7
- package/dist/admin/settings-general.js.map +1 -1
- package/dist/admin/settings-page.d.ts +3 -4
- package/dist/admin/settings-page.d.ts.map +1 -1
- package/dist/admin/settings-page.js +5 -6
- package/dist/admin/settings-page.js.map +1 -1
- package/dist/admin/settings-pages.d.ts +1 -1
- package/dist/admin/settings-pages.d.ts.map +1 -1
- package/dist/admin/settings-permalinks.js +1 -1
- package/dist/admin/settings-permalinks.js.map +1 -1
- package/dist/admin/settings-reading.d.ts +2 -2
- package/dist/admin/settings-reading.d.ts.map +1 -1
- package/dist/admin/settings-reading.js +4 -3
- package/dist/admin/settings-reading.js.map +1 -1
- package/dist/admin/settings.d.ts +0 -579
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +1 -1155
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/syndication-targets.d.ts +1 -1
- package/dist/admin/syndication-targets.d.ts.map +1 -1
- package/dist/admin/syndication-targets.js +11 -15
- package/dist/admin/syndication-targets.js.map +1 -1
- package/dist/admin/taxonomy.d.ts +2 -2
- package/dist/admin/taxonomy.d.ts.map +1 -1
- package/dist/admin/taxonomy.js +8 -11
- package/dist/admin/taxonomy.js.map +1 -1
- package/dist/admin/templates.js +1 -1
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/tools.d.ts +4 -4
- package/dist/admin/tools.d.ts.map +1 -1
- package/dist/admin/tools.js +3 -6
- package/dist/admin/tools.js.map +1 -1
- package/dist/admin/uploads.d.ts +1 -106
- package/dist/admin/uploads.d.ts.map +1 -1
- package/dist/admin/uploads.js +2 -191
- package/dist/admin/uploads.js.map +1 -1
- package/dist/admin/users.d.ts +20 -15
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +83 -80
- package/dist/admin/users.js.map +1 -1
- package/dist/avatars/avatars.d.ts +2 -2
- package/dist/avatars/avatars.d.ts.map +1 -1
- package/dist/avatars/avatars.js +6 -9
- package/dist/avatars/avatars.js.map +1 -1
- package/dist/avatars/index.d.ts +0 -1
- package/dist/avatars/index.d.ts.map +1 -1
- package/dist/avatars/index.js +0 -1
- package/dist/avatars/index.js.map +1 -1
- package/dist/cache.d.ts +4 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +11 -5
- package/dist/cache.js.map +1 -1
- package/dist/cli.d.ts +2 -33
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +245 -267
- package/dist/cli.js.map +1 -1
- package/dist/cms/app.d.ts +11 -0
- package/dist/cms/app.d.ts.map +1 -0
- package/dist/cms/app.js +115 -0
- package/dist/cms/app.js.map +1 -0
- package/dist/cms/boot.d.ts +14 -0
- package/dist/cms/boot.d.ts.map +1 -0
- package/dist/cms/boot.js +107 -0
- package/dist/cms/boot.js.map +1 -0
- package/dist/cms/create.d.ts +248 -0
- package/dist/cms/create.d.ts.map +1 -0
- package/dist/cms/create.js +167 -0
- package/dist/cms/create.js.map +1 -0
- package/dist/cms/lifecycle.d.ts +11 -0
- package/dist/cms/lifecycle.d.ts.map +1 -0
- package/dist/cms/lifecycle.js +15 -0
- package/dist/cms/lifecycle.js.map +1 -0
- package/dist/{web/errors.d.ts → cms/server-error.d.ts} +2 -8
- package/dist/cms/server-error.d.ts.map +1 -0
- package/dist/{web/errors.js → cms/server-error.js} +4 -14
- package/dist/cms/server-error.js.map +1 -0
- package/dist/cms/services.d.ts +55 -0
- package/dist/cms/services.d.ts.map +1 -0
- package/dist/cms/services.js +353 -0
- package/dist/cms/services.js.map +1 -0
- package/dist/cms/site-records.d.ts +4 -0
- package/dist/cms/site-records.d.ts.map +1 -0
- package/dist/cms/site-records.js +15 -0
- package/dist/cms/site-records.js.map +1 -0
- package/dist/comments/akismet.d.ts +1 -1
- package/dist/comments/akismet.d.ts.map +1 -1
- package/dist/comments/akismet.js +1 -3
- package/dist/comments/akismet.js.map +1 -1
- package/dist/comments/conversation.d.ts +334 -0
- package/dist/comments/conversation.d.ts.map +1 -0
- package/dist/comments/conversation.js +51 -0
- package/dist/comments/conversation.js.map +1 -0
- package/dist/comments/form.d.ts +2 -2
- package/dist/comments/form.d.ts.map +1 -1
- package/dist/comments/form.js +2 -2
- package/dist/comments/form.js.map +1 -1
- package/dist/comments/index.d.ts +12 -6
- package/dist/comments/index.d.ts.map +1 -1
- package/dist/comments/index.js +7 -4
- package/dist/comments/index.js.map +1 -1
- package/dist/comments/intake.d.ts +147 -0
- package/dist/comments/intake.d.ts.map +1 -0
- package/dist/comments/intake.js +161 -0
- package/dist/comments/intake.js.map +1 -0
- package/dist/comments/markdown.d.ts.map +1 -1
- package/dist/comments/markdown.js +2 -9
- package/dist/comments/markdown.js.map +1 -1
- package/dist/comments/migrations.d.ts +45 -0
- package/dist/comments/migrations.d.ts.map +1 -0
- package/dist/comments/migrations.js +194 -0
- package/dist/comments/migrations.js.map +1 -0
- package/dist/comments/moderate.d.ts +2 -2
- package/dist/comments/moderate.d.ts.map +1 -1
- package/dist/comments/moderate.js +3 -13
- package/dist/comments/moderate.js.map +1 -1
- package/dist/comments/page-form.d.ts +52 -0
- package/dist/comments/page-form.d.ts.map +1 -0
- package/dist/comments/page-form.js +62 -0
- package/dist/comments/page-form.js.map +1 -0
- package/dist/comments/policy.d.ts +1 -9
- package/dist/comments/policy.d.ts.map +1 -1
- package/dist/comments/policy.js +3 -18
- package/dist/comments/policy.js.map +1 -1
- package/dist/comments/records.d.ts +25 -173
- package/dist/comments/records.d.ts.map +1 -1
- package/dist/comments/records.js +69 -265
- package/dist/comments/records.js.map +1 -1
- package/dist/comments/reply-notices.d.ts +5 -5
- package/dist/comments/reply-notices.d.ts.map +1 -1
- package/dist/comments/reply-notices.js +6 -6
- package/dist/comments/reply-notices.js.map +1 -1
- package/dist/comments/reply-post.d.ts +2 -2
- package/dist/comments/reply-post.d.ts.map +1 -1
- package/dist/comments/reply-post.js +7 -5
- package/dist/comments/reply-post.js.map +1 -1
- package/dist/comments/routes.d.ts +3 -3
- package/dist/comments/routes.d.ts.map +1 -1
- package/dist/comments/routes.js +22 -34
- package/dist/comments/routes.js.map +1 -1
- package/dist/comments/submission.d.ts +5 -100
- package/dist/comments/submission.d.ts.map +1 -1
- package/dist/comments/submission.js +5 -20
- package/dist/comments/submission.js.map +1 -1
- package/dist/comments/viewer.d.ts +1 -25
- package/dist/comments/viewer.d.ts.map +1 -1
- package/dist/comments/viewer.js +1 -44
- package/dist/comments/viewer.js.map +1 -1
- package/dist/config-loader.d.ts +35 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +116 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/config.d.ts +72 -50
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +132 -180
- package/dist/config.js.map +1 -1
- package/dist/contact/delivery.d.ts +1 -1
- package/dist/contact/delivery.d.ts.map +1 -1
- package/dist/contact/delivery.js +5 -13
- package/dist/contact/delivery.js.map +1 -1
- package/dist/contact/form.d.ts +2 -4
- package/dist/contact/form.d.ts.map +1 -1
- package/dist/contact/form.js +3 -4
- package/dist/contact/form.js.map +1 -1
- package/dist/contact/index.d.ts +2 -2
- package/dist/contact/index.d.ts.map +1 -1
- package/dist/contact/index.js +2 -2
- package/dist/contact/index.js.map +1 -1
- package/dist/contact/records.d.ts.map +1 -1
- package/dist/contact/records.js +8 -11
- package/dist/contact/records.js.map +1 -1
- package/dist/contact/submission.d.ts +2 -2
- package/dist/contact/submission.d.ts.map +1 -1
- package/dist/contact/submission.js +7 -16
- package/dist/contact/submission.js.map +1 -1
- package/dist/{images → content}/alt-text.d.ts +1 -1
- package/dist/content/alt-text.d.ts.map +1 -0
- package/dist/{images → content}/alt-text.js +3 -5
- package/dist/content/alt-text.js.map +1 -0
- package/dist/content/authors.d.ts +79 -0
- package/dist/content/authors.d.ts.map +1 -0
- package/dist/content/authors.js +106 -0
- package/dist/content/authors.js.map +1 -0
- package/dist/content/citation.d.ts +3 -0
- package/dist/content/citation.d.ts.map +1 -1
- package/dist/content/citation.js +3 -0
- package/dist/content/citation.js.map +1 -1
- package/dist/content/comments.d.ts +3 -0
- package/dist/content/comments.d.ts.map +1 -0
- package/dist/content/comments.js +3 -0
- package/dist/content/comments.js.map +1 -0
- package/dist/content/contact.d.ts +3 -0
- package/dist/content/contact.d.ts.map +1 -0
- package/dist/content/contact.js +3 -0
- package/dist/content/contact.js.map +1 -0
- package/dist/content/document-form.d.ts +195 -0
- package/dist/content/document-form.d.ts.map +1 -0
- package/dist/content/document-form.js +201 -0
- package/dist/content/document-form.js.map +1 -0
- package/dist/content/document-kind.d.ts +55 -0
- package/dist/content/document-kind.d.ts.map +1 -0
- package/dist/content/document-kind.js +30 -0
- package/dist/content/document-kind.js.map +1 -0
- package/dist/{admin/enclosure-field.d.ts → content/enclosure-form.d.ts} +14 -34
- package/dist/content/enclosure-form.d.ts.map +1 -0
- package/dist/{admin/enclosure-field.js → content/enclosure-form.js} +39 -76
- package/dist/content/enclosure-form.js.map +1 -0
- package/dist/content/enclosure.d.ts.map +1 -1
- package/dist/content/enclosure.js +3 -4
- package/dist/content/enclosure.js.map +1 -1
- package/dist/{admin/event-field.d.ts → content/event-form.d.ts} +6 -5
- package/dist/content/event-form.d.ts.map +1 -0
- package/dist/{admin/event-field.js → content/event-form.js} +45 -12
- package/dist/content/event-form.js.map +1 -0
- package/dist/content/excerpt.d.ts +25 -0
- package/dist/content/excerpt.d.ts.map +1 -0
- package/dist/content/excerpt.js +43 -0
- package/dist/content/excerpt.js.map +1 -0
- package/dist/content/form-error.d.ts +10 -0
- package/dist/content/form-error.d.ts.map +1 -0
- package/dist/content/form-error.js +2 -0
- package/dist/content/form-error.js.map +1 -0
- package/dist/{web → content}/guids.d.ts +14 -19
- package/dist/content/guids.d.ts.map +1 -0
- package/dist/{web → content}/guids.js +30 -19
- package/dist/content/guids.js.map +1 -0
- package/dist/content/image-tags.d.ts +25 -0
- package/dist/content/image-tags.d.ts.map +1 -0
- package/dist/content/image-tags.js +55 -0
- package/dist/content/image-tags.js.map +1 -0
- package/dist/content/index.d.ts +9 -4
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +5 -2
- package/dist/content/index.js.map +1 -1
- package/dist/content/language.d.ts +19 -0
- package/dist/content/language.d.ts.map +1 -0
- package/dist/content/language.js +19 -0
- package/dist/content/language.js.map +1 -0
- package/dist/content/license.d.ts.map +1 -0
- package/dist/content/license.js.map +1 -0
- package/dist/{web → content}/locale.d.ts +0 -6
- package/dist/content/locale.d.ts.map +1 -0
- package/dist/{web → content}/locale.js +1 -6
- package/dist/content/locale.js.map +1 -0
- package/dist/content/location-form.d.ts +17 -0
- package/dist/content/location-form.d.ts.map +1 -0
- package/dist/{admin/location-field.js → content/location-form.js} +2 -23
- package/dist/content/location-form.js.map +1 -0
- package/dist/content/location.d.ts.map +1 -1
- package/dist/content/location.js +1 -3
- package/dist/content/location.js.map +1 -1
- package/dist/content/markdown-links.d.ts +11 -0
- package/dist/content/markdown-links.d.ts.map +1 -0
- package/dist/content/markdown-links.js +223 -0
- package/dist/content/markdown-links.js.map +1 -0
- package/dist/content/markdown.d.ts +2 -1
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +1 -1
- package/dist/content/markdown.js.map +1 -1
- package/dist/content/migrated.js +1 -1
- package/dist/content/migrated.js.map +1 -1
- package/dist/content/parser.d.ts.map +1 -1
- package/dist/content/parser.js +1 -12
- package/dist/content/parser.js.map +1 -1
- package/dist/content/permalinks.d.ts +34 -0
- package/dist/content/permalinks.d.ts.map +1 -0
- package/dist/{web/documents.js → content/permalinks.js} +6 -56
- package/dist/content/permalinks.js.map +1 -0
- package/dist/content/photo-form.d.ts +28 -0
- package/dist/content/photo-form.d.ts.map +1 -0
- package/dist/{admin/photo-field.js → content/photo-form.js} +36 -36
- package/dist/content/photo-form.js.map +1 -0
- package/dist/content/photo.d.ts +1 -1
- package/dist/content/photo.d.ts.map +1 -1
- package/dist/content/photo.js +1 -1
- package/dist/content/photo.js.map +1 -1
- package/dist/content/post-fields.d.ts +40 -0
- package/dist/content/post-fields.d.ts.map +1 -0
- package/dist/content/post-fields.js +256 -0
- package/dist/content/post-fields.js.map +1 -0
- package/dist/{admin/read-field.d.ts → content/read-form.d.ts} +6 -4
- package/dist/content/read-form.d.ts.map +1 -0
- package/dist/content/read-form.js +99 -0
- package/dist/content/read-form.js.map +1 -0
- package/dist/content/read.d.ts.map +1 -1
- package/dist/content/read.js +7 -11
- package/dist/content/read.js.map +1 -1
- package/dist/content/redirects.d.ts +84 -0
- package/dist/content/redirects.d.ts.map +1 -0
- package/dist/content/redirects.js +234 -0
- package/dist/content/redirects.js.map +1 -0
- package/dist/content/sanitize.d.ts +13 -0
- package/dist/content/sanitize.d.ts.map +1 -0
- package/dist/{web → content}/sanitize.js +4 -71
- package/dist/content/sanitize.js.map +1 -0
- package/dist/content/save.d.ts +5 -8
- package/dist/content/save.d.ts.map +1 -1
- package/dist/content/save.js +5 -26
- package/dist/content/save.js.map +1 -1
- package/dist/content/schedule.d.ts +2 -2
- package/dist/content/schedule.d.ts.map +1 -1
- package/dist/content/schedule.js +1 -3
- package/dist/content/schedule.js.map +1 -1
- package/dist/content/served.d.ts +58 -0
- package/dist/content/served.d.ts.map +1 -0
- package/dist/content/served.js +65 -0
- package/dist/content/served.js.map +1 -0
- package/dist/content/site-links.d.ts +72 -0
- package/dist/content/site-links.d.ts.map +1 -0
- package/dist/content/site-links.js +191 -0
- package/dist/content/site-links.js.map +1 -0
- package/dist/content/sqlite/archive.d.ts +4 -0
- package/dist/content/sqlite/archive.d.ts.map +1 -0
- package/dist/content/sqlite/archive.js +96 -0
- package/dist/content/sqlite/archive.js.map +1 -0
- package/dist/content/sqlite/backlinks.d.ts +4 -0
- package/dist/content/sqlite/backlinks.d.ts.map +1 -0
- package/dist/content/sqlite/backlinks.js +46 -0
- package/dist/content/sqlite/backlinks.js.map +1 -0
- package/dist/content/sqlite/catalog.d.ts +4 -0
- package/dist/content/sqlite/catalog.d.ts.map +1 -0
- package/dist/content/sqlite/catalog.js +62 -0
- package/dist/content/sqlite/catalog.js.map +1 -0
- package/dist/content/sqlite/clauses.d.ts +57 -0
- package/dist/content/sqlite/clauses.d.ts.map +1 -0
- package/dist/content/sqlite/clauses.js +76 -0
- package/dist/content/sqlite/clauses.js.map +1 -0
- package/dist/content/sqlite/database.d.ts +26 -0
- package/dist/content/sqlite/database.d.ts.map +1 -0
- package/dist/content/sqlite/database.js +27 -0
- package/dist/content/sqlite/database.js.map +1 -0
- package/dist/content/sqlite/documents.d.ts +12 -0
- package/dist/content/sqlite/documents.d.ts.map +1 -0
- package/dist/content/sqlite/documents.js +40 -0
- package/dist/content/sqlite/documents.js.map +1 -0
- package/dist/content/sqlite/lookups.d.ts +6 -0
- package/dist/content/sqlite/lookups.d.ts.map +1 -0
- package/dist/content/sqlite/lookups.js +25 -0
- package/dist/content/sqlite/lookups.js.map +1 -0
- package/dist/content/sqlite/open.d.ts +8 -0
- package/dist/content/sqlite/open.d.ts.map +1 -0
- package/dist/content/sqlite/open.js +63 -0
- package/dist/content/sqlite/open.js.map +1 -0
- package/dist/content/sqlite/replies.d.ts +4 -0
- package/dist/content/sqlite/replies.d.ts.map +1 -0
- package/dist/content/sqlite/replies.js +21 -0
- package/dist/content/sqlite/replies.js.map +1 -0
- package/dist/content/sqlite/rows.d.ts +22 -0
- package/dist/content/sqlite/rows.d.ts.map +1 -0
- package/dist/content/sqlite/rows.js +93 -0
- package/dist/content/sqlite/rows.js.map +1 -0
- package/dist/content/sqlite/schedule.d.ts +4 -0
- package/dist/content/sqlite/schedule.d.ts.map +1 -0
- package/dist/content/sqlite/schedule.js +16 -0
- package/dist/content/sqlite/schedule.js.map +1 -0
- package/dist/content/sqlite/schema.d.ts +10 -0
- package/dist/content/sqlite/schema.d.ts.map +1 -0
- package/dist/content/sqlite/schema.js +209 -0
- package/dist/content/sqlite/schema.js.map +1 -0
- package/dist/content/sqlite/search.d.ts +4 -0
- package/dist/content/sqlite/search.d.ts.map +1 -0
- package/dist/content/sqlite/search.js +54 -0
- package/dist/content/sqlite/search.js.map +1 -0
- package/dist/content/sqlite/spellings.d.ts +6 -0
- package/dist/content/sqlite/spellings.d.ts.map +1 -0
- package/dist/content/sqlite/spellings.js +80 -0
- package/dist/content/sqlite/spellings.js.map +1 -0
- package/dist/content/sqlite/taxonomy.d.ts +4 -0
- package/dist/content/sqlite/taxonomy.d.ts.map +1 -0
- package/dist/content/sqlite/taxonomy.js +75 -0
- package/dist/content/sqlite/taxonomy.js.map +1 -0
- package/dist/content/sqlite/writes.d.ts +9 -0
- package/dist/content/sqlite/writes.d.ts.map +1 -0
- package/dist/content/sqlite/writes.js +164 -0
- package/dist/content/sqlite/writes.js.map +1 -0
- package/dist/content/store.d.ts +142 -137
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +0 -1050
- package/dist/content/store.js.map +1 -1
- package/dist/content/sync.d.ts +12 -4
- package/dist/content/sync.d.ts.map +1 -1
- package/dist/content/sync.js +24 -41
- package/dist/content/sync.js.map +1 -1
- package/dist/content/syndicate-to.d.ts +25 -0
- package/dist/content/syndicate-to.d.ts.map +1 -0
- package/dist/content/syndicate-to.js +8 -0
- package/dist/content/syndicate-to.js.map +1 -0
- package/dist/{web → content}/taxonomy.d.ts +1 -1
- package/dist/content/taxonomy.d.ts.map +1 -0
- package/dist/{web → content}/taxonomy.js +2 -2
- package/dist/content/taxonomy.js.map +1 -0
- package/dist/content/time.d.ts +2 -2
- package/dist/content/time.d.ts.map +1 -1
- package/dist/content/time.js +3 -3
- package/dist/content/time.js.map +1 -1
- package/dist/content/trash.d.ts +35 -0
- package/dist/content/trash.d.ts.map +1 -0
- package/dist/content/trash.js +83 -0
- package/dist/content/trash.js.map +1 -0
- package/dist/content/uploads.d.ts +24 -0
- package/dist/content/uploads.d.ts.map +1 -0
- package/dist/content/uploads.js +27 -0
- package/dist/content/uploads.js.map +1 -0
- package/dist/content/video.d.ts.map +1 -1
- package/dist/content/video.js +3 -5
- package/dist/content/video.js.map +1 -1
- package/dist/content/write.d.ts +84 -0
- package/dist/content/write.d.ts.map +1 -0
- package/dist/content/write.js +566 -0
- package/dist/content/write.js.map +1 -0
- package/dist/content/writer.d.ts.map +1 -1
- package/dist/content/writer.js +1 -2
- package/dist/content/writer.js.map +1 -1
- package/dist/dev-mode.d.ts +5 -3
- package/dist/dev-mode.d.ts.map +1 -1
- package/dist/dev-mode.js +3 -3
- package/dist/dev-mode.js.map +1 -1
- package/dist/drain.d.ts +2 -3
- package/dist/drain.d.ts.map +1 -1
- package/dist/drain.js +2 -1
- package/dist/drain.js.map +1 -1
- package/dist/exports.d.ts +26 -0
- package/dist/exports.d.ts.map +1 -0
- package/dist/exports.js +8 -0
- package/dist/exports.js.map +1 -0
- package/dist/federation/actor.d.ts +1 -1
- package/dist/federation/actor.d.ts.map +1 -1
- package/dist/federation/actor.js +6 -13
- package/dist/federation/actor.js.map +1 -1
- package/dist/federation/article.d.ts +4 -14
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +19 -32
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/backfill.d.ts +4 -4
- package/dist/federation/backfill.d.ts.map +1 -1
- package/dist/federation/backfill.js +12 -13
- package/dist/federation/backfill.js.map +1 -1
- package/dist/federation/citations.d.ts.map +1 -1
- package/dist/federation/citations.js.map +1 -1
- package/dist/federation/cited-post.d.ts.map +1 -1
- package/dist/federation/cited-post.js +2 -4
- package/dist/federation/cited-post.js.map +1 -1
- package/dist/federation/delivery-plan.d.ts +85 -0
- package/dist/federation/delivery-plan.d.ts.map +1 -0
- package/dist/federation/delivery-plan.js +137 -0
- package/dist/federation/delivery-plan.js.map +1 -0
- package/dist/federation/delivery.d.ts +7 -32
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +64 -201
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts +5 -5
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +7 -6
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/followers.d.ts +1 -1
- package/dist/federation/followers.d.ts.map +1 -1
- package/dist/federation/inbox.d.ts +1 -1
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +5 -4
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +10 -8
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +7 -5
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/keys.d.ts +8 -27
- package/dist/federation/keys.d.ts.map +1 -1
- package/dist/federation/keys.js +4 -47
- package/dist/federation/keys.js.map +1 -1
- package/dist/federation/mount.d.ts +2 -2
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +9 -7
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/paths.d.ts +1 -9
- package/dist/federation/paths.d.ts.map +1 -1
- package/dist/federation/paths.js +2 -12
- package/dist/federation/paths.js.map +1 -1
- package/dist/federation/profiles.d.ts +1 -1
- package/dist/federation/profiles.d.ts.map +1 -1
- package/dist/federation/profiles.js +5 -8
- package/dist/federation/profiles.js.map +1 -1
- package/dist/federation/quotes.d.ts +2 -2
- package/dist/federation/quotes.d.ts.map +1 -1
- package/dist/federation/quotes.js +4 -4
- package/dist/federation/quotes.js.map +1 -1
- package/dist/federation/records.d.ts +2 -2
- package/dist/federation/records.d.ts.map +1 -1
- package/dist/federation/records.js +12 -19
- package/dist/federation/records.js.map +1 -1
- package/dist/federation/relays.d.ts +2 -3
- package/dist/federation/relays.d.ts.map +1 -1
- package/dist/federation/relays.js +22 -30
- package/dist/federation/relays.js.map +1 -1
- package/dist/federation/site-loaders.js +1 -1
- package/dist/federation/site-loaders.js.map +1 -1
- package/dist/federation/webfinger.d.ts +23 -0
- package/dist/federation/webfinger.d.ts.map +1 -0
- package/dist/federation/webfinger.js +70 -0
- package/dist/federation/webfinger.js.map +1 -0
- package/dist/files/atomic.d.ts.map +1 -1
- package/dist/files/atomic.js +4 -9
- package/dist/files/atomic.js.map +1 -1
- package/dist/files/static-files.d.ts +21 -0
- package/dist/files/static-files.d.ts.map +1 -0
- package/dist/files/static-files.js +88 -0
- package/dist/files/static-files.js.map +1 -0
- package/dist/forms/checker.d.ts +93 -0
- package/dist/forms/checker.d.ts.map +1 -0
- package/dist/forms/checker.js +2 -0
- package/dist/forms/checker.js.map +1 -0
- package/dist/forms/protection.d.ts +3 -1
- package/dist/forms/protection.d.ts.map +1 -1
- package/dist/forms/protection.js +3 -1
- package/dist/forms/protection.js.map +1 -1
- package/dist/images/icons.js +2 -2
- package/dist/images/icons.js.map +1 -1
- package/dist/images/index.d.ts +2 -1
- package/dist/images/index.d.ts.map +1 -1
- package/dist/images/index.js +2 -1
- package/dist/images/index.js.map +1 -1
- package/dist/images/markup.d.ts +0 -20
- package/dist/images/markup.d.ts.map +1 -1
- package/dist/images/markup.js +5 -64
- package/dist/images/markup.js.map +1 -1
- package/dist/images/paths.d.ts +0 -10
- package/dist/images/paths.d.ts.map +1 -1
- package/dist/images/paths.js +3 -11
- package/dist/images/paths.js.map +1 -1
- package/dist/images/variants.d.ts +2 -2
- package/dist/images/variants.d.ts.map +1 -1
- package/dist/images/variants.js +4 -3
- package/dist/images/variants.js.map +1 -1
- package/dist/index.d.ts +3 -291
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -838
- package/dist/index.js.map +1 -1
- package/dist/indexnow.d.ts.map +1 -1
- package/dist/indexnow.js +21 -26
- package/dist/indexnow.js.map +1 -1
- package/dist/indieauth/client.d.ts +1 -1
- package/dist/indieauth/client.d.ts.map +1 -1
- package/dist/indieauth/client.js +1 -1
- package/dist/indieauth/client.js.map +1 -1
- package/dist/indieauth/grants.d.ts +1 -1
- package/dist/indieauth/grants.d.ts.map +1 -1
- package/dist/indieauth/identity.d.ts +2 -2
- package/dist/indieauth/identity.d.ts.map +1 -1
- package/dist/indieauth/identity.js +5 -7
- package/dist/indieauth/identity.js.map +1 -1
- package/dist/indieauth/redeem.d.ts +1 -1
- package/dist/indieauth/redeem.d.ts.map +1 -1
- package/dist/indieauth/redeem.js.map +1 -1
- package/dist/indieauth/request.d.ts +5 -1
- package/dist/indieauth/request.d.ts.map +1 -1
- package/dist/indieauth/request.js +6 -2
- package/dist/indieauth/request.js.map +1 -1
- package/dist/indieauth/tokens.d.ts +1 -1
- package/dist/indieauth/tokens.d.ts.map +1 -1
- package/dist/indieauth/tokens.js +2 -2
- package/dist/indieauth/tokens.js.map +1 -1
- package/dist/mail/index.d.ts +1 -5
- package/dist/mail/index.d.ts.map +1 -1
- package/dist/mail/index.js +0 -2
- package/dist/mail/index.js.map +1 -1
- package/dist/mail/provider.d.ts +7 -0
- package/dist/mail/provider.d.ts.map +1 -1
- package/dist/maintenance.d.ts +1 -1
- package/dist/maintenance.d.ts.map +1 -1
- package/dist/media/library.d.ts +99 -0
- package/dist/media/library.d.ts.map +1 -0
- package/dist/media/library.js +157 -0
- package/dist/media/library.js.map +1 -0
- package/dist/media/uploads.d.ts +106 -0
- package/dist/media/uploads.d.ts.map +1 -0
- package/dist/media/uploads.js +192 -0
- package/dist/media/uploads.js.map +1 -0
- package/dist/micropub/content.js +1 -1
- package/dist/micropub/content.js.map +1 -1
- package/dist/micropub/create.d.ts +7 -15
- package/dist/micropub/create.d.ts.map +1 -1
- package/dist/micropub/create.js +48 -184
- package/dist/micropub/create.js.map +1 -1
- package/dist/micropub/endpoint.d.ts +2 -2
- package/dist/micropub/endpoint.d.ts.map +1 -1
- package/dist/micropub/endpoint.js +29 -40
- package/dist/micropub/endpoint.js.map +1 -1
- package/dist/micropub/media.d.ts +1 -1
- package/dist/micropub/media.d.ts.map +1 -1
- package/dist/micropub/media.js +6 -6
- package/dist/micropub/media.js.map +1 -1
- package/dist/micropub/update.d.ts +6 -14
- package/dist/micropub/update.d.ts.map +1 -1
- package/dist/micropub/update.js +37 -90
- package/dist/micropub/update.js.map +1 -1
- package/dist/notifications/comments.d.ts +4 -4
- package/dist/notifications/comments.d.ts.map +1 -1
- package/dist/notifications/comments.js +6 -14
- package/dist/notifications/comments.js.map +1 -1
- package/dist/notifications/digest.d.ts +4 -4
- package/dist/notifications/digest.d.ts.map +1 -1
- package/dist/notifications/digest.js +6 -16
- package/dist/notifications/digest.js.map +1 -1
- package/dist/notifications/index.d.ts +6 -3
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +3 -2
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/links.d.ts.map +1 -1
- package/dist/notifications/links.js +2 -2
- package/dist/notifications/links.js.map +1 -1
- package/dist/{mail/service.d.ts → notifications/mail-service.d.ts} +7 -13
- package/dist/notifications/mail-service.d.ts.map +1 -0
- package/dist/{mail/service.js → notifications/mail-service.js} +33 -54
- package/dist/notifications/mail-service.js.map +1 -0
- package/dist/{mail/templates.d.ts → notifications/mail-templates.d.ts} +4 -2
- package/dist/notifications/mail-templates.d.ts.map +1 -0
- package/dist/{mail/templates.js → notifications/mail-templates.js} +5 -3
- package/dist/notifications/mail-templates.js.map +1 -0
- package/dist/notifications/tokens.d.ts +2 -2
- package/dist/notifications/tokens.d.ts.map +1 -1
- package/dist/notifications/tokens.js +2 -2
- package/dist/notifications/tokens.js.map +1 -1
- package/dist/notify.d.ts.map +1 -1
- package/dist/notify.js +12 -24
- package/dist/notify.js.map +1 -1
- package/dist/plugin.d.ts +48 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +28 -2
- package/dist/plugin.js.map +1 -1
- package/dist/plugins/enabled.d.ts.map +1 -1
- package/dist/plugins/enabled.js +2 -4
- package/dist/plugins/enabled.js.map +1 -1
- package/dist/plugins/fetch.d.ts +1 -1
- package/dist/plugins/fetch.d.ts.map +1 -1
- package/dist/plugins/fetch.js +1 -1
- package/dist/plugins/fetch.js.map +1 -1
- package/dist/plugins/folder.d.ts.map +1 -1
- package/dist/plugins/folder.js +1 -3
- package/dist/plugins/folder.js.map +1 -1
- package/dist/plugins/install.d.ts.map +1 -1
- package/dist/plugins/install.js +7 -3
- package/dist/plugins/install.js.map +1 -1
- package/dist/plugins/manage.d.ts +1 -1
- package/dist/plugins/manage.d.ts.map +1 -1
- package/dist/plugins/registry.d.ts.map +1 -1
- package/dist/plugins/registry.js +7 -9
- package/dist/plugins/registry.js.map +1 -1
- package/dist/plugins/settings.d.ts.map +1 -1
- package/dist/plugins/settings.js +2 -3
- package/dist/plugins/settings.js.map +1 -1
- package/dist/plugins/site.d.ts +1 -1
- package/dist/plugins/site.d.ts.map +1 -1
- package/dist/plugins/site.js +10 -4
- package/dist/plugins/site.js.map +1 -1
- package/dist/plugins/upgrade.d.ts.map +1 -1
- package/dist/plugins/upgrade.js +4 -3
- package/dist/plugins/upgrade.js.map +1 -1
- package/dist/privacy/erase.d.ts +1 -1
- package/dist/privacy/erase.d.ts.map +1 -1
- package/dist/privacy/retention.d.ts +2 -2
- package/dist/privacy/retention.d.ts.map +1 -1
- package/dist/privacy/retention.js +9 -11
- package/dist/privacy/retention.js.map +1 -1
- package/dist/site/admin-paths.d.ts +23 -0
- package/dist/site/admin-paths.d.ts.map +1 -0
- package/dist/site/admin-paths.js +25 -0
- package/dist/site/admin-paths.js.map +1 -0
- package/dist/site/admin-theme.d.ts.map +1 -0
- package/dist/site/admin-theme.js.map +1 -0
- package/dist/{web → site}/authors.d.ts +1 -72
- package/dist/site/authors.d.ts.map +1 -0
- package/dist/site/authors.js +107 -0
- package/dist/site/authors.js.map +1 -0
- package/dist/site/feed-settings.d.ts +28 -0
- package/dist/site/feed-settings.d.ts.map +1 -0
- package/dist/site/feed-settings.js +22 -0
- package/dist/site/feed-settings.js.map +1 -0
- package/dist/{web/indexnow.d.ts → site/indexnow-key.d.ts} +1 -1
- package/dist/site/indexnow-key.d.ts.map +1 -0
- package/dist/{web/indexnow.js → site/indexnow-key.js} +1 -1
- package/dist/site/indexnow-key.js.map +1 -0
- package/dist/{web → site}/navigation.d.ts +7 -1
- package/dist/site/navigation.d.ts.map +1 -0
- package/dist/{web → site}/navigation.js +18 -0
- package/dist/site/navigation.js.map +1 -0
- package/dist/{notifications/preferences.d.ts → site/notification-preferences.d.ts} +2 -2
- package/dist/site/notification-preferences.d.ts.map +1 -0
- package/dist/{notifications/preferences.js → site/notification-preferences.js} +1 -1
- package/dist/site/notification-preferences.js.map +1 -0
- package/dist/site/passwords.d.ts.map +1 -0
- package/dist/site/passwords.js.map +1 -0
- package/dist/{privacy/policy.d.ts → site/retention-policy.d.ts} +1 -1
- package/dist/site/retention-policy.d.ts.map +1 -0
- package/dist/{privacy/policy.js → site/retention-policy.js} +1 -1
- package/dist/site/retention-policy.js.map +1 -0
- package/dist/site/robots.d.ts +62 -0
- package/dist/site/robots.d.ts.map +1 -0
- package/dist/site/robots.js +130 -0
- package/dist/site/robots.js.map +1 -0
- package/dist/site/setting-rows.d.ts +46 -0
- package/dist/site/setting-rows.d.ts.map +1 -0
- package/dist/site/setting-rows.js +480 -0
- package/dist/site/setting-rows.js.map +1 -0
- package/dist/site/setting-values.d.ts +63 -0
- package/dist/site/setting-values.d.ts.map +1 -0
- package/dist/site/setting-values.js +170 -0
- package/dist/site/setting-values.js.map +1 -0
- package/dist/site/settings-form.d.ts +30 -0
- package/dist/site/settings-form.d.ts.map +1 -0
- package/dist/site/settings-form.js +58 -0
- package/dist/site/settings-form.js.map +1 -0
- package/dist/site/settings.d.ts +345 -0
- package/dist/site/settings.d.ts.map +1 -0
- package/dist/site/settings.js +107 -0
- package/dist/site/settings.js.map +1 -0
- package/dist/site/site-json.d.ts +69 -0
- package/dist/site/site-json.d.ts.map +1 -0
- package/dist/site/site-json.js +113 -0
- package/dist/site/site-json.js.map +1 -0
- package/dist/{admin/accounts.d.ts → site/users.d.ts} +25 -41
- package/dist/site/users.d.ts.map +1 -0
- package/dist/{admin/accounts.js → site/users.js} +49 -155
- package/dist/site/users.js.map +1 -0
- package/dist/store/admin-store.d.ts +72 -0
- package/dist/store/admin-store.d.ts.map +1 -0
- package/dist/store/admin-store.js +62 -0
- package/dist/store/admin-store.js.map +1 -0
- package/dist/store/comments.d.ts +253 -0
- package/dist/store/comments.d.ts.map +1 -0
- package/dist/store/comments.js +234 -0
- package/dist/store/comments.js.map +1 -0
- package/dist/store/conversation.d.ts +28 -0
- package/dist/store/conversation.d.ts.map +1 -0
- package/dist/store/conversation.js +16 -0
- package/dist/store/conversation.js.map +1 -0
- package/dist/store/deliveries.d.ts +92 -0
- package/dist/store/deliveries.d.ts.map +1 -0
- package/dist/store/deliveries.js +88 -0
- package/dist/store/deliveries.js.map +1 -0
- package/dist/store/followers.d.ts +91 -0
- package/dist/store/followers.d.ts.map +1 -0
- package/dist/store/followers.js +79 -0
- package/dist/store/followers.js.map +1 -0
- package/dist/{federation/replies.d.ts → store/inbox-replies.d.ts} +2 -2
- package/dist/store/inbox-replies.d.ts.map +1 -0
- package/dist/{federation/replies.js → store/inbox-replies.js} +2 -4
- package/dist/store/inbox-replies.js.map +1 -0
- package/dist/store/inbox.d.ts +132 -0
- package/dist/store/inbox.d.ts.map +1 -0
- package/dist/store/inbox.js +157 -0
- package/dist/store/inbox.js.map +1 -0
- package/dist/store/profiles.d.ts +49 -0
- package/dist/store/profiles.d.ts.map +1 -0
- package/dist/store/profiles.js +71 -0
- package/dist/store/profiles.js.map +1 -0
- package/dist/store/relays.d.ts +66 -0
- package/dist/store/relays.d.ts.map +1 -0
- package/dist/store/relays.js +69 -0
- package/dist/store/relays.js.map +1 -0
- package/dist/store/rows.d.ts +33 -0
- package/dist/store/rows.d.ts.map +1 -0
- package/dist/store/rows.js +44 -0
- package/dist/store/rows.js.map +1 -0
- package/dist/store/schema.d.ts +14 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +588 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/store/sessions.d.ts +90 -0
- package/dist/store/sessions.d.ts.map +1 -0
- package/dist/store/sessions.js +107 -0
- package/dist/store/sessions.js.map +1 -0
- package/dist/store/state.d.ts +18 -0
- package/dist/store/state.d.ts.map +1 -0
- package/dist/store/state.js +19 -0
- package/dist/store/state.js.map +1 -0
- package/dist/store/tokens.d.ts +75 -0
- package/dist/store/tokens.d.ts.map +1 -0
- package/dist/store/tokens.js +82 -0
- package/dist/store/tokens.js.map +1 -0
- package/dist/store/webmentions.d.ts +66 -0
- package/dist/store/webmentions.d.ts.map +1 -0
- package/dist/store/webmentions.js +84 -0
- package/dist/store/webmentions.js.map +1 -0
- package/dist/supervisor/primary.d.ts +1 -1
- package/dist/supervisor/primary.d.ts.map +1 -1
- package/dist/supervisor/primary.js +31 -11
- package/dist/supervisor/primary.js.map +1 -1
- package/dist/supervisor/worker.d.ts +6 -2
- package/dist/supervisor/worker.d.ts.map +1 -1
- package/dist/supervisor/worker.js +4 -4
- package/dist/supervisor/worker.js.map +1 -1
- package/dist/testing.d.ts +8 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +6 -0
- package/dist/testing.js.map +1 -0
- package/dist/{web → theme}/assets.d.ts +1 -32
- package/dist/theme/assets.d.ts.map +1 -0
- package/dist/{web → theme}/assets.js +2 -100
- package/dist/theme/assets.js.map +1 -0
- package/dist/theme/site-data.d.ts +187 -0
- package/dist/theme/site-data.d.ts.map +1 -0
- package/dist/theme/site-data.js +160 -0
- package/dist/theme/site-data.js.map +1 -0
- package/dist/{web → theme}/templates.d.ts +2 -0
- package/dist/theme/templates.d.ts.map +1 -0
- package/dist/{web → theme}/templates.js +9 -32
- package/dist/theme/templates.js.map +1 -0
- package/dist/{web → theme}/themes.d.ts +1 -0
- package/dist/theme/themes.d.ts.map +1 -0
- package/dist/{web → theme}/themes.js +6 -3
- package/dist/theme/themes.js.map +1 -0
- package/dist/util/client-id.d.ts.map +1 -0
- package/dist/util/client-id.js.map +1 -0
- package/dist/util/clock.d.ts +9 -0
- package/dist/util/clock.d.ts.map +1 -0
- package/dist/util/clock.js +2 -0
- package/dist/util/clock.js.map +1 -0
- package/dist/util/errors.d.ts +3 -0
- package/dist/util/errors.d.ts.map +1 -0
- package/dist/util/errors.js +5 -0
- package/dist/util/errors.js.map +1 -0
- package/dist/util/files.d.ts +5 -0
- package/dist/util/files.d.ts.map +1 -0
- package/dist/util/files.js +38 -0
- package/dist/util/files.js.map +1 -0
- package/dist/util/forms.d.ts +5 -0
- package/dist/util/forms.d.ts.map +1 -0
- package/dist/util/forms.js +17 -0
- package/dist/util/forms.js.map +1 -0
- package/dist/util/guards.d.ts +4 -0
- package/dist/util/guards.d.ts.map +1 -0
- package/dist/util/guards.js +12 -0
- package/dist/util/guards.js.map +1 -0
- package/dist/{webmention/html.d.ts → util/html-tree.d.ts} +2 -2
- package/dist/util/html-tree.d.ts.map +1 -0
- package/dist/{webmention/html.js → util/html-tree.js} +3 -64
- package/dist/util/html-tree.js.map +1 -0
- package/dist/util/html.d.ts +4 -0
- package/dist/util/html.d.ts.map +1 -0
- package/dist/util/html.js +34 -0
- package/dist/util/html.js.map +1 -0
- package/dist/util/public-address.d.ts.map +1 -0
- package/dist/util/public-address.js.map +1 -0
- package/dist/util/queue.d.ts +7 -0
- package/dist/util/queue.d.ts.map +1 -0
- package/dist/util/queue.js +23 -0
- package/dist/util/queue.js.map +1 -0
- package/dist/util/retry.d.ts +11 -0
- package/dist/util/retry.d.ts.map +1 -0
- package/dist/util/retry.js +14 -0
- package/dist/util/retry.js.map +1 -0
- package/dist/util/url.d.ts +11 -0
- package/dist/util/url.d.ts.map +1 -0
- package/dist/util/url.js +20 -0
- package/dist/util/url.js.map +1 -0
- package/dist/web/absolute-urls.js +1 -1
- package/dist/web/absolute-urls.js.map +1 -1
- package/dist/web/archive.js +2 -2
- package/dist/web/archive.js.map +1 -1
- package/dist/web/asset-routes.d.ts +48 -0
- package/dist/web/asset-routes.d.ts.map +1 -0
- package/dist/web/asset-routes.js +107 -0
- package/dist/web/asset-routes.js.map +1 -0
- package/dist/{avatars/routes.d.ts → web/avatar-routes.d.ts} +2 -2
- package/dist/web/avatar-routes.d.ts.map +1 -0
- package/dist/{avatars/routes.js → web/avatar-routes.js} +3 -3
- package/dist/web/avatar-routes.js.map +1 -0
- package/dist/web/comment-routes.d.ts +18 -0
- package/dist/web/comment-routes.d.ts.map +1 -0
- package/dist/web/comment-routes.js +177 -0
- package/dist/web/comment-routes.js.map +1 -0
- package/dist/web/compression.d.ts.map +1 -1
- package/dist/web/compression.js +1 -2
- package/dist/web/compression.js.map +1 -1
- package/dist/{contact/routes.d.ts → web/contact-routes.d.ts} +2 -2
- package/dist/web/contact-routes.d.ts.map +1 -0
- package/dist/{contact/routes.js → web/contact-routes.js} +14 -17
- package/dist/web/contact-routes.js.map +1 -0
- package/dist/web/context.d.ts +1 -187
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +5 -171
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts +6 -333
- package/dist/web/conversation.d.ts.map +1 -1
- package/dist/web/conversation.js +280 -220
- package/dist/web/conversation.js.map +1 -1
- package/dist/web/document-page.d.ts +13 -0
- package/dist/web/document-page.d.ts.map +1 -0
- package/dist/web/document-page.js +136 -0
- package/dist/web/document-page.js.map +1 -0
- package/dist/web/document-site.d.ts +14 -0
- package/dist/web/document-site.d.ts.map +1 -0
- package/dist/web/document-site.js +28 -0
- package/dist/web/document-site.js.map +1 -0
- package/dist/web/embed.d.ts +13 -0
- package/dist/web/embed.d.ts.map +1 -0
- package/dist/web/embed.js +66 -0
- package/dist/web/embed.js.map +1 -0
- package/dist/{env.d.ts → web/env.d.ts} +27 -26
- package/dist/web/env.d.ts.map +1 -0
- package/dist/web/env.js.map +1 -0
- package/dist/web/federation-routes.d.ts +33 -0
- package/dist/web/federation-routes.d.ts.map +1 -0
- package/dist/web/federation-routes.js +280 -0
- package/dist/web/federation-routes.js.map +1 -0
- package/dist/web/feed-atom.d.ts.map +1 -1
- package/dist/web/feed-atom.js +4 -3
- package/dist/web/feed-atom.js.map +1 -1
- package/dist/web/feed-item.d.ts +4 -39
- package/dist/web/feed-item.d.ts.map +1 -1
- package/dist/web/feed-item.js +8 -72
- package/dist/web/feed-item.js.map +1 -1
- package/dist/web/feed-json.js +2 -2
- package/dist/web/feed-json.js.map +1 -1
- package/dist/web/feed-routes.d.ts +36 -0
- package/dist/web/feed-routes.d.ts.map +1 -0
- package/dist/web/feed-routes.js +124 -0
- package/dist/web/feed-routes.js.map +1 -0
- package/dist/web/feed-rss.d.ts.map +1 -1
- package/dist/web/feed-rss.js +9 -6
- package/dist/web/feed-rss.js.map +1 -1
- package/dist/web/feed-source.d.ts +13 -40
- package/dist/web/feed-source.d.ts.map +1 -1
- package/dist/web/feed-source.js +14 -43
- package/dist/web/feed-source.js.map +1 -1
- package/dist/web/feeds.d.ts +4 -2
- package/dist/web/feeds.d.ts.map +1 -1
- package/dist/web/feeds.js +8 -5
- package/dist/web/feeds.js.map +1 -1
- package/dist/web/health.d.ts +1 -1
- package/dist/web/health.d.ts.map +1 -1
- package/dist/web/index.d.ts +53 -29
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +37 -18
- package/dist/web/index.js.map +1 -1
- package/dist/{indieauth/activity-log.d.ts → web/indieauth-activity-log.d.ts} +3 -3
- package/dist/web/indieauth-activity-log.d.ts.map +1 -0
- package/dist/{indieauth/activity-log.js → web/indieauth-activity-log.js} +5 -6
- package/dist/web/indieauth-activity-log.js.map +1 -0
- package/dist/{indieauth/bearer.d.ts → web/indieauth-bearer.d.ts} +5 -5
- package/dist/web/indieauth-bearer.d.ts.map +1 -0
- package/dist/{indieauth/bearer.js → web/indieauth-bearer.js} +4 -4
- package/dist/web/indieauth-bearer.js.map +1 -0
- package/dist/{indieauth/discovery.d.ts → web/indieauth-discovery.d.ts} +2 -7
- package/dist/web/indieauth-discovery.d.ts.map +1 -0
- package/dist/{indieauth/discovery.js → web/indieauth-discovery.js} +6 -9
- package/dist/web/indieauth-discovery.js.map +1 -0
- package/dist/{indieauth/token.d.ts → web/indieauth-token.d.ts} +2 -2
- package/dist/web/indieauth-token.d.ts.map +1 -0
- package/dist/{indieauth/token.js → web/indieauth-token.js} +7 -7
- package/dist/web/indieauth-token.js.map +1 -0
- package/dist/web/listing-pages.d.ts +19 -0
- package/dist/web/listing-pages.d.ts.map +1 -0
- package/dist/web/listing-pages.js +148 -0
- package/dist/web/listing-pages.js.map +1 -0
- package/dist/web/listing-subject.d.ts +58 -0
- package/dist/web/listing-subject.d.ts.map +1 -0
- package/dist/web/listing-subject.js +89 -0
- package/dist/web/listing-subject.js.map +1 -0
- package/dist/web/llms.d.ts +16 -15
- package/dist/web/llms.d.ts.map +1 -1
- package/dist/web/llms.js +23 -35
- package/dist/web/llms.js.map +1 -1
- package/dist/web/maintenance.d.ts +1 -1
- package/dist/web/maintenance.d.ts.map +1 -1
- package/dist/web/maintenance.js +7 -13
- package/dist/web/maintenance.js.map +1 -1
- package/dist/web/manifest.d.ts +1 -1
- package/dist/web/manifest.d.ts.map +1 -1
- package/dist/web/manifest.js +2 -1
- package/dist/web/manifest.js.map +1 -1
- package/dist/web/markdown-page.d.ts +76 -0
- package/dist/web/markdown-page.d.ts.map +1 -0
- package/dist/web/markdown-page.js +79 -0
- package/dist/web/markdown-page.js.map +1 -0
- package/dist/web/markdown-representation.d.ts +15 -0
- package/dist/web/markdown-representation.d.ts.map +1 -0
- package/dist/web/markdown-representation.js +130 -0
- package/dist/web/markdown-representation.js.map +1 -0
- package/dist/web/negotiate.d.ts +5 -12
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +11 -18
- package/dist/web/negotiate.js.map +1 -1
- package/dist/{notifications/routes.d.ts → web/notification-routes.d.ts} +2 -2
- package/dist/web/notification-routes.d.ts.map +1 -0
- package/dist/{notifications/routes.js → web/notification-routes.js} +24 -29
- package/dist/web/notification-routes.js.map +1 -0
- package/dist/web/oembed.d.ts +2 -2
- package/dist/web/oembed.d.ts.map +1 -1
- package/dist/web/oembed.js +5 -4
- package/dist/web/oembed.js.map +1 -1
- package/dist/web/opensearch.d.ts.map +1 -1
- package/dist/web/opensearch.js +2 -1
- package/dist/web/opensearch.js.map +1 -1
- package/dist/web/page-sources.d.ts +15 -0
- package/dist/web/page-sources.d.ts.map +1 -0
- package/dist/web/page-sources.js +44 -0
- package/dist/web/page-sources.js.map +1 -0
- package/dist/web/pagination.d.ts +1 -0
- package/dist/web/pagination.d.ts.map +1 -1
- package/dist/web/pagination.js +4 -1
- package/dist/web/pagination.js.map +1 -1
- package/dist/web/paths.d.ts +52 -0
- package/dist/web/paths.d.ts.map +1 -0
- package/dist/web/paths.js +208 -0
- package/dist/web/paths.js.map +1 -0
- package/dist/web/pingback-routes.d.ts +5 -0
- package/dist/web/pingback-routes.d.ts.map +1 -0
- package/dist/web/pingback-routes.js +100 -0
- package/dist/web/pingback-routes.js.map +1 -0
- package/dist/{plugins/federation.d.ts → web/plugin-federation.d.ts} +3 -3
- package/dist/web/plugin-federation.d.ts.map +1 -0
- package/dist/{plugins/federation.js → web/plugin-federation.js} +5 -5
- package/dist/web/plugin-federation.js.map +1 -0
- package/dist/{plugins/mount.d.ts → web/plugin-routes.d.ts} +3 -3
- package/dist/web/plugin-routes.d.ts.map +1 -0
- package/dist/{plugins/mount.js → web/plugin-routes.js} +2 -2
- package/dist/web/plugin-routes.js.map +1 -0
- package/dist/web/redirects.d.ts +1 -84
- package/dist/web/redirects.d.ts.map +1 -1
- package/dist/web/redirects.js +0 -232
- package/dist/web/redirects.js.map +1 -1
- package/dist/web/render.d.ts +43 -7
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +96 -48
- package/dist/web/render.js.map +1 -1
- package/dist/web/request.d.ts +44 -0
- package/dist/web/request.d.ts.map +1 -0
- package/dist/web/request.js +82 -0
- package/dist/web/request.js.map +1 -0
- package/dist/web/robots.d.ts +1 -46
- package/dist/web/robots.d.ts.map +1 -1
- package/dist/web/robots.js +5 -131
- package/dist/web/robots.js.map +1 -1
- package/dist/web/routes.d.ts +5 -39
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +112 -1373
- package/dist/web/routes.js.map +1 -1
- package/dist/web/search.d.ts.map +1 -1
- package/dist/web/search.js +2 -9
- package/dist/web/search.js.map +1 -1
- package/dist/{admin → web}/session.d.ts +1 -5
- package/dist/web/session.d.ts.map +1 -0
- package/dist/{admin → web}/session.js +0 -4
- package/dist/web/session.js.map +1 -0
- package/dist/web/share-image.d.ts.map +1 -1
- package/dist/web/share-image.js +3 -2
- package/dist/web/share-image.js.map +1 -1
- package/dist/web/signed-in.d.ts +27 -0
- package/dist/web/signed-in.d.ts.map +1 -0
- package/dist/web/signed-in.js +45 -0
- package/dist/web/signed-in.js.map +1 -0
- package/dist/web/site-index.d.ts +13 -0
- package/dist/web/site-index.d.ts.map +1 -0
- package/dist/web/site-index.js +143 -0
- package/dist/web/site-index.js.map +1 -0
- package/dist/web/site-view.d.ts +45 -0
- package/dist/web/site-view.d.ts.map +1 -0
- package/dist/web/site-view.js +67 -0
- package/dist/web/site-view.js.map +1 -0
- package/dist/web/sitemap.d.ts.map +1 -1
- package/dist/web/sitemap.js +5 -7
- package/dist/web/sitemap.js.map +1 -1
- package/dist/{admin → web}/throttle.d.ts +3 -4
- package/dist/web/throttle.d.ts.map +1 -0
- package/dist/{admin → web}/throttle.js +1 -2
- package/dist/web/throttle.js.map +1 -0
- package/dist/web/webmention-routes.d.ts +11 -0
- package/dist/web/webmention-routes.d.ts.map +1 -0
- package/dist/web/webmention-routes.js +51 -0
- package/dist/web/webmention-routes.js.map +1 -0
- package/dist/web/well-known.d.ts +2 -2
- package/dist/web/well-known.d.ts.map +1 -1
- package/dist/web/well-known.js +5 -14
- package/dist/web/well-known.js.map +1 -1
- package/dist/webmention/cited-picture.d.ts +1 -2
- package/dist/webmention/cited-picture.d.ts.map +1 -1
- package/dist/webmention/cited-picture.js +4 -6
- package/dist/webmention/cited-picture.js.map +1 -1
- package/dist/webmention/discovery.d.ts +2 -13
- package/dist/webmention/discovery.d.ts.map +1 -1
- package/dist/webmention/discovery.js +18 -73
- package/dist/webmention/discovery.js.map +1 -1
- package/dist/webmention/endpoint.d.ts +27 -0
- package/dist/webmention/endpoint.d.ts.map +1 -0
- package/dist/webmention/endpoint.js +26 -0
- package/dist/webmention/endpoint.js.map +1 -0
- package/dist/webmention/fetch-public.d.ts +18 -1
- package/dist/webmention/fetch-public.d.ts.map +1 -1
- package/dist/webmention/fetch-public.js +57 -23
- package/dist/webmention/fetch-public.js.map +1 -1
- package/dist/webmention/index.d.ts +11 -9
- package/dist/webmention/index.d.ts.map +1 -1
- package/dist/webmention/index.js +7 -6
- package/dist/webmention/index.js.map +1 -1
- package/dist/webmention/links.d.ts +0 -55
- package/dist/webmention/links.d.ts.map +1 -1
- package/dist/webmention/links.js +2 -185
- package/dist/webmention/links.js.map +1 -1
- package/dist/webmention/microformats.d.ts +1 -1
- package/dist/webmention/microformats.d.ts.map +1 -1
- package/dist/webmention/microformats.js +1 -1
- package/dist/webmention/microformats.js.map +1 -1
- package/dist/webmention/pingback.d.ts +12 -4
- package/dist/webmention/pingback.d.ts.map +1 -1
- package/dist/webmention/pingback.js +4 -102
- package/dist/webmention/pingback.js.map +1 -1
- package/dist/webmention/receive.d.ts +7 -4
- package/dist/webmention/receive.d.ts.map +1 -1
- package/dist/webmention/receive.js +34 -42
- package/dist/webmention/receive.js.map +1 -1
- package/dist/webmention/reply-context/fediverse.d.ts +29 -0
- package/dist/webmention/reply-context/fediverse.d.ts.map +1 -0
- package/dist/webmention/reply-context/fediverse.js +59 -0
- package/dist/webmention/reply-context/fediverse.js.map +1 -0
- package/dist/webmention/reply-context/json-ld.d.ts +5 -0
- package/dist/webmention/reply-context/json-ld.d.ts.map +1 -0
- package/dist/webmention/reply-context/json-ld.js +78 -0
- package/dist/webmention/reply-context/json-ld.js.map +1 -0
- package/dist/webmention/reply-context/oembed.d.ts +21 -0
- package/dist/webmention/reply-context/oembed.d.ts.map +1 -0
- package/dist/webmention/reply-context/oembed.js +137 -0
- package/dist/webmention/reply-context/oembed.js.map +1 -0
- package/dist/webmention/reply-context/page.d.ts +30 -0
- package/dist/webmention/reply-context/page.d.ts.map +1 -0
- package/dist/webmention/reply-context/page.js +134 -0
- package/dist/webmention/reply-context/page.js.map +1 -0
- package/dist/webmention/reply-context/source.d.ts +29 -0
- package/dist/webmention/reply-context/source.d.ts.map +1 -0
- package/dist/webmention/reply-context/source.js +46 -0
- package/dist/webmention/reply-context/source.js.map +1 -0
- package/dist/webmention/reply-context.d.ts +5 -34
- package/dist/webmention/reply-context.d.ts.map +1 -1
- package/dist/webmention/reply-context.js +9 -432
- package/dist/webmention/reply-context.js.map +1 -1
- package/dist/webmention/reply-contexts.d.ts +3 -3
- package/dist/webmention/reply-contexts.d.ts.map +1 -1
- package/dist/webmention/reply-contexts.js +7 -10
- package/dist/webmention/reply-contexts.js.map +1 -1
- package/dist/webmention/routes.d.ts +1 -1
- package/dist/webmention/routes.d.ts.map +1 -1
- package/dist/webmention/routes.js +5 -8
- package/dist/webmention/routes.js.map +1 -1
- package/dist/webmention/service.d.ts +7 -7
- package/dist/webmention/service.d.ts.map +1 -1
- package/dist/webmention/service.js +49 -61
- package/dist/webmention/service.js.map +1 -1
- package/dist/webmention/syndication.d.ts +3 -26
- package/dist/webmention/syndication.d.ts.map +1 -1
- package/dist/webmention/syndication.js +6 -20
- package/dist/webmention/syndication.js.map +1 -1
- package/package.json +5 -1
- package/themes/default/README.md +36 -2329
- package/themes/default/layouts/base.njk +5 -4
- package/themes/default/layouts/comment.njk +3 -3
- package/themes/default/layouts/front-page.njk +4 -3
- package/themes/default/layouts/page.njk +2 -0
- package/themes/default/partials/comment-form.njk +1 -1
- package/themes/default/partials/comment.njk +5 -5
- package/themes/default/partials/contact-form.njk +1 -2
- package/themes/default/partials/conversation.njk +1 -2
- package/themes/default/partials/markdown-footer.md.njk +24 -0
- package/themes/default/partials/markdown-header.md.njk +31 -0
- package/themes/default/src/style.css +6 -6
- package/dist/admin/accounts.d.ts.map +0 -1
- package/dist/admin/accounts.js.map +0 -1
- package/dist/admin/admin-theme.d.ts.map +0 -1
- package/dist/admin/admin-theme.js.map +0 -1
- package/dist/admin/enclosure-field.d.ts.map +0 -1
- package/dist/admin/enclosure-field.js.map +0 -1
- package/dist/admin/event-field.d.ts.map +0 -1
- package/dist/admin/event-field.js.map +0 -1
- package/dist/admin/location-field.d.ts +0 -27
- package/dist/admin/location-field.d.ts.map +0 -1
- package/dist/admin/location-field.js.map +0 -1
- package/dist/admin/passwords.d.ts.map +0 -1
- package/dist/admin/passwords.js.map +0 -1
- package/dist/admin/photo-field.d.ts +0 -38
- package/dist/admin/photo-field.d.ts.map +0 -1
- package/dist/admin/photo-field.js.map +0 -1
- package/dist/admin/read-field.d.ts.map +0 -1
- package/dist/admin/read-field.js +0 -61
- package/dist/admin/read-field.js.map +0 -1
- package/dist/admin/session.d.ts.map +0 -1
- package/dist/admin/session.js.map +0 -1
- package/dist/admin/store.d.ts +0 -998
- package/dist/admin/store.d.ts.map +0 -1
- package/dist/admin/store.js +0 -1588
- package/dist/admin/store.js.map +0 -1
- package/dist/admin/throttle.d.ts.map +0 -1
- package/dist/admin/throttle.js.map +0 -1
- package/dist/avatars/routes.d.ts.map +0 -1
- package/dist/avatars/routes.js.map +0 -1
- package/dist/contact/routes.d.ts.map +0 -1
- package/dist/contact/routes.js.map +0 -1
- package/dist/env.d.ts.map +0 -1
- package/dist/env.js.map +0 -1
- package/dist/federation/replies.d.ts.map +0 -1
- package/dist/federation/replies.js.map +0 -1
- package/dist/images/alt-text.d.ts.map +0 -1
- package/dist/images/alt-text.js.map +0 -1
- package/dist/indieauth/activity-log.d.ts.map +0 -1
- package/dist/indieauth/activity-log.js.map +0 -1
- package/dist/indieauth/app-activity.d.ts.map +0 -1
- package/dist/indieauth/app-activity.js.map +0 -1
- package/dist/indieauth/bearer.d.ts.map +0 -1
- package/dist/indieauth/bearer.js.map +0 -1
- package/dist/indieauth/client-id.d.ts.map +0 -1
- package/dist/indieauth/client-id.js.map +0 -1
- package/dist/indieauth/connected-apps.d.ts.map +0 -1
- package/dist/indieauth/connected-apps.js.map +0 -1
- package/dist/indieauth/consent.d.ts.map +0 -1
- package/dist/indieauth/consent.js.map +0 -1
- package/dist/indieauth/discovery.d.ts.map +0 -1
- package/dist/indieauth/discovery.js.map +0 -1
- package/dist/indieauth/token.d.ts.map +0 -1
- package/dist/indieauth/token.js.map +0 -1
- package/dist/mail/service.d.ts.map +0 -1
- package/dist/mail/service.js.map +0 -1
- package/dist/mail/templates.d.ts.map +0 -1
- package/dist/mail/templates.js.map +0 -1
- package/dist/notifications/preferences.d.ts.map +0 -1
- package/dist/notifications/preferences.js.map +0 -1
- package/dist/notifications/routes.d.ts.map +0 -1
- package/dist/notifications/routes.js.map +0 -1
- package/dist/plugins/federation.d.ts.map +0 -1
- package/dist/plugins/federation.js.map +0 -1
- package/dist/plugins/mount.d.ts.map +0 -1
- package/dist/plugins/mount.js.map +0 -1
- package/dist/privacy/policy.d.ts.map +0 -1
- package/dist/privacy/policy.js.map +0 -1
- package/dist/web/admin-bar.d.ts.map +0 -1
- package/dist/web/admin-bar.js.map +0 -1
- package/dist/web/assets.d.ts.map +0 -1
- package/dist/web/assets.js.map +0 -1
- package/dist/web/authors.d.ts.map +0 -1
- package/dist/web/authors.js +0 -211
- package/dist/web/authors.js.map +0 -1
- package/dist/web/documents.d.ts +0 -81
- package/dist/web/documents.d.ts.map +0 -1
- package/dist/web/documents.js.map +0 -1
- package/dist/web/errors.d.ts.map +0 -1
- package/dist/web/errors.js.map +0 -1
- package/dist/web/guids.d.ts.map +0 -1
- package/dist/web/guids.js.map +0 -1
- package/dist/web/indexnow.d.ts.map +0 -1
- package/dist/web/indexnow.js.map +0 -1
- package/dist/web/license.d.ts.map +0 -1
- package/dist/web/license.js.map +0 -1
- package/dist/web/locale.d.ts.map +0 -1
- package/dist/web/locale.js.map +0 -1
- package/dist/web/navigation.d.ts.map +0 -1
- package/dist/web/navigation.js.map +0 -1
- package/dist/web/recent.d.ts +0 -43
- package/dist/web/recent.d.ts.map +0 -1
- package/dist/web/recent.js +0 -37
- package/dist/web/recent.js.map +0 -1
- package/dist/web/sanitize.d.ts +0 -29
- package/dist/web/sanitize.d.ts.map +0 -1
- package/dist/web/sanitize.js.map +0 -1
- package/dist/web/taxonomy.d.ts.map +0 -1
- package/dist/web/taxonomy.js.map +0 -1
- package/dist/web/templates.d.ts.map +0 -1
- package/dist/web/templates.js.map +0 -1
- package/dist/web/themes.d.ts.map +0 -1
- package/dist/web/themes.js.map +0 -1
- package/dist/webmention/html.d.ts.map +0 -1
- package/dist/webmention/html.js.map +0 -1
- package/dist/webmention/public-address.d.ts.map +0 -1
- package/dist/webmention/public-address.js.map +0 -1
- /package/dist/{web → content}/license.d.ts +0 -0
- /package/dist/{web → content}/license.js +0 -0
- /package/dist/{admin → site}/admin-theme.d.ts +0 -0
- /package/dist/{admin → site}/admin-theme.js +0 -0
- /package/dist/{admin → site}/passwords.d.ts +0 -0
- /package/dist/{admin → site}/passwords.js +0 -0
- /package/dist/{indieauth → util}/client-id.d.ts +0 -0
- /package/dist/{indieauth → util}/client-id.js +0 -0
- /package/dist/{webmention → util}/public-address.d.ts +0 -0
- /package/dist/{webmention → util}/public-address.js +0 -0
- /package/dist/{env.js → web/env.js} +0 -0
package/dist/admin/store.js
DELETED
|
@@ -1,1588 +0,0 @@
|
|
|
1
|
-
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
-
import { DatabaseSync } from 'node:sqlite';
|
|
3
|
-
import { databaseFile, openDatabase } from '../cache.js';
|
|
4
|
-
import { rsvpValue } from '../content/rsvp.js';
|
|
5
|
-
import { REPLY_ACTIVITY_TYPE, replyIdOf, replyTargetOf } from '../federation/replies.js';
|
|
6
|
-
import { repliesKey } from '../web/feed-source.js';
|
|
7
|
-
import { replyGuid } from '../web/guids.js';
|
|
8
|
-
/**
|
|
9
|
-
* Which rows of the inbox log are replies: a `Create` that named something it
|
|
10
|
-
* answers. Spelled once, because a count and a listing that disagreed about it
|
|
11
|
-
* would show a post a number no page of comments could produce.
|
|
12
|
-
*/
|
|
13
|
-
const IS_REPLY = `activity_type = '${REPLY_ACTIVITY_TYPE}' AND in_reply_to IS NOT NULL`;
|
|
14
|
-
/** How long a session id is, in bytes. 32 is the 256 bits doc-5 asks for. */
|
|
15
|
-
export const SESSION_ID_BYTES = 32;
|
|
16
|
-
/** How one delivery of one activity to one follower ended. */
|
|
17
|
-
export const DELIVERY_STATUSES = ['sent', 'queued', 'failed'];
|
|
18
|
-
/** Where a relay subscription stands (FEP-ae0c). */
|
|
19
|
-
export const RELAY_STATES = ['pending', 'accepted', 'rejected'];
|
|
20
|
-
/** How one webmention this site sent to one page ended. */
|
|
21
|
-
export const WEBMENTION_SEND_STATUSES = ['sent', 'none', 'failed'];
|
|
22
|
-
/** Where a comment came from. */
|
|
23
|
-
export const COMMENT_SOURCES = ['comment', 'webmention', 'activitypub'];
|
|
24
|
-
/** What a comment is: something written, or a wordless pointer at the post. */
|
|
25
|
-
export const COMMENT_KINDS = ['reply', 'like', 'boost', 'mention', 'repost'];
|
|
26
|
-
/** Where a comment stands with the moderator. */
|
|
27
|
-
export const COMMENT_STATUSES = ['pending', 'approved', 'spam'];
|
|
28
|
-
/** What a comment can have had removed from it for privacy (TASK-135). */
|
|
29
|
-
export const REDACTED_FIELDS = ['email', 'addressHash', 'author'];
|
|
30
|
-
/** A comment's {@link CommentRecord.rsvp} as a record carries it: present only when there is one. */
|
|
31
|
-
export function rsvpField(rsvp) {
|
|
32
|
-
return rsvp === undefined ? {} : { rsvp };
|
|
33
|
-
}
|
|
34
|
-
/** A comment's {@link CommentRecord.via} as a record carries it: present only when there is one. */
|
|
35
|
-
export function viaField(via) {
|
|
36
|
-
return via === undefined || via === null || via === '' ? {} : { via };
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Open (and if needed create) the admin tables in `dataDir`, applying every
|
|
40
|
-
* migration the package ships. Applying them is idempotent.
|
|
41
|
-
*
|
|
42
|
-
* The connection is its own; SQLite in WAL mode is happy with the content
|
|
43
|
-
* index holding a second one on the same file.
|
|
44
|
-
*/
|
|
45
|
-
export function openAdminStore(options) {
|
|
46
|
-
const file = databaseFile(options.dataDir);
|
|
47
|
-
const db = openDatabase({ dataDir: options.dataDir, ledger: LEDGER, migrations: MIGRATIONS });
|
|
48
|
-
const statements = {
|
|
49
|
-
deleteSessionsForUser: db.prepare('DELETE FROM sessions WHERE user_id = ? AND id IS NOT ?'),
|
|
50
|
-
insertSession: db.prepare(`
|
|
51
|
-
INSERT INTO sessions (id, user_id, csrf_token, created_at, expires_at)
|
|
52
|
-
VALUES (?, ?, ?, ?, ?)
|
|
53
|
-
`),
|
|
54
|
-
sessionById: db.prepare('SELECT * FROM sessions WHERE id = ?'),
|
|
55
|
-
deleteSession: db.prepare('DELETE FROM sessions WHERE id = ?'),
|
|
56
|
-
pruneSessions: db.prepare('DELETE FROM sessions WHERE expires_at <= ?'),
|
|
57
|
-
readFlash: db.prepare('SELECT flash FROM sessions WHERE id = ?'),
|
|
58
|
-
writeFlash: db.prepare('UPDATE sessions SET flash = ? WHERE id = ?'),
|
|
59
|
-
insertPasswordReset: db.prepare(`
|
|
60
|
-
INSERT INTO password_resets (token_hash, user_id, created_at, expires_at)
|
|
61
|
-
VALUES (?, ?, ?, ?)
|
|
62
|
-
`),
|
|
63
|
-
passwordResetByHash: db.prepare('SELECT * FROM password_resets WHERE token_hash = ?'),
|
|
64
|
-
deletePasswordReset: db.prepare('DELETE FROM password_resets WHERE token_hash = ?'),
|
|
65
|
-
deletePasswordResetsForUser: db.prepare('DELETE FROM password_resets WHERE user_id = ?'),
|
|
66
|
-
prunePasswordResets: db.prepare('DELETE FROM password_resets WHERE expires_at <= ?'),
|
|
67
|
-
spendToken: db.prepare(`
|
|
68
|
-
INSERT OR IGNORE INTO spent_tokens (token_hash, spent_at, expires_at) VALUES (?, ?, ?)
|
|
69
|
-
`),
|
|
70
|
-
pruneSpentTokens: db.prepare('DELETE FROM spent_tokens WHERE expires_at <= ?'),
|
|
71
|
-
getState: db.prepare('SELECT value FROM cms_state WHERE key = ?'),
|
|
72
|
-
putState: db.prepare(`
|
|
73
|
-
INSERT INTO cms_state (key, value, updated_at) VALUES (?, ?, ?)
|
|
74
|
-
ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at
|
|
75
|
-
`),
|
|
76
|
-
// `?1 IS NULL` is how one statement answers both questions: naming a user
|
|
77
|
-
// counts theirs, naming nobody counts the site's.
|
|
78
|
-
countFollowers: db.prepare('SELECT COUNT(*) AS count FROM followers WHERE ?1 IS NULL OR username = ?1'),
|
|
79
|
-
listFollowers: db.prepare(`
|
|
80
|
-
SELECT * FROM followers
|
|
81
|
-
WHERE ?1 IS NULL OR username = ?1
|
|
82
|
-
ORDER BY followed_at DESC, actor_id DESC
|
|
83
|
-
LIMIT ?2 OFFSET ?3
|
|
84
|
-
`),
|
|
85
|
-
followerById: db.prepare('SELECT * FROM followers WHERE username = ? AND actor_id = ?'),
|
|
86
|
-
isAvatarSource: db.prepare(`
|
|
87
|
-
SELECT 1 FROM followers
|
|
88
|
-
WHERE icon_url = ?1 AND actor_id IN (SELECT actor_id FROM ap_inbox)
|
|
89
|
-
UNION ALL
|
|
90
|
-
SELECT 1 FROM actor_profiles
|
|
91
|
-
WHERE icon_url = ?1 AND actor_id IN (SELECT actor_id FROM ap_inbox)
|
|
92
|
-
UNION ALL
|
|
93
|
-
SELECT 1 FROM comments WHERE author_avatar = ?1 AND status = 'approved'
|
|
94
|
-
LIMIT 1
|
|
95
|
-
`),
|
|
96
|
-
listAvatarSources: db.prepare(`
|
|
97
|
-
SELECT icon_url AS url FROM followers
|
|
98
|
-
WHERE icon_url IS NOT NULL AND actor_id IN (SELECT actor_id FROM ap_inbox)
|
|
99
|
-
UNION
|
|
100
|
-
SELECT icon_url AS url FROM actor_profiles
|
|
101
|
-
WHERE icon_url IS NOT NULL AND actor_id IN (SELECT actor_id FROM ap_inbox)
|
|
102
|
-
UNION
|
|
103
|
-
SELECT author_avatar AS url FROM comments
|
|
104
|
-
WHERE author_avatar IS NOT NULL AND status = 'approved'
|
|
105
|
-
`),
|
|
106
|
-
actorProfileById: db.prepare('SELECT * FROM actor_profiles WHERE actor_id = ?'),
|
|
107
|
-
putActorProfile: db.prepare(`
|
|
108
|
-
INSERT INTO actor_profiles (actor_id, handle, name, icon_url, url, fetched_at)
|
|
109
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
110
|
-
ON CONFLICT (actor_id) DO UPDATE SET
|
|
111
|
-
handle = excluded.handle,
|
|
112
|
-
name = excluded.name,
|
|
113
|
-
icon_url = excluded.icon_url,
|
|
114
|
-
url = excluded.url,
|
|
115
|
-
fetched_at = excluded.fetched_at
|
|
116
|
-
`),
|
|
117
|
-
listActorsToProfile: db.prepare(`
|
|
118
|
-
SELECT DISTINCT actor_id FROM ap_inbox
|
|
119
|
-
WHERE actor_id NOT IN (SELECT actor_id FROM followers)
|
|
120
|
-
AND actor_id NOT IN (SELECT actor_id FROM actor_profiles WHERE fetched_at >= ?)
|
|
121
|
-
ORDER BY actor_id
|
|
122
|
-
`),
|
|
123
|
-
putFollower: db.prepare(`
|
|
124
|
-
INSERT INTO followers (
|
|
125
|
-
username, actor_id, inbox_id, shared_inbox_id, handle, name, icon_url, url, followed_at
|
|
126
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
127
|
-
ON CONFLICT (username, actor_id) DO UPDATE SET
|
|
128
|
-
inbox_id = excluded.inbox_id,
|
|
129
|
-
shared_inbox_id = excluded.shared_inbox_id,
|
|
130
|
-
handle = excluded.handle,
|
|
131
|
-
name = excluded.name,
|
|
132
|
-
icon_url = excluded.icon_url,
|
|
133
|
-
url = excluded.url
|
|
134
|
-
`),
|
|
135
|
-
deleteFollower: db.prepare('DELETE FROM followers WHERE username = ? AND actor_id = ?'),
|
|
136
|
-
clearFollowers: db.prepare('DELETE FROM followers'),
|
|
137
|
-
clearInboxActivities: db.prepare('DELETE FROM ap_inbox'),
|
|
138
|
-
resetInboxSequence: db.prepare("DELETE FROM sqlite_sequence WHERE name = 'ap_inbox'"),
|
|
139
|
-
countInboxActivities: db.prepare('SELECT COUNT(*) AS count FROM ap_inbox'),
|
|
140
|
-
deleteInboxActivity: db.prepare('DELETE FROM ap_inbox WHERE id = ? RETURNING *'),
|
|
141
|
-
listInboxActivities: db.prepare(`
|
|
142
|
-
SELECT * FROM ap_inbox
|
|
143
|
-
ORDER BY received_at DESC, id DESC
|
|
144
|
-
LIMIT ? OFFSET ?
|
|
145
|
-
`),
|
|
146
|
-
logInboxActivity: db.prepare(`
|
|
147
|
-
INSERT INTO ap_inbox (
|
|
148
|
-
activity_id, activity_type, actor_id, object_id, in_reply_to, reply_key, recipient,
|
|
149
|
-
received_at, fetched, json
|
|
150
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
151
|
-
ON CONFLICT (activity_id) DO UPDATE SET
|
|
152
|
-
activity_type = excluded.activity_type,
|
|
153
|
-
actor_id = excluded.actor_id,
|
|
154
|
-
object_id = excluded.object_id,
|
|
155
|
-
in_reply_to = excluded.in_reply_to,
|
|
156
|
-
reply_key = excluded.reply_key,
|
|
157
|
-
recipient = excluded.recipient,
|
|
158
|
-
received_at = excluded.received_at,
|
|
159
|
-
fetched = excluded.fetched,
|
|
160
|
-
json = excluded.json
|
|
161
|
-
RETURNING *
|
|
162
|
-
`),
|
|
163
|
-
countReplies: db.prepare(`SELECT COUNT(*) AS count FROM ap_inbox WHERE ${IS_REPLY}`),
|
|
164
|
-
listReplies: db.prepare(`
|
|
165
|
-
SELECT * FROM ap_inbox WHERE ${IS_REPLY}
|
|
166
|
-
ORDER BY received_at DESC, id DESC
|
|
167
|
-
LIMIT ? OFFSET ?
|
|
168
|
-
`),
|
|
169
|
-
countRepliesTo: db.prepare(`
|
|
170
|
-
SELECT COUNT(*) AS count FROM ap_inbox WHERE ${IS_REPLY} AND in_reply_to = ?
|
|
171
|
-
`),
|
|
172
|
-
listRepliesTo: db.prepare(`
|
|
173
|
-
SELECT * FROM ap_inbox WHERE ${IS_REPLY} AND in_reply_to = ?
|
|
174
|
-
ORDER BY received_at DESC, id DESC
|
|
175
|
-
LIMIT ? OFFSET ?
|
|
176
|
-
`),
|
|
177
|
-
listCommentsFor: db.prepare(`
|
|
178
|
-
SELECT * FROM comments WHERE slug = ? ORDER BY submitted_at, id
|
|
179
|
-
`),
|
|
180
|
-
commentById: db.prepare('SELECT * FROM comments WHERE id = ?'),
|
|
181
|
-
commentsAt: db.prepare('SELECT * FROM comments WHERE url = ? ORDER BY submitted_at'),
|
|
182
|
-
commentsByRepliesKey: db.prepare('SELECT * FROM comments WHERE replies_key = ? ORDER BY submitted_at, id'),
|
|
183
|
-
staleCommentKeys: db.prepare('SELECT id, source FROM comments WHERE keys_base IS NOT ?'),
|
|
184
|
-
writeCommentKey: db.prepare('UPDATE comments SET replies_key = ?, keys_base = ? WHERE id = ?'),
|
|
185
|
-
repliesByKey: db.prepare(`
|
|
186
|
-
SELECT * FROM ap_inbox WHERE ${IS_REPLY} AND reply_key = ? ORDER BY received_at, id
|
|
187
|
-
`),
|
|
188
|
-
countCommentsByStatus: db.prepare('SELECT status, COUNT(*) AS count FROM comments GROUP BY status'),
|
|
189
|
-
hasApprovedAuthor: db.prepare(`
|
|
190
|
-
SELECT 1 FROM comments
|
|
191
|
-
WHERE status = 'approved' AND author_name = ? AND author_email IS ?
|
|
192
|
-
AND NOT EXISTS (SELECT 1 FROM json_each(comments.redacted) WHERE value = 'email')
|
|
193
|
-
LIMIT 1
|
|
194
|
-
`),
|
|
195
|
-
putComment: db.prepare(`
|
|
196
|
-
INSERT INTO comments (
|
|
197
|
-
id, slug, permalink, source, kind, status,
|
|
198
|
-
author_name, author_url, author_email,
|
|
199
|
-
markdown, html, submitted_at, address_hash, in_reply_to, url, author_avatar, notify,
|
|
200
|
-
redacted, rsvp, via, replies_key, keys_base
|
|
201
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
202
|
-
ON CONFLICT (id) DO UPDATE SET
|
|
203
|
-
slug = excluded.slug,
|
|
204
|
-
permalink = excluded.permalink,
|
|
205
|
-
source = excluded.source,
|
|
206
|
-
kind = excluded.kind,
|
|
207
|
-
status = excluded.status,
|
|
208
|
-
author_name = excluded.author_name,
|
|
209
|
-
author_url = excluded.author_url,
|
|
210
|
-
author_email = excluded.author_email,
|
|
211
|
-
markdown = excluded.markdown,
|
|
212
|
-
html = excluded.html,
|
|
213
|
-
submitted_at = excluded.submitted_at,
|
|
214
|
-
address_hash = excluded.address_hash,
|
|
215
|
-
in_reply_to = excluded.in_reply_to,
|
|
216
|
-
url = excluded.url,
|
|
217
|
-
author_avatar = excluded.author_avatar,
|
|
218
|
-
notify = excluded.notify,
|
|
219
|
-
redacted = excluded.redacted,
|
|
220
|
-
rsvp = excluded.rsvp,
|
|
221
|
-
via = excluded.via,
|
|
222
|
-
replies_key = excluded.replies_key,
|
|
223
|
-
keys_base = excluded.keys_base
|
|
224
|
-
`),
|
|
225
|
-
deleteComment: db.prepare('DELETE FROM comments WHERE id = ?'),
|
|
226
|
-
clearComments: db.prepare('DELETE FROM comments'),
|
|
227
|
-
recordDelivery: db.prepare(`
|
|
228
|
-
INSERT INTO ap_deliveries (
|
|
229
|
-
activity_id, activity_type, object_id, slug,
|
|
230
|
-
actor_id, inbox_id, status, error, attempted_at
|
|
231
|
-
)
|
|
232
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
233
|
-
ON CONFLICT (activity_id, actor_id) DO UPDATE SET
|
|
234
|
-
activity_type = excluded.activity_type,
|
|
235
|
-
object_id = excluded.object_id,
|
|
236
|
-
slug = excluded.slug,
|
|
237
|
-
inbox_id = excluded.inbox_id,
|
|
238
|
-
status = excluded.status,
|
|
239
|
-
error = excluded.error,
|
|
240
|
-
attempted_at = excluded.attempted_at
|
|
241
|
-
RETURNING *
|
|
242
|
-
`),
|
|
243
|
-
listDeliveries: db.prepare(`
|
|
244
|
-
SELECT * FROM ap_deliveries WHERE activity_id = ? ORDER BY actor_id
|
|
245
|
-
`),
|
|
246
|
-
countDeliveriesByStatus: db.prepare(`
|
|
247
|
-
SELECT status, COUNT(*) AS count FROM ap_deliveries WHERE activity_id = ? GROUP BY status
|
|
248
|
-
`),
|
|
249
|
-
lastDeliveryToInbox: db.prepare(`
|
|
250
|
-
SELECT * FROM ap_deliveries WHERE inbox_id = ?
|
|
251
|
-
ORDER BY attempted_at DESC, rowid DESC
|
|
252
|
-
LIMIT 1
|
|
253
|
-
`),
|
|
254
|
-
lastDeliveryToObject: db.prepare(`
|
|
255
|
-
SELECT * FROM ap_deliveries WHERE object_id = ?
|
|
256
|
-
ORDER BY attempted_at DESC, rowid DESC
|
|
257
|
-
LIMIT 1
|
|
258
|
-
`),
|
|
259
|
-
recordSentWebmention: db.prepare(`
|
|
260
|
-
INSERT INTO webmentions_sent (
|
|
261
|
-
slug, source, target, endpoint, status, error, attempted_at
|
|
262
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
263
|
-
ON CONFLICT (slug, target) DO UPDATE SET
|
|
264
|
-
source = excluded.source,
|
|
265
|
-
endpoint = excluded.endpoint,
|
|
266
|
-
status = excluded.status,
|
|
267
|
-
error = excluded.error,
|
|
268
|
-
attempted_at = excluded.attempted_at
|
|
269
|
-
RETURNING *
|
|
270
|
-
`),
|
|
271
|
-
listSentWebmentions: db.prepare('SELECT * FROM webmentions_sent WHERE slug = ? ORDER BY target'),
|
|
272
|
-
listSentWebmentionSources: db.prepare('SELECT DISTINCT slug, source FROM webmentions_sent ORDER BY slug, source'),
|
|
273
|
-
copySentWebmentions: db.prepare(`
|
|
274
|
-
INSERT INTO webmentions_sent (
|
|
275
|
-
slug, source, target, endpoint, status, error, attempted_at
|
|
276
|
-
)
|
|
277
|
-
SELECT :to, source, target, endpoint, status, error, attempted_at
|
|
278
|
-
FROM webmentions_sent WHERE slug = :slug AND source = :source
|
|
279
|
-
ON CONFLICT (slug, target) DO UPDATE SET
|
|
280
|
-
source = excluded.source,
|
|
281
|
-
endpoint = excluded.endpoint,
|
|
282
|
-
status = excluded.status,
|
|
283
|
-
error = excluded.error,
|
|
284
|
-
attempted_at = excluded.attempted_at
|
|
285
|
-
WHERE excluded.attempted_at > webmentions_sent.attempted_at
|
|
286
|
-
`),
|
|
287
|
-
deleteSentWebmentions: db.prepare('DELETE FROM webmentions_sent WHERE slug = :slug AND source = :source'),
|
|
288
|
-
countSentWebmentionsByStatus: db.prepare(`
|
|
289
|
-
SELECT status, COUNT(*) AS count FROM webmentions_sent WHERE slug = ? GROUP BY status
|
|
290
|
-
`),
|
|
291
|
-
listRelays: db.prepare('SELECT * FROM ap_relays ORDER BY created_at, inbox_id'),
|
|
292
|
-
relayByInbox: db.prepare('SELECT * FROM ap_relays WHERE inbox_id = ?'),
|
|
293
|
-
relayByFollow: db.prepare('SELECT * FROM ap_relays WHERE follow_id = ?'),
|
|
294
|
-
putRelay: db.prepare(`
|
|
295
|
-
INSERT INTO ap_relays (
|
|
296
|
-
inbox_id, actor_id, state, reason, follow_id, created_at, updated_at
|
|
297
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
298
|
-
ON CONFLICT (inbox_id) DO UPDATE SET
|
|
299
|
-
actor_id = excluded.actor_id,
|
|
300
|
-
state = excluded.state,
|
|
301
|
-
reason = excluded.reason,
|
|
302
|
-
follow_id = excluded.follow_id,
|
|
303
|
-
updated_at = excluded.updated_at
|
|
304
|
-
RETURNING *
|
|
305
|
-
`),
|
|
306
|
-
deleteRelay: db.prepare('DELETE FROM ap_relays WHERE inbox_id = ?'),
|
|
307
|
-
};
|
|
308
|
-
let open = true;
|
|
309
|
-
let readOnly = false;
|
|
310
|
-
/**
|
|
311
|
-
* Run a body with every write in it committed together, or none of them.
|
|
312
|
-
*
|
|
313
|
-
* The rebuilds are what need it: emptying an index and filling it again is
|
|
314
|
-
* one step to everything reading it, and a half-emptied `followers` is a
|
|
315
|
-
* site that has quietly stopped delivering to half its followers.
|
|
316
|
-
*/
|
|
317
|
-
function inTransaction(body) {
|
|
318
|
-
db.exec('BEGIN');
|
|
319
|
-
try {
|
|
320
|
-
body();
|
|
321
|
-
db.exec('COMMIT');
|
|
322
|
-
}
|
|
323
|
-
catch (error) {
|
|
324
|
-
db.exec('ROLLBACK');
|
|
325
|
-
throw error;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* The messages queued on a session. A column that will not parse is treated
|
|
330
|
-
* as empty: a flash is a convenience, and losing one is better than a 500 on
|
|
331
|
-
* every admin page until the row is cleaned up by hand.
|
|
332
|
-
*/
|
|
333
|
-
function readFlash(sessionId) {
|
|
334
|
-
const row = statements.readFlash.get(sessionId);
|
|
335
|
-
const raw = row?.['flash'];
|
|
336
|
-
if (typeof raw !== 'string' || raw === '')
|
|
337
|
-
return [];
|
|
338
|
-
try {
|
|
339
|
-
const parsed = JSON.parse(raw);
|
|
340
|
-
return Array.isArray(parsed) ? parsed.filter(isFlashMessage) : [];
|
|
341
|
-
}
|
|
342
|
-
catch {
|
|
343
|
-
return [];
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
/** Work out again every comment key worked out against another base, or none. */
|
|
347
|
-
function refreshCommentKeys(baseUrl) {
|
|
348
|
-
inTransaction(() => {
|
|
349
|
-
for (const row of statements.staleCommentKeys.all(baseUrl)) {
|
|
350
|
-
const comment = {
|
|
351
|
-
id: String(row['id']),
|
|
352
|
-
source: oneOf(row['source'], COMMENT_SOURCES, 'comment'),
|
|
353
|
-
};
|
|
354
|
-
statements.writeCommentKey.run(...commentKey(comment, baseUrl), comment.id);
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
if (options.baseUrl !== undefined)
|
|
359
|
-
refreshCommentKeys(options.baseUrl);
|
|
360
|
-
const listeners = new Set();
|
|
361
|
-
const written = (change) => {
|
|
362
|
-
for (const listener of listeners)
|
|
363
|
-
listener(change);
|
|
364
|
-
};
|
|
365
|
-
return {
|
|
366
|
-
file,
|
|
367
|
-
onConversationWrite(listener) {
|
|
368
|
-
listeners.add(listener);
|
|
369
|
-
return () => listeners.delete(listener);
|
|
370
|
-
},
|
|
371
|
-
createSession(input) {
|
|
372
|
-
const now = input.now ?? new Date();
|
|
373
|
-
const session = {
|
|
374
|
-
id: randomToken(),
|
|
375
|
-
userId: input.userId,
|
|
376
|
-
csrfToken: randomToken(),
|
|
377
|
-
createdAt: now.toISOString(),
|
|
378
|
-
expiresAt: new Date(now.getTime() + input.lifetimeSeconds * 1000).toISOString(),
|
|
379
|
-
};
|
|
380
|
-
statements.insertSession.run(session.id, session.userId, session.csrfToken, session.createdAt, session.expiresAt);
|
|
381
|
-
return session;
|
|
382
|
-
},
|
|
383
|
-
getSession(id, now = new Date()) {
|
|
384
|
-
const row = statements.sessionById.get(id);
|
|
385
|
-
if (row === undefined)
|
|
386
|
-
return undefined;
|
|
387
|
-
const session = toSession(row);
|
|
388
|
-
// ISO 8601 in UTC sorts the way time runs, so string order is time order.
|
|
389
|
-
if (session.expiresAt <= now.toISOString()) {
|
|
390
|
-
statements.deleteSession.run(id);
|
|
391
|
-
return undefined;
|
|
392
|
-
}
|
|
393
|
-
return session;
|
|
394
|
-
},
|
|
395
|
-
deleteSession(id) {
|
|
396
|
-
return statements.deleteSession.run(id).changes > 0;
|
|
397
|
-
},
|
|
398
|
-
deleteSessionsForUser(userId, options = {}) {
|
|
399
|
-
// `IS NOT` rather than `<>`, so a missing `except` compares against NULL
|
|
400
|
-
// and spares nothing instead of matching nothing.
|
|
401
|
-
return Number(statements.deleteSessionsForUser.run(userId, options.except ?? null).changes);
|
|
402
|
-
},
|
|
403
|
-
createPasswordReset(input) {
|
|
404
|
-
const now = input.now ?? new Date();
|
|
405
|
-
const token = randomToken();
|
|
406
|
-
const reset = {
|
|
407
|
-
token,
|
|
408
|
-
userId: input.userId,
|
|
409
|
-
createdAt: now.toISOString(),
|
|
410
|
-
expiresAt: new Date(now.getTime() + input.lifetimeSeconds * 1000).toISOString(),
|
|
411
|
-
};
|
|
412
|
-
statements.insertPasswordReset.run(hashToken(token), reset.userId, reset.createdAt, reset.expiresAt);
|
|
413
|
-
return reset;
|
|
414
|
-
},
|
|
415
|
-
getPasswordReset(token, now = new Date()) {
|
|
416
|
-
const hash = hashToken(token);
|
|
417
|
-
const row = statements.passwordResetByHash.get(hash);
|
|
418
|
-
if (row === undefined)
|
|
419
|
-
return undefined;
|
|
420
|
-
const reset = {
|
|
421
|
-
userId: Number(row['user_id']),
|
|
422
|
-
createdAt: String(row['created_at']),
|
|
423
|
-
expiresAt: String(row['expires_at']),
|
|
424
|
-
};
|
|
425
|
-
// The same rule the sessions follow: an expired row is deleted rather
|
|
426
|
-
// than ignored, so a clock that goes backwards cannot revive a link.
|
|
427
|
-
if (reset.expiresAt <= now.toISOString()) {
|
|
428
|
-
statements.deletePasswordReset.run(hash);
|
|
429
|
-
return undefined;
|
|
430
|
-
}
|
|
431
|
-
return reset;
|
|
432
|
-
},
|
|
433
|
-
deletePasswordReset(token) {
|
|
434
|
-
return statements.deletePasswordReset.run(hashToken(token)).changes > 0;
|
|
435
|
-
},
|
|
436
|
-
deletePasswordResetsForUser(userId) {
|
|
437
|
-
return Number(statements.deletePasswordResetsForUser.run(userId).changes);
|
|
438
|
-
},
|
|
439
|
-
prunePasswordResets(now = new Date()) {
|
|
440
|
-
return Number(statements.prunePasswordResets.run(now.toISOString()).changes);
|
|
441
|
-
},
|
|
442
|
-
spendToken(token, expiresAt, now = new Date()) {
|
|
443
|
-
// `INSERT OR IGNORE` rather than a read then a write: two clicks on the
|
|
444
|
-
// same link arriving together must not both find nothing and both act.
|
|
445
|
-
const written = statements.spendToken.run(hashToken(token), now.toISOString(), expiresAt);
|
|
446
|
-
return Number(written.changes) > 0;
|
|
447
|
-
},
|
|
448
|
-
pruneSpentTokens(now = new Date()) {
|
|
449
|
-
return Number(statements.pruneSpentTokens.run(now.toISOString()).changes);
|
|
450
|
-
},
|
|
451
|
-
countFollowers(username) {
|
|
452
|
-
const row = statements.countFollowers.get(username ?? null);
|
|
453
|
-
return Number(row?.['count'] ?? 0);
|
|
454
|
-
},
|
|
455
|
-
listFollowers(username, options = {}) {
|
|
456
|
-
const rows = statements.listFollowers.all(username ?? null, options.limit ?? NO_LIMIT, options.offset ?? 0);
|
|
457
|
-
return rows.map(toFollower);
|
|
458
|
-
},
|
|
459
|
-
getFollower(username, actorId) {
|
|
460
|
-
const row = statements.followerById.get(username, actorId);
|
|
461
|
-
return row === undefined ? undefined : toFollower(row);
|
|
462
|
-
},
|
|
463
|
-
isAvatarSource(url) {
|
|
464
|
-
return statements.isAvatarSource.get(url) !== undefined;
|
|
465
|
-
},
|
|
466
|
-
listAvatarSources() {
|
|
467
|
-
return statements.listAvatarSources.all().map((row) => String(row['url']));
|
|
468
|
-
},
|
|
469
|
-
getActorProfile(actorId) {
|
|
470
|
-
const row = statements.actorProfileById.get(actorId);
|
|
471
|
-
return row === undefined ? undefined : toActorProfile(row);
|
|
472
|
-
},
|
|
473
|
-
putActorProfile(profile) {
|
|
474
|
-
statements.putActorProfile.run(profile.actorId, profile.handle, profile.name, profile.iconUrl, profile.url, profile.fetchedAt);
|
|
475
|
-
},
|
|
476
|
-
listActorsToProfile(fetchedBefore) {
|
|
477
|
-
return statements.listActorsToProfile.all(fetchedBefore).map((row) => String(row['actor_id']));
|
|
478
|
-
},
|
|
479
|
-
putFollower(follower) {
|
|
480
|
-
statements.putFollower.run(follower.username, follower.actorId, follower.inboxId, follower.sharedInboxId, follower.handle, follower.name, follower.iconUrl, follower.url, follower.followedAt ?? new Date().toISOString());
|
|
481
|
-
// Read back rather than returning what was written: the upsert leaves an
|
|
482
|
-
// existing `followed_at` alone, so the row is the only thing that knows
|
|
483
|
-
// when the follow really began.
|
|
484
|
-
const row = statements.followerById.get(follower.username, follower.actorId);
|
|
485
|
-
if (row === undefined) {
|
|
486
|
-
throw new Error(`The follower "${follower.actorId}" vanished between insert and read.`);
|
|
487
|
-
}
|
|
488
|
-
return toFollower(row);
|
|
489
|
-
},
|
|
490
|
-
deleteFollower(username, actorId) {
|
|
491
|
-
return statements.deleteFollower.run(username, actorId).changes > 0;
|
|
492
|
-
},
|
|
493
|
-
replaceFollowers(followers) {
|
|
494
|
-
inTransaction(() => {
|
|
495
|
-
statements.clearFollowers.run();
|
|
496
|
-
for (const follower of followers) {
|
|
497
|
-
statements.putFollower.run(follower.username, follower.actorId, follower.inboxId, follower.sharedInboxId, follower.handle, follower.name, follower.iconUrl, follower.url, follower.followedAt ?? new Date().toISOString());
|
|
498
|
-
}
|
|
499
|
-
});
|
|
500
|
-
},
|
|
501
|
-
countInboxActivities() {
|
|
502
|
-
const row = statements.countInboxActivities.get();
|
|
503
|
-
return Number(row?.['count'] ?? 0);
|
|
504
|
-
},
|
|
505
|
-
listInboxActivities(options = {}) {
|
|
506
|
-
const rows = statements.listInboxActivities.all(options.limit ?? NO_LIMIT, options.offset ?? 0);
|
|
507
|
-
return rows.map(toInboxActivity);
|
|
508
|
-
},
|
|
509
|
-
logInboxActivity(activity) {
|
|
510
|
-
const row = statements.logInboxActivity.get(activity.activityId, activity.activityType, activity.actorId, activity.objectId,
|
|
511
|
-
// Derived here rather than passed in, so the column cannot say
|
|
512
|
-
// something the stored activity does not.
|
|
513
|
-
replyTargetOf(activity.json), replyKeyOf(activity), activity.recipient ?? null, activity.receivedAt ?? new Date().toISOString(), activity.fetched === true ? 1 : 0, activity.json);
|
|
514
|
-
if (row === undefined) {
|
|
515
|
-
throw new Error(`The activity "${activity.activityType}" was not written to the log.`);
|
|
516
|
-
}
|
|
517
|
-
const logged = toInboxActivity(row);
|
|
518
|
-
written(activityWrite(logged));
|
|
519
|
-
return logged;
|
|
520
|
-
},
|
|
521
|
-
deleteInboxActivity(id) {
|
|
522
|
-
const row = statements.deleteInboxActivity.get(id);
|
|
523
|
-
if (row === undefined)
|
|
524
|
-
return false;
|
|
525
|
-
written(activityWrite(toInboxActivity(row)));
|
|
526
|
-
return true;
|
|
527
|
-
},
|
|
528
|
-
replaceInboxActivities(activities) {
|
|
529
|
-
inTransaction(() => {
|
|
530
|
-
statements.clearInboxActivities.run();
|
|
531
|
-
// The AUTOINCREMENT high-water mark goes with the rows, so the same
|
|
532
|
-
// log always produces the same ids however many times it is rebuilt.
|
|
533
|
-
statements.resetInboxSequence.run();
|
|
534
|
-
for (const activity of activities) {
|
|
535
|
-
statements.logInboxActivity.run(activity.activityId, activity.activityType, activity.actorId, activity.objectId, replyTargetOf(activity.json), replyKeyOf(activity), activity.recipient ?? null, activity.receivedAt ?? new Date().toISOString(), activity.fetched === true ? 1 : 0, activity.json);
|
|
536
|
-
}
|
|
537
|
-
});
|
|
538
|
-
},
|
|
539
|
-
countReplies() {
|
|
540
|
-
const row = statements.countReplies.get();
|
|
541
|
-
return Number(row?.['count'] ?? 0);
|
|
542
|
-
},
|
|
543
|
-
listReplies(options = {}) {
|
|
544
|
-
const rows = statements.listReplies.all(options.limit ?? NO_LIMIT, options.offset ?? 0);
|
|
545
|
-
return rows.map(toInboxActivity);
|
|
546
|
-
},
|
|
547
|
-
countRepliesTo(objectId) {
|
|
548
|
-
const row = statements.countRepliesTo.get(objectId);
|
|
549
|
-
return Number(row?.['count'] ?? 0);
|
|
550
|
-
},
|
|
551
|
-
listRepliesTo(objectId, options = {}) {
|
|
552
|
-
const rows = statements.listRepliesTo.all(objectId, options.limit ?? NO_LIMIT, options.offset ?? 0);
|
|
553
|
-
return rows.map(toInboxActivity);
|
|
554
|
-
},
|
|
555
|
-
listActivitiesAbout(objectIds) {
|
|
556
|
-
if (objectIds.length === 0)
|
|
557
|
-
return [];
|
|
558
|
-
// Prepared here rather than beside the others because the number of
|
|
559
|
-
// placeholders is the number of ids: a conversation asks about the post,
|
|
560
|
-
// then about the notes that answered it, and neither count is known when
|
|
561
|
-
// the statements are built.
|
|
562
|
-
const placeholders = objectIds.map(() => '?').join(', ');
|
|
563
|
-
const rows = db
|
|
564
|
-
.prepare(`SELECT * FROM ap_inbox
|
|
565
|
-
WHERE object_id IN (${placeholders}) OR in_reply_to IN (${placeholders})
|
|
566
|
-
ORDER BY id ASC`)
|
|
567
|
-
.all(...objectIds, ...objectIds);
|
|
568
|
-
return rows.map(toInboxActivity);
|
|
569
|
-
},
|
|
570
|
-
listCommentsFor(slug) {
|
|
571
|
-
return statements.listCommentsFor.all(slug).map(toComment);
|
|
572
|
-
},
|
|
573
|
-
listComments(options = {}) {
|
|
574
|
-
// Prepared here rather than beside the others because the `WHERE` is not
|
|
575
|
-
// fixed: the screen asks for one status and the site-wide feed asks for
|
|
576
|
-
// approved comments across every post.
|
|
577
|
-
const where = options.status === undefined ? '' : 'WHERE status = ?';
|
|
578
|
-
const parameters = options.status === undefined ? [] : [options.status];
|
|
579
|
-
const rows = db
|
|
580
|
-
.prepare(`SELECT * FROM comments ${where}
|
|
581
|
-
ORDER BY submitted_at DESC, id DESC
|
|
582
|
-
LIMIT ? OFFSET ?`)
|
|
583
|
-
.all(...parameters, options.limit ?? NO_LIMIT, options.offset ?? 0);
|
|
584
|
-
return rows.map(toComment);
|
|
585
|
-
},
|
|
586
|
-
getComment(id) {
|
|
587
|
-
const row = statements.commentById.get(id);
|
|
588
|
-
return row === undefined ? undefined : toComment(row);
|
|
589
|
-
},
|
|
590
|
-
listCommentsAt(url) {
|
|
591
|
-
return statements.commentsAt.all(url).map(toComment);
|
|
592
|
-
},
|
|
593
|
-
listCommentsByRepliesKey(key) {
|
|
594
|
-
return statements.commentsByRepliesKey.all(key).map(toComment);
|
|
595
|
-
},
|
|
596
|
-
listRepliesByKey(key) {
|
|
597
|
-
return statements.repliesByKey.all(key).map(toInboxActivity);
|
|
598
|
-
},
|
|
599
|
-
countCommentsByStatus() {
|
|
600
|
-
const counts = { pending: 0, approved: 0, spam: 0 };
|
|
601
|
-
for (const row of statements.countCommentsByStatus.all()) {
|
|
602
|
-
counts[commentStatus(row['status'])] += Number(row['count'] ?? 0);
|
|
603
|
-
}
|
|
604
|
-
return counts;
|
|
605
|
-
},
|
|
606
|
-
hasApprovedAuthor(name, email) {
|
|
607
|
-
// `IS` rather than `=`, so an author who gave no email is matched by the
|
|
608
|
-
// rows that gave none either instead of matching nothing.
|
|
609
|
-
return statements.hasApprovedAuthor.get(name, email) !== undefined;
|
|
610
|
-
},
|
|
611
|
-
putComment(comment) {
|
|
612
|
-
const before = statements.commentById.get(comment.id);
|
|
613
|
-
statements.putComment.run(comment.id, comment.slug, comment.permalink, comment.source, comment.kind, comment.status, comment.author.name, comment.author.url, comment.author.email, comment.content.markdown, comment.content.html, comment.submitted, comment.addressHash, comment.inReplyTo, comment.url, comment.author.avatar, comment.notify ? 1 : 0, redactedColumn(comment.redacted), comment.rsvp ?? null, comment.via ?? null, ...commentKey(comment, options.baseUrl));
|
|
614
|
-
written({
|
|
615
|
-
kind: 'comment',
|
|
616
|
-
slug: comment.slug,
|
|
617
|
-
id: comment.id,
|
|
618
|
-
approved: comment.status === 'approved' && before?.['status'] !== 'approved',
|
|
619
|
-
});
|
|
620
|
-
return comment;
|
|
621
|
-
},
|
|
622
|
-
deleteComment(id) {
|
|
623
|
-
const row = statements.commentById.get(id);
|
|
624
|
-
const slug = row === undefined ? undefined : String(row['slug']);
|
|
625
|
-
const deleted = statements.deleteComment.run(id).changes > 0;
|
|
626
|
-
if (slug !== undefined)
|
|
627
|
-
written({ kind: 'comment', slug, id, approved: false });
|
|
628
|
-
return deleted;
|
|
629
|
-
},
|
|
630
|
-
replaceComments(comments) {
|
|
631
|
-
inTransaction(() => {
|
|
632
|
-
statements.clearComments.run();
|
|
633
|
-
for (const comment of comments) {
|
|
634
|
-
statements.putComment.run(comment.id, comment.slug, comment.permalink, comment.source, comment.kind, comment.status, comment.author.name, comment.author.url, comment.author.email, comment.content.markdown, comment.content.html, comment.submitted, comment.addressHash, comment.inReplyTo, comment.url, comment.author.avatar, comment.notify ? 1 : 0, redactedColumn(comment.redacted), comment.rsvp ?? null, comment.via ?? null, ...commentKey(comment, options.baseUrl));
|
|
635
|
-
}
|
|
636
|
-
});
|
|
637
|
-
},
|
|
638
|
-
recordDelivery(delivery) {
|
|
639
|
-
const row = statements.recordDelivery.get(delivery.activityId, delivery.activityType, delivery.objectId, delivery.slug, delivery.actorId, delivery.inboxId, delivery.status, delivery.error, delivery.attemptedAt ?? new Date().toISOString());
|
|
640
|
-
if (row === undefined) {
|
|
641
|
-
throw new Error(`The delivery of "${delivery.activityId}" to "${delivery.actorId}" was not recorded.`);
|
|
642
|
-
}
|
|
643
|
-
return toDelivery(row);
|
|
644
|
-
},
|
|
645
|
-
listDeliveries(activityId) {
|
|
646
|
-
const rows = statements.listDeliveries.all(activityId);
|
|
647
|
-
return rows.map(toDelivery);
|
|
648
|
-
},
|
|
649
|
-
countDeliveriesByStatus(activityId) {
|
|
650
|
-
const counts = { sent: 0, queued: 0, failed: 0 };
|
|
651
|
-
for (const row of statements.countDeliveriesByStatus.all(activityId)) {
|
|
652
|
-
const status = deliveryStatus(row['status']);
|
|
653
|
-
counts[status] += Number(row['count'] ?? 0);
|
|
654
|
-
}
|
|
655
|
-
return counts;
|
|
656
|
-
},
|
|
657
|
-
lastDeliveryToInbox(inboxId) {
|
|
658
|
-
const row = statements.lastDeliveryToInbox.get(inboxId);
|
|
659
|
-
return row === undefined ? undefined : toDelivery(row);
|
|
660
|
-
},
|
|
661
|
-
lastDeliveryToObject(objectId) {
|
|
662
|
-
const row = statements.lastDeliveryToObject.get(objectId);
|
|
663
|
-
return row === undefined ? undefined : toDelivery(row);
|
|
664
|
-
},
|
|
665
|
-
recordSentWebmention(sent) {
|
|
666
|
-
const row = statements.recordSentWebmention.get(sent.slug, sent.source, sent.target, sent.endpoint, sent.status, sent.error, sent.attemptedAt ?? new Date().toISOString());
|
|
667
|
-
if (row === undefined) {
|
|
668
|
-
throw new Error(`The webmention to ${sent.target} could not be recorded.`);
|
|
669
|
-
}
|
|
670
|
-
return toSentWebmention(row);
|
|
671
|
-
},
|
|
672
|
-
listSentWebmentions(slug) {
|
|
673
|
-
const rows = statements.listSentWebmentions.all(slug);
|
|
674
|
-
return rows.map(toSentWebmention);
|
|
675
|
-
},
|
|
676
|
-
listSentWebmentionSources() {
|
|
677
|
-
const rows = statements.listSentWebmentionSources.all();
|
|
678
|
-
return rows.map((row) => ({ slug: String(row['slug']), source: String(row['source']) }));
|
|
679
|
-
},
|
|
680
|
-
moveSentWebmentions(from, to) {
|
|
681
|
-
if (from.slug === to)
|
|
682
|
-
return;
|
|
683
|
-
inTransaction(() => {
|
|
684
|
-
statements.copySentWebmentions.run({ ...from, to });
|
|
685
|
-
statements.deleteSentWebmentions.run(from);
|
|
686
|
-
});
|
|
687
|
-
},
|
|
688
|
-
countSentWebmentionsByStatus(slug) {
|
|
689
|
-
const counts = { sent: 0, none: 0, failed: 0 };
|
|
690
|
-
const rows = statements.countSentWebmentionsByStatus.all(slug);
|
|
691
|
-
for (const row of rows) {
|
|
692
|
-
counts[webmentionSendStatus(row['status'])] = Number(row['count']);
|
|
693
|
-
}
|
|
694
|
-
return counts;
|
|
695
|
-
},
|
|
696
|
-
listRelays() {
|
|
697
|
-
return statements.listRelays.all().map(toRelay);
|
|
698
|
-
},
|
|
699
|
-
getRelay(inboxId) {
|
|
700
|
-
const row = statements.relayByInbox.get(inboxId);
|
|
701
|
-
return row === undefined ? undefined : toRelay(row);
|
|
702
|
-
},
|
|
703
|
-
getRelayByFollow(followId) {
|
|
704
|
-
const row = statements.relayByFollow.get(followId);
|
|
705
|
-
return row === undefined ? undefined : toRelay(row);
|
|
706
|
-
},
|
|
707
|
-
putRelay(relay) {
|
|
708
|
-
const now = new Date().toISOString();
|
|
709
|
-
const row = statements.putRelay.get(relay.inboxId, relay.actorId, relay.state, relay.reason, relay.followId, relay.createdAt ?? now, now);
|
|
710
|
-
if (row === undefined) {
|
|
711
|
-
throw new Error(`The relay subscription to "${relay.inboxId}" was not written.`);
|
|
712
|
-
}
|
|
713
|
-
return toRelay(row);
|
|
714
|
-
},
|
|
715
|
-
deleteRelay(inboxId) {
|
|
716
|
-
return statements.deleteRelay.run(inboxId).changes > 0;
|
|
717
|
-
},
|
|
718
|
-
pruneSessions(now = new Date()) {
|
|
719
|
-
return Number(statements.pruneSessions.run(now.toISOString()).changes);
|
|
720
|
-
},
|
|
721
|
-
legacySettings() {
|
|
722
|
-
// Prepared here rather than with the rest, because the table this reads
|
|
723
|
-
// is one that will not be there: a statement over a missing table throws
|
|
724
|
-
// when it is prepared, which would take the whole store down.
|
|
725
|
-
if (!hasTable(db, 'settings'))
|
|
726
|
-
return undefined;
|
|
727
|
-
return db.prepare('SELECT key, value, updated_at FROM settings').all().map((row) => ({
|
|
728
|
-
key: String(row['key']),
|
|
729
|
-
value: String(row['value']),
|
|
730
|
-
updatedAt: String(row['updated_at']),
|
|
731
|
-
}));
|
|
732
|
-
},
|
|
733
|
-
legacyActorKeys() {
|
|
734
|
-
// Prepared here for the same reason `legacySettings` is: the table is one
|
|
735
|
-
// that will not be there, and a statement over a missing table throws
|
|
736
|
-
// when it is prepared rather than when it is run.
|
|
737
|
-
if (!hasTable(db, 'actor_keys'))
|
|
738
|
-
return undefined;
|
|
739
|
-
return db.prepare('SELECT identifier, algorithm, private_jwk FROM actor_keys').all().map((row) => ({
|
|
740
|
-
identifier: String(row['identifier']),
|
|
741
|
-
algorithm: String(row['algorithm']),
|
|
742
|
-
privateJwk: String(row['private_jwk']),
|
|
743
|
-
}));
|
|
744
|
-
},
|
|
745
|
-
legacyUsers() {
|
|
746
|
-
// Prepared here for the same reason `legacySettings` is: the table is
|
|
747
|
-
// one that will not be there, and a statement over a missing table
|
|
748
|
-
// throws when it is prepared rather than when it is run.
|
|
749
|
-
if (!hasTable(db, 'users'))
|
|
750
|
-
return undefined;
|
|
751
|
-
return db
|
|
752
|
-
.prepare('SELECT id, username, password_hash, created_at FROM users ORDER BY id')
|
|
753
|
-
.all().map((row) => ({
|
|
754
|
-
id: Number(row['id']),
|
|
755
|
-
username: String(row['username']),
|
|
756
|
-
passwordHash: String(row['password_hash']),
|
|
757
|
-
createdAt: String(row['created_at']),
|
|
758
|
-
}));
|
|
759
|
-
},
|
|
760
|
-
dropLegacyTable(name) {
|
|
761
|
-
// The name is never a caller's to invent: it is one of this file's own
|
|
762
|
-
// shipped table names, so quoting it is enough.
|
|
763
|
-
db.exec(`DROP TABLE IF EXISTS "${name.replace(/"/g, '""')}"`);
|
|
764
|
-
},
|
|
765
|
-
getState(key) {
|
|
766
|
-
const row = statements.getState.get(key);
|
|
767
|
-
return row === undefined ? undefined : String(row['value']);
|
|
768
|
-
},
|
|
769
|
-
setState(key, value) {
|
|
770
|
-
statements.putState.run(key, value, new Date().toISOString());
|
|
771
|
-
},
|
|
772
|
-
pushFlash(sessionId, entry) {
|
|
773
|
-
const queued = [...readFlash(sessionId), entry];
|
|
774
|
-
statements.writeFlash.run(JSON.stringify(queued), sessionId);
|
|
775
|
-
},
|
|
776
|
-
takeFlash(sessionId) {
|
|
777
|
-
const queued = readFlash(sessionId);
|
|
778
|
-
if (!readOnly)
|
|
779
|
-
statements.writeFlash.run(null, sessionId);
|
|
780
|
-
return queued;
|
|
781
|
-
},
|
|
782
|
-
setReadOnly(on) {
|
|
783
|
-
db.exec(`PRAGMA query_only = ${on ? 'ON' : 'OFF'}`);
|
|
784
|
-
readOnly = on;
|
|
785
|
-
},
|
|
786
|
-
close() {
|
|
787
|
-
if (!open)
|
|
788
|
-
return;
|
|
789
|
-
open = false;
|
|
790
|
-
db.close();
|
|
791
|
-
},
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
function isFlashMessage(value) {
|
|
795
|
-
if (typeof value !== 'object' || value === null)
|
|
796
|
-
return false;
|
|
797
|
-
const entry = value;
|
|
798
|
-
return ((entry['kind'] === 'notice' || entry['kind'] === 'warning' || entry['kind'] === 'error') &&
|
|
799
|
-
typeof entry['message'] === 'string');
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* What a `LIMIT` means when the caller named none. SQLite reads a negative
|
|
803
|
-
* limit as "every row", which is what an unpaged list asks for.
|
|
804
|
-
*/
|
|
805
|
-
const NO_LIMIT = -1;
|
|
806
|
-
/**
|
|
807
|
-
* A `TEXT` column that may be `NULL`, as a string or `null`.
|
|
808
|
-
*
|
|
809
|
-
* Anything that is not text is read as `null` rather than stringified: every
|
|
810
|
-
* column this is used on is declared `TEXT`, so a value of another shape is a
|
|
811
|
-
* row somebody else wrote, and `[object Object]` is a worse answer than none.
|
|
812
|
-
*/
|
|
813
|
-
function nullableText(value) {
|
|
814
|
-
return typeof value === 'string' ? value : null;
|
|
815
|
-
}
|
|
816
|
-
function toFollower(row) {
|
|
817
|
-
return {
|
|
818
|
-
username: String(row['username']),
|
|
819
|
-
actorId: String(row['actor_id']),
|
|
820
|
-
inboxId: String(row['inbox_id']),
|
|
821
|
-
sharedInboxId: nullableText(row['shared_inbox_id']),
|
|
822
|
-
handle: nullableText(row['handle']),
|
|
823
|
-
name: nullableText(row['name']),
|
|
824
|
-
iconUrl: nullableText(row['icon_url']),
|
|
825
|
-
url: nullableText(row['url']),
|
|
826
|
-
followedAt: String(row['followed_at']),
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
function toActorProfile(row) {
|
|
830
|
-
return {
|
|
831
|
-
actorId: String(row['actor_id']),
|
|
832
|
-
handle: nullableText(row['handle']),
|
|
833
|
-
name: nullableText(row['name']),
|
|
834
|
-
iconUrl: nullableText(row['icon_url']),
|
|
835
|
-
url: nullableText(row['url']),
|
|
836
|
-
fetchedAt: String(row['fetched_at']),
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
function toInboxActivity(row) {
|
|
840
|
-
return {
|
|
841
|
-
id: Number(row['id']),
|
|
842
|
-
activityId: nullableText(row['activity_id']),
|
|
843
|
-
activityType: String(row['activity_type']),
|
|
844
|
-
actorId: String(row['actor_id']),
|
|
845
|
-
objectId: nullableText(row['object_id']),
|
|
846
|
-
inReplyTo: nullableText(row['in_reply_to']),
|
|
847
|
-
recipient: nullableText(row['recipient']),
|
|
848
|
-
receivedAt: String(row['received_at']),
|
|
849
|
-
fetched: Number(row['fetched']) === 1,
|
|
850
|
-
json: String(row['json']),
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
function toDelivery(row) {
|
|
854
|
-
return {
|
|
855
|
-
activityId: String(row['activity_id']),
|
|
856
|
-
activityType: String(row['activity_type']),
|
|
857
|
-
objectId: String(row['object_id']),
|
|
858
|
-
slug: nullableText(row['slug']),
|
|
859
|
-
actorId: String(row['actor_id']),
|
|
860
|
-
inboxId: String(row['inbox_id']),
|
|
861
|
-
status: deliveryStatus(row['status']),
|
|
862
|
-
error: nullableText(row['error']),
|
|
863
|
-
attemptedAt: String(row['attempted_at']),
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
function toSentWebmention(row) {
|
|
867
|
-
return {
|
|
868
|
-
slug: String(row['slug']),
|
|
869
|
-
source: String(row['source']),
|
|
870
|
-
target: String(row['target']),
|
|
871
|
-
endpoint: nullableText(row['endpoint']),
|
|
872
|
-
status: webmentionSendStatus(row['status']),
|
|
873
|
-
error: nullableText(row['error']),
|
|
874
|
-
attemptedAt: String(row['attempted_at']),
|
|
875
|
-
};
|
|
876
|
-
}
|
|
877
|
-
/** A stored send status, or `failed` for one this version does not know. */
|
|
878
|
-
function webmentionSendStatus(value) {
|
|
879
|
-
return oneOf(value, WEBMENTION_SEND_STATUSES, 'failed');
|
|
880
|
-
}
|
|
881
|
-
function toComment(row) {
|
|
882
|
-
return {
|
|
883
|
-
id: String(row['id']),
|
|
884
|
-
slug: String(row['slug']),
|
|
885
|
-
permalink: String(row['permalink']),
|
|
886
|
-
source: oneOf(row['source'], COMMENT_SOURCES, 'comment'),
|
|
887
|
-
kind: oneOf(row['kind'], COMMENT_KINDS, 'reply'),
|
|
888
|
-
status: commentStatus(row['status']),
|
|
889
|
-
author: {
|
|
890
|
-
name: String(row['author_name']),
|
|
891
|
-
url: nullableText(row['author_url']),
|
|
892
|
-
email: nullableText(row['author_email']),
|
|
893
|
-
avatar: nullableText(row['author_avatar']),
|
|
894
|
-
},
|
|
895
|
-
content: { markdown: String(row['markdown']), html: String(row['html']) },
|
|
896
|
-
submitted: String(row['submitted_at']),
|
|
897
|
-
addressHash: nullableText(row['address_hash']),
|
|
898
|
-
inReplyTo: nullableText(row['in_reply_to']),
|
|
899
|
-
url: nullableText(row['url']),
|
|
900
|
-
notify: Number(row['notify'] ?? 0) === 1,
|
|
901
|
-
...redactedOf(row['redacted']),
|
|
902
|
-
...rsvpField(rsvpValue(row['rsvp'])),
|
|
903
|
-
...viaField(nullableText(row['via'])),
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
/** A comment's {@link CommentRecord.redacted} as its column holds it: JSON, or `NULL`. */
|
|
907
|
-
function redactedColumn(redacted) {
|
|
908
|
-
return redacted === undefined || redacted.length === 0 ? null : JSON.stringify(redacted);
|
|
909
|
-
}
|
|
910
|
-
/** The column read back, as the key a record carries only when something was removed. */
|
|
911
|
-
function redactedOf(value) {
|
|
912
|
-
if (typeof value !== 'string')
|
|
913
|
-
return {};
|
|
914
|
-
let parsed;
|
|
915
|
-
try {
|
|
916
|
-
parsed = JSON.parse(value);
|
|
917
|
-
}
|
|
918
|
-
catch {
|
|
919
|
-
return {};
|
|
920
|
-
}
|
|
921
|
-
const fields = Array.isArray(parsed)
|
|
922
|
-
? REDACTED_FIELDS.filter((field) => parsed.includes(field))
|
|
923
|
-
: [];
|
|
924
|
-
return fields.length === 0 ? {} : { redacted: fields };
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
* A stored comment status, or `pending` for one this version does not know.
|
|
928
|
-
*
|
|
929
|
-
* Pending is the safe reading: showing a comment nobody approved is the one
|
|
930
|
-
* mistake a moderation queue cannot make, and the screen is right there for
|
|
931
|
-
* the row.
|
|
932
|
-
*/
|
|
933
|
-
function commentStatus(value) {
|
|
934
|
-
return oneOf(value, COMMENT_STATUSES, 'pending');
|
|
935
|
-
}
|
|
936
|
-
/** A stored enumeration value, or the fallback for one this version does not know. */
|
|
937
|
-
function oneOf(value, allowed, fallback) {
|
|
938
|
-
return allowed.includes(value) ? value : fallback;
|
|
939
|
-
}
|
|
940
|
-
function toRelay(row) {
|
|
941
|
-
return {
|
|
942
|
-
inboxId: String(row['inbox_id']),
|
|
943
|
-
actorId: nullableText(row['actor_id']),
|
|
944
|
-
state: relayState(row['state']),
|
|
945
|
-
reason: nullableText(row['reason']),
|
|
946
|
-
followId: nullableText(row['follow_id']),
|
|
947
|
-
createdAt: String(row['created_at']),
|
|
948
|
-
updatedAt: String(row['updated_at']),
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* A stored relay state, or `pending` for one this version does not know.
|
|
953
|
-
*
|
|
954
|
-
* Pending is the safe reading of an unknown state: a subscription this version
|
|
955
|
-
* cannot make sense of is one it should not be delivering public posts to, and
|
|
956
|
-
* Retry is on the screen for exactly that row.
|
|
957
|
-
*/
|
|
958
|
-
function relayState(value) {
|
|
959
|
-
return RELAY_STATES.includes(value) ? value : 'pending';
|
|
960
|
-
}
|
|
961
|
-
/**
|
|
962
|
-
* A stored status, or `failed` for one this version does not know.
|
|
963
|
-
*
|
|
964
|
-
* An unreadable status is reported as the pessimistic one: an admin screen
|
|
965
|
-
* showing a delivery as failed when it was not is a nuisance, and showing one
|
|
966
|
-
* as sent when nobody knows is a lie.
|
|
967
|
-
*/
|
|
968
|
-
function deliveryStatus(value) {
|
|
969
|
-
return DELIVERY_STATUSES.includes(value) ? value : 'failed';
|
|
970
|
-
}
|
|
971
|
-
function toSession(row) {
|
|
972
|
-
const userId = row['user_id'];
|
|
973
|
-
return {
|
|
974
|
-
id: String(row['id']),
|
|
975
|
-
userId: userId === null || userId === undefined ? null : Number(userId),
|
|
976
|
-
csrfToken: String(row['csrf_token']),
|
|
977
|
-
createdAt: String(row['created_at']),
|
|
978
|
-
expiresAt: String(row['expires_at']),
|
|
979
|
-
};
|
|
980
|
-
}
|
|
981
|
-
/**
|
|
982
|
-
* 256 unguessable bits, hex encoded. Session ids, CSRF tokens and password
|
|
983
|
-
* reset tokens are all this.
|
|
984
|
-
*/
|
|
985
|
-
function randomToken() {
|
|
986
|
-
return randomBytes(SESSION_ID_BYTES).toString('hex');
|
|
987
|
-
}
|
|
988
|
-
/**
|
|
989
|
-
* A reset token as the database keeps it: its SHA-256, hex encoded.
|
|
990
|
-
*
|
|
991
|
-
* Plain SHA-256 rather than argon2 on purpose. What argon2 buys is time
|
|
992
|
-
* against somebody guessing a password people chose, and there is nothing to
|
|
993
|
-
* guess here: the token is 256 bits out of `randomBytes`, so the only way to
|
|
994
|
-
* hold a valid one is to have been sent it. What the hash is for is that a
|
|
995
|
-
* copy of `geekity.db` — a backup, a stray file — is not a stack of working
|
|
996
|
-
* reset links.
|
|
997
|
-
*/
|
|
998
|
-
function hashToken(token) {
|
|
999
|
-
return createHash('sha256').update(token, 'utf8').digest('hex');
|
|
1000
|
-
}
|
|
1001
|
-
/** Whether the database has a table by that name. */
|
|
1002
|
-
function hasTable(db, name) {
|
|
1003
|
-
return (db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?").all(name)
|
|
1004
|
-
.length > 0);
|
|
1005
|
-
}
|
|
1006
|
-
/** The table this store's applied versions are recorded in. */
|
|
1007
|
-
const LEDGER = 'admin_migrations';
|
|
1008
|
-
/**
|
|
1009
|
-
* Schema versions for the admin tables, applied in order. They keep their own
|
|
1010
|
-
* ledger so their numbering never collides with the content index's.
|
|
1011
|
-
*
|
|
1012
|
-
* Never edit a migration that has shipped; append a new one.
|
|
1013
|
-
*/
|
|
1014
|
-
const MIGRATIONS = [
|
|
1015
|
-
{
|
|
1016
|
-
// Users and sessions, when SQLite still held both. decision-9 moved the
|
|
1017
|
-
// accounts into `data/users.json`, so nothing reads the users table any
|
|
1018
|
-
// more: `migrateUsersToFile` writes its rows out on the first boot of that
|
|
1019
|
-
// version and drops it. The migration stays exactly as it shipped, because
|
|
1020
|
-
// a shipped migration is never edited — which does mean a brand new
|
|
1021
|
-
// database creates the table here and drops it a moment later. Migration
|
|
1022
|
-
// 11 is where sessions lose the foreign key into it.
|
|
1023
|
-
version: 1,
|
|
1024
|
-
sql: `
|
|
1025
|
-
CREATE TABLE users (
|
|
1026
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1027
|
-
username TEXT NOT NULL,
|
|
1028
|
-
password_hash TEXT NOT NULL,
|
|
1029
|
-
created_at TEXT NOT NULL
|
|
1030
|
-
);
|
|
1031
|
-
|
|
1032
|
-
CREATE UNIQUE INDEX users_username ON users (username);
|
|
1033
|
-
|
|
1034
|
-
CREATE TABLE sessions (
|
|
1035
|
-
id TEXT PRIMARY KEY,
|
|
1036
|
-
user_id INTEGER REFERENCES users (id) ON DELETE CASCADE,
|
|
1037
|
-
csrf_token TEXT NOT NULL,
|
|
1038
|
-
created_at TEXT NOT NULL,
|
|
1039
|
-
expires_at TEXT NOT NULL
|
|
1040
|
-
);
|
|
1041
|
-
|
|
1042
|
-
CREATE INDEX sessions_expires_at ON sessions (expires_at);
|
|
1043
|
-
CREATE INDEX sessions_user_id ON sessions (user_id);
|
|
1044
|
-
`,
|
|
1045
|
-
},
|
|
1046
|
-
{
|
|
1047
|
-
// Flash messages: a JSON array of {kind, message}, queued by the request
|
|
1048
|
-
// that redirects and cleared by the one that renders them. They hang off
|
|
1049
|
-
// the session rather than a cookie so they cannot be forged or replayed,
|
|
1050
|
-
// and so they go when the session does.
|
|
1051
|
-
version: 2,
|
|
1052
|
-
sql: `ALTER TABLE sessions ADD COLUMN flash TEXT`,
|
|
1053
|
-
},
|
|
1054
|
-
{
|
|
1055
|
-
// Site settings, when SQLite was still the source of them. decision-9
|
|
1056
|
-
// moved them into content/_data/site.json, so nothing reads this table
|
|
1057
|
-
// any more: `migrateSettingsToFile` writes its rows out on the first boot
|
|
1058
|
-
// of that version and drops it. The migration stays exactly as it shipped,
|
|
1059
|
-
// because a shipped migration is never edited — which does mean a brand
|
|
1060
|
-
// new database creates the table here and drops it a moment later.
|
|
1061
|
-
version: 3,
|
|
1062
|
-
sql: `
|
|
1063
|
-
CREATE TABLE settings (
|
|
1064
|
-
key TEXT PRIMARY KEY,
|
|
1065
|
-
value TEXT NOT NULL,
|
|
1066
|
-
updated_at TEXT NOT NULL
|
|
1067
|
-
);
|
|
1068
|
-
`,
|
|
1069
|
-
},
|
|
1070
|
-
{
|
|
1071
|
-
// The site actor's signing keys, when SQLite still held them. decision-9
|
|
1072
|
-
// moved them into JWK files under `data/keys`, so nothing reads this table
|
|
1073
|
-
// any more: `migrateActorKeysToFiles` writes its rows out on the first boot
|
|
1074
|
-
// of that version and drops it. The migration stays exactly as it shipped,
|
|
1075
|
-
// because a shipped migration is never edited — which does mean a brand new
|
|
1076
|
-
// database creates the table here and drops it a moment later.
|
|
1077
|
-
version: 4,
|
|
1078
|
-
sql: `
|
|
1079
|
-
CREATE TABLE actor_keys (
|
|
1080
|
-
identifier TEXT NOT NULL,
|
|
1081
|
-
algorithm TEXT NOT NULL,
|
|
1082
|
-
private_jwk TEXT NOT NULL,
|
|
1083
|
-
public_jwk TEXT NOT NULL,
|
|
1084
|
-
created_at TEXT NOT NULL,
|
|
1085
|
-
PRIMARY KEY (identifier, algorithm)
|
|
1086
|
-
);
|
|
1087
|
-
`,
|
|
1088
|
-
},
|
|
1089
|
-
{
|
|
1090
|
-
// The site's followers (doc-4). Fedify's KV store is a cache and may be
|
|
1091
|
-
// thrown away; a follower may not, because an actor that followed and was
|
|
1092
|
-
// forgotten simply stops hearing from the site. Keyed by actor id, which
|
|
1093
|
-
// is what a `Follow`, an `Undo(Follow)` and an actor's own `Delete` all
|
|
1094
|
-
// name, so all three find the same row.
|
|
1095
|
-
version: 5,
|
|
1096
|
-
sql: `
|
|
1097
|
-
CREATE TABLE followers (
|
|
1098
|
-
actor_id TEXT PRIMARY KEY,
|
|
1099
|
-
inbox_id TEXT NOT NULL,
|
|
1100
|
-
shared_inbox_id TEXT,
|
|
1101
|
-
handle TEXT,
|
|
1102
|
-
name TEXT,
|
|
1103
|
-
icon_url TEXT,
|
|
1104
|
-
url TEXT,
|
|
1105
|
-
followed_at TEXT NOT NULL
|
|
1106
|
-
);
|
|
1107
|
-
|
|
1108
|
-
CREATE INDEX followers_followed_at ON followers (followed_at);
|
|
1109
|
-
`,
|
|
1110
|
-
},
|
|
1111
|
-
{
|
|
1112
|
-
// Inbound activities that are recorded rather than acted on: likes,
|
|
1113
|
-
// boosts and replies, which a later phase surfaces. The raw JSON-LD is
|
|
1114
|
-
// kept because what that phase wants out of an activity is not knowable
|
|
1115
|
-
// yet. The unique index on the activity id is what makes a redelivery an
|
|
1116
|
-
// update rather than a second like; SQLite counts NULLs as distinct, so
|
|
1117
|
-
// an activity that arrived without an id is always its own row.
|
|
1118
|
-
version: 6,
|
|
1119
|
-
sql: `
|
|
1120
|
-
CREATE TABLE ap_inbox (
|
|
1121
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1122
|
-
activity_id TEXT,
|
|
1123
|
-
activity_type TEXT NOT NULL,
|
|
1124
|
-
actor_id TEXT NOT NULL,
|
|
1125
|
-
object_id TEXT,
|
|
1126
|
-
received_at TEXT NOT NULL,
|
|
1127
|
-
json TEXT NOT NULL
|
|
1128
|
-
);
|
|
1129
|
-
|
|
1130
|
-
CREATE UNIQUE INDEX ap_inbox_activity_id ON ap_inbox (activity_id);
|
|
1131
|
-
CREATE INDEX ap_inbox_received_at ON ap_inbox (received_at);
|
|
1132
|
-
CREATE INDEX ap_inbox_actor_id ON ap_inbox (actor_id);
|
|
1133
|
-
`,
|
|
1134
|
-
},
|
|
1135
|
-
{
|
|
1136
|
-
// Outbound delivery (doc-4, decision-5). Two tables, because an activity
|
|
1137
|
-
// is one thing and its fate at each follower is another: keeping the
|
|
1138
|
-
// JSON-LD once rather than once per follower is what makes a redelivery to
|
|
1139
|
-
// a thousand followers a single read, and one row per (activity, follower)
|
|
1140
|
-
// is what lets the admin see which follower did not get it.
|
|
1141
|
-
//
|
|
1142
|
-
// The activity's own id is the key. It is derived from the post's object
|
|
1143
|
-
// id — `#create`, `#update/{hash}`, `#delete/{time}` — so re-sending the
|
|
1144
|
-
// same announcement updates the row it belongs to instead of writing a
|
|
1145
|
-
// second one that says the same thing.
|
|
1146
|
-
version: 7,
|
|
1147
|
-
sql: `
|
|
1148
|
-
CREATE TABLE ap_outbound (
|
|
1149
|
-
activity_id TEXT PRIMARY KEY,
|
|
1150
|
-
activity_type TEXT NOT NULL,
|
|
1151
|
-
object_id TEXT NOT NULL,
|
|
1152
|
-
slug TEXT,
|
|
1153
|
-
created_at TEXT NOT NULL,
|
|
1154
|
-
json TEXT NOT NULL
|
|
1155
|
-
);
|
|
1156
|
-
|
|
1157
|
-
CREATE INDEX ap_outbound_created_at ON ap_outbound (created_at);
|
|
1158
|
-
CREATE INDEX ap_outbound_object_id ON ap_outbound (object_id);
|
|
1159
|
-
|
|
1160
|
-
CREATE TABLE ap_deliveries (
|
|
1161
|
-
activity_id TEXT NOT NULL REFERENCES ap_outbound (activity_id) ON DELETE CASCADE,
|
|
1162
|
-
actor_id TEXT NOT NULL,
|
|
1163
|
-
inbox_id TEXT NOT NULL,
|
|
1164
|
-
status TEXT NOT NULL,
|
|
1165
|
-
error TEXT,
|
|
1166
|
-
attempted_at TEXT NOT NULL,
|
|
1167
|
-
PRIMARY KEY (activity_id, actor_id)
|
|
1168
|
-
);
|
|
1169
|
-
|
|
1170
|
-
CREATE INDEX ap_deliveries_attempted_at ON ap_deliveries (attempted_at);
|
|
1171
|
-
CREATE INDEX ap_deliveries_status ON ap_deliveries (status);
|
|
1172
|
-
`,
|
|
1173
|
-
},
|
|
1174
|
-
{
|
|
1175
|
-
// What a logged reply answers, so a post's comments can be counted and
|
|
1176
|
-
// listed without reading every activity the site was ever sent.
|
|
1177
|
-
//
|
|
1178
|
-
// It is an index of the JSON beside it rather than a fact of its own: the
|
|
1179
|
-
// backfill runs the very function the writer runs, so a database rebuilt
|
|
1180
|
-
// from the inbox log (TASK-32) holds what this one holds.
|
|
1181
|
-
version: 8,
|
|
1182
|
-
sql: `
|
|
1183
|
-
ALTER TABLE ap_inbox ADD COLUMN in_reply_to TEXT;
|
|
1184
|
-
CREATE INDEX ap_inbox_in_reply_to ON ap_inbox (in_reply_to);
|
|
1185
|
-
`,
|
|
1186
|
-
run(db) {
|
|
1187
|
-
const rows = db.prepare('SELECT id, json FROM ap_inbox').all();
|
|
1188
|
-
const update = db.prepare('UPDATE ap_inbox SET in_reply_to = ? WHERE id = ?');
|
|
1189
|
-
for (const row of rows) {
|
|
1190
|
-
update.run(replyTargetOf(String(row['json'])), Number(row['id']));
|
|
1191
|
-
}
|
|
1192
|
-
},
|
|
1193
|
-
},
|
|
1194
|
-
{
|
|
1195
|
-
// Relay subscriptions (FEP-ae0c, TASK-40). The list of relays is a
|
|
1196
|
-
// setting mirrored to site.json; this is where each handshake stands,
|
|
1197
|
-
// which is operational state and derivable again from the file — a relay
|
|
1198
|
-
// in the list with no row here is simply followed again on the next boot.
|
|
1199
|
-
//
|
|
1200
|
-
// Keyed by the inbox rather than by the relay's actor id, because the
|
|
1201
|
-
// inbox is the only thing known when the `Follow` goes out: the actor id
|
|
1202
|
-
// arrives with the `Accept`, days later if a human has to approve it.
|
|
1203
|
-
version: 9,
|
|
1204
|
-
sql: `
|
|
1205
|
-
CREATE TABLE ap_relays (
|
|
1206
|
-
inbox_id TEXT PRIMARY KEY,
|
|
1207
|
-
actor_id TEXT,
|
|
1208
|
-
state TEXT NOT NULL,
|
|
1209
|
-
reason TEXT,
|
|
1210
|
-
follow_id TEXT,
|
|
1211
|
-
created_at TEXT NOT NULL,
|
|
1212
|
-
updated_at TEXT NOT NULL
|
|
1213
|
-
);
|
|
1214
|
-
|
|
1215
|
-
CREATE INDEX ap_relays_follow_id ON ap_relays (follow_id);
|
|
1216
|
-
CREATE INDEX ap_relays_actor_id ON ap_relays (actor_id);
|
|
1217
|
-
`,
|
|
1218
|
-
},
|
|
1219
|
-
{
|
|
1220
|
-
// The CMS's own operational state, as opposed to the site's settings. It
|
|
1221
|
-
// is a table of its own rather than more rows in `settings` because the
|
|
1222
|
-
// number of settings is what decides whether a site is seeded from
|
|
1223
|
-
// content/_data/site.json, and because nothing here belongs in that file.
|
|
1224
|
-
version: 10,
|
|
1225
|
-
sql: `
|
|
1226
|
-
CREATE TABLE cms_state (
|
|
1227
|
-
key TEXT PRIMARY KEY,
|
|
1228
|
-
value TEXT NOT NULL,
|
|
1229
|
-
updated_at TEXT NOT NULL
|
|
1230
|
-
);
|
|
1231
|
-
`,
|
|
1232
|
-
},
|
|
1233
|
-
{
|
|
1234
|
-
// Sessions without the foreign key into `users`, because there is no users
|
|
1235
|
-
// table any more: decision-9 moved the accounts into `data/users.json` and
|
|
1236
|
-
// `migrateUsersToFile` drops the table on the boot after this migration
|
|
1237
|
-
// runs. The constraint could not survive that either way — with
|
|
1238
|
-
// `foreign_keys` on, dropping the parent cascades every login away, and an
|
|
1239
|
-
// insert afterwards fails with "no such table: main.users" — and SQLite
|
|
1240
|
-
// cannot drop a constraint in place, so the table is rebuilt. Every row is
|
|
1241
|
-
// copied across, so a site upgrading keeps the logins it had. What the key
|
|
1242
|
-
// was doing is done in the admin guard instead: a session naming a user
|
|
1243
|
-
// the file no longer holds is not a session.
|
|
1244
|
-
version: 11,
|
|
1245
|
-
sql: `
|
|
1246
|
-
CREATE TABLE sessions_without_users (
|
|
1247
|
-
id TEXT PRIMARY KEY,
|
|
1248
|
-
user_id INTEGER,
|
|
1249
|
-
csrf_token TEXT NOT NULL,
|
|
1250
|
-
created_at TEXT NOT NULL,
|
|
1251
|
-
expires_at TEXT NOT NULL,
|
|
1252
|
-
flash TEXT
|
|
1253
|
-
);
|
|
1254
|
-
|
|
1255
|
-
INSERT INTO sessions_without_users (
|
|
1256
|
-
id, user_id, csrf_token, created_at, expires_at, flash
|
|
1257
|
-
)
|
|
1258
|
-
SELECT id, user_id, csrf_token, created_at, expires_at, flash FROM sessions;
|
|
1259
|
-
|
|
1260
|
-
DROP TABLE sessions;
|
|
1261
|
-
ALTER TABLE sessions_without_users RENAME TO sessions;
|
|
1262
|
-
|
|
1263
|
-
CREATE INDEX sessions_expires_at ON sessions (expires_at);
|
|
1264
|
-
CREATE INDEX sessions_user_id ON sessions (user_id);
|
|
1265
|
-
`,
|
|
1266
|
-
},
|
|
1267
|
-
{
|
|
1268
|
-
// The outcomes without the payloads. decision-9 replaces "send this stored
|
|
1269
|
-
// activity again" with "send this post as it now reads", so nothing needs
|
|
1270
|
-
// the JSON-LD any more and `ap_outbound` goes: an activity rebuilt from
|
|
1271
|
-
// the file is the current answer, and a copy of what went out last time
|
|
1272
|
-
// could only ever be a staler one.
|
|
1273
|
-
//
|
|
1274
|
-
// What that table held about an activity that an outcome cannot do
|
|
1275
|
-
// without — its type, the object it was about and the slug — moves onto
|
|
1276
|
-
// the outcome row, which is now the whole of what SQLite remembers about
|
|
1277
|
-
// anything the site has sent. The foreign key has to go with the parent,
|
|
1278
|
-
// and SQLite cannot drop a constraint in place, so `ap_deliveries` is
|
|
1279
|
-
// rebuilt the way migration 11 rebuilt `sessions`. Every row that has an
|
|
1280
|
-
// activity to name is carried across as a courtesy: this table is a cache
|
|
1281
|
-
// and is allowed to be empty, so a row whose activity is somehow missing
|
|
1282
|
-
// is dropped rather than invented a type for.
|
|
1283
|
-
version: 12,
|
|
1284
|
-
sql: `
|
|
1285
|
-
CREATE TABLE ap_deliveries_standalone (
|
|
1286
|
-
activity_id TEXT NOT NULL,
|
|
1287
|
-
activity_type TEXT NOT NULL,
|
|
1288
|
-
object_id TEXT NOT NULL,
|
|
1289
|
-
slug TEXT,
|
|
1290
|
-
actor_id TEXT NOT NULL,
|
|
1291
|
-
inbox_id TEXT NOT NULL,
|
|
1292
|
-
status TEXT NOT NULL,
|
|
1293
|
-
error TEXT,
|
|
1294
|
-
attempted_at TEXT NOT NULL,
|
|
1295
|
-
PRIMARY KEY (activity_id, actor_id)
|
|
1296
|
-
);
|
|
1297
|
-
|
|
1298
|
-
INSERT INTO ap_deliveries_standalone (
|
|
1299
|
-
activity_id, activity_type, object_id, slug,
|
|
1300
|
-
actor_id, inbox_id, status, error, attempted_at
|
|
1301
|
-
)
|
|
1302
|
-
SELECT
|
|
1303
|
-
ap_deliveries.activity_id,
|
|
1304
|
-
ap_outbound.activity_type,
|
|
1305
|
-
ap_outbound.object_id,
|
|
1306
|
-
ap_outbound.slug,
|
|
1307
|
-
ap_deliveries.actor_id,
|
|
1308
|
-
ap_deliveries.inbox_id,
|
|
1309
|
-
ap_deliveries.status,
|
|
1310
|
-
ap_deliveries.error,
|
|
1311
|
-
ap_deliveries.attempted_at
|
|
1312
|
-
FROM ap_deliveries
|
|
1313
|
-
JOIN ap_outbound ON ap_outbound.activity_id = ap_deliveries.activity_id;
|
|
1314
|
-
|
|
1315
|
-
DROP TABLE ap_deliveries;
|
|
1316
|
-
ALTER TABLE ap_deliveries_standalone RENAME TO ap_deliveries;
|
|
1317
|
-
|
|
1318
|
-
CREATE INDEX ap_deliveries_attempted_at ON ap_deliveries (attempted_at);
|
|
1319
|
-
CREATE INDEX ap_deliveries_status ON ap_deliveries (status);
|
|
1320
|
-
CREATE INDEX ap_deliveries_object_id ON ap_deliveries (object_id, attempted_at);
|
|
1321
|
-
|
|
1322
|
-
DROP TABLE ap_outbound;
|
|
1323
|
-
`,
|
|
1324
|
-
},
|
|
1325
|
-
{
|
|
1326
|
-
// What a post's conversation is read by (TASK-49). `in_reply_to` already
|
|
1327
|
-
// had an index because a post's replies are counted on every feed; the
|
|
1328
|
-
// object an activity is about had none, and that is the column a like, a
|
|
1329
|
-
// boost, a `Delete` of a reply and an `Undo` of a like are all found by.
|
|
1330
|
-
version: 13,
|
|
1331
|
-
sql: `
|
|
1332
|
-
CREATE INDEX ap_inbox_object_id ON ap_inbox (object_id);
|
|
1333
|
-
`,
|
|
1334
|
-
},
|
|
1335
|
-
{
|
|
1336
|
-
// Native comments (TASK-50), which are files under
|
|
1337
|
-
// `content/_data/comments/` and nothing else: this table is an index of
|
|
1338
|
-
// them, emptied and read back on every boot exactly as `followers` and
|
|
1339
|
-
// `ap_inbox` are. Nothing here is a fact the files do not carry.
|
|
1340
|
-
//
|
|
1341
|
-
// The id is the comment's own name rather than a row number, because it is
|
|
1342
|
-
// what a reply names, what a moderation form posts and what the page
|
|
1343
|
-
// anchors on — all three have to survive a rebuilt index. The author's
|
|
1344
|
-
// name and email are indexed together because that pair is the whole of
|
|
1345
|
-
// WordPress's auto-approval rule.
|
|
1346
|
-
version: 14,
|
|
1347
|
-
sql: `
|
|
1348
|
-
CREATE TABLE comments (
|
|
1349
|
-
id TEXT PRIMARY KEY,
|
|
1350
|
-
slug TEXT NOT NULL,
|
|
1351
|
-
permalink TEXT NOT NULL,
|
|
1352
|
-
source TEXT NOT NULL,
|
|
1353
|
-
kind TEXT NOT NULL,
|
|
1354
|
-
status TEXT NOT NULL,
|
|
1355
|
-
author_name TEXT NOT NULL,
|
|
1356
|
-
author_url TEXT,
|
|
1357
|
-
author_email TEXT,
|
|
1358
|
-
markdown TEXT NOT NULL,
|
|
1359
|
-
html TEXT NOT NULL,
|
|
1360
|
-
submitted_at TEXT NOT NULL,
|
|
1361
|
-
address_hash TEXT,
|
|
1362
|
-
in_reply_to TEXT
|
|
1363
|
-
);
|
|
1364
|
-
|
|
1365
|
-
CREATE INDEX comments_slug ON comments (slug, submitted_at);
|
|
1366
|
-
CREATE INDEX comments_status ON comments (status, submitted_at);
|
|
1367
|
-
CREATE INDEX comments_author ON comments (author_name, author_email, status);
|
|
1368
|
-
`,
|
|
1369
|
-
},
|
|
1370
|
-
{
|
|
1371
|
-
// Webmentions (TASK-51), which are two different things and so two changes.
|
|
1372
|
-
//
|
|
1373
|
-
// A comment may now say where it lives, because a webmention lives on
|
|
1374
|
-
// somebody else's page: it is what a later webmention from that page is
|
|
1375
|
-
// recognised by, and what the thread's permalink points at for an entry
|
|
1376
|
-
// this site did not host. Its author may now have a face, out of the source
|
|
1377
|
-
// page's `h-card`. Both columns are an index of the comment files like
|
|
1378
|
-
// every other column of this table, so nothing backfills them — the rebuild
|
|
1379
|
-
// on the next boot does.
|
|
1380
|
-
//
|
|
1381
|
-
// What the site has sent is the other half, and it is a cache of outcomes
|
|
1382
|
-
// exactly as `ap_deliveries` is: no payload, one row per (post, target),
|
|
1383
|
-
// and a resend moves the row rather than adding to it. It is a table of
|
|
1384
|
-
// its own rather than a use of `ap_deliveries` because the federation
|
|
1385
|
-
// screen counts that table per activity, and a webmention is not one.
|
|
1386
|
-
version: 15,
|
|
1387
|
-
sql: `
|
|
1388
|
-
ALTER TABLE comments ADD COLUMN url TEXT;
|
|
1389
|
-
ALTER TABLE comments ADD COLUMN author_avatar TEXT;
|
|
1390
|
-
|
|
1391
|
-
CREATE TABLE webmentions_sent (
|
|
1392
|
-
slug TEXT NOT NULL,
|
|
1393
|
-
source TEXT NOT NULL,
|
|
1394
|
-
target TEXT NOT NULL,
|
|
1395
|
-
endpoint TEXT,
|
|
1396
|
-
status TEXT NOT NULL,
|
|
1397
|
-
error TEXT,
|
|
1398
|
-
attempted_at TEXT NOT NULL,
|
|
1399
|
-
PRIMARY KEY (slug, target)
|
|
1400
|
-
);
|
|
1401
|
-
|
|
1402
|
-
CREATE INDEX webmentions_sent_attempted_at ON webmentions_sent (attempted_at);
|
|
1403
|
-
`,
|
|
1404
|
-
},
|
|
1405
|
-
{
|
|
1406
|
-
// Password reset tokens (TASK-54). They sit beside the sessions, and for
|
|
1407
|
-
// the same reason: a reset link is a second, shorter-lived way of proving
|
|
1408
|
-
// you are somebody, and it is a cache — losing one costs the person
|
|
1409
|
-
// nothing but a second click on Forgot password. So `data/users.json`
|
|
1410
|
-
// stays the whole of what a site must back up, and a restart, a rebuild or
|
|
1411
|
-
// a `geekity rebuild` invalidates every link in flight, which is the safe
|
|
1412
|
-
// direction to fail in.
|
|
1413
|
-
//
|
|
1414
|
-
// The key is the token's SHA-256 rather than the token, so the database
|
|
1415
|
-
// holds nothing a working link could be rebuilt from: somebody who reads
|
|
1416
|
-
// this table — a backup, a stray copy of the file — learns that a reset
|
|
1417
|
-
// was asked for and nothing else. It is a plain hash rather than argon2
|
|
1418
|
-
// because the token is 256 random bits and there is no guess to slow down;
|
|
1419
|
-
// what argon2 buys on a password it cannot buy here.
|
|
1420
|
-
version: 16,
|
|
1421
|
-
sql: `
|
|
1422
|
-
CREATE TABLE password_resets (
|
|
1423
|
-
token_hash TEXT PRIMARY KEY,
|
|
1424
|
-
user_id INTEGER NOT NULL,
|
|
1425
|
-
created_at TEXT NOT NULL,
|
|
1426
|
-
expires_at TEXT NOT NULL
|
|
1427
|
-
);
|
|
1428
|
-
|
|
1429
|
-
CREATE INDEX password_resets_expires_at ON password_resets (expires_at);
|
|
1430
|
-
CREATE INDEX password_resets_user_id ON password_resets (user_id);
|
|
1431
|
-
`,
|
|
1432
|
-
},
|
|
1433
|
-
{
|
|
1434
|
-
// The two halves of a notification's one-click links (TASK-55).
|
|
1435
|
-
//
|
|
1436
|
-
// `spent_tokens` is what makes such a link single use. The link itself is
|
|
1437
|
-
// not stored — it is an HMAC-signed claim, so that a moderation link in an
|
|
1438
|
-
// inbox goes on working across a rebuilt or restored cache, which is a
|
|
1439
|
-
// thing decision-9 says a site may do whenever it likes. Only the fact
|
|
1440
|
-
// that one has been used is written down, keyed by its SHA-256 for the
|
|
1441
|
-
// reason `password_resets` is, and swept once the signature has expired.
|
|
1442
|
-
// Losing this table forgets which links were spent, and that costs a site
|
|
1443
|
-
// nothing: every action a link performs is idempotent, so doing it a
|
|
1444
|
-
// second time is doing it once.
|
|
1445
|
-
//
|
|
1446
|
-
// `comments.notify` is the commenter's "tell me about replies", which the
|
|
1447
|
-
// file says and this column indexes like every other column of that table.
|
|
1448
|
-
// Nothing backfills it: the rebuild on the next boot does, and a comment
|
|
1449
|
-
// written before this shipped never asked to be told.
|
|
1450
|
-
version: 17,
|
|
1451
|
-
sql: `
|
|
1452
|
-
CREATE TABLE spent_tokens (
|
|
1453
|
-
token_hash TEXT PRIMARY KEY,
|
|
1454
|
-
spent_at TEXT NOT NULL,
|
|
1455
|
-
expires_at TEXT NOT NULL
|
|
1456
|
-
);
|
|
1457
|
-
|
|
1458
|
-
CREATE INDEX spent_tokens_expires_at ON spent_tokens (expires_at);
|
|
1459
|
-
|
|
1460
|
-
ALTER TABLE comments ADD COLUMN notify INTEGER NOT NULL DEFAULT 0;
|
|
1461
|
-
`,
|
|
1462
|
-
},
|
|
1463
|
-
{
|
|
1464
|
-
// Followers belong to a user, and the inbox log says who was told
|
|
1465
|
-
// (decision-14, TASK-68). The site actor is gone, so there is nothing to
|
|
1466
|
-
// backfill: the `followers` table is rebuilt on every boot from the files
|
|
1467
|
-
// under `content/_data/federation/{username}/`, and the rows a site
|
|
1468
|
-
// carried for the site actor name nobody. The table is therefore dropped
|
|
1469
|
-
// and made again with the new key rather than altered — `actor_id` was its
|
|
1470
|
-
// primary key, and one actor may follow two of this site's users.
|
|
1471
|
-
version: 18,
|
|
1472
|
-
sql: `
|
|
1473
|
-
DROP TABLE followers;
|
|
1474
|
-
|
|
1475
|
-
CREATE TABLE followers (
|
|
1476
|
-
username TEXT NOT NULL,
|
|
1477
|
-
actor_id TEXT NOT NULL,
|
|
1478
|
-
inbox_id TEXT NOT NULL,
|
|
1479
|
-
shared_inbox_id TEXT,
|
|
1480
|
-
handle TEXT,
|
|
1481
|
-
name TEXT,
|
|
1482
|
-
icon_url TEXT,
|
|
1483
|
-
url TEXT,
|
|
1484
|
-
followed_at TEXT NOT NULL,
|
|
1485
|
-
PRIMARY KEY (username, actor_id)
|
|
1486
|
-
);
|
|
1487
|
-
|
|
1488
|
-
CREATE INDEX followers_followed_at ON followers (followed_at);
|
|
1489
|
-
CREATE INDEX followers_actor_id ON followers (actor_id);
|
|
1490
|
-
|
|
1491
|
-
ALTER TABLE ap_inbox ADD COLUMN recipient TEXT;
|
|
1492
|
-
|
|
1493
|
-
CREATE INDEX ap_inbox_recipient ON ap_inbox (recipient);
|
|
1494
|
-
`,
|
|
1495
|
-
},
|
|
1496
|
-
{
|
|
1497
|
-
// The avatar proxy asks, per request for a picture, whether its URL is one
|
|
1498
|
-
// the site has recorded (TASK-134). Both columns are indexed so that
|
|
1499
|
-
// question is a lookup rather than a scan of every follower and comment.
|
|
1500
|
-
version: 19,
|
|
1501
|
-
sql: `
|
|
1502
|
-
CREATE INDEX followers_icon_url ON followers (icon_url);
|
|
1503
|
-
CREATE INDEX comments_author_avatar ON comments (author_avatar);
|
|
1504
|
-
`,
|
|
1505
|
-
},
|
|
1506
|
-
{
|
|
1507
|
-
// What a comment has had removed for privacy (TASK-135), as the JSON list
|
|
1508
|
-
// its file carries. Nothing backfills it: the rebuild on the next boot
|
|
1509
|
-
// does, and a comment nothing was removed from leaves it `NULL`.
|
|
1510
|
-
version: 20,
|
|
1511
|
-
sql: `ALTER TABLE comments ADD COLUMN redacted TEXT;`,
|
|
1512
|
-
},
|
|
1513
|
-
{
|
|
1514
|
-
// The profiles of actors who are not followers (TASK-184): whoever liked,
|
|
1515
|
-
// boosted, answered or quoted a post, as their actor document named them.
|
|
1516
|
-
// A cache and nothing else (decision-9). Nothing backfills it here: the
|
|
1517
|
-
// profile sweep fetches every actor the inbox log names that has none.
|
|
1518
|
-
version: 21,
|
|
1519
|
-
sql: `
|
|
1520
|
-
CREATE TABLE actor_profiles (
|
|
1521
|
-
actor_id TEXT PRIMARY KEY,
|
|
1522
|
-
handle TEXT,
|
|
1523
|
-
name TEXT,
|
|
1524
|
-
icon_url TEXT,
|
|
1525
|
-
url TEXT,
|
|
1526
|
-
fetched_at TEXT NOT NULL
|
|
1527
|
-
);
|
|
1528
|
-
|
|
1529
|
-
CREATE INDEX actor_profiles_icon_url ON actor_profiles (icon_url);
|
|
1530
|
-
`,
|
|
1531
|
-
},
|
|
1532
|
-
{
|
|
1533
|
-
version: 22,
|
|
1534
|
-
sql: `ALTER TABLE comments ADD COLUMN rsvp TEXT;`,
|
|
1535
|
-
},
|
|
1536
|
-
{
|
|
1537
|
-
// What a \`/replies/\` key names (TASK-327), so resolving one is a lookup
|
|
1538
|
-
// rather than a walk of every comment and logged reply. A note's key is
|
|
1539
|
-
// its id's and is backfilled here; a native comment's hangs off the base
|
|
1540
|
-
// URL, which a migration does not know, so those rows are filled when the
|
|
1541
|
-
// store is opened with one, as they are whenever that base changes.
|
|
1542
|
-
version: 23,
|
|
1543
|
-
sql: `
|
|
1544
|
-
ALTER TABLE comments ADD COLUMN replies_key TEXT;
|
|
1545
|
-
ALTER TABLE comments ADD COLUMN keys_base TEXT;
|
|
1546
|
-
CREATE INDEX comments_replies_key ON comments (replies_key);
|
|
1547
|
-
ALTER TABLE ap_inbox ADD COLUMN reply_key TEXT;
|
|
1548
|
-
CREATE INDEX ap_inbox_reply_key ON ap_inbox (reply_key);
|
|
1549
|
-
`,
|
|
1550
|
-
run(db) {
|
|
1551
|
-
const rows = db.prepare('SELECT id, activity_type, object_id, json FROM ap_inbox').all();
|
|
1552
|
-
const update = db.prepare('UPDATE ap_inbox SET reply_key = ? WHERE id = ?');
|
|
1553
|
-
for (const row of rows) {
|
|
1554
|
-
const key = replyKeyOf({
|
|
1555
|
-
activityType: String(row['activity_type']),
|
|
1556
|
-
objectId: nullableText(row['object_id']),
|
|
1557
|
-
json: String(row['json']),
|
|
1558
|
-
});
|
|
1559
|
-
update.run(key, Number(row['id']));
|
|
1560
|
-
}
|
|
1561
|
-
},
|
|
1562
|
-
},
|
|
1563
|
-
{
|
|
1564
|
-
version: 24,
|
|
1565
|
-
sql: `ALTER TABLE comments ADD COLUMN via TEXT;`,
|
|
1566
|
-
},
|
|
1567
|
-
{
|
|
1568
|
-
version: 25,
|
|
1569
|
-
sql: `ALTER TABLE ap_inbox ADD COLUMN fetched INTEGER NOT NULL DEFAULT 0;`,
|
|
1570
|
-
},
|
|
1571
|
-
];
|
|
1572
|
-
/** What {@link AdminStore.onConversationWrite} hears about one logged activity. */
|
|
1573
|
-
function activityWrite(activity) {
|
|
1574
|
-
return {
|
|
1575
|
-
kind: 'activity',
|
|
1576
|
-
about: [activity.objectId, activity.inReplyTo].filter((id) => id !== null),
|
|
1577
|
-
};
|
|
1578
|
-
}
|
|
1579
|
-
/** The `/replies/` key of a logged reply's note, or `null` for anything else. */
|
|
1580
|
-
function replyKeyOf(activity) {
|
|
1581
|
-
const id = replyIdOf(activity);
|
|
1582
|
-
return id === null ? null : repliesKey(id);
|
|
1583
|
-
}
|
|
1584
|
-
/** A comment's `/replies/` key and the base it was worked out against, as columns. */
|
|
1585
|
-
function commentKey(comment, baseUrl) {
|
|
1586
|
-
return baseUrl === undefined ? [null, null] : [repliesKey(replyGuid(comment, baseUrl)), baseUrl];
|
|
1587
|
-
}
|
|
1588
|
-
//# sourceMappingURL=store.js.map
|