directus 9.22.3 → 9.23.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/dist/app.js +5 -4
- package/dist/auth/drivers/ldap.d.ts +2 -2
- package/dist/auth/drivers/ldap.js +8 -8
- package/dist/auth/drivers/oauth2.js +2 -2
- package/dist/auth/drivers/openid.js +2 -2
- package/dist/cache.js +4 -4
- package/dist/cli/commands/schema/apply.js +19 -17
- package/dist/cli/utils/create-db-connection.d.ts +2 -1
- package/dist/cli/utils/create-env/env-stub.liquid +1 -1
- package/dist/cli/utils/drivers.d.ts +3 -9
- package/dist/constants.d.ts +2 -8
- package/dist/constants.js +3 -7
- package/dist/controllers/assets.js +5 -5
- package/dist/controllers/extensions.js +7 -7
- package/dist/controllers/files.js +1 -1
- package/dist/controllers/graphql.js +8 -0
- package/dist/controllers/schema.d.ts +2 -0
- package/dist/controllers/schema.js +98 -0
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/oracle.d.ts +4 -1
- package/dist/database/helpers/schema/dialects/oracle.js +25 -0
- package/dist/database/helpers/schema/types.d.ts +8 -6
- package/dist/database/helpers/schema/types.js +7 -1
- package/dist/database/index.d.ts +2 -1
- package/dist/database/run-ast.js +2 -2
- package/dist/env.js +9 -2
- package/dist/extensions.js +1 -1
- package/dist/flows.js +17 -8
- package/dist/middleware/cache.js +2 -2
- package/dist/middleware/respond.js +14 -9
- package/dist/operations/item-create/index.test.d.ts +1 -0
- package/dist/operations/item-update/index.test.d.ts +1 -0
- package/dist/operations/log/index.test.d.ts +1 -0
- package/dist/operations/notification/index.test.d.ts +1 -0
- package/dist/operations/request/index.js +2 -1
- package/dist/operations/request/index.test.d.ts +1 -0
- package/dist/operations/sleep/index.test.d.ts +1 -0
- package/dist/operations/transform/index.test.d.ts +1 -0
- package/dist/operations/trigger/index.d.ts +2 -0
- package/dist/operations/trigger/index.js +26 -9
- package/dist/operations/trigger/index.test.d.ts +1 -0
- package/dist/request/index.d.ts +5 -0
- package/dist/request/index.js +18 -0
- package/dist/request/index.test.d.ts +1 -0
- package/dist/request/request-interceptor.d.ts +2 -0
- package/dist/request/request-interceptor.js +33 -0
- package/dist/request/request-interceptor.test.d.ts +1 -0
- package/dist/request/response-interceptor.d.ts +2 -0
- package/dist/request/response-interceptor.js +9 -0
- package/dist/request/response-interceptor.test.d.ts +1 -0
- package/dist/request/validate-ip.d.ts +1 -0
- package/dist/request/validate-ip.js +27 -0
- package/dist/request/validate-ip.test.d.ts +1 -0
- package/dist/services/assets.d.ts +1 -1
- package/dist/services/assets.js +11 -2
- package/dist/services/authentication.js +5 -5
- package/dist/services/fields.js +1 -0
- package/dist/services/files.js +44 -88
- package/dist/services/graphql/index.js +14 -8
- package/dist/services/graphql/utils/process-error.js +22 -9
- package/dist/services/import-export.d.ts +4 -2
- package/dist/services/import-export.js +17 -3
- package/dist/services/import-export.test.d.ts +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.js +34 -15
- package/dist/services/relations.js +2 -0
- package/dist/services/roles.js +32 -11
- package/dist/services/schema.d.ts +15 -0
- package/dist/services/schema.js +58 -0
- package/dist/services/schema.test.d.ts +1 -0
- package/dist/services/shares.d.ts +2 -2
- package/dist/services/shares.js +9 -9
- package/dist/services/users.js +74 -47
- package/dist/types/assets.d.ts +1 -1
- package/dist/types/database.d.ts +3 -0
- package/dist/types/database.js +4 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/items.d.ts +5 -0
- package/dist/types/snapshot.d.ts +22 -0
- package/dist/types/snapshot.js +14 -0
- package/dist/utils/apply-diff.d.ts +9 -0
- package/dist/utils/apply-diff.js +259 -0
- package/dist/utils/apply-diff.test.d.ts +1 -0
- package/dist/utils/apply-query.js +8 -6
- package/dist/utils/apply-snapshot.d.ts +1 -3
- package/dist/utils/apply-snapshot.js +4 -234
- package/dist/utils/get-cache-headers.d.ts +3 -1
- package/dist/utils/get-cache-headers.js +20 -19
- package/dist/utils/get-cache-headers.test.d.ts +1 -0
- package/dist/utils/get-milliseconds.d.ts +4 -0
- package/dist/utils/get-milliseconds.js +15 -0
- package/dist/utils/get-milliseconds.test.d.ts +1 -0
- package/dist/utils/get-snapshot-diff.js +11 -7
- package/dist/utils/get-snapshot.js +29 -6
- package/dist/utils/get-versioned-hash.d.ts +1 -0
- package/dist/utils/get-versioned-hash.js +12 -0
- package/dist/utils/get-versioned-hash.test.d.ts +1 -0
- package/dist/utils/map-values-deep.d.ts +1 -0
- package/dist/utils/map-values-deep.js +29 -0
- package/dist/utils/map-values-deep.test.d.ts +1 -0
- package/dist/utils/sanitize-schema.d.ts +30 -0
- package/dist/utils/sanitize-schema.js +80 -0
- package/dist/utils/sanitize-schema.test.d.ts +1 -0
- package/dist/utils/track.js +3 -3
- package/dist/utils/url.js +2 -6
- package/dist/utils/url.test.d.ts +1 -0
- package/dist/utils/validate-diff.d.ts +7 -0
- package/dist/utils/validate-diff.js +114 -0
- package/dist/utils/validate-diff.test.d.ts +1 -0
- package/dist/utils/validate-query.js +2 -2
- package/dist/utils/validate-query.test.d.ts +1 -0
- package/dist/utils/validate-snapshot.d.ts +5 -0
- package/dist/utils/validate-snapshot.js +71 -0
- package/dist/utils/validate-snapshot.test.d.ts +1 -0
- package/dist/utils/with-timeout.d.ts +1 -0
- package/dist/utils/with-timeout.js +16 -0
- package/dist/webhooks.js +3 -2
- package/package.json +54 -53
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isNestedMetaUpdate = exports.applyDiff = void 0;
|
|
7
|
+
const services_1 = require("../services");
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
const get_schema_1 = require("./get-schema");
|
|
10
|
+
const database_1 = __importDefault(require("../database"));
|
|
11
|
+
const deep_diff_1 = require("deep-diff");
|
|
12
|
+
const lodash_1 = require("lodash");
|
|
13
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
14
|
+
const emitter_1 = __importDefault(require("../emitter"));
|
|
15
|
+
const cache_1 = require("../cache");
|
|
16
|
+
async function applyDiff(currentSnapshot, snapshotDiff, options) {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
const database = (_a = options === null || options === void 0 ? void 0 : options.database) !== null && _a !== void 0 ? _a : (0, database_1.default)();
|
|
19
|
+
const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database, bypassCache: true }));
|
|
20
|
+
const nestedActionEvents = [];
|
|
21
|
+
const mutationOptions = {
|
|
22
|
+
autoPurgeSystemCache: false,
|
|
23
|
+
bypassEmitAction: (params) => nestedActionEvents.push(params),
|
|
24
|
+
};
|
|
25
|
+
await database.transaction(async (trx) => {
|
|
26
|
+
const collectionsService = new services_1.CollectionsService({ knex: trx, schema });
|
|
27
|
+
const getNestedCollectionsToCreate = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].rhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
|
|
28
|
+
const getNestedCollectionsToDelete = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].lhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
|
|
29
|
+
const createCollections = async (collections) => {
|
|
30
|
+
for (const { collection, diff } of collections) {
|
|
31
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.NEW && diff[0].rhs) {
|
|
32
|
+
// We'll nest the to-be-created fields in the same collection creation, to prevent
|
|
33
|
+
// creating a collection without a primary key
|
|
34
|
+
const fields = snapshotDiff.fields
|
|
35
|
+
.filter((fieldDiff) => fieldDiff.collection === collection)
|
|
36
|
+
.map((fieldDiff) => fieldDiff.diff[0].rhs)
|
|
37
|
+
.map((fieldDiff) => {
|
|
38
|
+
var _a, _b, _c, _d, _e;
|
|
39
|
+
// Casts field type to UUID when applying non-PostgreSQL schema onto PostgreSQL database.
|
|
40
|
+
// This is needed because they snapshots UUID fields as char/varchar with length 36.
|
|
41
|
+
if (['char', 'varchar'].includes(String((_a = fieldDiff.schema) === null || _a === void 0 ? void 0 : _a.data_type).toLowerCase()) &&
|
|
42
|
+
((_b = fieldDiff.schema) === null || _b === void 0 ? void 0 : _b.max_length) === 36 &&
|
|
43
|
+
(((_c = fieldDiff.schema) === null || _c === void 0 ? void 0 : _c.is_primary_key) ||
|
|
44
|
+
(((_d = fieldDiff.schema) === null || _d === void 0 ? void 0 : _d.foreign_key_table) && ((_e = fieldDiff.schema) === null || _e === void 0 ? void 0 : _e.foreign_key_column)))) {
|
|
45
|
+
return (0, lodash_1.merge)(fieldDiff, { type: 'uuid', schema: { data_type: 'uuid', max_length: null } });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
return fieldDiff;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
try {
|
|
52
|
+
await collectionsService.createOne({
|
|
53
|
+
...diff[0].rhs,
|
|
54
|
+
fields,
|
|
55
|
+
}, mutationOptions);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
logger_1.default.error(`Failed to create collection "${collection}"`);
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
// Now that the fields are in for this collection, we can strip them from the field edits
|
|
62
|
+
snapshotDiff.fields = snapshotDiff.fields.filter((fieldDiff) => fieldDiff.collection !== collection);
|
|
63
|
+
await createCollections(getNestedCollectionsToCreate(collection));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const deleteCollections = async (collections) => {
|
|
68
|
+
for (const { collection, diff } of collections) {
|
|
69
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.DELETE) {
|
|
70
|
+
const relations = schema.relations.filter((r) => r.related_collection === collection || r.collection === collection);
|
|
71
|
+
if (relations.length > 0) {
|
|
72
|
+
const relationsService = new services_1.RelationsService({ knex: trx, schema });
|
|
73
|
+
for (const relation of relations) {
|
|
74
|
+
try {
|
|
75
|
+
await relationsService.deleteOne(relation.collection, relation.field, mutationOptions);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
logger_1.default.error(`Failed to delete collection "${collection}" due to relation "${relation.collection}.${relation.field}"`);
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// clean up deleted relations from existing schema
|
|
83
|
+
schema.relations = schema.relations.filter((r) => r.related_collection !== collection && r.collection !== collection);
|
|
84
|
+
}
|
|
85
|
+
await deleteCollections(getNestedCollectionsToDelete(collection));
|
|
86
|
+
try {
|
|
87
|
+
await collectionsService.deleteOne(collection, mutationOptions);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
logger_1.default.error(`Failed to delete collection "${collection}"`);
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
// Finds all collections that need to be created
|
|
97
|
+
const filterCollectionsForCreation = ({ diff }) => {
|
|
98
|
+
var _a;
|
|
99
|
+
// Check new collections only
|
|
100
|
+
const isNewCollection = diff[0].kind === types_1.DiffKind.NEW;
|
|
101
|
+
if (!isNewCollection)
|
|
102
|
+
return false;
|
|
103
|
+
// Create now if no group
|
|
104
|
+
const groupName = (_a = diff[0].rhs.meta) === null || _a === void 0 ? void 0 : _a.group;
|
|
105
|
+
if (!groupName)
|
|
106
|
+
return true;
|
|
107
|
+
// Check if parent collection already exists in schema
|
|
108
|
+
const parentExists = currentSnapshot.collections.find((c) => c.collection === groupName) !== undefined;
|
|
109
|
+
// If this is a new collection and the parent collection doesn't exist in current schema ->
|
|
110
|
+
// Check if the parent collection will be created as part of applying this snapshot ->
|
|
111
|
+
// If yes -> this collection will be created recursively
|
|
112
|
+
// If not -> create now
|
|
113
|
+
// (ex.)
|
|
114
|
+
// TopLevelCollection - I exist in current schema
|
|
115
|
+
// NestedCollection - I exist in snapshotDiff as a new collection
|
|
116
|
+
// TheCurrentCollectionInIteration - I exist in snapshotDiff as a new collection but will be created as part of NestedCollection
|
|
117
|
+
const parentWillBeCreatedInThisApply = snapshotDiff.collections.filter(({ collection, diff }) => diff[0].kind === types_1.DiffKind.NEW && collection === groupName).length > 0;
|
|
118
|
+
// Has group, but parent is not new, parent is also not being created in this snapshot apply
|
|
119
|
+
if (parentExists && !parentWillBeCreatedInThisApply)
|
|
120
|
+
return true;
|
|
121
|
+
return false;
|
|
122
|
+
};
|
|
123
|
+
// Create top level collections (no group, or highest level in existing group) first,
|
|
124
|
+
// then continue with nested collections recursively
|
|
125
|
+
await createCollections(snapshotDiff.collections.filter(filterCollectionsForCreation));
|
|
126
|
+
// delete top level collections (no group) first, then continue with nested collections recursively
|
|
127
|
+
await deleteCollections(snapshotDiff.collections.filter(({ diff }) => { var _a; return diff[0].kind === types_1.DiffKind.DELETE && ((_a = diff[0].lhs.meta) === null || _a === void 0 ? void 0 : _a.group) === null; }));
|
|
128
|
+
for (const { collection, diff } of snapshotDiff.collections) {
|
|
129
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.EDIT || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.ARRAY) {
|
|
130
|
+
const currentCollection = currentSnapshot.collections.find((field) => {
|
|
131
|
+
return field.collection === collection;
|
|
132
|
+
});
|
|
133
|
+
if (currentCollection) {
|
|
134
|
+
try {
|
|
135
|
+
const newValues = diff.reduce((acc, currentDiff) => {
|
|
136
|
+
(0, deep_diff_1.applyChange)(acc, undefined, currentDiff);
|
|
137
|
+
return acc;
|
|
138
|
+
}, (0, lodash_1.cloneDeep)(currentCollection));
|
|
139
|
+
await collectionsService.updateOne(collection, newValues, mutationOptions);
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
logger_1.default.error(`Failed to update collection "${collection}"`);
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const fieldsService = new services_1.FieldsService({
|
|
149
|
+
knex: trx,
|
|
150
|
+
schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
|
|
151
|
+
});
|
|
152
|
+
for (const { collection, field, diff } of snapshotDiff.fields) {
|
|
153
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.NEW && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
154
|
+
try {
|
|
155
|
+
await fieldsService.createField(collection, diff[0].rhs, undefined, mutationOptions);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
logger_1.default.error(`Failed to create field "${collection}.${field}"`);
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.EDIT || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.ARRAY || isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
163
|
+
const currentField = currentSnapshot.fields.find((snapshotField) => {
|
|
164
|
+
return snapshotField.collection === collection && snapshotField.field === field;
|
|
165
|
+
});
|
|
166
|
+
if (currentField) {
|
|
167
|
+
try {
|
|
168
|
+
const newValues = diff.reduce((acc, currentDiff) => {
|
|
169
|
+
(0, deep_diff_1.applyChange)(acc, undefined, currentDiff);
|
|
170
|
+
return acc;
|
|
171
|
+
}, (0, lodash_1.cloneDeep)(currentField));
|
|
172
|
+
await fieldsService.updateField(collection, newValues, mutationOptions);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
logger_1.default.error(`Failed to update field "${collection}.${field}"`);
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.DELETE && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
181
|
+
try {
|
|
182
|
+
await fieldsService.deleteField(collection, field, mutationOptions);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
logger_1.default.error(`Failed to delete field "${collection}.${field}"`);
|
|
186
|
+
throw err;
|
|
187
|
+
}
|
|
188
|
+
// Field deletion also cleans up the relationship. We should ignore any relationship
|
|
189
|
+
// changes attached to this now non-existing field
|
|
190
|
+
snapshotDiff.relations = snapshotDiff.relations.filter((relation) => (relation.collection === collection && relation.field === field) === false);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const relationsService = new services_1.RelationsService({
|
|
194
|
+
knex: trx,
|
|
195
|
+
schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
|
|
196
|
+
});
|
|
197
|
+
for (const { collection, field, diff } of snapshotDiff.relations) {
|
|
198
|
+
const structure = {};
|
|
199
|
+
for (const diffEdit of diff) {
|
|
200
|
+
(0, lodash_1.set)(structure, diffEdit.path, undefined);
|
|
201
|
+
}
|
|
202
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.NEW) {
|
|
203
|
+
try {
|
|
204
|
+
await relationsService.createOne(diff[0].rhs, mutationOptions);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
logger_1.default.error(`Failed to create relation "${collection}.${field}"`);
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.EDIT || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.ARRAY) {
|
|
212
|
+
const currentRelation = currentSnapshot.relations.find((relation) => {
|
|
213
|
+
return relation.collection === collection && relation.field === field;
|
|
214
|
+
});
|
|
215
|
+
if (currentRelation) {
|
|
216
|
+
try {
|
|
217
|
+
const newValues = diff.reduce((acc, currentDiff) => {
|
|
218
|
+
(0, deep_diff_1.applyChange)(acc, undefined, currentDiff);
|
|
219
|
+
return acc;
|
|
220
|
+
}, (0, lodash_1.cloneDeep)(currentRelation));
|
|
221
|
+
await relationsService.updateOne(collection, field, newValues, mutationOptions);
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
logger_1.default.error(`Failed to update relation "${collection}.${field}"`);
|
|
225
|
+
throw err;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === types_1.DiffKind.DELETE) {
|
|
230
|
+
try {
|
|
231
|
+
await relationsService.deleteOne(collection, field, mutationOptions);
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
logger_1.default.error(`Failed to delete relation "${collection}.${field}"`);
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
await (0, cache_1.clearSystemCache)();
|
|
241
|
+
if (nestedActionEvents.length > 0) {
|
|
242
|
+
const updatedSchema = await (0, get_schema_1.getSchema)({ database, bypassCache: true });
|
|
243
|
+
for (const nestedActionEvent of nestedActionEvents) {
|
|
244
|
+
nestedActionEvent.context.schema = updatedSchema;
|
|
245
|
+
emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
exports.applyDiff = applyDiff;
|
|
250
|
+
function isNestedMetaUpdate(diff) {
|
|
251
|
+
if (!diff)
|
|
252
|
+
return false;
|
|
253
|
+
if (diff.kind !== types_1.DiffKind.NEW && diff.kind !== types_1.DiffKind.DELETE)
|
|
254
|
+
return false;
|
|
255
|
+
if (!diff.path || diff.path.length < 2 || diff.path[0] !== 'meta')
|
|
256
|
+
return false;
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
exports.isNestedMetaUpdate = isNestedMetaUpdate;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -23,15 +23,15 @@ function applyQuery(knex, collection, dbQuery, query, schema, options) {
|
|
|
23
23
|
var _a;
|
|
24
24
|
const aliasMap = (_a = options === null || options === void 0 ? void 0 : options.aliasMap) !== null && _a !== void 0 ? _a : Object.create(null);
|
|
25
25
|
let hasMultiRelationalFilter = false;
|
|
26
|
-
if (query.sort && !(options === null || options === void 0 ? void 0 : options.isInnerQuery) && !(options === null || options === void 0 ? void 0 : options.hasMultiRelationalSort)) {
|
|
27
|
-
applySort(knex, schema, dbQuery, query.sort, collection, aliasMap);
|
|
28
|
-
}
|
|
29
26
|
applyLimit(knex, dbQuery, query.limit);
|
|
30
27
|
if (query.offset) {
|
|
31
28
|
applyOffset(knex, dbQuery, query.offset);
|
|
32
29
|
}
|
|
33
30
|
if (query.page && query.limit && query.limit !== -1) {
|
|
34
|
-
dbQuery
|
|
31
|
+
applyOffset(knex, dbQuery, query.limit * (query.page - 1));
|
|
32
|
+
}
|
|
33
|
+
if (query.sort && !(options === null || options === void 0 ? void 0 : options.isInnerQuery) && !(options === null || options === void 0 ? void 0 : options.hasMultiRelationalSort)) {
|
|
34
|
+
applySort(knex, schema, dbQuery, query.sort, collection, aliasMap);
|
|
35
35
|
}
|
|
36
36
|
if (query.search) {
|
|
37
37
|
applySearch(schema, dbQuery, query.search, collection);
|
|
@@ -170,6 +170,8 @@ function applySort(knex, schema, rootQuery, rootSort, collection, aliasMap, retu
|
|
|
170
170
|
});
|
|
171
171
|
if (returnRecords)
|
|
172
172
|
return { sortRecords, hasMultiRelationalSort };
|
|
173
|
+
// Clears the order if any, eg: from MSSQL offset
|
|
174
|
+
rootQuery.clear('order');
|
|
173
175
|
rootQuery.orderBy(sortRecords);
|
|
174
176
|
}
|
|
175
177
|
exports.applySort = applySort;
|
|
@@ -333,12 +335,12 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, aliasMap)
|
|
|
333
335
|
}
|
|
334
336
|
if (operator === '_empty' || (operator === '_nempty' && compareValue === false)) {
|
|
335
337
|
dbQuery[logical].andWhere((query) => {
|
|
336
|
-
query.
|
|
338
|
+
query.whereNull(key).orWhere(key, '=', '');
|
|
337
339
|
});
|
|
338
340
|
}
|
|
339
341
|
if (operator === '_nempty' || (operator === '_empty' && compareValue === false)) {
|
|
340
342
|
dbQuery[logical].andWhere((query) => {
|
|
341
|
-
query.
|
|
343
|
+
query.whereNotNull(key).orWhere(key, '!=', '');
|
|
342
344
|
});
|
|
343
345
|
}
|
|
344
346
|
// The following fields however, require a value to be run. If no value is passed, we
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { SchemaOverview } from '@directus/shared/types';
|
|
2
|
-
import { Diff } from 'deep-diff';
|
|
3
2
|
import { Knex } from 'knex';
|
|
4
|
-
import { Snapshot, SnapshotDiff
|
|
3
|
+
import { Snapshot, SnapshotDiff } from '../types';
|
|
5
4
|
export declare function applySnapshot(snapshot: Snapshot, options?: {
|
|
6
5
|
database?: Knex;
|
|
7
6
|
schema?: SchemaOverview;
|
|
8
7
|
current?: Snapshot;
|
|
9
8
|
diff?: SnapshotDiff;
|
|
10
9
|
}): Promise<void>;
|
|
11
|
-
export declare function isNestedMetaUpdate(diff: Diff<SnapshotField | undefined>): boolean;
|
|
@@ -3,16 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const
|
|
6
|
+
exports.applySnapshot = void 0;
|
|
7
|
+
const cache_1 = require("../cache");
|
|
8
8
|
const database_1 = __importDefault(require("../database"));
|
|
9
|
-
const
|
|
10
|
-
const services_1 = require("../services");
|
|
9
|
+
const apply_diff_1 = require("./apply-diff");
|
|
11
10
|
const get_schema_1 = require("./get-schema");
|
|
12
11
|
const get_snapshot_1 = require("./get-snapshot");
|
|
13
12
|
const get_snapshot_diff_1 = require("./get-snapshot-diff");
|
|
14
|
-
const cache_1 = require("../cache");
|
|
15
|
-
const emitter_1 = __importDefault(require("../emitter"));
|
|
16
13
|
async function applySnapshot(snapshot, options) {
|
|
17
14
|
var _a, _b, _c, _d;
|
|
18
15
|
const database = (_a = options === null || options === void 0 ? void 0 : options.database) !== null && _a !== void 0 ? _a : (0, database_1.default)();
|
|
@@ -20,234 +17,7 @@ async function applySnapshot(snapshot, options) {
|
|
|
20
17
|
const { systemCache } = (0, cache_1.getCache)();
|
|
21
18
|
const current = (_c = options === null || options === void 0 ? void 0 : options.current) !== null && _c !== void 0 ? _c : (await (0, get_snapshot_1.getSnapshot)({ database, schema }));
|
|
22
19
|
const snapshotDiff = (_d = options === null || options === void 0 ? void 0 : options.diff) !== null && _d !== void 0 ? _d : (0, get_snapshot_diff_1.getSnapshotDiff)(current, snapshot);
|
|
23
|
-
|
|
24
|
-
const mutationOptions = {
|
|
25
|
-
autoPurgeSystemCache: false,
|
|
26
|
-
bypassEmitAction: (params) => nestedActionEvents.push(params),
|
|
27
|
-
};
|
|
28
|
-
await database.transaction(async (trx) => {
|
|
29
|
-
const collectionsService = new services_1.CollectionsService({ knex: trx, schema });
|
|
30
|
-
const getNestedCollectionsToCreate = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].rhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
|
|
31
|
-
const getNestedCollectionsToDelete = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].lhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
|
|
32
|
-
const createCollections = async (collections) => {
|
|
33
|
-
for (const { collection, diff } of collections) {
|
|
34
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N' && diff[0].rhs) {
|
|
35
|
-
// We'll nest the to-be-created fields in the same collection creation, to prevent
|
|
36
|
-
// creating a collection without a primary key
|
|
37
|
-
const fields = snapshotDiff.fields
|
|
38
|
-
.filter((fieldDiff) => fieldDiff.collection === collection)
|
|
39
|
-
.map((fieldDiff) => fieldDiff.diff[0].rhs)
|
|
40
|
-
.map((fieldDiff) => {
|
|
41
|
-
var _a, _b, _c, _d, _e;
|
|
42
|
-
// Casts field type to UUID when applying non-PostgreSQL schema onto PostgreSQL database.
|
|
43
|
-
// This is needed because they snapshots UUID fields as char with length 36.
|
|
44
|
-
if (((_a = fieldDiff.schema) === null || _a === void 0 ? void 0 : _a.data_type) === 'char' &&
|
|
45
|
-
((_b = fieldDiff.schema) === null || _b === void 0 ? void 0 : _b.max_length) === 36 &&
|
|
46
|
-
(((_c = fieldDiff.schema) === null || _c === void 0 ? void 0 : _c.is_primary_key) ||
|
|
47
|
-
(((_d = fieldDiff.schema) === null || _d === void 0 ? void 0 : _d.foreign_key_table) && ((_e = fieldDiff.schema) === null || _e === void 0 ? void 0 : _e.foreign_key_column)))) {
|
|
48
|
-
return (0, lodash_1.merge)(fieldDiff, { type: 'uuid', schema: { data_type: 'uuid', max_length: null } });
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
return fieldDiff;
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
try {
|
|
55
|
-
await collectionsService.createOne({
|
|
56
|
-
...diff[0].rhs,
|
|
57
|
-
fields,
|
|
58
|
-
}, mutationOptions);
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
logger_1.default.error(`Failed to create collection "${collection}"`);
|
|
62
|
-
throw err;
|
|
63
|
-
}
|
|
64
|
-
// Now that the fields are in for this collection, we can strip them from the field edits
|
|
65
|
-
snapshotDiff.fields = snapshotDiff.fields.filter((fieldDiff) => fieldDiff.collection !== collection);
|
|
66
|
-
await createCollections(getNestedCollectionsToCreate(collection));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
const deleteCollections = async (collections) => {
|
|
71
|
-
for (const { collection, diff } of collections) {
|
|
72
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
|
|
73
|
-
const relations = schema.relations.filter((r) => r.related_collection === collection || r.collection === collection);
|
|
74
|
-
if (relations.length > 0) {
|
|
75
|
-
const relationsService = new services_1.RelationsService({ knex: trx, schema });
|
|
76
|
-
for (const relation of relations) {
|
|
77
|
-
try {
|
|
78
|
-
await relationsService.deleteOne(relation.collection, relation.field, mutationOptions);
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
logger_1.default.error(`Failed to delete collection "${collection}" due to relation "${relation.collection}.${relation.field}"`);
|
|
82
|
-
throw err;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// clean up deleted relations from existing schema
|
|
86
|
-
schema.relations = schema.relations.filter((r) => r.related_collection !== collection && r.collection !== collection);
|
|
87
|
-
}
|
|
88
|
-
await deleteCollections(getNestedCollectionsToDelete(collection));
|
|
89
|
-
try {
|
|
90
|
-
await collectionsService.deleteOne(collection, mutationOptions);
|
|
91
|
-
}
|
|
92
|
-
catch (err) {
|
|
93
|
-
logger_1.default.error(`Failed to delete collection "${collection}"`);
|
|
94
|
-
throw err;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
// Finds all collections that need to be created
|
|
100
|
-
const filterCollectionsForCreation = ({ diff }) => {
|
|
101
|
-
var _a;
|
|
102
|
-
// Check new collections only
|
|
103
|
-
const isNewCollection = diff[0].kind === 'N';
|
|
104
|
-
if (!isNewCollection)
|
|
105
|
-
return false;
|
|
106
|
-
// Create now if no group
|
|
107
|
-
const groupName = (_a = diff[0].rhs.meta) === null || _a === void 0 ? void 0 : _a.group;
|
|
108
|
-
if (!groupName)
|
|
109
|
-
return true;
|
|
110
|
-
// Check if parent collection already exists in schema
|
|
111
|
-
const parentExists = current.collections.find((c) => c.collection === groupName) !== undefined;
|
|
112
|
-
// If this is a new collection and the parent collection doesn't exist in current schema ->
|
|
113
|
-
// Check if the parent collection will be created as part of applying this snapshot ->
|
|
114
|
-
// If yes -> this collection will be created recursively
|
|
115
|
-
// If not -> create now
|
|
116
|
-
// (ex.)
|
|
117
|
-
// TopLevelCollection - I exist in current schema
|
|
118
|
-
// NestedCollection - I exist in snapshotDiff as a new collection
|
|
119
|
-
// TheCurrentCollectionInIteration - I exist in snapshotDiff as a new collection but will be created as part of NestedCollection
|
|
120
|
-
const parentWillBeCreatedInThisApply = snapshotDiff.collections.filter(({ collection, diff }) => diff[0].kind === 'N' && collection === groupName)
|
|
121
|
-
.length > 0;
|
|
122
|
-
// Has group, but parent is not new, parent is also not being created in this snapshot apply
|
|
123
|
-
if (parentExists && !parentWillBeCreatedInThisApply)
|
|
124
|
-
return true;
|
|
125
|
-
return false;
|
|
126
|
-
};
|
|
127
|
-
// Create top level collections (no group, or highest level in existing group) first,
|
|
128
|
-
// then continue with nested collections recursively
|
|
129
|
-
await createCollections(snapshotDiff.collections.filter(filterCollectionsForCreation));
|
|
130
|
-
// delete top level collections (no group) first, then continue with nested collections recursively
|
|
131
|
-
await deleteCollections(snapshotDiff.collections.filter(({ diff }) => { var _a; return diff[0].kind === 'D' && ((_a = diff[0].lhs.meta) === null || _a === void 0 ? void 0 : _a.group) === null; }));
|
|
132
|
-
for (const { collection, diff } of snapshotDiff.collections) {
|
|
133
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
|
|
134
|
-
const newValues = snapshot.collections.find((field) => {
|
|
135
|
-
return field.collection === collection;
|
|
136
|
-
});
|
|
137
|
-
if (newValues) {
|
|
138
|
-
try {
|
|
139
|
-
await collectionsService.updateOne(collection, newValues, mutationOptions);
|
|
140
|
-
}
|
|
141
|
-
catch (err) {
|
|
142
|
-
logger_1.default.error(`Failed to update collection "${collection}"`);
|
|
143
|
-
throw err;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const fieldsService = new services_1.FieldsService({
|
|
149
|
-
knex: trx,
|
|
150
|
-
schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
|
|
151
|
-
});
|
|
152
|
-
for (const { collection, field, diff } of snapshotDiff.fields) {
|
|
153
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
154
|
-
try {
|
|
155
|
-
await fieldsService.createField(collection, diff[0].rhs, undefined, mutationOptions);
|
|
156
|
-
}
|
|
157
|
-
catch (err) {
|
|
158
|
-
logger_1.default.error(`Failed to create field "${collection}.${field}"`);
|
|
159
|
-
throw err;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A' || isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
163
|
-
const newValues = snapshot.fields.find((snapshotField) => {
|
|
164
|
-
return snapshotField.collection === collection && snapshotField.field === field;
|
|
165
|
-
});
|
|
166
|
-
if (newValues) {
|
|
167
|
-
try {
|
|
168
|
-
await fieldsService.updateField(collection, {
|
|
169
|
-
...newValues,
|
|
170
|
-
}, mutationOptions);
|
|
171
|
-
}
|
|
172
|
-
catch (err) {
|
|
173
|
-
logger_1.default.error(`Failed to update field "${collection}.${field}"`);
|
|
174
|
-
throw err;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
179
|
-
try {
|
|
180
|
-
await fieldsService.deleteField(collection, field, mutationOptions);
|
|
181
|
-
}
|
|
182
|
-
catch (err) {
|
|
183
|
-
logger_1.default.error(`Failed to delete field "${collection}.${field}"`);
|
|
184
|
-
throw err;
|
|
185
|
-
}
|
|
186
|
-
// Field deletion also cleans up the relationship. We should ignore any relationship
|
|
187
|
-
// changes attached to this now non-existing field
|
|
188
|
-
snapshotDiff.relations = snapshotDiff.relations.filter((relation) => (relation.collection === collection && relation.field === field) === false);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const relationsService = new services_1.RelationsService({
|
|
192
|
-
knex: trx,
|
|
193
|
-
schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
|
|
194
|
-
});
|
|
195
|
-
for (const { collection, field, diff } of snapshotDiff.relations) {
|
|
196
|
-
const structure = {};
|
|
197
|
-
for (const diffEdit of diff) {
|
|
198
|
-
(0, lodash_1.set)(structure, diffEdit.path, undefined);
|
|
199
|
-
}
|
|
200
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N') {
|
|
201
|
-
try {
|
|
202
|
-
await relationsService.createOne(diff[0].rhs, mutationOptions);
|
|
203
|
-
}
|
|
204
|
-
catch (err) {
|
|
205
|
-
logger_1.default.error(`Failed to create relation "${collection}.${field}"`);
|
|
206
|
-
throw err;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
|
|
210
|
-
const newValues = snapshot.relations.find((relation) => {
|
|
211
|
-
return relation.collection === collection && relation.field === field;
|
|
212
|
-
});
|
|
213
|
-
if (newValues) {
|
|
214
|
-
try {
|
|
215
|
-
await relationsService.updateOne(collection, field, newValues, mutationOptions);
|
|
216
|
-
}
|
|
217
|
-
catch (err) {
|
|
218
|
-
logger_1.default.error(`Failed to update relation "${collection}.${field}"`);
|
|
219
|
-
throw err;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
|
|
224
|
-
try {
|
|
225
|
-
await relationsService.deleteOne(collection, field, mutationOptions);
|
|
226
|
-
}
|
|
227
|
-
catch (err) {
|
|
228
|
-
logger_1.default.error(`Failed to delete relation "${collection}.${field}"`);
|
|
229
|
-
throw err;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
20
|
+
await (0, apply_diff_1.applyDiff)(current, snapshotDiff, { database, schema });
|
|
234
21
|
await (systemCache === null || systemCache === void 0 ? void 0 : systemCache.clear());
|
|
235
|
-
if (nestedActionEvents.length > 0) {
|
|
236
|
-
const updatedSchema = await (0, get_schema_1.getSchema)({ database, bypassCache: true });
|
|
237
|
-
for (const nestedActionEvent of nestedActionEvents) {
|
|
238
|
-
nestedActionEvent.context.schema = updatedSchema;
|
|
239
|
-
emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
22
|
}
|
|
243
23
|
exports.applySnapshot = applySnapshot;
|
|
244
|
-
function isNestedMetaUpdate(diff) {
|
|
245
|
-
if (!diff)
|
|
246
|
-
return false;
|
|
247
|
-
if (diff.kind !== 'N' && diff.kind !== 'D')
|
|
248
|
-
return false;
|
|
249
|
-
if (!diff.path || diff.path.length < 2 || diff.path[0] !== 'meta')
|
|
250
|
-
return false;
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
exports.isNestedMetaUpdate = isNestedMetaUpdate;
|
|
@@ -4,5 +4,7 @@ import { Request } from 'express';
|
|
|
4
4
|
*
|
|
5
5
|
* @param req Express request object
|
|
6
6
|
* @param ttl TTL of the cache in ms
|
|
7
|
+
* @param globalCacheSettings Whether requests are affected by the global cache settings (i.e. for dynamic API requests)
|
|
8
|
+
* @param personalized Whether requests depend on the authentication status of users
|
|
7
9
|
*/
|
|
8
|
-
export declare function getCacheControlHeader(req: Request, ttl: number |
|
|
10
|
+
export declare function getCacheControlHeader(req: Request, ttl: number | undefined, globalCacheSettings: boolean, personalized: boolean): string;
|
|
@@ -10,34 +10,35 @@ const env_1 = __importDefault(require("../env"));
|
|
|
10
10
|
*
|
|
11
11
|
* @param req Express request object
|
|
12
12
|
* @param ttl TTL of the cache in ms
|
|
13
|
+
* @param globalCacheSettings Whether requests are affected by the global cache settings (i.e. for dynamic API requests)
|
|
14
|
+
* @param personalized Whether requests depend on the authentication status of users
|
|
13
15
|
*/
|
|
14
|
-
function getCacheControlHeader(req, ttl) {
|
|
16
|
+
function getCacheControlHeader(req, ttl, globalCacheSettings, personalized) {
|
|
15
17
|
var _a, _b, _c;
|
|
16
|
-
// When the resource / current request isn't cached
|
|
17
|
-
if (ttl === null)
|
|
18
|
-
return 'no-cache';
|
|
19
|
-
// When the API cache can invalidate at any moment
|
|
20
|
-
if (env_1.default.CACHE_AUTO_PURGE === true)
|
|
21
|
-
return 'no-cache';
|
|
22
18
|
const noCacheRequested = ((_a = req.headers['cache-control']) === null || _a === void 0 ? void 0 : _a.includes('no-store')) || ((_b = req.headers['Cache-Control']) === null || _b === void 0 ? void 0 : _b.includes('no-store'));
|
|
23
19
|
// When the user explicitly asked to skip the cache
|
|
24
20
|
if (noCacheRequested)
|
|
25
21
|
return 'no-store';
|
|
22
|
+
// When the resource / current request shouldn't be cached
|
|
23
|
+
if (ttl === undefined || ttl < 0)
|
|
24
|
+
return 'no-cache';
|
|
25
|
+
// When the API cache can invalidate at any moment
|
|
26
|
+
if (globalCacheSettings && env_1.default.CACHE_AUTO_PURGE === true)
|
|
27
|
+
return 'no-cache';
|
|
28
|
+
const headerValues = [];
|
|
29
|
+
// When caching depends on the authentication status of the users
|
|
30
|
+
if (personalized) {
|
|
31
|
+
// Allow response to be stored in shared cache (public) or local cache only (private)
|
|
32
|
+
const access = !!((_c = req.accountability) === null || _c === void 0 ? void 0 : _c.role) === false ? 'public' : 'private';
|
|
33
|
+
headerValues.push(access);
|
|
34
|
+
}
|
|
26
35
|
// Cache control header uses seconds for everything
|
|
27
36
|
const ttlSeconds = Math.round(ttl / 1000);
|
|
28
|
-
|
|
29
|
-
let headerValue = `${access}, max-age=${ttlSeconds}`;
|
|
37
|
+
headerValues.push(`max-age=${ttlSeconds}`);
|
|
30
38
|
// When the s-maxage flag should be included
|
|
31
|
-
if (env_1.default.CACHE_CONTROL_S_MAXAGE
|
|
32
|
-
|
|
33
|
-
if (env_1.default.CACHE_CONTROL_S_MAXAGE === true) {
|
|
34
|
-
headerValue += `, s-maxage=${ttlSeconds}`;
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
// Set to custom value
|
|
38
|
-
headerValue += `, s-maxage=${env_1.default.CACHE_CONTROL_S_MAXAGE}`;
|
|
39
|
-
}
|
|
39
|
+
if (globalCacheSettings && Number.isInteger(env_1.default.CACHE_CONTROL_S_MAXAGE) && env_1.default.CACHE_CONTROL_S_MAXAGE >= 0) {
|
|
40
|
+
headerValues.push(`s-maxage=${env_1.default.CACHE_CONTROL_S_MAXAGE}`);
|
|
40
41
|
}
|
|
41
|
-
return
|
|
42
|
+
return headerValues.join(', ');
|
|
42
43
|
}
|
|
43
44
|
exports.getCacheControlHeader = getCacheControlHeader;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|