ghost 5.115.1 → 5.116.1
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.1.tgz → tryghost-api-framework-5.116.1.tgz} +0 -0
- package/components/tryghost-constants-5.116.1.tgz +0 -0
- package/components/tryghost-custom-fonts-5.116.1.tgz +0 -0
- package/components/{tryghost-custom-theme-settings-service-5.115.1.tgz → tryghost-custom-theme-settings-service-5.116.1.tgz} +0 -0
- package/components/{tryghost-domain-events-5.115.1.tgz → tryghost-domain-events-5.116.1.tgz} +0 -0
- package/components/{tryghost-donations-5.115.1.tgz → tryghost-donations-5.116.1.tgz} +0 -0
- package/components/tryghost-email-addresses-5.116.1.tgz +0 -0
- package/components/tryghost-email-service-5.116.1.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.116.1.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.116.1.tgz +0 -0
- package/components/tryghost-i18n-5.116.1.tgz +0 -0
- package/components/tryghost-job-manager-5.116.1.tgz +0 -0
- package/components/tryghost-link-replacer-5.116.1.tgz +0 -0
- package/components/tryghost-magic-link-5.116.1.tgz +0 -0
- package/components/{tryghost-member-attribution-5.115.1.tgz → tryghost-member-attribution-5.116.1.tgz} +0 -0
- package/components/tryghost-member-events-5.116.1.tgz +0 -0
- package/components/tryghost-members-api-5.116.1.tgz +0 -0
- package/components/tryghost-members-csv-5.116.1.tgz +0 -0
- package/components/{tryghost-members-offers-5.115.1.tgz → tryghost-members-offers-5.116.1.tgz} +0 -0
- package/components/{tryghost-milestones-5.115.1.tgz → tryghost-milestones-5.116.1.tgz} +0 -0
- package/components/{tryghost-mw-error-handler-5.115.1.tgz → tryghost-mw-error-handler-5.116.1.tgz} +0 -0
- package/components/tryghost-mw-vhost-5.116.1.tgz +0 -0
- package/components/{tryghost-post-events-5.115.1.tgz → tryghost-post-events-5.116.1.tgz} +0 -0
- package/components/{tryghost-post-revisions-5.115.1.tgz → tryghost-post-revisions-5.116.1.tgz} +0 -0
- package/components/tryghost-posts-service-5.116.1.tgz +0 -0
- package/components/{tryghost-prometheus-metrics-5.115.1.tgz → tryghost-prometheus-metrics-5.116.1.tgz} +0 -0
- package/components/tryghost-security-5.116.1.tgz +0 -0
- package/components/{tryghost-tiers-5.115.1.tgz → tryghost-tiers-5.116.1.tgz} +0 -0
- package/components/tryghost-webmentions-5.116.1.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 +6 -11
- package/content/themes/source/partials/feature-image.hbs +2 -2
- package/core/boot.js +0 -42
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +24764 -24129
- package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +1 -1
- package/core/built/admin/assets/admin-x-demo/{index-15df2af5.mjs → index-a9601514.mjs} +3 -3
- package/core/built/admin/assets/admin-x-demo/{modals-8ca61d78.mjs → modals-c1789d04.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-d2e6872f.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-8e8821e5.mjs → index-84580c3a.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-f5cb3db3.mjs → index-f744cab7.mjs} +49 -35
- package/core/built/admin/assets/admin-x-settings/{modals-e8ae4d46.mjs → modals-d9ca60c5.mjs} +1198 -1192
- package/core/built/admin/assets/chunk.524.cb72a86e19c9ffd6172e.js +35 -0
- package/core/built/admin/assets/chunk.582.4f4d38ffe79fbdbd26f7.js +37 -0
- package/core/built/admin/assets/{chunk.874.461cb3cf5b6b36915f8c.js → chunk.713.e9027c0cc3c56110f5da.js} +125 -98
- package/core/built/admin/assets/{ghost-df7b9558260aa27d18b195ee895b487d.js → ghost-03b64c086f3c60cabc85fe7a7e2b640a.js} +144 -145
- 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 +71082 -7533
- 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 +6 -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/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/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 +1 -1
- 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/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 +1 -1
- package/core/server/services/auth/session/session-service.js +15 -5
- package/core/server/services/custom-redirects/index.js +1 -1
- package/core/server/services/email-analytics/EmailAnalyticsProviderMailgun.js +1 -1
- 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/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/InMemoryMailEventRepository.js +2 -2
- package/core/server/services/mail-events/InMemoryMailEventRepository.ts +1 -1
- package/core/server/services/members-events/LastSeenAtUpdater.js +1 -1
- package/core/server/services/offers/service.js +1 -1
- 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/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/web/api/endpoints/admin/app.js +1 -21
- package/core/server/web/api/middleware/version-match.js +41 -0
- package/core/shared/labs.js +2 -2
- package/package.json +87 -104
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +1470 -1540
- package/components/tryghost-adapter-cache-redis-5.115.1.tgz +0 -0
- package/components/tryghost-adapter-manager-5.115.1.tgz +0 -0
- package/components/tryghost-announcement-bar-settings-5.115.1.tgz +0 -0
- package/components/tryghost-constants-5.115.1.tgz +0 -0
- package/components/tryghost-custom-fonts-5.115.1.tgz +0 -0
- package/components/tryghost-data-generator-5.115.1.tgz +0 -0
- package/components/tryghost-email-addresses-5.115.1.tgz +0 -0
- package/components/tryghost-email-content-generator-5.115.1.tgz +0 -0
- package/components/tryghost-email-events-5.115.1.tgz +0 -0
- package/components/tryghost-email-service-5.115.1.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.115.1.tgz +0 -0
- package/components/tryghost-express-dynamic-redirects-5.115.1.tgz +0 -0
- package/components/tryghost-ghost-5.115.1.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.115.1.tgz +0 -0
- package/components/tryghost-i18n-5.115.1.tgz +0 -0
- package/components/tryghost-importer-handler-content-files-5.115.1.tgz +0 -0
- package/components/tryghost-in-memory-repository-5.115.1.tgz +0 -0
- package/components/tryghost-job-manager-5.115.1.tgz +0 -0
- package/components/tryghost-link-redirects-5.115.1.tgz +0 -0
- package/components/tryghost-link-replacer-5.115.1.tgz +0 -0
- package/components/tryghost-magic-link-5.115.1.tgz +0 -0
- package/components/tryghost-mailgun-client-5.115.1.tgz +0 -0
- package/components/tryghost-member-events-5.115.1.tgz +0 -0
- package/components/tryghost-members-api-5.115.1.tgz +0 -0
- package/components/tryghost-members-csv-5.115.1.tgz +0 -0
- package/components/tryghost-members-payments-5.115.1.tgz +0 -0
- package/components/tryghost-minifier-5.115.1.tgz +0 -0
- package/components/tryghost-mw-version-match-5.115.1.tgz +0 -0
- package/components/tryghost-mw-vhost-5.115.1.tgz +0 -0
- package/components/tryghost-posts-service-5.115.1.tgz +0 -0
- package/components/tryghost-recommendations-5.115.1.tgz +0 -0
- package/components/tryghost-security-5.115.1.tgz +0 -0
- package/components/tryghost-slack-notifications-5.115.1.tgz +0 -0
- package/components/tryghost-webmentions-5.115.1.tgz +0 -0
- package/core/built/admin/assets/chunk.524.2439684964c164c598ab.js +0 -35
- package/core/built/admin/assets/chunk.582.bf5a2bbb2c4eb69ef1e7.js +0 -37
- package/core/built/admin/assets/ghost-327b17ea23cb8c89bd7e6a51e18e8506.css +0 -1
- package/core/built/admin/assets/ghost-dark-f30a597ac19632a118939492591c531b.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,32 @@
|
|
|
1
|
+
const TableImporter = require('./TableImporter');
|
|
2
|
+
const {faker} = require('@faker-js/faker');
|
|
3
|
+
const {luck} = require('../utils/random');
|
|
4
|
+
|
|
5
|
+
class RecommendationSubscribeEventsImporter extends TableImporter {
|
|
6
|
+
static table = 'recommendation_subscribe_events';
|
|
7
|
+
static dependencies = ['recommendations', 'members'];
|
|
8
|
+
|
|
9
|
+
constructor(knex, transaction) {
|
|
10
|
+
super(RecommendationSubscribeEventsImporter.table, knex, transaction);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async import(quantity) {
|
|
14
|
+
const recommendations = await this.transaction.select('id', 'created_at').from('recommendations').where('one_click_subscribe', true);
|
|
15
|
+
this.members = await this.transaction.select('id').from('members').limit(500);
|
|
16
|
+
|
|
17
|
+
await this.importForEach(recommendations, quantity ? quantity / recommendations.length : () => faker.datatype.number({min: 0, max: 50}));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
generate() {
|
|
21
|
+
// Not unique
|
|
22
|
+
const member = luck(1) ? null : faker.helpers.arrayElement(this.members);
|
|
23
|
+
return {
|
|
24
|
+
id: this.fastFakeObjectId(),
|
|
25
|
+
recommendation_id: this.model.id,
|
|
26
|
+
member_id: member?.id ?? null,
|
|
27
|
+
created_at: faker.date.past()
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = RecommendationSubscribeEventsImporter;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const TableImporter = require('./TableImporter');
|
|
2
|
+
const {faker} = require('@faker-js/faker');
|
|
3
|
+
|
|
4
|
+
function capitalize(str) {
|
|
5
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class RecommendationsImporter extends TableImporter {
|
|
9
|
+
static table = 'recommendations';
|
|
10
|
+
static dependencies = [];
|
|
11
|
+
defaultQuantity = 15;
|
|
12
|
+
|
|
13
|
+
constructor(knex, transaction) {
|
|
14
|
+
super(RecommendationsImporter.table, knex, transaction);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
generate() {
|
|
18
|
+
const id = this.fastFakeObjectId();
|
|
19
|
+
return {
|
|
20
|
+
id,
|
|
21
|
+
url: faker.internet.url(),
|
|
22
|
+
title: capitalize(`${faker.word.adjective()} ${faker.word.noun()}`),
|
|
23
|
+
excerpt: faker.lorem.sentence(),
|
|
24
|
+
featured_image: `https://api.dicebear.com/5.x/shapes/png?size=256&seed=${id}`,
|
|
25
|
+
favicon: `https://api.dicebear.com/5.x/shapes/png?size=32&seed=${id}`,
|
|
26
|
+
description: faker.lorem.sentence(),
|
|
27
|
+
one_click_subscribe: faker.datatype.boolean(),
|
|
28
|
+
created_at: faker.date.past(),
|
|
29
|
+
updated_at: faker.date.past()
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = RecommendationsImporter;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const TableImporter = require('./TableImporter');
|
|
2
|
+
const {faker} = require('@faker-js/faker');
|
|
3
|
+
|
|
4
|
+
class RedirectsImporter extends TableImporter {
|
|
5
|
+
static table = 'redirects';
|
|
6
|
+
static dependencies = ['posts'];
|
|
7
|
+
|
|
8
|
+
constructor(knex, transaction) {
|
|
9
|
+
super(RedirectsImporter.table, knex, transaction);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async import(quantity) {
|
|
13
|
+
const posts = await this.transaction
|
|
14
|
+
.select('id', 'published_at')
|
|
15
|
+
.from('posts')
|
|
16
|
+
.where('type', 'post')
|
|
17
|
+
.andWhere('status', 'published');
|
|
18
|
+
|
|
19
|
+
this.quantity = quantity ? quantity / posts.length : 10;
|
|
20
|
+
await this.importForEach(posts, this.quantity);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setReferencedModel(model) {
|
|
24
|
+
this.model = model;
|
|
25
|
+
|
|
26
|
+
// Reset the amount for each model
|
|
27
|
+
this.amount = faker.datatype.number({
|
|
28
|
+
min: 0,
|
|
29
|
+
max: this.quantity
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
generate() {
|
|
34
|
+
if (this.amount <= 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
this.amount -= 1;
|
|
38
|
+
return {
|
|
39
|
+
id: this.fastFakeObjectId(),
|
|
40
|
+
from: `/r/${faker.datatype.hexadecimal({length: 8, prefix: '', case: 'lower'})}`,
|
|
41
|
+
to: `${faker.internet.url()}/${faker.helpers.slugify(`${faker.word.adjective()} ${faker.word.noun()}`).toLowerCase()}`,
|
|
42
|
+
post_id: this.model.id,
|
|
43
|
+
created_at: this.model.published_at,
|
|
44
|
+
updated_at: this.model.published_at
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = RedirectsImporter;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const {faker} = require('@faker-js/faker');
|
|
2
|
+
const TableImporter = require('./TableImporter');
|
|
3
|
+
|
|
4
|
+
class RolesUsersImporter extends TableImporter {
|
|
5
|
+
static table = 'roles_users';
|
|
6
|
+
// No roles imorter, since roles are statically defined in database
|
|
7
|
+
static dependencies = ['users'];
|
|
8
|
+
|
|
9
|
+
constructor(knex, transaction) {
|
|
10
|
+
super(RolesUsersImporter.table, knex, transaction);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Ignore overriden quantity for 1:1 relationship
|
|
15
|
+
*/
|
|
16
|
+
async import() {
|
|
17
|
+
const users = await this.transaction.select('id').from('users').whereNot('id', 1);
|
|
18
|
+
this.roles = await this.transaction.select('id', 'name').from('roles');
|
|
19
|
+
|
|
20
|
+
await this.importForEach(users, 1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
generate() {
|
|
24
|
+
const userRoles = ['Editor', 'Contributor', 'Author'];
|
|
25
|
+
const userRole = userRoles[faker.datatype.number({
|
|
26
|
+
min: 0,
|
|
27
|
+
max: userRoles.length - 1
|
|
28
|
+
})];
|
|
29
|
+
const actualRole = this.roles.find(role => role.name === userRole);
|
|
30
|
+
if (!actualRole) {
|
|
31
|
+
// No roles defined in database, don't bother creating user role
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
id: this.fastFakeObjectId(),
|
|
36
|
+
role_id: actualRole.id,
|
|
37
|
+
user_id: this.model.id
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = RolesUsersImporter;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const {faker} = require('@faker-js/faker');
|
|
2
|
+
const TableImporter = require('./TableImporter');
|
|
3
|
+
const {blogStartDate} = require('../utils/blog-info');
|
|
4
|
+
|
|
5
|
+
const sixWeeksLater = new Date(blogStartDate);
|
|
6
|
+
sixWeeksLater.setDate(sixWeeksLater.getDate() + (7 * 6));
|
|
7
|
+
|
|
8
|
+
class StripePricesImporter extends TableImporter {
|
|
9
|
+
static table = 'stripe_prices';
|
|
10
|
+
static dependencies = ['products', 'stripe_products'];
|
|
11
|
+
|
|
12
|
+
constructor(knex, transaction) {
|
|
13
|
+
super(StripePricesImporter.table, knex, transaction);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async import() {
|
|
17
|
+
const stripeProducts = await this.transaction.select('id', 'stripe_product_id', 'product_id').from('stripe_products');
|
|
18
|
+
this.products = await this.transaction.select('id', 'monthly_price', 'yearly_price').from('products');
|
|
19
|
+
|
|
20
|
+
await this.importForEach(stripeProducts, 2);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setReferencedModel(model) {
|
|
24
|
+
this.model = model;
|
|
25
|
+
this.count = 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
generate() {
|
|
29
|
+
const count = this.count;
|
|
30
|
+
this.count = this.count + 1;
|
|
31
|
+
|
|
32
|
+
const relatedProduct = this.products.find(product => product.id === this.model.product_id);
|
|
33
|
+
|
|
34
|
+
if (count === 1 && relatedProduct.monthly_price === null) {
|
|
35
|
+
// Only single complimentary price (yearly)
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const billingCycle = {
|
|
40
|
+
nickname: 'Monthly',
|
|
41
|
+
interval: 'month',
|
|
42
|
+
type: 'recurring',
|
|
43
|
+
currency: 'usd',
|
|
44
|
+
amount: relatedProduct.monthly_price
|
|
45
|
+
};
|
|
46
|
+
if (count === 1) {
|
|
47
|
+
billingCycle.nickname = 'Yearly';
|
|
48
|
+
billingCycle.interval = 'year';
|
|
49
|
+
billingCycle.amount = relatedProduct.yearly_price;
|
|
50
|
+
} else if (relatedProduct.monthly_price === null) {
|
|
51
|
+
billingCycle.nickname = 'Complimentary';
|
|
52
|
+
billingCycle.interval = 'year';
|
|
53
|
+
billingCycle.amount = 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Object.assign({}, {
|
|
57
|
+
id: this.fastFakeObjectId(),
|
|
58
|
+
stripe_price_id: faker.datatype.hexadecimal({
|
|
59
|
+
length: 64,
|
|
60
|
+
prefix: ''
|
|
61
|
+
}),
|
|
62
|
+
stripe_product_id: this.model.stripe_product_id,
|
|
63
|
+
active: true,
|
|
64
|
+
created_at: faker.date.between(blogStartDate, sixWeeksLater)
|
|
65
|
+
}, billingCycle);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = StripePricesImporter;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const {faker} = require('@faker-js/faker');
|
|
2
|
+
const TableImporter = require('./TableImporter');
|
|
3
|
+
const {blogStartDate} = require('../utils/blog-info');
|
|
4
|
+
|
|
5
|
+
const sixWeeksLater = new Date(blogStartDate);
|
|
6
|
+
sixWeeksLater.setDate(sixWeeksLater.getDate() + (7 * 6));
|
|
7
|
+
|
|
8
|
+
class StripeProductsImporter extends TableImporter {
|
|
9
|
+
static table = 'stripe_products';
|
|
10
|
+
static dependencies = ['products'];
|
|
11
|
+
|
|
12
|
+
constructor(knex, transaction) {
|
|
13
|
+
super(StripeProductsImporter.table, knex, transaction);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async import() {
|
|
17
|
+
const products = await this.transaction.select('id').from('products');
|
|
18
|
+
await this.importForEach(products, 1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
generate() {
|
|
22
|
+
return {
|
|
23
|
+
id: this.fastFakeObjectId(),
|
|
24
|
+
product_id: this.model.id,
|
|
25
|
+
stripe_product_id: faker.datatype.hexadecimal({
|
|
26
|
+
length: 64,
|
|
27
|
+
prefix: ''
|
|
28
|
+
}),
|
|
29
|
+
created_at: faker.date.between(blogStartDate, sixWeeksLater)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = StripeProductsImporter;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
const debug = require('@tryghost/debug')('TableImporter');
|
|
2
|
+
const dateToDatabaseString = require('../utils/database-date');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const {luck} = require('../utils/random');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
const logging = require('@tryghost/logging');
|
|
10
|
+
const errors = require('@tryghost/errors');
|
|
11
|
+
|
|
12
|
+
class TableImporter {
|
|
13
|
+
/**
|
|
14
|
+
* @type {object|undefined} model Referenced model when generating data
|
|
15
|
+
*/
|
|
16
|
+
model;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {number|undefined} defaultQuantity Default number of records to import
|
|
20
|
+
*/
|
|
21
|
+
defaultQuantity;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Transaction and knex need to be separate since we're using the batchInsert helper
|
|
25
|
+
* @param {string} name Name of the table to be generated
|
|
26
|
+
* @param {import('knex/types').Knex} knex Database connection
|
|
27
|
+
* @param {import('knex/types').Knex.Transaction} transaction Transaction to be used for import
|
|
28
|
+
*/
|
|
29
|
+
constructor(name, knex, transaction) {
|
|
30
|
+
this.name = name;
|
|
31
|
+
this.knex = knex;
|
|
32
|
+
this.transaction = transaction;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fastFakeObjectId() {
|
|
36
|
+
// It is important that IDs are generated for a timestamp < NOW (for email batch sending) and that
|
|
37
|
+
// generating the ids is fast.
|
|
38
|
+
return `00000000` + crypto.randomBytes(8).toString('hex');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async #generateData(amount = this.defaultQuantity) {
|
|
42
|
+
let data = [];
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < amount; i++) {
|
|
45
|
+
const model = await this.generate();
|
|
46
|
+
if (model) {
|
|
47
|
+
data.push(model);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async import(amount = this.defaultQuantity) {
|
|
55
|
+
const generateNow = Date.now();
|
|
56
|
+
const data = await this.#generateData(amount);
|
|
57
|
+
debug(`${this.name} generated ${data.length} records in ${Date.now() - generateNow}ms`);
|
|
58
|
+
|
|
59
|
+
if (data.length > 0) {
|
|
60
|
+
await this.batchInsert(data);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {Array<Object>} models List of models to reference
|
|
66
|
+
* @param {Number|function} amount Number of records to import per model
|
|
67
|
+
*/
|
|
68
|
+
async importForEach(models = [], amount) {
|
|
69
|
+
const data = [];
|
|
70
|
+
|
|
71
|
+
debug (`Generating data for ${models.length} models x ${amount} for ${this.name}`);
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
let settingReferenceModel = 0;
|
|
74
|
+
|
|
75
|
+
for (const model of models) {
|
|
76
|
+
let s = Date.now();
|
|
77
|
+
this.setReferencedModel(model);
|
|
78
|
+
settingReferenceModel += Date.now() - s;
|
|
79
|
+
|
|
80
|
+
let currentAmount = (typeof amount === 'function') ? amount() : amount;
|
|
81
|
+
if (!Number.isInteger(currentAmount)) {
|
|
82
|
+
currentAmount = Math.floor(currentAmount) + luck((currentAmount % 1) * 100);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const generatedData = await this.#generateData(currentAmount);
|
|
86
|
+
if (generatedData.length > 0) {
|
|
87
|
+
data.push(...generatedData);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
debug(`${this.name} generated ${data.length} records in ${Date.now() - now}ms (${settingReferenceModel}ms setting reference model)`);
|
|
92
|
+
|
|
93
|
+
if (data.length > 0) {
|
|
94
|
+
await this.batchInsert(data);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async batchInsert(data) {
|
|
99
|
+
// Write to CSV file
|
|
100
|
+
const rootFolder = os.tmpdir();
|
|
101
|
+
const filePath = path.join(rootFolder, `${this.name}.csv`);
|
|
102
|
+
let now = Date.now();
|
|
103
|
+
|
|
104
|
+
if (data.length > 5000 && !process.env.DISABLE_FAST_IMPORT) {
|
|
105
|
+
try {
|
|
106
|
+
await fs.promises.unlink(filePath);
|
|
107
|
+
} catch (e) {
|
|
108
|
+
// Ignore: file doesn't exist
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const csvWriter = createCsvWriter({
|
|
112
|
+
path: filePath,
|
|
113
|
+
header: Object.keys(data[0]).map((key) => {
|
|
114
|
+
return {id: key, title: key};
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Loop the data in chunks of 50.000 items
|
|
119
|
+
const batchSize = 50000;
|
|
120
|
+
|
|
121
|
+
// Otherwise we get a out of range error because csvWriter tries to create a string that is too long
|
|
122
|
+
for (let i = 0; i < data.length; i += batchSize) {
|
|
123
|
+
const slicedData = data.slice(i, i + batchSize);
|
|
124
|
+
|
|
125
|
+
// Map data to what MySQL expects in the CSV for values like booleans, null and dates
|
|
126
|
+
for (let j = 0; j < slicedData.length; j++) {
|
|
127
|
+
const obj = slicedData[j];
|
|
128
|
+
|
|
129
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
130
|
+
if (typeof value === 'boolean') {
|
|
131
|
+
obj[key] = value ? 1 : 0;
|
|
132
|
+
} else if (value instanceof Date) {
|
|
133
|
+
obj[key] = dateToDatabaseString(value);
|
|
134
|
+
} else if (value === null) {
|
|
135
|
+
obj[key] = '\\N';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
await csvWriter.writeRecords(slicedData);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
debug(`${this.name} saved CSV import file in ${Date.now() - now}ms`);
|
|
143
|
+
now = Date.now();
|
|
144
|
+
|
|
145
|
+
// Import from CSV file
|
|
146
|
+
const [result] = await this.transaction.raw(`LOAD DATA LOCAL INFILE '${filePath}' INTO TABLE \`${this.name}\` FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 LINES (${Object.keys(data[0]).map(d => '`' + d + '`').join(',')});`);
|
|
147
|
+
if (result.affectedRows !== data.length) {
|
|
148
|
+
if (Math.abs(result.affectedRows - data.length) > 0.01 * data.length) {
|
|
149
|
+
throw new errors.InternalServerError({
|
|
150
|
+
message: `CSV import failed: expected ${data.length} imported rows, got ${result.affectedRows}`
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
logging.warn(`CSV import warning: expected ${data.length} imported rows, got ${result.affectedRows}.`);
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
await this.knex.batchInsert(this.name, data).transacting(this.transaction);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
debug(`${this.name} imported ${data.length} records in ${Date.now() - now}ms`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Finalise the imported data, e.g. adding summary records based on a table's dependents
|
|
164
|
+
*/
|
|
165
|
+
async finalise() {
|
|
166
|
+
// No-op by default
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Sets the model which newly generated data will reference
|
|
171
|
+
* @param {Object} model Model to reference when generating data
|
|
172
|
+
*/
|
|
173
|
+
setReferencedModel(model) {
|
|
174
|
+
this.model = model;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Generates the data for a single model to be imported
|
|
179
|
+
* @returns {Object|null} Data to import, optional
|
|
180
|
+
*/
|
|
181
|
+
generate() {
|
|
182
|
+
// Should never be called
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = TableImporter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const {faker} = require('@faker-js/faker');
|
|
2
|
+
const {slugify} = require('@tryghost/string');
|
|
3
|
+
const TableImporter = require('./TableImporter');
|
|
4
|
+
const dateToDatabaseString = require('../utils/database-date');
|
|
5
|
+
|
|
6
|
+
class TagsImporter extends TableImporter {
|
|
7
|
+
static table = 'tags';
|
|
8
|
+
static dependencies = ['users'];
|
|
9
|
+
defaultQuantity = faker.datatype.number({
|
|
10
|
+
min: 16,
|
|
11
|
+
max: 24
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
constructor(knex, transaction) {
|
|
15
|
+
super(TagsImporter.table, knex, transaction);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async import(quantity = this.defaultQuantity) {
|
|
19
|
+
this.users = await this.transaction.select('id').from('users');
|
|
20
|
+
await super.import(quantity);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
generate() {
|
|
24
|
+
let name = `${faker.color.human()} ${faker.name.jobType()}`;
|
|
25
|
+
name = `${name[0].toUpperCase()}${name.slice(1)}`;
|
|
26
|
+
const threeYearsAgo = new Date();
|
|
27
|
+
threeYearsAgo.setFullYear(threeYearsAgo.getFullYear() - 3);
|
|
28
|
+
const twoYearsAgo = new Date();
|
|
29
|
+
twoYearsAgo.setFullYear(twoYearsAgo.getFullYear() - 2);
|
|
30
|
+
return {
|
|
31
|
+
id: this.fastFakeObjectId(),
|
|
32
|
+
name: name,
|
|
33
|
+
slug: `${slugify(name)}-${faker.random.numeric(3)}`,
|
|
34
|
+
description: faker.lorem.sentence(),
|
|
35
|
+
created_at: dateToDatabaseString(faker.date.between(threeYearsAgo, twoYearsAgo)),
|
|
36
|
+
created_by: this.users[faker.datatype.number(this.users.length - 1)].id
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = TagsImporter;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const TableImporter = require('./TableImporter');
|
|
2
|
+
const {faker} = require('@faker-js/faker');
|
|
3
|
+
const {slugify} = require('@tryghost/string');
|
|
4
|
+
const security = require('@tryghost/security');
|
|
5
|
+
const dateToDatabaseString = require('../utils/database-date');
|
|
6
|
+
|
|
7
|
+
class UsersImporter extends TableImporter {
|
|
8
|
+
static table = 'users';
|
|
9
|
+
static dependencies = [];
|
|
10
|
+
defaultQuantity = 8;
|
|
11
|
+
|
|
12
|
+
constructor(knex, transaction) {
|
|
13
|
+
super(UsersImporter.table, knex, transaction);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async generate() {
|
|
17
|
+
const name = `${faker.name.firstName()} ${faker.name.lastName()}`;
|
|
18
|
+
return {
|
|
19
|
+
id: this.fastFakeObjectId(),
|
|
20
|
+
name: name,
|
|
21
|
+
slug: slugify(name),
|
|
22
|
+
password: await security.password.hash(faker.color.human()),
|
|
23
|
+
email: faker.internet.email(name),
|
|
24
|
+
profile_image: faker.internet.avatar(),
|
|
25
|
+
created_at: dateToDatabaseString(faker.date.between(new Date(2016, 0), new Date())),
|
|
26
|
+
created_by: 'unused'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = UsersImporter;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const TableImporter = require('./TableImporter');
|
|
2
|
+
const {faker} = require('@faker-js/faker');
|
|
3
|
+
const dateToDatabaseString = require('../utils/database-date');
|
|
4
|
+
|
|
5
|
+
class WebMentionsImporter extends TableImporter {
|
|
6
|
+
static table = 'mentions';
|
|
7
|
+
static dependencies = [];
|
|
8
|
+
defaultQuantity = 23;
|
|
9
|
+
|
|
10
|
+
constructor(knex, transaction, {baseUrl}) {
|
|
11
|
+
super(WebMentionsImporter.table, knex, transaction);
|
|
12
|
+
|
|
13
|
+
this.baseUrl = baseUrl;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
generate() {
|
|
17
|
+
const id = this.fastFakeObjectId();
|
|
18
|
+
|
|
19
|
+
const author = `${faker.name.fullName()}`;
|
|
20
|
+
|
|
21
|
+
// Generating only incoming recommendations for now, since we don't use webmentions for other things atm
|
|
22
|
+
return {
|
|
23
|
+
id,
|
|
24
|
+
source: `${faker.internet.url()}/.well-known/recommendations.json`,
|
|
25
|
+
source_title: faker.lorem.sentence(5),
|
|
26
|
+
source_site_title: `${author}'s ${faker.word.noun()}`,
|
|
27
|
+
source_excerpt: faker.lorem.paragraph(),
|
|
28
|
+
source_author: author,
|
|
29
|
+
source_featured_image: `https://api.dicebear.com/5.x/shapes/png?size=256&seed=${id}`,
|
|
30
|
+
source_favicon: `https://api.dicebear.com/5.x/bottts/png?size=32&seed=${id}`,
|
|
31
|
+
target: `${this.baseUrl}`,
|
|
32
|
+
resource_id: null,
|
|
33
|
+
resource_type: null,
|
|
34
|
+
created_at: dateToDatabaseString(faker.date.past()),
|
|
35
|
+
payload: JSON.stringify({}),
|
|
36
|
+
deleted: 0,
|
|
37
|
+
verified: 1
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = WebMentionsImporter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module.exports = [
|
|
2
|
+
require('./NewslettersImporter'),
|
|
3
|
+
require('./PostsImporter'),
|
|
4
|
+
require('./UsersImporter'),
|
|
5
|
+
require('./TagsImporter'),
|
|
6
|
+
require('./ProductsImporter'),
|
|
7
|
+
require('./MembersImporter'),
|
|
8
|
+
require('./BenefitsImporter'),
|
|
9
|
+
require('./WebMentionsImporter'),
|
|
10
|
+
require('./PostsAuthorsImporter'),
|
|
11
|
+
require('./PostsTagsImporter'),
|
|
12
|
+
require('./ProductsBenefitsImporter'),
|
|
13
|
+
require('./MembersProductsImporter'),
|
|
14
|
+
require('./PostsProductsImporter'),
|
|
15
|
+
require('./MembersNewslettersImporter'),
|
|
16
|
+
require('./StripeProductsImporter'),
|
|
17
|
+
require('./StripePricesImporter'),
|
|
18
|
+
require('./EmailsImporter'),
|
|
19
|
+
require('./EmailBatchesImporter'),
|
|
20
|
+
require('./EmailRecipientsImporter'),
|
|
21
|
+
require('./EmailRecipientFailuresImporter'),
|
|
22
|
+
require('./RedirectsImporter'),
|
|
23
|
+
require('./MembersClickEventsImporter'),
|
|
24
|
+
require('./OffersImporter'),
|
|
25
|
+
require('./MembersCreatedEventsImporter'),
|
|
26
|
+
require('./MembersLoginEventsImporter'),
|
|
27
|
+
require('./MembersStatusEventsImporter'),
|
|
28
|
+
require('./MembersStripeCustomersImporter'),
|
|
29
|
+
require('./MembersStripeCustomersSubscriptionsImporter'),
|
|
30
|
+
require('./MembersPaidSubscriptionEventsImporter'),
|
|
31
|
+
require('./MembersSubscriptionCreatedEventsImporter'),
|
|
32
|
+
require('./MembersSubscribeEventsImporter'),
|
|
33
|
+
require('./LabelsImporter'),
|
|
34
|
+
require('./MembersLabelsImporter'),
|
|
35
|
+
require('./RolesUsersImporter'),
|
|
36
|
+
require('./MembersFeedbackImporter'),
|
|
37
|
+
require('./RecommendationsImporter'),
|
|
38
|
+
require('./RecommendationClickEventsImporter'),
|
|
39
|
+
require('./RecommendationSubscribeEventsImporter'),
|
|
40
|
+
require('./CommentsImporter')
|
|
41
|
+
];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const TableImporter = require('../importers/TableImporter');
|
|
2
|
+
|
|
3
|
+
class JsonImporter extends TableImporter {
|
|
4
|
+
constructor(knex, transaction) {
|
|
5
|
+
super();
|
|
6
|
+
this.knex = knex;
|
|
7
|
+
this.transaction = transaction;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} JsonImportOptions
|
|
12
|
+
* @property {string} name Name of the table to import
|
|
13
|
+
* @property {Object} data Models without ids to be imported
|
|
14
|
+
* @property {Array<string>} [rows] Set of rows to be returned
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Import a dataset to the database
|
|
19
|
+
* @param {JsonImportOptions} options
|
|
20
|
+
* @returns {Promise}
|
|
21
|
+
*/
|
|
22
|
+
async import({
|
|
23
|
+
name,
|
|
24
|
+
data,
|
|
25
|
+
rows = []
|
|
26
|
+
}) {
|
|
27
|
+
for (const obj of data) {
|
|
28
|
+
if (!('id' in obj)) {
|
|
29
|
+
obj.id = this.fastFakeObjectId();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (rows.findIndex(row => row === 'id') === -1) {
|
|
33
|
+
rows.unshift('id');
|
|
34
|
+
}
|
|
35
|
+
await this.knex.batchInsert(name, data, 500).transacting(this.transaction);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = JsonImporter;
|