ghost 5.115.0 → 5.116.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/components/{tryghost-api-framework-5.115.0.tgz → tryghost-api-framework-5.116.0.tgz} +0 -0
- package/components/tryghost-constants-5.116.0.tgz +0 -0
- package/components/tryghost-custom-fonts-5.116.0.tgz +0 -0
- package/components/{tryghost-custom-theme-settings-service-5.115.0.tgz → tryghost-custom-theme-settings-service-5.116.0.tgz} +0 -0
- package/components/tryghost-domain-events-5.116.0.tgz +0 -0
- package/components/{tryghost-donations-5.115.0.tgz → tryghost-donations-5.116.0.tgz} +0 -0
- package/components/tryghost-email-addresses-5.116.0.tgz +0 -0
- package/components/tryghost-email-service-5.116.0.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.116.0.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.116.0.tgz +0 -0
- package/components/tryghost-i18n-5.116.0.tgz +0 -0
- package/components/tryghost-job-manager-5.116.0.tgz +0 -0
- package/components/tryghost-link-replacer-5.116.0.tgz +0 -0
- package/components/tryghost-magic-link-5.116.0.tgz +0 -0
- package/components/tryghost-member-attribution-5.116.0.tgz +0 -0
- package/components/tryghost-member-events-5.116.0.tgz +0 -0
- package/components/tryghost-members-api-5.116.0.tgz +0 -0
- package/components/tryghost-members-csv-5.116.0.tgz +0 -0
- package/components/{tryghost-members-offers-5.115.0.tgz → tryghost-members-offers-5.116.0.tgz} +0 -0
- package/components/{tryghost-milestones-5.115.0.tgz → tryghost-milestones-5.116.0.tgz} +0 -0
- package/components/{tryghost-mw-error-handler-5.115.0.tgz → tryghost-mw-error-handler-5.116.0.tgz} +0 -0
- package/components/tryghost-mw-vhost-5.116.0.tgz +0 -0
- package/components/{tryghost-post-events-5.115.0.tgz → tryghost-post-events-5.116.0.tgz} +0 -0
- package/components/{tryghost-post-revisions-5.115.0.tgz → tryghost-post-revisions-5.116.0.tgz} +0 -0
- package/components/tryghost-posts-service-5.116.0.tgz +0 -0
- package/components/{tryghost-prometheus-metrics-5.115.0.tgz → tryghost-prometheus-metrics-5.116.0.tgz} +0 -0
- package/components/tryghost-security-5.116.0.tgz +0 -0
- package/components/{tryghost-tiers-5.115.0.tgz → tryghost-tiers-5.116.0.tgz} +0 -0
- package/components/tryghost-webmentions-5.116.0.tgz +0 -0
- package/content/themes/casper/LICENSE +1 -1
- package/content/themes/casper/README.md +1 -1
- package/content/themes/source/LICENSE +1 -1
- package/content/themes/source/README.md +1 -1
- package/content/themes/source/assets/built/screen.css +1 -1
- package/content/themes/source/assets/built/screen.css.map +1 -1
- package/content/themes/source/assets/css/screen.css +11 -6
- package/content/themes/source/partials/feature-image.hbs +2 -2
- package/core/boot.js +3 -43
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +30494 -29403
- package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +1 -1
- package/core/built/admin/assets/admin-x-demo/{index-0040480a.mjs → index-a9601514.mjs} +5 -4
- package/core/built/admin/assets/admin-x-demo/{modals-fb35c86c.mjs → modals-c1789d04.mjs} +67 -65
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-806ef39c.mjs → CodeEditorView-e9c9deb8.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-376f847c.mjs → index-84580c3a.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-8fa19303.mjs → index-f744cab7.mjs} +3147 -3123
- package/core/built/admin/assets/admin-x-settings/{modals-36775d71.mjs → modals-d9ca60c5.mjs} +1198 -1192
- package/core/built/admin/assets/chunk.524.8371443ef8f60db429d0.js +35 -0
- package/core/built/admin/assets/chunk.582.f90151775f2e53dd21d9.js +37 -0
- package/core/built/admin/assets/{chunk.874.461cb3cf5b6b36915f8c.js → chunk.713.e9027c0cc3c56110f5da.js} +125 -98
- package/core/built/admin/assets/{ghost-938b3d9c29e3564a53a22f8c8f82d351.js → ghost-03b64c086f3c60cabc85fe7a7e2b640a.js} +272 -251
- package/core/built/admin/assets/ghost-ba58e9822f7384461e926c7e23f04a75.css +1 -0
- package/core/built/admin/assets/ghost-dark-f1f29683b14ffa11615b3bba8b6ab92c.css +1 -0
- package/core/built/admin/assets/koenig-lexical/index.css +1 -1
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +20563 -20891
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +139 -139
- package/core/built/admin/assets/posts/posts.js +5732 -5667
- package/core/built/admin/assets/stats/stats.js +75373 -0
- package/core/built/admin/assets/{vendor-68a4aa424a179a90f5bbc2b750def576.js → vendor-72026232b36d97babc6320917c16c321.js} +36 -34
- package/core/built/admin/index.html +6 -6
- package/core/cli/generate-data.js +1 -1
- package/core/frontend/helpers/ghost_head.js +8 -1
- package/core/frontend/public/ghost-stats.js +55 -2
- package/core/frontend/services/assets-minification/AdminAuthAssets.js +2 -1
- package/core/frontend/services/assets-minification/CardAssets.js +1 -1
- package/core/frontend/services/assets-minification/CommentCountsAssets.js +1 -1
- package/core/frontend/services/assets-minification/MemberAttributionAssets.js +1 -1
- package/core/frontend/services/assets-minification/Minifier.js +191 -0
- package/core/frontend/services/routing/controllers/previews.js +2 -1
- package/core/frontend/src/cards/css/cta.css +1 -1
- package/core/server/adapters/cache/Redis.js +1 -1
- package/core/server/adapters/lib/redis/AdapterCacheRedis.js +287 -0
- package/core/server/adapters/lib/redis/redis-store-factory.js +22 -0
- package/core/server/api/endpoints/posts.js +9 -3
- package/core/server/api/endpoints/previews.js +35 -1
- package/core/server/api/endpoints/slugs.js +6 -2
- package/core/server/api/endpoints/utils/serializers/output/utils/post-gating.js +6 -9
- package/core/server/api/endpoints/utils/validators/input/settings.js +1 -1
- package/core/server/data/db/connection.js +2 -0
- package/core/server/data/db/index.js +1 -0
- package/core/server/data/importer/handlers/ImporterContentFileHandler.js +90 -0
- package/core/server/data/importer/import-manager.js +3 -3
- package/core/server/data/importer/importers/importer-revue.js +128 -0
- package/core/server/data/importer/importers/json-to-html.js +107 -0
- package/core/server/data/migrations/utils/tables.js +2 -4
- package/core/server/data/seeders/DataGenerator.js +288 -0
- package/core/server/data/seeders/importers/BenefitsImporter.js +28 -0
- package/core/server/data/seeders/importers/CommentsImporter.js +73 -0
- package/core/server/data/seeders/importers/EmailBatchesImporter.js +38 -0
- package/core/server/data/seeders/importers/EmailRecipientFailuresImporter.js +67 -0
- package/core/server/data/seeders/importers/EmailRecipientsImporter.js +212 -0
- package/core/server/data/seeders/importers/EmailsImporter.js +99 -0
- package/core/server/data/seeders/importers/LabelsImporter.js +41 -0
- package/core/server/data/seeders/importers/MembersClickEventsImporter.js +69 -0
- package/core/server/data/seeders/importers/MembersCreatedEventsImporter.js +103 -0
- package/core/server/data/seeders/importers/MembersFeedbackImporter.js +45 -0
- package/core/server/data/seeders/importers/MembersImporter.js +111 -0
- package/core/server/data/seeders/importers/MembersLabelsImporter.js +39 -0
- package/core/server/data/seeders/importers/MembersLoginEventsImporter.js +69 -0
- package/core/server/data/seeders/importers/MembersNewslettersImporter.js +38 -0
- package/core/server/data/seeders/importers/MembersPaidSubscriptionEventsImporter.js +99 -0
- package/core/server/data/seeders/importers/MembersProductsImporter.js +42 -0
- package/core/server/data/seeders/importers/MembersStatusEventsImporter.js +58 -0
- package/core/server/data/seeders/importers/MembersStripeCustomersImporter.js +60 -0
- package/core/server/data/seeders/importers/MembersStripeCustomersSubscriptionsImporter.js +259 -0
- package/core/server/data/seeders/importers/MembersSubscribeEventsImporter.js +69 -0
- package/core/server/data/seeders/importers/MembersSubscriptionCreatedEventsImporter.js +95 -0
- package/core/server/data/seeders/importers/NewslettersImporter.js +40 -0
- package/core/server/data/seeders/importers/OffersImporter.js +70 -0
- package/core/server/data/seeders/importers/PostsAuthorsImporter.js +32 -0
- package/core/server/data/seeders/importers/PostsImporter.js +102 -0
- package/core/server/data/seeders/importers/PostsProductsImporter.js +35 -0
- package/core/server/data/seeders/importers/PostsTagsImporter.js +46 -0
- package/core/server/data/seeders/importers/ProductsBenefitsImporter.js +54 -0
- package/core/server/data/seeders/importers/ProductsImporter.js +90 -0
- package/core/server/data/seeders/importers/RecommendationClickEventsImporter.js +32 -0
- package/core/server/data/seeders/importers/RecommendationSubscribeEventsImporter.js +32 -0
- package/core/server/data/seeders/importers/RecommendationsImporter.js +34 -0
- package/core/server/data/seeders/importers/RedirectsImporter.js +49 -0
- package/core/server/data/seeders/importers/RolesUsersImporter.js +42 -0
- package/core/server/data/seeders/importers/StripePricesImporter.js +69 -0
- package/core/server/data/seeders/importers/StripeProductsImporter.js +34 -0
- package/core/server/data/seeders/importers/TableImporter.js +187 -0
- package/core/server/data/seeders/importers/TagsImporter.js +41 -0
- package/core/server/data/seeders/importers/UsersImporter.js +31 -0
- package/core/server/data/seeders/importers/WebMentionsImporter.js +42 -0
- package/core/server/data/seeders/importers/index.js +41 -0
- package/core/server/data/seeders/utils/JsonImporter.js +39 -0
- package/core/server/data/seeders/utils/blog-info.js +3 -0
- package/core/server/data/seeders/utils/database-date.js +7 -0
- package/core/server/data/seeders/utils/event-generator.js +48 -0
- package/core/server/data/seeders/utils/random.js +13 -0
- package/core/server/data/seeders/utils/topological-sort.js +33 -0
- package/core/server/lib/bootstrap-socket.js +87 -0
- package/core/server/lib/package-json/index.js +1 -0
- package/core/server/lib/package-json/package-json.js +160 -0
- package/core/server/lib/package-json/parse.js +57 -0
- package/core/server/models/base/plugins/actions.js +44 -31
- package/core/server/models/base/plugins/generate-slug.js +6 -0
- package/core/server/notify.js +1 -1
- package/core/server/services/activitypub/ActivityPubService.ts +1 -1
- package/core/server/services/adapter-manager/AdapterManager.js +161 -0
- package/core/server/services/adapter-manager/index.js +1 -1
- package/core/server/services/announcement-bar-service/AnnouncementBarSettings.js +54 -0
- package/core/server/services/announcement-bar-service/AnnouncementVisibilityValues.js +11 -0
- package/core/server/services/announcement-bar-service/index.js +1 -1
- package/core/server/services/api-version-compatibility/APIVersionCompatibilityService.js +99 -0
- package/core/server/services/api-version-compatibility/VersionNotificationsDataService.js +80 -0
- package/core/server/services/api-version-compatibility/extract-api-key.js +57 -0
- package/core/server/services/api-version-compatibility/index.js +2 -2
- package/core/server/services/api-version-compatibility/mw-api-version-mismatch.js +31 -0
- package/core/server/services/audience-feedback/AudienceFeedbackController.js +85 -0
- package/core/server/services/audience-feedback/AudienceFeedbackService.js +34 -0
- package/core/server/services/audience-feedback/Feedback.js +35 -0
- package/core/server/services/audience-feedback/index.js +4 -2
- package/core/server/services/auth/session/emails/signin.js +168 -0
- package/core/server/services/auth/session/index.js +2 -2
- package/core/server/services/auth/session/session-from-token.js +69 -0
- package/core/server/services/auth/session/session-service.js +374 -0
- package/core/server/services/custom-redirects/index.js +1 -1
- package/core/server/services/email-analytics/EmailAnalyticsProviderMailgun.js +62 -0
- package/core/server/services/email-analytics/EmailAnalyticsService.js +552 -0
- package/core/server/services/email-analytics/EmailAnalyticsServiceWrapper.js +3 -3
- package/core/server/services/email-analytics/EventProcessingResult.js +66 -0
- package/core/server/services/email-service/EmailServiceWrapper.js +4 -4
- package/core/server/services/email-suppression-list/MailgunEmailSuppressionList.js +1 -1
- package/core/server/services/email-suppression-list/service.js +1 -1
- package/core/server/services/explore-ping/ExplorePingService.js +106 -0
- package/core/server/services/explore-ping/index.js +31 -0
- package/core/server/services/identity-tokens/IdentityTokenService.js +30 -0
- package/core/server/services/identity-tokens/IdentityTokenService.ts +28 -0
- package/core/server/services/identity-tokens/IdentityTokenServiceWrapper.js +1 -1
- package/core/server/services/invitations/accept.js +5 -2
- package/core/server/services/lib/DynamicRedirectManager.js +156 -0
- package/core/server/services/lib/EmailContentGenerator.js +54 -0
- package/core/server/services/lib/InMemoryRepository.js +62 -0
- package/core/server/services/lib/InMemoryRepository.ts +80 -0
- package/core/server/services/lib/MailgunClient.js +364 -0
- package/core/server/services/link-redirection/LinkRedirect.js +26 -0
- package/core/server/services/link-redirection/LinkRedirectRepository.js +7 -7
- package/core/server/services/link-redirection/LinkRedirectsService.js +123 -0
- package/core/server/services/link-redirection/README.md +151 -0
- package/core/server/services/link-redirection/RedirectEvent.js +24 -0
- package/core/server/services/link-redirection/index.js +1 -1
- package/core/server/services/link-tracking/LinkClickTrackingService.js +1 -1
- package/core/server/services/mail/index.js +1 -1
- package/core/server/services/mail-events/BookshelfMailEventRepository.js +2 -2
- package/core/server/services/mail-events/InMemoryMailEventRepository.js +10 -0
- package/core/server/services/mail-events/InMemoryMailEventRepository.ts +8 -0
- package/core/server/services/mail-events/MailEvent.js +20 -0
- package/core/server/services/mail-events/MailEvent.ts +10 -0
- package/core/server/services/mail-events/MailEventRepository.js +2 -0
- package/core/server/services/mail-events/MailEventRepository.ts +5 -0
- package/core/server/services/mail-events/MailEventService.js +124 -0
- package/core/server/services/mail-events/MailEventService.ts +169 -0
- package/core/server/services/mail-events/index.js +1 -1
- package/core/server/services/mail-events/libraries.d.ts +2 -0
- package/core/server/services/members/CaptchaService.js +80 -0
- package/core/server/services/members/api.js +1 -1
- package/core/server/services/members/importer/MembersCSVImporter.js +464 -0
- package/core/server/services/members/importer/MembersCSVImporterStripeUtils.js +194 -0
- package/core/server/services/members/importer/email-template.js +182 -0
- package/core/server/services/members/importer/index.js +30 -0
- package/core/server/services/members/members-ssr.js +333 -0
- package/core/server/services/members/service.js +2 -2
- package/core/server/services/members-events/LastSeenAtUpdater.js +1 -1
- package/core/server/services/offers/service.js +1 -1
- package/core/server/services/posts/stats/PostStats.js +13 -0
- package/core/server/services/recommendations/RecommendationServiceWrapper.js +8 -8
- package/core/server/services/recommendations/service/BookshelfClickEventRepository.js +48 -0
- package/core/server/services/recommendations/service/BookshelfClickEventRepository.ts +49 -0
- package/core/server/services/recommendations/service/BookshelfRecommendationRepository.js +98 -0
- package/core/server/services/recommendations/service/BookshelfRecommendationRepository.ts +117 -0
- package/core/server/services/recommendations/service/BookshelfRepository.js +134 -0
- package/core/server/services/recommendations/service/BookshelfRepository.ts +196 -0
- package/core/server/services/recommendations/service/BookshelfSubscribeEventRepository.js +48 -0
- package/core/server/services/recommendations/service/BookshelfSubscribeEventRepository.ts +49 -0
- package/core/server/services/recommendations/service/ClickEvent.js +33 -0
- package/core/server/services/recommendations/service/ClickEvent.ts +32 -0
- package/core/server/services/recommendations/service/InMemoryRecommendationRepository.js +19 -0
- package/core/server/services/recommendations/service/InMemoryRecommendationRepository.ts +20 -0
- package/core/server/services/recommendations/service/IncomingRecommendationController.js +34 -0
- package/core/server/services/recommendations/service/IncomingRecommendationController.ts +51 -0
- package/core/server/services/recommendations/service/IncomingRecommendationEmailRenderer.js +25 -0
- package/core/server/services/recommendations/service/IncomingRecommendationEmailRenderer.ts +37 -0
- package/core/server/services/recommendations/service/IncomingRecommendationService.js +93 -0
- package/core/server/services/recommendations/service/IncomingRecommendationService.ts +160 -0
- package/core/server/services/recommendations/service/Recommendation.js +140 -0
- package/core/server/services/recommendations/service/Recommendation.ts +201 -0
- package/core/server/services/recommendations/service/RecommendationController.js +208 -0
- package/core/server/services/recommendations/service/RecommendationController.ts +258 -0
- package/core/server/services/recommendations/service/RecommendationMetadataService.js +86 -0
- package/core/server/services/recommendations/service/RecommendationMetadataService.ts +128 -0
- package/core/server/services/recommendations/service/RecommendationRepository.js +2 -0
- package/core/server/services/recommendations/service/RecommendationRepository.ts +13 -0
- package/core/server/services/recommendations/service/RecommendationService.js +228 -0
- package/core/server/services/recommendations/service/RecommendationService.ts +281 -0
- package/core/server/services/recommendations/service/SubscribeEvent.js +33 -0
- package/core/server/services/recommendations/service/SubscribeEvent.ts +32 -0
- package/core/server/services/recommendations/service/UnsafeData.js +183 -0
- package/core/server/services/recommendations/service/UnsafeData.ts +217 -0
- package/core/server/services/recommendations/service/WellknownService.js +36 -0
- package/core/server/services/recommendations/service/WellknownService.ts +47 -0
- package/core/server/services/recommendations/service/index.js +31 -0
- package/core/server/services/recommendations/service/index.ts +15 -0
- package/core/server/services/recommendations/service/libraries.d.ts +5 -0
- package/core/server/services/route-settings/SettingsPathManager.js +47 -0
- package/core/server/services/route-settings/index.js +1 -1
- package/core/server/services/slack-notifications/SlackNotifications.js +211 -0
- package/core/server/services/slack-notifications/SlackNotificationsService.js +90 -0
- package/core/server/services/slack-notifications/service.js +4 -6
- package/core/server/services/stripe/README.md +63 -0
- package/core/server/services/stripe/StripeAPI.js +931 -0
- package/core/server/services/stripe/StripeMigrations.js +613 -0
- package/core/server/services/stripe/StripeService.js +175 -0
- package/core/server/services/stripe/WebhookController.js +100 -0
- package/core/server/services/stripe/WebhookManager.js +175 -0
- package/core/server/services/stripe/events/StripeLiveDisabledEvent.js +23 -0
- package/core/server/services/stripe/events/StripeLiveEnabledEvent.js +23 -0
- package/core/server/services/stripe/events/index.js +4 -0
- package/core/server/services/stripe/service.js +1 -1
- package/core/server/services/stripe/services/webhook/CheckoutSessionEventService.js +255 -0
- package/core/server/services/stripe/services/webhook/InvoiceEventService.js +70 -0
- package/core/server/services/stripe/services/webhook/SubscriptionEventService.js +54 -0
- package/core/server/services/themes/loader.js +1 -1
- package/core/server/services/themes/to-json.js +1 -1
- package/core/server/web/api/endpoints/admin/app.js +1 -21
- package/core/server/web/api/endpoints/admin/routes.js +1 -0
- package/core/server/web/api/middleware/version-match.js +41 -0
- package/core/server/web/shared/middleware/cache-control.js +51 -0
- package/core/server/web/shared/middleware/index.js +1 -1
- package/core/server/web/well-known.js +1 -1
- package/core/shared/labs.js +5 -3
- package/core/shared/settings-cache/CacheManager.js +64 -6
- package/package.json +98 -146
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +1478 -1634
- package/components/tryghost-adapter-cache-redis-5.115.0.tgz +0 -0
- package/components/tryghost-adapter-manager-5.115.0.tgz +0 -0
- package/components/tryghost-announcement-bar-settings-5.115.0.tgz +0 -0
- package/components/tryghost-api-version-compatibility-service-5.115.0.tgz +0 -0
- package/components/tryghost-audience-feedback-5.115.0.tgz +0 -0
- package/components/tryghost-bookshelf-repository-5.115.0.tgz +0 -0
- package/components/tryghost-bootstrap-socket-5.115.0.tgz +0 -0
- package/components/tryghost-captcha-service-5.115.0.tgz +0 -0
- package/components/tryghost-constants-5.115.0.tgz +0 -0
- package/components/tryghost-custom-fonts-5.115.0.tgz +0 -0
- package/components/tryghost-data-generator-5.115.0.tgz +0 -0
- package/components/tryghost-domain-events-5.115.0.tgz +0 -0
- package/components/tryghost-email-addresses-5.115.0.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.115.0.tgz +0 -0
- package/components/tryghost-email-analytics-service-5.115.0.tgz +0 -0
- package/components/tryghost-email-content-generator-5.115.0.tgz +0 -0
- package/components/tryghost-email-events-5.115.0.tgz +0 -0
- package/components/tryghost-email-service-5.115.0.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.115.0.tgz +0 -0
- package/components/tryghost-express-dynamic-redirects-5.115.0.tgz +0 -0
- package/components/tryghost-extract-api-key-5.115.0.tgz +0 -0
- package/components/tryghost-ghost-5.115.0.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.115.0.tgz +0 -0
- package/components/tryghost-i18n-5.115.0.tgz +0 -0
- package/components/tryghost-identity-token-service-5.115.0.tgz +0 -0
- package/components/tryghost-importer-handler-content-files-5.115.0.tgz +0 -0
- package/components/tryghost-importer-revue-5.115.0.tgz +0 -0
- package/components/tryghost-in-memory-repository-5.115.0.tgz +0 -0
- package/components/tryghost-job-manager-5.115.0.tgz +0 -0
- package/components/tryghost-link-redirects-5.115.0.tgz +0 -0
- package/components/tryghost-link-replacer-5.115.0.tgz +0 -0
- package/components/tryghost-magic-link-5.115.0.tgz +0 -0
- package/components/tryghost-mail-events-5.115.0.tgz +0 -0
- package/components/tryghost-mailgun-client-5.115.0.tgz +0 -0
- package/components/tryghost-member-attribution-5.115.0.tgz +0 -0
- package/components/tryghost-member-events-5.115.0.tgz +0 -0
- package/components/tryghost-members-api-5.115.0.tgz +0 -0
- package/components/tryghost-members-csv-5.115.0.tgz +0 -0
- package/components/tryghost-members-importer-5.115.0.tgz +0 -0
- package/components/tryghost-members-payments-5.115.0.tgz +0 -0
- package/components/tryghost-members-ssr-5.115.0.tgz +0 -0
- package/components/tryghost-members-stripe-service-5.115.0.tgz +0 -0
- package/components/tryghost-minifier-5.115.0.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.115.0.tgz +0 -0
- package/components/tryghost-mw-cache-control-5.115.0.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.115.0.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.115.0.tgz +0 -0
- package/components/tryghost-mw-version-match-5.115.0.tgz +0 -0
- package/components/tryghost-mw-vhost-5.115.0.tgz +0 -0
- package/components/tryghost-package-json-5.115.0.tgz +0 -0
- package/components/tryghost-posts-service-5.115.0.tgz +0 -0
- package/components/tryghost-recommendations-5.115.0.tgz +0 -0
- package/components/tryghost-referrers-5.115.0.tgz +0 -0
- package/components/tryghost-security-5.115.0.tgz +0 -0
- package/components/tryghost-session-service-5.115.0.tgz +0 -0
- package/components/tryghost-settings-path-manager-5.115.0.tgz +0 -0
- package/components/tryghost-slack-notifications-5.115.0.tgz +0 -0
- package/components/tryghost-version-notifications-data-service-5.115.0.tgz +0 -0
- package/components/tryghost-webmentions-5.115.0.tgz +0 -0
- package/core/built/admin/assets/chunk.524.31419fdf6fb3859ecc1e.js +0 -35
- package/core/built/admin/assets/chunk.582.08c816d5e4ab766486a7.js +0 -37
- package/core/built/admin/assets/ghost-c2a7c4a1b76550c4219adb2ed4124ce0.css +0 -1
- package/core/built/admin/assets/ghost-dark-f91e4a479c6d38d94d5d1b14727871dc.css +0 -1
- /package/core/built/admin/assets/{chunk.874.461cb3cf5b6b36915f8c.js.LICENSE.txt → chunk.713.e9027c0cc3c56110f5da.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* # Package Utils
|
|
3
|
+
*
|
|
4
|
+
* Ghost has support for several different types of sub-packages:
|
|
5
|
+
* - Themes: have always been packages, but we're going to lean more heavily on npm & package.json in future
|
|
6
|
+
* - Adapters: replace fundamental pieces like storage, will become npm modules
|
|
7
|
+
*
|
|
8
|
+
* These utils facilitate loading, reading, managing etc, packages from the file system.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
const _ = require('lodash');
|
|
12
|
+
const fs = require('fs-extra');
|
|
13
|
+
const join = require('path').join;
|
|
14
|
+
const errors = require('@tryghost/errors');
|
|
15
|
+
const parse = require('./parse');
|
|
16
|
+
|
|
17
|
+
const notAPackageRegex = /^\.|_messages|README.md|node_modules|bower_components/i;
|
|
18
|
+
const packageJSONPath = 'package.json';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {object} PackageList
|
|
22
|
+
* @typedef {object} Package
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Recursively read directory and find the packages in it
|
|
27
|
+
*
|
|
28
|
+
* @param {string} absolutePath
|
|
29
|
+
* @param {string} packageName
|
|
30
|
+
* @returns {Promise<Package>}
|
|
31
|
+
*/
|
|
32
|
+
async function processPackage(absolutePath, packageName) {
|
|
33
|
+
const pkg = {
|
|
34
|
+
name: packageName,
|
|
35
|
+
path: absolutePath
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const packageJSON = await parse(join(absolutePath, packageJSONPath));
|
|
40
|
+
pkg['package.json'] = packageJSON;
|
|
41
|
+
} catch (err) {
|
|
42
|
+
// ignore invalid package.json for now,
|
|
43
|
+
// because Ghost does not rely/use them at the moment
|
|
44
|
+
// in the future, this .catch() will need to be removed,
|
|
45
|
+
// so that error is thrown on invalid json syntax
|
|
46
|
+
pkg['package.json'] = null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return pkg;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* ### Filter Packages
|
|
54
|
+
* Normalizes packages read by readPackages so that the themes module can use them.
|
|
55
|
+
* Iterates over each package and return an array of objects which are simplified representations of the package
|
|
56
|
+
* with 3 properties:
|
|
57
|
+
*
|
|
58
|
+
* @typedef {object} SimplePackage
|
|
59
|
+
* @prop {string} name - the package name
|
|
60
|
+
* @prop {object|boolean} package - contents of the package.json or false if there isn't one
|
|
61
|
+
* @prop {boolean} active - set to true if this package is active
|
|
62
|
+
*
|
|
63
|
+
* This data structure is used for listings of packages provided over the API and as such
|
|
64
|
+
* deliberately combines multiple sources of information in order to be efficient.
|
|
65
|
+
*
|
|
66
|
+
* TODO: simplify the package.json representation to contain only fields we use
|
|
67
|
+
*
|
|
68
|
+
* @param {PackageList} packages object made up of packages keyed by name as returned by readPackages
|
|
69
|
+
* @param {array|string} [active] optional set of names of packages that are active
|
|
70
|
+
* @returns {Array<SimplePackage>} array of objects with useful info about themes
|
|
71
|
+
*/
|
|
72
|
+
function filter(packages, active) {
|
|
73
|
+
// turn active into an array if it isn't one, so this function can deal with lists and one-offs
|
|
74
|
+
if (!Array.isArray(active)) {
|
|
75
|
+
active = [active];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return _.reduce(packages, function (result, pkg, key) {
|
|
79
|
+
let item = {};
|
|
80
|
+
if (!key.match(notAPackageRegex)) {
|
|
81
|
+
item = {
|
|
82
|
+
name: key,
|
|
83
|
+
package: pkg['package.json'] || false,
|
|
84
|
+
active: _.indexOf(active, key) !== -1
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
result.push(item);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return result;
|
|
91
|
+
}, []);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {string} packagePath
|
|
96
|
+
* @param {string} packageName
|
|
97
|
+
* @returns {Promise<Package>}
|
|
98
|
+
*/
|
|
99
|
+
async function readPackage(packagePath, packageName) {
|
|
100
|
+
const absolutePath = join(packagePath, packageName);
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const stat = await fs.stat(absolutePath);
|
|
104
|
+
if (!stat.isDirectory()) {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const pkg = await processPackage(absolutePath, packageName);
|
|
109
|
+
const res = {};
|
|
110
|
+
res[packageName] = pkg;
|
|
111
|
+
return res;
|
|
112
|
+
} catch (err) {
|
|
113
|
+
return Promise.reject(new errors.NotFoundError({
|
|
114
|
+
message: 'Package not found',
|
|
115
|
+
err: err,
|
|
116
|
+
help: 'path: ' + packagePath,
|
|
117
|
+
context: 'name: ' + packageName
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {string} packagePath
|
|
124
|
+
* @returns {Promise<PackageList>}
|
|
125
|
+
*/
|
|
126
|
+
async function readPackages(packagePath) {
|
|
127
|
+
const files = await fs.promises.readdir(packagePath, {withFileTypes: true});
|
|
128
|
+
const packages = await Promise.all(files.map(async (file) => {
|
|
129
|
+
// Filter out things which are not packages by regex
|
|
130
|
+
if (file.name.match(notAPackageRegex)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (file.isSymbolicLink()) {
|
|
135
|
+
try {
|
|
136
|
+
const packageFileOrig = await fs.stat(join(packagePath, file.name));
|
|
137
|
+
return packageFileOrig.isDirectory();
|
|
138
|
+
} catch (err) {
|
|
139
|
+
// if there's an error reading the symlink, we should just return false
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check the remaining items to ensure they are a directory
|
|
145
|
+
return file.isDirectory();
|
|
146
|
+
}))
|
|
147
|
+
.then(results => files.filter((_v, index) => results[index]))
|
|
148
|
+
.then(packageFiles => Promise.all(packageFiles.map((packageFile) => {
|
|
149
|
+
const absolutePath = join(packagePath, packageFile.name);
|
|
150
|
+
return processPackage(absolutePath, packageFile.name);
|
|
151
|
+
})));
|
|
152
|
+
|
|
153
|
+
return _.keyBy(packages, 'name');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
filter,
|
|
158
|
+
readPackage,
|
|
159
|
+
readPackages
|
|
160
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const errors = require('@tryghost/errors');
|
|
3
|
+
const tpl = require('@tryghost/tpl');
|
|
4
|
+
|
|
5
|
+
const messages = {
|
|
6
|
+
couldNotReadPackage: 'Could not read package.json file',
|
|
7
|
+
nameOrVersionMissing: '"name" or "version" is missing from theme package.json file.',
|
|
8
|
+
willBeRequired: 'This will be required in future. Please see {url}',
|
|
9
|
+
themeFileIsMalformed: 'Theme package.json file is malformed'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Parse package.json and validate it has
|
|
14
|
+
* all the required fields
|
|
15
|
+
*
|
|
16
|
+
* @param {string} path
|
|
17
|
+
* @returns {Promise<object>}
|
|
18
|
+
*/
|
|
19
|
+
async function parse(path) {
|
|
20
|
+
let source;
|
|
21
|
+
let json;
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
source = await fs.readFile(path, {encoding: 'utf8'});
|
|
25
|
+
} catch (readError) {
|
|
26
|
+
throw new errors.IncorrectUsageError({
|
|
27
|
+
message: tpl(messages.couldNotReadPackage),
|
|
28
|
+
context: path,
|
|
29
|
+
err: readError
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
json = JSON.parse(source);
|
|
35
|
+
} catch (parseError) {
|
|
36
|
+
throw new errors.IncorrectUsageError({
|
|
37
|
+
message: tpl(messages.themeFileIsMalformed),
|
|
38
|
+
context: path,
|
|
39
|
+
err: parseError,
|
|
40
|
+
help: tpl(messages.willBeRequired, {url: 'https://ghost.org/docs/themes/'})
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const hasRequiredKeys = json.name && json.version;
|
|
45
|
+
|
|
46
|
+
if (!hasRequiredKeys) {
|
|
47
|
+
throw new errors.IncorrectUsageError({
|
|
48
|
+
message: tpl(messages.nameOrVersionMissing),
|
|
49
|
+
context: path,
|
|
50
|
+
help: tpl(messages.willBeRequired, {url: 'https://ghost.org/docs/themes/'})
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return json;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = parse;
|
|
@@ -3,9 +3,20 @@ const errors = require('@tryghost/errors');
|
|
|
3
3
|
const logging = require('@tryghost/logging');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
+
* This plugin is used to add actions to the database. It backs the "audit log" feature we have in Ghost.
|
|
7
|
+
*
|
|
8
|
+
* The functions here are triggered by the `onCreated`, `onUpdated`, `onDeleted` functions in the `events`
|
|
9
|
+
* plugin, with some extra ones for niche other events.
|
|
10
|
+
*
|
|
6
11
|
* @param {import('bookshelf')} Bookshelf
|
|
7
12
|
*/
|
|
8
13
|
module.exports = function (Bookshelf) {
|
|
14
|
+
/**
|
|
15
|
+
* Insert an action into the database
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} data - The data to insert
|
|
18
|
+
* @param {Object} options - The options object
|
|
19
|
+
*/
|
|
9
20
|
const insertAction = (data, options) => {
|
|
10
21
|
// CASE: model does not support action for target event
|
|
11
22
|
if (!data) {
|
|
@@ -39,7 +50,13 @@ module.exports = function (Bookshelf) {
|
|
|
39
50
|
}
|
|
40
51
|
};
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Add an action to the database
|
|
55
|
+
*
|
|
56
|
+
* @param {import('bookshelf').Model} model - The model to add the action to
|
|
57
|
+
* @param {string} event - The event that triggered the action
|
|
58
|
+
* @param {Object} options - The options object
|
|
59
|
+
*/
|
|
43
60
|
const addAction = (model, event, options) => {
|
|
44
61
|
if (!model.wasChanged()) {
|
|
45
62
|
return;
|
|
@@ -58,11 +75,14 @@ module.exports = function (Bookshelf) {
|
|
|
58
75
|
/**
|
|
59
76
|
* Constructs data to be stored in the database with info
|
|
60
77
|
* on particular actions
|
|
78
|
+
*
|
|
79
|
+
* @param {string} event - The event that triggered the action
|
|
80
|
+
* @param {Object} options - The options object
|
|
81
|
+
* @returns {Object} The data to be stored in the database
|
|
61
82
|
*/
|
|
62
83
|
getAction(event, options) {
|
|
84
|
+
// Ignore internal updates (`options.context.internal`) for now
|
|
63
85
|
const actor = this.getActor(options);
|
|
64
|
-
|
|
65
|
-
// @NOTE: we ignore internal updates (`options.context.internal`) for now
|
|
66
86
|
if (!actor) {
|
|
67
87
|
return;
|
|
68
88
|
}
|
|
@@ -71,12 +91,7 @@ module.exports = function (Bookshelf) {
|
|
|
71
91
|
return;
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (typeof resourceType === 'function') {
|
|
77
|
-
resourceType = resourceType.bind(this)();
|
|
78
|
-
}
|
|
79
|
-
|
|
94
|
+
const resourceType = this.actionsResourceType;
|
|
80
95
|
if (!resourceType) {
|
|
81
96
|
return;
|
|
82
97
|
}
|
|
@@ -85,12 +100,14 @@ module.exports = function (Bookshelf) {
|
|
|
85
100
|
action_name: options.actionName
|
|
86
101
|
};
|
|
87
102
|
|
|
103
|
+
// Used to attach extra content to the action (ie. the key + group for settings changes)
|
|
88
104
|
if (this.actionsExtraContext && Array.isArray(this.actionsExtraContext)) {
|
|
89
105
|
for (const c of this.actionsExtraContext) {
|
|
90
106
|
context[c] = this.get(c) || this.previous(c);
|
|
91
107
|
}
|
|
92
108
|
}
|
|
93
109
|
|
|
110
|
+
// Attach the primary name to the action (ie. the title or name of the model)
|
|
94
111
|
if (event === 'deleted') {
|
|
95
112
|
context.primary_name = (this.previous('title') || this.previous('name'));
|
|
96
113
|
} else if (['added', 'edited'].includes(event)) {
|
|
@@ -112,21 +129,17 @@ module.exports = function (Bookshelf) {
|
|
|
112
129
|
return data;
|
|
113
130
|
},
|
|
114
131
|
|
|
115
|
-
/**
|
|
116
|
-
* @NOTE:
|
|
117
|
-
*
|
|
118
|
-
* We add actions step by step and define how they should look like.
|
|
119
|
-
* Each post update triggers a couple of events, which we don't want to add actions for.
|
|
120
|
-
*
|
|
121
|
-
* e.g. transform post to page triggers a handful of events including `post.deleted` and `page.added`
|
|
122
|
-
*
|
|
123
|
-
* We protect adding too many and uncontrolled events.
|
|
124
|
-
*
|
|
125
|
-
* We could embed adding actions more nicely in the future e.g. plugin.
|
|
126
|
-
*/
|
|
127
132
|
addAction
|
|
128
133
|
}, {
|
|
129
134
|
addAction,
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Add actions for bulk actions
|
|
138
|
+
*
|
|
139
|
+
* @param {string} event - The event that triggered the action
|
|
140
|
+
* @param {number[]} ids - The ids of the models that were affected
|
|
141
|
+
* @param {Object} options - The options object
|
|
142
|
+
*/
|
|
130
143
|
async addActions(event, ids, options) {
|
|
131
144
|
if (ids.length === 1) {
|
|
132
145
|
// We want to store an event for a single model in the actions table
|
|
@@ -141,27 +154,27 @@ module.exports = function (Bookshelf) {
|
|
|
141
154
|
},
|
|
142
155
|
|
|
143
156
|
/**
|
|
144
|
-
* Constructs data to be stored in the database
|
|
145
|
-
*
|
|
157
|
+
* Constructs data for bulk actions to be stored in the database
|
|
158
|
+
*
|
|
159
|
+
* @param {string} event - The event that triggered the action
|
|
160
|
+
* @param {number} count - The number of models that were affected
|
|
161
|
+
* @param {Object} options - The options object
|
|
162
|
+
* @returns {Object} The data to be stored in the database
|
|
146
163
|
*/
|
|
147
164
|
getBulkAction(event, count, options) {
|
|
165
|
+
// Ignore internal updates (`options.context.internal`) for now
|
|
148
166
|
const actor = this.prototype.getActor(options);
|
|
149
|
-
|
|
150
|
-
// @NOTE: we ignore internal updates (`options.context.internal`) for now
|
|
151
167
|
if (!actor) {
|
|
152
168
|
return;
|
|
153
169
|
}
|
|
154
170
|
|
|
171
|
+
// Models can opt-in to their CRUD actions being collected (we do this so we don't
|
|
172
|
+
// log every single action)
|
|
155
173
|
if (!this.prototype.actionsCollectCRUD) {
|
|
156
174
|
return;
|
|
157
175
|
}
|
|
158
176
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (typeof resourceType === 'function') {
|
|
162
|
-
resourceType = resourceType.bind(this)();
|
|
163
|
-
}
|
|
164
|
-
|
|
177
|
+
const resourceType = this.prototype.actionsResourceType;
|
|
165
178
|
if (!resourceType) {
|
|
166
179
|
return;
|
|
167
180
|
}
|
|
@@ -39,6 +39,12 @@ module.exports = function (Bookshelf) {
|
|
|
39
39
|
return slugToFind;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
if (options.modelId) {
|
|
43
|
+
if (found.id === options.modelId) {
|
|
44
|
+
return slugToFind;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
slugTryCount += 1;
|
|
43
49
|
|
|
44
50
|
// If we shortened, go back to the full version and try again
|
package/core/server/notify.js
CHANGED
|
@@ -51,7 +51,7 @@ async function notify(type, error = null) {
|
|
|
51
51
|
// CASE: use bootstrap socket to communicate with CLI for systemd
|
|
52
52
|
let socketAddress = config.get('bootstrap-socket');
|
|
53
53
|
if (socketAddress) {
|
|
54
|
-
const bootstrapSocket = require('
|
|
54
|
+
const bootstrapSocket = require('./lib/bootstrap-socket');
|
|
55
55
|
return bootstrapSocket.connectAndSend(socketAddress, message);
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ObjectID from 'bson-objectid';
|
|
2
2
|
import {Knex} from 'knex';
|
|
3
|
-
import {IdentityTokenService} from '
|
|
3
|
+
import {IdentityTokenService} from '../identity-tokens/IdentityTokenService';
|
|
4
4
|
import fetch from 'node-fetch';
|
|
5
5
|
|
|
6
6
|
type ExpectedWebhook = {
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const errors = require('@tryghost/errors');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef { function(new: Adapter, object) } AdapterConstructor
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} Adapter
|
|
10
|
+
* @prop {string[]} requiredFns
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
module.exports = class AdapterManager {
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} config
|
|
16
|
+
* @param {string[]} config.pathsToAdapters The paths to check, e.g. ['content/adapters', 'core/server/adapters']
|
|
17
|
+
* @param {(path: string) => AdapterConstructor} config.loadAdapterFromPath A function to load adapters, e.g. global.require
|
|
18
|
+
*/
|
|
19
|
+
constructor({pathsToAdapters, loadAdapterFromPath}) {
|
|
20
|
+
/**
|
|
21
|
+
* @private
|
|
22
|
+
* @type {Object.<string, AdapterConstructor>}
|
|
23
|
+
*/
|
|
24
|
+
this.baseClasses = {};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @private
|
|
28
|
+
* @type {Object.<string, Object.<string, Adapter>>}
|
|
29
|
+
*/
|
|
30
|
+
this.instanceCache = {};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @private
|
|
34
|
+
* @type {string[]}
|
|
35
|
+
*/
|
|
36
|
+
this.pathsToAdapters = pathsToAdapters;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @private
|
|
40
|
+
* @type {(path: string) => AdapterConstructor}
|
|
41
|
+
*/
|
|
42
|
+
this.loadAdapterFromPath = loadAdapterFromPath;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Register an adapter type and the corresponding base class. Must be called before requesting adapters of that type
|
|
47
|
+
*
|
|
48
|
+
* @param {string} type The name for the type of adapter
|
|
49
|
+
* @param {AdapterConstructor} BaseClass The class from which all adapters of this type must extend
|
|
50
|
+
*/
|
|
51
|
+
registerAdapter(type, BaseClass) {
|
|
52
|
+
this.instanceCache[type] = {};
|
|
53
|
+
this.baseClasses[type] = BaseClass;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Force recreation of all instances instead of reusing cached instances. Use when editing config file during tests.
|
|
58
|
+
*/
|
|
59
|
+
clearInstanceCache() {
|
|
60
|
+
for (const key of Object.keys(this.instanceCache)) {
|
|
61
|
+
this.instanceCache[key] = {};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* getAdapter
|
|
67
|
+
*
|
|
68
|
+
* @param {string} adapterName The name of the type of adapter, e.g. "storage" or "scheduling", optionally including the feature, e.g. "storage:files"
|
|
69
|
+
* @param {string} adapterClassName The active adapter instance class name e.g. "LocalFileStorage"
|
|
70
|
+
* @param {object} [config] The config the adapter could be instantiated with
|
|
71
|
+
*
|
|
72
|
+
* @returns {Adapter} The resolved and instantiated adapter
|
|
73
|
+
*/
|
|
74
|
+
getAdapter(adapterName, adapterClassName, config) {
|
|
75
|
+
if (!adapterName || !adapterClassName) {
|
|
76
|
+
throw new errors.IncorrectUsageError({
|
|
77
|
+
message: 'getAdapter must be called with a adapterName and a adapterClassName.'
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let adapterType;
|
|
82
|
+
if (adapterName.includes(':')) {
|
|
83
|
+
[adapterType] = adapterName.split(':');
|
|
84
|
+
} else {
|
|
85
|
+
adapterType = adapterName;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const adapterCache = this.instanceCache[adapterType];
|
|
89
|
+
|
|
90
|
+
if (!adapterCache) {
|
|
91
|
+
throw new errors.NotFoundError({
|
|
92
|
+
message: `Unknown adapter type ${adapterType}. Please register adapter.`
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// @NOTE: example cache key value 'email:newsletters:custom-newsletter-adapter'
|
|
97
|
+
const adapterCacheKey = `${adapterName}:${adapterClassName}`;
|
|
98
|
+
if (adapterCache[adapterCacheKey]) {
|
|
99
|
+
return adapterCache[adapterCacheKey];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** @type AdapterConstructor */
|
|
103
|
+
let Adapter;
|
|
104
|
+
for (const pathToAdapters of this.pathsToAdapters) {
|
|
105
|
+
const pathToAdapter = path.join(pathToAdapters, adapterType, adapterClassName);
|
|
106
|
+
try {
|
|
107
|
+
Adapter = this.loadAdapterFromPath(pathToAdapter);
|
|
108
|
+
if (Adapter) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
// Catch runtime errors
|
|
113
|
+
if (err.code !== 'MODULE_NOT_FOUND') {
|
|
114
|
+
throw new errors.IncorrectUsageError({err});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Catch missing dependencies BUT NOT missing adapter
|
|
118
|
+
if (!err.message.includes(pathToAdapter)) {
|
|
119
|
+
throw new errors.IncorrectUsageError({
|
|
120
|
+
message: `You are missing dependencies in your adapter ${pathToAdapter}`,
|
|
121
|
+
err
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!Adapter) {
|
|
128
|
+
throw new errors.IncorrectUsageError({
|
|
129
|
+
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${this.pathsToAdapters}.`
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const adapter = new Adapter(config);
|
|
134
|
+
|
|
135
|
+
if (!(adapter instanceof this.baseClasses[adapterType])) {
|
|
136
|
+
if (Object.getPrototypeOf(Adapter).name !== this.baseClasses[adapterType].name) {
|
|
137
|
+
throw new errors.IncorrectUsageError({
|
|
138
|
+
message: `${adapterType} adapter ${adapterClassName} does not inherit from the base class.`
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!adapter.requiredFns) {
|
|
144
|
+
throw new errors.IncorrectUsageError({
|
|
145
|
+
message: `${adapterType} adapter ${adapterClassName} does not have the requiredFns.`
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (const requiredFn of adapter.requiredFns) {
|
|
150
|
+
if (typeof adapter[requiredFn] !== 'function') {
|
|
151
|
+
throw new errors.IncorrectUsageError({
|
|
152
|
+
message: `${adapterType} adapter ${adapterClassName} is missing the ${requiredFn} method.`
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
adapterCache[adapterCacheKey] = adapter;
|
|
158
|
+
|
|
159
|
+
return adapter;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const AdapterManager = require('
|
|
1
|
+
const AdapterManager = require('./AdapterManager');
|
|
2
2
|
const getAdapterServiceConfig = require('./config');
|
|
3
3
|
const resolveAdapterOptions = require('./options-resolver');
|
|
4
4
|
const config = require('../../../shared/config');
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const AnnouncementVisibilityValues = require('./AnnouncementVisibilityValues');
|
|
2
|
+
|
|
3
|
+
class AnnouncementBarSettings {
|
|
4
|
+
#getAnnouncementSettings;
|
|
5
|
+
|
|
6
|
+
static VisibilityValues = AnnouncementVisibilityValues;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} deps
|
|
11
|
+
* @param {() => {announcement: string, announcement_visibility: string[], announcement_background: string}} deps.getAnnouncementSettings
|
|
12
|
+
*/
|
|
13
|
+
constructor(deps) {
|
|
14
|
+
this.#getAnnouncementSettings = deps.getAnnouncementSettings;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {Object} [member]
|
|
19
|
+
* @param {string} member.status
|
|
20
|
+
* @returns {{announcement: string, announcement_background: string}}
|
|
21
|
+
*/
|
|
22
|
+
getAnnouncementSettings(member) {
|
|
23
|
+
let announcement = undefined;
|
|
24
|
+
|
|
25
|
+
// NOTE: combination of 'free_members' & 'paid_members' makes just a 'members' filter
|
|
26
|
+
const announcementSettings = this.#getAnnouncementSettings();
|
|
27
|
+
|
|
28
|
+
if (announcementSettings.announcement) {
|
|
29
|
+
const visibilities = announcementSettings.announcement_visibility;
|
|
30
|
+
const announcementContent = announcementSettings.announcement;
|
|
31
|
+
|
|
32
|
+
if (visibilities.length === 0) {
|
|
33
|
+
announcement = undefined;
|
|
34
|
+
} else {
|
|
35
|
+
if (visibilities.includes(AnnouncementVisibilityValues.VISITORS) && !member) {
|
|
36
|
+
announcement = announcementContent;
|
|
37
|
+
} else if (visibilities.includes(AnnouncementVisibilityValues.FREE_MEMBERS) && (member?.status === 'free')) {
|
|
38
|
+
announcement = announcementContent;
|
|
39
|
+
} else if (visibilities.includes(AnnouncementVisibilityValues.PAID_MEMBERS) && (member && member.status !== 'free')) {
|
|
40
|
+
announcement = announcementContent;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (announcement !== undefined) {
|
|
46
|
+
return {
|
|
47
|
+
announcement,
|
|
48
|
+
announcement_background: announcementSettings.announcement_background
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = AnnouncementBarSettings;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Available visibilities:
|
|
2
|
+
// 'visitors' - anonymous visitors
|
|
3
|
+
// 'free_members' - free members
|
|
4
|
+
// 'paid_members' - paid members (aka non-free members)
|
|
5
|
+
class AnnouncementVisibilityValues {
|
|
6
|
+
static VISITORS = 'visitors';
|
|
7
|
+
static FREE_MEMBERS = 'free_members';
|
|
8
|
+
static PAID_MEMBERS = 'paid_members';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = AnnouncementVisibilityValues;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const settingsCache = require('../../../shared/settings-cache');
|
|
2
|
-
const AnnouncementBarSettings = require('
|
|
2
|
+
const AnnouncementBarSettings = require('./AnnouncementBarSettings');
|
|
3
3
|
|
|
4
4
|
const announcementBarService = new AnnouncementBarSettings({
|
|
5
5
|
getAnnouncementSettings: () => ({
|