ghost 4.37.0 → 4.39.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/.c8rc.json +1 -1
- package/README.md +26 -18
- package/content/themes/casper/LICENSE +1 -1
- package/content/themes/casper/README.md +1 -1
- package/content/themes/casper/assets/built/global.css +1 -1
- package/content/themes/casper/assets/built/global.css.map +1 -1
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/global.css +14 -6
- package/content/themes/casper/assets/css/screen.css +9 -1
- package/content/themes/casper/package.json +2 -2
- package/content/themes/casper/partials/post-card.hbs +1 -1
- package/content/themes/casper/post.hbs +18 -19
- package/content/themes/casper/yarn.lock +186 -217
- package/core/built/assets/{chunk.3.4906cf0b01d6d8e33374.js → chunk.3.6e2ed2d00856e12bd81a.js} +19 -19
- package/core/built/assets/ghost-dark-498ff8339a89bb68c3f78f59bee4146e.css +1 -0
- package/core/built/assets/ghost.min-77b93478f83b0def6ddc5a4f23ce963e.css +1 -0
- package/core/built/assets/{ghost.min-c1938f6ee696bf08bd6bf93cac341ea2.js → ghost.min-e6559d901897066aa6a6d4145e3728ed.js} +466 -413
- package/core/built/assets/icons/{event-changed-subscription.svg → event-subscriptions.svg} +0 -1
- package/core/built/assets/icons/eye.svg +4 -1
- package/core/built/assets/icons/member-add.svg +3 -0
- package/core/built/assets/icons/member.svg +3 -0
- package/core/built/assets/icons/pin.svg +4 -1
- package/core/built/assets/{vendor.min-6dc30be68238b5c55df0cdc1f2dc8b8d.js → vendor.min-c39476bced9adb98ee2b292d01c7a8f4.js} +2303 -1372
- package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
- package/core/frontend/apps/private-blogging/lib/views/private.hbs +9 -10
- package/core/frontend/helpers/get.js +4 -0
- package/core/frontend/helpers/match.js +12 -0
- package/core/frontend/helpers/prev_post.js +11 -1
- package/core/frontend/helpers/tiers.js +59 -0
- package/core/frontend/helpers/tpl/content-cta.hbs +1 -1
- package/core/frontend/public/ghost.css +205 -143
- package/core/frontend/services/routing/router-manager.js +1 -1
- package/core/frontend/views/unsubscribe.hbs +28 -33
- package/core/frontend/web/middleware/error-handler.js +2 -2
- package/core/frontend/web/site.js +10 -0
- package/core/server/api/canary/authentication.js +7 -0
- package/core/server/api/canary/index.js +4 -0
- package/core/server/api/canary/members.js +9 -2
- package/core/server/api/canary/products.js +3 -6
- package/core/server/api/canary/tiers-public.js +34 -0
- package/core/server/api/canary/tiers.js +6 -7
- package/core/server/api/canary/utils/serializers/input/pages.js +1 -1
- package/core/server/api/canary/utils/serializers/input/posts.js +1 -1
- package/core/server/api/canary/utils/serializers/output/email-posts.js +7 -1
- package/core/server/api/canary/utils/serializers/output/pages.js +9 -2
- package/core/server/api/canary/utils/serializers/output/posts.js +8 -2
- package/core/server/api/canary/utils/serializers/output/preview.js +7 -1
- package/core/server/api/canary/utils/serializers/output/products.js +3 -1
- package/core/server/api/canary/utils/serializers/output/tiers.js +4 -2
- package/core/server/api/canary/utils/serializers/output/utils/mapper.js +17 -7
- package/core/server/api/shared/serializers/handle.js +2 -2
- package/core/server/api/v2/utils/serializers/input/pages.js +1 -1
- package/core/server/api/v2/utils/serializers/input/posts.js +1 -1
- package/core/server/api/v3/utils/serializers/input/pages.js +1 -1
- package/core/server/api/v3/utils/serializers/input/posts.js +1 -1
- package/core/server/data/db/connection.js +3 -2
- package/core/server/data/importer/import-manager.js +152 -113
- package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -1
- package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -1
- package/core/server/data/migrations/versions/3.29/03-remove-orphaned-customers.js +2 -1
- package/core/server/data/migrations/versions/3.29/04-remove-orphaned-subscriptions.js +2 -1
- package/core/server/data/migrations/versions/3.29/05-add-member-constraints.js +3 -2
- package/core/server/data/migrations/versions/3.39/06-add-email-recipient-index.js +4 -3
- package/core/server/data/migrations/versions/4.0/14-remove-orphaned-stripe-records.js +2 -1
- package/core/server/data/migrations/versions/4.0/26-add-cascade-on-delete.js +2 -1
- package/core/server/data/migrations/versions/4.0/29-fix-foreign-key-for-members-stripe-customers-subscriptions.js +2 -1
- package/core/server/data/migrations/versions/4.1/02-add-unique-constraint-for-member-stripe-tables.js +2 -1
- package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +3 -2
- package/core/server/data/migrations/versions/4.33/2022-01-14-11-51-add-default-free-tier.js +3 -0
- package/core/server/data/migrations/versions/4.33/2022-01-18-09-07-remove-duplicate-offer-redemptions.js +2 -2
- package/core/server/data/migrations/versions/4.35/2022-02-01-11-48-update-email-recipient-filter-column-type.js +2 -1
- package/core/server/data/migrations/versions/4.35/2022-02-01-12-03-update-recipient-filter-column-type.js +2 -1
- package/core/server/data/migrations/versions/4.37/2022-02-21-09-53-backfill-members-last-seen-at-column.js +3 -2
- package/core/server/data/migrations/versions/4.38/2022-03-01-08-46-add-visibility-to-tiers.js +11 -0
- package/core/server/data/migrations/versions/4.38/2022-03-03-16-12-add-visibility-to-tiers.js +8 -0
- package/core/server/data/migrations/versions/4.38/2022-03-03-16-17-drop-tiers-visible-column.js +7 -0
- package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-free-products-visibility-column.js +66 -0
- package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-products-visibility-column.js +36 -0
- package/core/server/data/schema/clients/index.js +1 -1
- package/core/server/data/schema/clients/mysql.js +4 -4
- package/core/server/data/schema/commands.js +42 -50
- package/core/server/data/schema/default-settings/default-settings.json +2 -2
- package/core/server/data/schema/fixtures/fixtures.json +18 -161
- package/core/server/data/schema/schema.js +7 -0
- package/core/server/frontend/ghost.min.css +1 -1
- package/core/server/lib/image/image-size.js +12 -4
- package/core/server/models/base/plugins/generate-slug.js +13 -1
- package/core/server/models/base/plugins/raw-knex.js +1 -1
- package/core/server/models/post.js +16 -6
- package/core/server/models/product.js +2 -1
- package/core/server/models/user.js +1 -1
- package/core/server/services/auth/api-key/admin.js +15 -6
- package/core/server/services/auth/setup.js +34 -13
- package/core/server/services/email-analytics/lib/event-processor.js +18 -1
- package/core/server/services/mega/mega.js +4 -4
- package/core/server/services/mega/template.js +1 -1
- package/core/server/services/members/content-gating.js +1 -1
- package/core/server/services/members/middleware.js +4 -0
- package/core/server/services/members/service.js +13 -1
- package/core/server/services/posts/posts-service.js +1 -1
- package/core/server/services/url/UrlGenerator.js +1 -1
- package/core/server/services/webhooks/webhooks-service.js +2 -0
- package/core/server/views/maintenance.html +2 -2
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/app.js +3 -0
- package/core/server/web/api/canary/admin/middleware.js +2 -0
- package/core/server/web/api/canary/content/routes.js +1 -0
- package/core/server/web/members/app.js +1 -1
- package/core/server/web/parent/backend.js +2 -1
- package/core/server/web/shared/middleware/uncapitalise.js +3 -2
- package/core/shared/config/defaults.json +2 -2
- package/core/shared/config/utils.js +5 -1
- package/core/shared/labs.js +8 -9
- package/core/shared/url-utils.js +4 -1
- package/package.json +56 -52
- package/yarn.lock +809 -607
- package/core/built/assets/ghost-dark-d54723f7267e66fa2595f897076e86c2.css +0 -1
- package/core/built/assets/ghost.min-02a5f8954bd85fe28817b8c8b111b8aa.css +0 -1
- package/core/built/assets/icons/event-started-subscription.svg +0 -6
- package/core/built/assets/icons/locked-email-back.svg +0 -1
- package/core/built/assets/icons/locked-email-front.svg +0 -1
- package/core/built/assets/icons/locked-email-lock.svg +0 -1
- package/core/built/assets/img/ghost-logo-de2acf283f53ba1fd1149928faeaaa74.png +0 -0
|
@@ -19,6 +19,9 @@ module.exports = createTransactionalMigration(
|
|
|
19
19
|
const id = ObjectID().toHexString();
|
|
20
20
|
|
|
21
21
|
logging.info(`Adding tier "${name}"`);
|
|
22
|
+
|
|
23
|
+
// `slugify(id) is used to ensure unique slug here, as existing tiers could be using any name including "Free"
|
|
24
|
+
// slugs are not used anywhere user-facing so the value is acceptable
|
|
22
25
|
await knex('products')
|
|
23
26
|
.insert({
|
|
24
27
|
id: id,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const logging = require('@tryghost/logging');
|
|
2
|
-
|
|
3
2
|
const {createTransactionalMigration} = require('../../utils');
|
|
3
|
+
const DatabaseInfo = require('@tryghost/database-info');
|
|
4
4
|
|
|
5
5
|
module.exports = createTransactionalMigration(
|
|
6
6
|
async function up(knex) {
|
|
7
|
-
if (knex
|
|
7
|
+
if (!DatabaseInfo.isMySQL(knex)) {
|
|
8
8
|
logging.warn('Skipping cleanup of duplicate offer redemptions - database is not MySQL');
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const logging = require('@tryghost/logging');
|
|
2
2
|
const {createNonTransactionalMigration} = require('../../utils');
|
|
3
|
+
const DatabaseInfo = require('@tryghost/database-info');
|
|
3
4
|
|
|
4
5
|
module.exports = createNonTransactionalMigration(
|
|
5
6
|
async function up(knex) {
|
|
6
|
-
if (knex
|
|
7
|
+
if (DatabaseInfo.isSQLite(knex)) {
|
|
7
8
|
logging.warn('Skipping migration for SQLite3');
|
|
8
9
|
return;
|
|
9
10
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const logging = require('@tryghost/logging');
|
|
2
2
|
const {createNonTransactionalMigration} = require('../../utils');
|
|
3
|
+
const DatabaseInfo = require('@tryghost/database-info');
|
|
3
4
|
|
|
4
5
|
module.exports = createNonTransactionalMigration(
|
|
5
6
|
async function up(knex) {
|
|
6
|
-
if (knex
|
|
7
|
+
if (DatabaseInfo.isSQLite(knex)) {
|
|
7
8
|
logging.warn('Skipping migration for SQLite3');
|
|
8
9
|
return;
|
|
9
10
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const logging = require('@tryghost/logging');
|
|
2
2
|
const {createTransactionalMigration} = require('../../utils');
|
|
3
|
+
const DatabaseInfo = require('@tryghost/database-info');
|
|
3
4
|
|
|
4
5
|
module.exports = createTransactionalMigration(
|
|
5
6
|
async function up(knex) {
|
|
6
|
-
if (knex
|
|
7
|
+
if (DatabaseInfo.isSQLite(knex)) {
|
|
7
8
|
logging.warn('Skipping migration for SQLite3');
|
|
8
9
|
return;
|
|
9
10
|
}
|
|
@@ -21,7 +22,7 @@ module.exports = createTransactionalMigration(
|
|
|
21
22
|
`);
|
|
22
23
|
},
|
|
23
24
|
async function down(knex) {
|
|
24
|
-
if (knex
|
|
25
|
+
if (DatabaseInfo.isSQLite(knex)) {
|
|
25
26
|
logging.warn('Skipping migration for SQLite3');
|
|
26
27
|
return;
|
|
27
28
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const {createAddColumnMigration} = require('../../utils');
|
|
2
|
+
|
|
3
|
+
module.exports = createAddColumnMigration('products', 'visible', {
|
|
4
|
+
type: 'boolean',
|
|
5
|
+
nullable: false,
|
|
6
|
+
defaultTo: false
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
module.exports.up = async () => {
|
|
10
|
+
// noop - column will be replaced with `visibility` instead
|
|
11
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createTransactionalMigration} = require('../../utils');
|
|
3
|
+
|
|
4
|
+
module.exports = createTransactionalMigration(
|
|
5
|
+
async function up(knex) {
|
|
6
|
+
const portalPlanSetting = await knex('settings').select('value').where('key', 'portal_plans').first();
|
|
7
|
+
|
|
8
|
+
if (!portalPlanSetting) {
|
|
9
|
+
logging.warn('Could not find portal_plans setting - skipping migration');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const settingData = JSON.parse(portalPlanSetting.value);
|
|
15
|
+
|
|
16
|
+
if (!settingData.includes('free')) {
|
|
17
|
+
logging.warn(`portal_plans does not include "free" - skipping migration`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
logging.info(`Updating free products to visible`);
|
|
22
|
+
await knex('products').update('visibility', 'public').where('type', 'free');
|
|
23
|
+
} catch (err) {
|
|
24
|
+
logging.error(err);
|
|
25
|
+
logging.warn('portal_plans setting is invalid - skipping migration');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
async function down(knex) {
|
|
30
|
+
const freeTier = await knex('products').select('id').where('type', 'free').first();
|
|
31
|
+
const portalPlanSetting = await knex('settings').select('value').where('key', 'portal_plans').first();
|
|
32
|
+
|
|
33
|
+
if (!freeTier) {
|
|
34
|
+
logging.info('Free tier is not visible, not updating portal_plans');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!portalPlanSetting) {
|
|
39
|
+
logging.warn('Could not find portal_plans setting - skipping migration');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const existingSettingData = JSON.parse(portalPlanSetting.value);
|
|
45
|
+
let settingData;
|
|
46
|
+
|
|
47
|
+
if (freeTier.visibility === 'public') {
|
|
48
|
+
if (existingSettingData.includes('free')) {
|
|
49
|
+
logging.info('portal_plans setting already contains "free" - skipping update');
|
|
50
|
+
return;
|
|
51
|
+
} else {
|
|
52
|
+
settingData = JSON.stringify(existingSettingData.concat('free'));
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
settingData = JSON.stringify(existingSettingData.filter(value => value !== 'free'));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
logging.info(`Updating portal_plans to ${settingData}`);
|
|
59
|
+
await knex('settings').update('value', settingData).where('key', 'portal_plans');
|
|
60
|
+
} catch (err) {
|
|
61
|
+
logging.error(err);
|
|
62
|
+
logging.warn('portal_plans setting is invalid - skipping migration');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createTransactionalMigration} = require('../../utils');
|
|
3
|
+
|
|
4
|
+
module.exports = createTransactionalMigration(
|
|
5
|
+
async function up(knex) {
|
|
6
|
+
const portalProductSetting = await knex('settings').select('value').where('key', 'portal_products').first();
|
|
7
|
+
|
|
8
|
+
if (!portalProductSetting) {
|
|
9
|
+
logging.warn('Could not find portal_products setting - skipping migration');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const settingData = JSON.parse(portalProductSetting.value);
|
|
15
|
+
|
|
16
|
+
if (settingData.length === 0) {
|
|
17
|
+
logging.warn(`portal_product is empty, skipping migrations`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
logging.info(`Updating ${settingData.length} products to visible, ${settingData}`);
|
|
22
|
+
await knex('products').update('visibility', 'public').whereIn('id', settingData);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
logging.warn('portal_products setting is invalid - skipping migration');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
async function down(knex) {
|
|
29
|
+
const visibleTiers = await knex('products').select('id').where('visibility', 'public');
|
|
30
|
+
|
|
31
|
+
const settingData = JSON.stringify(visibleTiers.map(obj => obj.id));
|
|
32
|
+
|
|
33
|
+
logging.info(`Updating portal_products to ${settingData}`);
|
|
34
|
+
await knex('settings').update('value', settingData).where('key', 'portal_products');
|
|
35
|
+
}
|
|
36
|
+
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const db = require('../../../data/db');
|
|
3
3
|
|
|
4
|
-
const doRawAndFlatten = function doRaw(query, transaction, flattenFn) {
|
|
5
|
-
return
|
|
4
|
+
const doRawAndFlatten = function doRaw(query, transaction = db.knex, flattenFn) {
|
|
5
|
+
return transaction.raw(query).then(function (response) {
|
|
6
6
|
return _.flatten(flattenFn(response));
|
|
7
7
|
});
|
|
8
8
|
};
|
|
@@ -31,8 +31,8 @@ const getColumns = function getColumns(table, transaction) {
|
|
|
31
31
|
// a wrong datatype in schema.js some installations using mysql could have been created using the
|
|
32
32
|
// data type text instead of mediumtext.
|
|
33
33
|
// For details see: https://github.com/TryGhost/Ghost/issues/1947
|
|
34
|
-
const checkPostTable = function checkPostTable(transaction) {
|
|
35
|
-
return
|
|
34
|
+
const checkPostTable = function checkPostTable(transaction = db.knex) {
|
|
35
|
+
return transaction.raw('SHOW FIELDS FROM posts where Field ="html" OR Field = "markdown"').then(function (response) {
|
|
36
36
|
return _.flatten(_.map(response[0], function (entry) {
|
|
37
37
|
if (entry.Type.toLowerCase() !== 'mediumtext') {
|
|
38
38
|
return (transaction || db.knex).raw('ALTER TABLE posts MODIFY ' + entry.Field + ' MEDIUMTEXT');
|
|
@@ -4,6 +4,7 @@ const logging = require('@tryghost/logging');
|
|
|
4
4
|
const errors = require('@tryghost/errors');
|
|
5
5
|
const tpl = require('@tryghost/tpl');
|
|
6
6
|
const db = require('../db');
|
|
7
|
+
const DatabaseInfo = require('@tryghost/database-info');
|
|
7
8
|
const schema = require('./schema');
|
|
8
9
|
const clients = require('./clients');
|
|
9
10
|
|
|
@@ -58,14 +59,14 @@ function addTableColumn(tableName, table, columnName, columnSpec = schema[tableN
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
function addColumn(tableName, column, transaction, columnSpec) {
|
|
62
|
-
return
|
|
62
|
+
function addColumn(tableName, column, transaction = db.knex, columnSpec) {
|
|
63
|
+
return transaction.schema.table(tableName, function (table) {
|
|
63
64
|
addTableColumn(tableName, table, column, columnSpec);
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
function dropColumn(tableName, column, transaction) {
|
|
68
|
-
return
|
|
68
|
+
function dropColumn(tableName, column, transaction = db.knex) {
|
|
69
|
+
return transaction.schema.table(tableName, function (table) {
|
|
69
70
|
table.dropColumn(column);
|
|
70
71
|
});
|
|
71
72
|
}
|
|
@@ -77,11 +78,11 @@ function dropColumn(tableName, column, transaction) {
|
|
|
77
78
|
* @param {string|[string]} columns - column(s) to form unique constraint with
|
|
78
79
|
* @param {import('knex')} transaction - connection object containing knex reference
|
|
79
80
|
*/
|
|
80
|
-
async function addUnique(tableName, columns, transaction) {
|
|
81
|
+
async function addUnique(tableName, columns, transaction = db.knex) {
|
|
81
82
|
try {
|
|
82
83
|
logging.info(`Adding unique constraint for: ${columns} in table ${tableName}`);
|
|
83
84
|
|
|
84
|
-
return await
|
|
85
|
+
return await transaction.schema.table(tableName, function (table) {
|
|
85
86
|
table.unique(columns);
|
|
86
87
|
});
|
|
87
88
|
} catch (err) {
|
|
@@ -104,11 +105,11 @@ async function addUnique(tableName, columns, transaction) {
|
|
|
104
105
|
* @param {string|[string]} columns - column(s) unique constraint was formed
|
|
105
106
|
* @param {import('knex')} transaction - connection object containing knex reference
|
|
106
107
|
*/
|
|
107
|
-
async function dropUnique(tableName, columns, transaction) {
|
|
108
|
+
async function dropUnique(tableName, columns, transaction = db.knex) {
|
|
108
109
|
try {
|
|
109
110
|
logging.info(`Dropping unique constraint for: ${columns} in table: ${tableName}`);
|
|
110
111
|
|
|
111
|
-
return await
|
|
112
|
+
return await transaction.schema.table(tableName, function (table) {
|
|
112
113
|
table.dropUnique(columns);
|
|
113
114
|
});
|
|
114
115
|
} catch (err) {
|
|
@@ -134,17 +135,14 @@ async function dropUnique(tableName, columns, transaction) {
|
|
|
134
135
|
* @param {string} configuration.toColumn - column of the table to point the foreign key to
|
|
135
136
|
* @param {import('knex')} configuration.transaction - connection object containing knex reference
|
|
136
137
|
*/
|
|
137
|
-
async function hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, transaction}) {
|
|
138
|
-
|
|
139
|
-
const client = knex.client.config.client;
|
|
140
|
-
|
|
141
|
-
if (client !== 'sqlite3') {
|
|
138
|
+
async function hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, transaction = db.knex}) {
|
|
139
|
+
if (!DatabaseInfo.isSQLite(transaction)) {
|
|
142
140
|
throw new errors.InternalServerError({
|
|
143
141
|
message: tpl(messages.hasForeignSQLite3)
|
|
144
142
|
});
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
const foreignKeys = await
|
|
145
|
+
const foreignKeys = await transaction.raw(`PRAGMA foreign_key_list('${fromTable}');`);
|
|
148
146
|
|
|
149
147
|
const hasForeignKey = foreignKeys.some(foreignKey => foreignKey.table === toTable && foreignKey.from === fromColumn && foreignKey.to === toColumn);
|
|
150
148
|
|
|
@@ -162,9 +160,8 @@ async function hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, trans
|
|
|
162
160
|
* @param {Boolean} configuration.cascadeDelete - adds the "on delete cascade" option if true
|
|
163
161
|
* @param {import('knex')} configuration.transaction - connection object containing knex reference
|
|
164
162
|
*/
|
|
165
|
-
async function addForeign({fromTable, fromColumn, toTable, toColumn, cascadeDelete = false, transaction}) {
|
|
166
|
-
|
|
167
|
-
if (isSQLite) {
|
|
163
|
+
async function addForeign({fromTable, fromColumn, toTable, toColumn, cascadeDelete = false, transaction = db.knex}) {
|
|
164
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
168
165
|
const foreignKeyExists = await hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, transaction});
|
|
169
166
|
if (foreignKeyExists) {
|
|
170
167
|
logging.warn(`Skipped adding foreign key from ${fromTable}.${fromColumn} to ${toTable}.${toColumn} - foreign key already exists`);
|
|
@@ -176,14 +173,14 @@ async function addForeign({fromTable, fromColumn, toTable, toColumn, cascadeDele
|
|
|
176
173
|
|
|
177
174
|
//disable and re-enable foreign key checks on sqlite because of https://github.com/knex/knex/issues/4155
|
|
178
175
|
let foreignKeysEnabled;
|
|
179
|
-
if (isSQLite) {
|
|
176
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
180
177
|
foreignKeysEnabled = await db.knex.raw('PRAGMA foreign_keys;');
|
|
181
178
|
if (foreignKeysEnabled[0].foreign_keys) {
|
|
182
179
|
await db.knex.raw('PRAGMA foreign_keys = OFF;');
|
|
183
180
|
}
|
|
184
181
|
}
|
|
185
182
|
|
|
186
|
-
await
|
|
183
|
+
await transaction.schema.table(fromTable, function (table) {
|
|
187
184
|
if (cascadeDelete) {
|
|
188
185
|
table.foreign(fromColumn).references(`${toTable}.${toColumn}`).onDelete('CASCADE');
|
|
189
186
|
} else {
|
|
@@ -191,13 +188,13 @@ async function addForeign({fromTable, fromColumn, toTable, toColumn, cascadeDele
|
|
|
191
188
|
}
|
|
192
189
|
});
|
|
193
190
|
|
|
194
|
-
if (isSQLite) {
|
|
191
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
195
192
|
if (foreignKeysEnabled[0].foreign_keys) {
|
|
196
193
|
await db.knex.raw('PRAGMA foreign_keys = ON;');
|
|
197
194
|
}
|
|
198
195
|
}
|
|
199
196
|
} catch (err) {
|
|
200
|
-
if (err.code === 'ER_DUP_KEY') {
|
|
197
|
+
if (err.code === 'ER_DUP_KEY' || err.code === 'ER_FK_DUP_KEY' || err.code === 'ER_FK_DUP_NAME') {
|
|
201
198
|
logging.warn(`Skipped adding foreign key from ${fromTable}.${fromColumn} to ${toTable}.${toColumn} - foreign key already exists`);
|
|
202
199
|
return;
|
|
203
200
|
}
|
|
@@ -215,9 +212,8 @@ async function addForeign({fromTable, fromColumn, toTable, toColumn, cascadeDele
|
|
|
215
212
|
* @param {string} configuration.toColumn - column of the table to point the foreign key to
|
|
216
213
|
* @param {import('knex')} configuration.transaction - connection object containing knex reference
|
|
217
214
|
*/
|
|
218
|
-
async function dropForeign({fromTable, fromColumn, toTable, toColumn, transaction}) {
|
|
219
|
-
|
|
220
|
-
if (isSQLite) {
|
|
215
|
+
async function dropForeign({fromTable, fromColumn, toTable, toColumn, transaction = db.knex}) {
|
|
216
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
221
217
|
const foreignKeyExists = await hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, transaction});
|
|
222
218
|
if (!foreignKeyExists) {
|
|
223
219
|
logging.warn(`Skipped dropping foreign key from ${fromTable}.${fromColumn} to ${toTable}.${toColumn} - foreign key does not exist`);
|
|
@@ -229,18 +225,18 @@ async function dropForeign({fromTable, fromColumn, toTable, toColumn, transactio
|
|
|
229
225
|
|
|
230
226
|
//disable and re-enable foreign key checks on sqlite because of https://github.com/knex/knex/issues/4155
|
|
231
227
|
let foreignKeysEnabled;
|
|
232
|
-
if (isSQLite) {
|
|
228
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
233
229
|
foreignKeysEnabled = await db.knex.raw('PRAGMA foreign_keys;');
|
|
234
230
|
if (foreignKeysEnabled[0].foreign_keys) {
|
|
235
231
|
await db.knex.raw('PRAGMA foreign_keys = OFF;');
|
|
236
232
|
}
|
|
237
233
|
}
|
|
238
234
|
|
|
239
|
-
await
|
|
235
|
+
await transaction.schema.table(fromTable, function (table) {
|
|
240
236
|
table.dropForeign(fromColumn);
|
|
241
237
|
});
|
|
242
238
|
|
|
243
|
-
if (isSQLite) {
|
|
239
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
244
240
|
if (foreignKeysEnabled[0].foreign_keys) {
|
|
245
241
|
await db.knex.raw('PRAGMA foreign_keys = ON;');
|
|
246
242
|
}
|
|
@@ -260,17 +256,14 @@ async function dropForeign({fromTable, fromColumn, toTable, toColumn, transactio
|
|
|
260
256
|
* @param {string} tableName - name of the table to check primary key constraint on
|
|
261
257
|
* @param {import('knex')} transaction - connection object containing knex reference
|
|
262
258
|
*/
|
|
263
|
-
async function hasPrimaryKeySQLite(tableName, transaction) {
|
|
264
|
-
|
|
265
|
-
const client = knex.client.config.client;
|
|
266
|
-
|
|
267
|
-
if (client !== 'sqlite3') {
|
|
259
|
+
async function hasPrimaryKeySQLite(tableName, transaction = db.knex) {
|
|
260
|
+
if (!DatabaseInfo.isSQLite(transaction)){
|
|
268
261
|
throw new errors.InternalServerError({
|
|
269
262
|
message: tpl(messages.hasPrimaryKeySQLiteError)
|
|
270
263
|
});
|
|
271
264
|
}
|
|
272
265
|
|
|
273
|
-
const rawConstraints = await
|
|
266
|
+
const rawConstraints = await transaction.raw(`PRAGMA index_list('${tableName}');`);
|
|
274
267
|
const tablePrimaryKey = rawConstraints.find(c => c.origin === 'pk');
|
|
275
268
|
|
|
276
269
|
return tablePrimaryKey;
|
|
@@ -283,9 +276,8 @@ async function hasPrimaryKeySQLite(tableName, transaction) {
|
|
|
283
276
|
* @param {string|[string]} columns - column(s) to form primary key constraint with
|
|
284
277
|
* @param {import('knex')} transaction - connection object containing knex reference
|
|
285
278
|
*/
|
|
286
|
-
async function addPrimaryKey(tableName, columns, transaction) {
|
|
287
|
-
|
|
288
|
-
if (isSQLite) {
|
|
279
|
+
async function addPrimaryKey(tableName, columns, transaction = db.knex) {
|
|
280
|
+
if (DatabaseInfo.isSQLite(transaction)) {
|
|
289
281
|
const primaryKeyExists = await hasPrimaryKeySQLite(tableName, transaction);
|
|
290
282
|
if (primaryKeyExists) {
|
|
291
283
|
logging.warn(`Primary key constraint for: ${columns} already exists for table: ${tableName}`);
|
|
@@ -294,7 +286,7 @@ async function addPrimaryKey(tableName, columns, transaction) {
|
|
|
294
286
|
}
|
|
295
287
|
try {
|
|
296
288
|
logging.info(`Adding primary key constraint for: ${columns} in table ${tableName}`);
|
|
297
|
-
return await
|
|
289
|
+
return await transaction.schema.table(tableName, function (table) {
|
|
298
290
|
table.primary(columns);
|
|
299
291
|
});
|
|
300
292
|
} catch (err) {
|
|
@@ -316,8 +308,8 @@ async function addPrimaryKey(tableName, columns, transaction) {
|
|
|
316
308
|
* @param {import('knex').Transaction} transaction - connection to the DB
|
|
317
309
|
* @param {Object} [tableSpec] - table schema to generate table with
|
|
318
310
|
*/
|
|
319
|
-
function createTable(table, transaction, tableSpec = schema[table]) {
|
|
320
|
-
return
|
|
311
|
+
function createTable(table, transaction = db.knex, tableSpec = schema[table]) {
|
|
312
|
+
return transaction.schema.createTable(table, function (t) {
|
|
321
313
|
Object.keys(tableSpec)
|
|
322
314
|
.filter(column => !(column.startsWith('@@')))
|
|
323
315
|
.forEach(column => addTableColumn(table, t, column, tableSpec[column]));
|
|
@@ -331,12 +323,12 @@ function createTable(table, transaction, tableSpec = schema[table]) {
|
|
|
331
323
|
});
|
|
332
324
|
}
|
|
333
325
|
|
|
334
|
-
function deleteTable(table, transaction) {
|
|
335
|
-
return
|
|
326
|
+
function deleteTable(table, transaction = db.knex) {
|
|
327
|
+
return transaction.schema.dropTableIfExists(table);
|
|
336
328
|
}
|
|
337
329
|
|
|
338
|
-
function getTables(transaction) {
|
|
339
|
-
const client =
|
|
330
|
+
function getTables(transaction = db.knex) {
|
|
331
|
+
const client = transaction.client.config.client;
|
|
340
332
|
|
|
341
333
|
if (_.includes(_.keys(clients), client)) {
|
|
342
334
|
return clients[client].getTables(transaction);
|
|
@@ -345,8 +337,8 @@ function getTables(transaction) {
|
|
|
345
337
|
return Promise.reject(tpl(messages.noSupportForDatabase, {client: client}));
|
|
346
338
|
}
|
|
347
339
|
|
|
348
|
-
function getIndexes(table, transaction) {
|
|
349
|
-
const client =
|
|
340
|
+
function getIndexes(table, transaction = db.knex) {
|
|
341
|
+
const client = transaction.client.config.client;
|
|
350
342
|
|
|
351
343
|
if (_.includes(_.keys(clients), client)) {
|
|
352
344
|
return clients[client].getIndexes(table, transaction);
|
|
@@ -355,8 +347,8 @@ function getIndexes(table, transaction) {
|
|
|
355
347
|
return Promise.reject(tpl(messages.noSupportForDatabase, {client: client}));
|
|
356
348
|
}
|
|
357
349
|
|
|
358
|
-
function getColumns(table, transaction) {
|
|
359
|
-
const client =
|
|
350
|
+
function getColumns(table, transaction = db.knex) {
|
|
351
|
+
const client = transaction.client.config.client;
|
|
360
352
|
|
|
361
353
|
if (_.includes(_.keys(clients), client)) {
|
|
362
354
|
return clients[client].getColumns(table);
|
|
@@ -365,10 +357,10 @@ function getColumns(table, transaction) {
|
|
|
365
357
|
return Promise.reject(tpl(messages.noSupportForDatabase, {client: client}));
|
|
366
358
|
}
|
|
367
359
|
|
|
368
|
-
function checkTables(transaction) {
|
|
369
|
-
const client =
|
|
360
|
+
function checkTables(transaction = db.knex) {
|
|
361
|
+
const client = transaction.client.config.client;
|
|
370
362
|
|
|
371
|
-
if (
|
|
363
|
+
if (DatabaseInfo.isMySQL(transaction)) {
|
|
372
364
|
return clients[client].checkPostTable();
|
|
373
365
|
}
|
|
374
366
|
}
|
|
@@ -126,11 +126,11 @@
|
|
|
126
126
|
"type": "string"
|
|
127
127
|
},
|
|
128
128
|
"navigation": {
|
|
129
|
-
"defaultValue": "[{\"label\":\"Home\",\"url\":\"/\"},{\"label\":\"About\",\"url\":\"/about/\"}
|
|
129
|
+
"defaultValue": "[{\"label\":\"Home\",\"url\":\"/\"},{\"label\":\"About\",\"url\":\"/about/\"}]",
|
|
130
130
|
"type": "array"
|
|
131
131
|
},
|
|
132
132
|
"secondary_navigation": {
|
|
133
|
-
"defaultValue": "[{\"label\":\"
|
|
133
|
+
"defaultValue": "[{\"label\":\"Sign up\",\"url\":\"#/portal/\"}]",
|
|
134
134
|
"type": "array"
|
|
135
135
|
},
|
|
136
136
|
"meta_title": {
|