directus 9.8.0 → 9.9.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/dist/__mocks__/cache.d.ts +5 -0
- package/dist/__mocks__/cache.js +7 -0
- package/dist/auth/drivers/ldap.js +10 -11
- package/dist/auth/drivers/oauth2.js +9 -4
- package/dist/auth/drivers/openid.js +7 -4
- package/dist/cli/commands/schema/apply.js +9 -3
- package/dist/controllers/assets.js +5 -0
- package/dist/controllers/files.d.ts +2 -0
- package/dist/controllers/files.js +10 -5
- package/dist/database/helpers/date/dialects/mssql.d.ts +4 -0
- package/dist/database/helpers/date/dialects/mssql.js +12 -0
- package/dist/database/helpers/date/dialects/mysql.d.ts +5 -0
- package/dist/database/helpers/date/dialects/mysql.js +16 -0
- package/dist/database/helpers/date/dialects/oracle.d.ts +4 -0
- package/dist/database/helpers/date/dialects/oracle.js +15 -0
- package/dist/database/helpers/date/dialects/sqlite.d.ts +1 -0
- package/dist/database/helpers/date/dialects/sqlite.js +8 -0
- package/dist/database/helpers/date/index.d.ts +3 -3
- package/dist/database/helpers/date/index.js +6 -6
- package/dist/database/helpers/date/types.d.ts +3 -0
- package/dist/database/helpers/date/types.js +10 -0
- package/dist/database/helpers/index.d.ts +1 -1
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.d.ts +3 -0
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.js +22 -0
- package/dist/database/system-data/fields/settings.yaml +0 -1
- package/dist/database/system-data/fields/users.yaml +3 -0
- package/dist/env.js +3 -1
- package/dist/exceptions/index.d.ts +1 -0
- package/dist/exceptions/index.js +1 -0
- package/dist/exceptions/token-expired.d.ts +4 -0
- package/dist/exceptions/token-expired.js +10 -0
- package/dist/middleware/cache.js +10 -0
- package/dist/services/authorization.js +72 -30
- package/dist/services/collections.d.ts +2 -0
- package/dist/services/collections.js +8 -0
- package/dist/services/fields.js +24 -1
- package/dist/services/files.d.ts +5 -1
- package/dist/services/files.js +59 -40
- package/dist/services/graphql.d.ts +2 -3
- package/dist/services/graphql.js +39 -9
- package/dist/services/payload.d.ts +1 -0
- package/dist/services/payload.js +19 -16
- package/dist/types/files.d.ts +8 -0
- package/dist/utils/apply-query.js +17 -7
- package/dist/utils/apply-snapshot.d.ts +3 -1
- package/dist/utils/apply-snapshot.js +34 -5
- package/dist/utils/get-graphql-type.js +1 -0
- package/dist/utils/get-local-type.js +5 -0
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/validate-query.js +19 -15
- package/example.env +4 -0
- package/package.json +14 -13
package/dist/services/payload.js
CHANGED
|
@@ -89,14 +89,14 @@ class PayloadService {
|
|
|
89
89
|
return (accountability === null || accountability === void 0 ? void 0 : accountability.role) || null;
|
|
90
90
|
return value;
|
|
91
91
|
},
|
|
92
|
-
async 'date-created'({ action, value }) {
|
|
92
|
+
async 'date-created'({ action, value, helpers }) {
|
|
93
93
|
if (action === 'create')
|
|
94
|
-
return new Date();
|
|
94
|
+
return new Date(helpers.date.writeTimestamp(new Date().toISOString()));
|
|
95
95
|
return value;
|
|
96
96
|
},
|
|
97
|
-
async 'date-updated'({ action, value }) {
|
|
97
|
+
async 'date-updated'({ action, value, helpers }) {
|
|
98
98
|
if (action === 'update')
|
|
99
|
-
return new Date();
|
|
99
|
+
return new Date(helpers.date.writeTimestamp(new Date().toISOString()));
|
|
100
100
|
return value;
|
|
101
101
|
},
|
|
102
102
|
async 'cast-csv'({ action, value }) {
|
|
@@ -181,6 +181,7 @@ class PayloadService {
|
|
|
181
181
|
payload,
|
|
182
182
|
accountability,
|
|
183
183
|
specials: fieldSpecials,
|
|
184
|
+
helpers: this.helpers,
|
|
184
185
|
});
|
|
185
186
|
}
|
|
186
187
|
}
|
|
@@ -233,21 +234,23 @@ class PayloadService {
|
|
|
233
234
|
value = new Date(value);
|
|
234
235
|
}
|
|
235
236
|
if (dateColumn.type === 'timestamp') {
|
|
236
|
-
const newValue = value.toISOString();
|
|
237
|
+
const newValue = this.helpers.date.readTimestampString(value.toISOString());
|
|
237
238
|
payload[name] = newValue;
|
|
238
239
|
}
|
|
239
240
|
if (dateColumn.type === 'dateTime') {
|
|
240
|
-
const year = String(value.
|
|
241
|
-
const month = String(value.
|
|
242
|
-
const
|
|
243
|
-
const hours = String(value.
|
|
244
|
-
const minutes = String(value.
|
|
245
|
-
const seconds = String(value.
|
|
246
|
-
const newValue = `${year}-${month}-${
|
|
241
|
+
const year = String(value.getFullYear());
|
|
242
|
+
const month = String(value.getMonth() + 1).padStart(2, '0');
|
|
243
|
+
const day = String(value.getDate()).padStart(2, '0');
|
|
244
|
+
const hours = String(value.getHours()).padStart(2, '0');
|
|
245
|
+
const minutes = String(value.getMinutes()).padStart(2, '0');
|
|
246
|
+
const seconds = String(value.getSeconds()).padStart(2, '0');
|
|
247
|
+
const newValue = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
|
|
247
248
|
payload[name] = newValue;
|
|
248
249
|
}
|
|
249
250
|
if (dateColumn.type === 'date') {
|
|
250
|
-
const
|
|
251
|
+
const year = String(value.getFullYear());
|
|
252
|
+
const month = String(value.getMonth() + 1).padStart(2, '0');
|
|
253
|
+
const day = String(value.getDate()).padStart(2, '0');
|
|
251
254
|
// Strip off the time / timezone information from a date-only value
|
|
252
255
|
const newValue = `${year}-${month}-${day}`;
|
|
253
256
|
payload[name] = newValue;
|
|
@@ -258,16 +261,16 @@ class PayloadService {
|
|
|
258
261
|
if (dateColumn.type === 'date') {
|
|
259
262
|
const [date] = value.split('T');
|
|
260
263
|
const [year, month, day] = date.split('-');
|
|
261
|
-
payload[name] = new Date(
|
|
264
|
+
payload[name] = new Date(Number(year), Number(month) - 1, Number(day));
|
|
262
265
|
}
|
|
263
266
|
if (dateColumn.type === 'dateTime') {
|
|
264
267
|
const [date, time] = value.split('T');
|
|
265
268
|
const [year, month, day] = date.split('-');
|
|
266
269
|
const [hours, minutes, seconds] = time.substring(0, 8).split(':');
|
|
267
|
-
payload[name] = new Date(
|
|
270
|
+
payload[name] = new Date(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes), Number(seconds));
|
|
268
271
|
}
|
|
269
272
|
if (dateColumn.type === 'timestamp') {
|
|
270
|
-
const newValue =
|
|
273
|
+
const newValue = this.helpers.date.writeTimestamp(value);
|
|
271
274
|
payload[name] = newValue;
|
|
272
275
|
}
|
|
273
276
|
}
|
package/dist/types/files.d.ts
CHANGED
|
@@ -19,3 +19,11 @@ export declare type File = {
|
|
|
19
19
|
tags: string | null;
|
|
20
20
|
metadata: Record<string, any> | null;
|
|
21
21
|
};
|
|
22
|
+
export declare type Metadata = {
|
|
23
|
+
height?: number | undefined;
|
|
24
|
+
width?: number | undefined;
|
|
25
|
+
description?: string | undefined;
|
|
26
|
+
title?: string | undefined;
|
|
27
|
+
tags?: any | undefined;
|
|
28
|
+
metadata?: any | undefined;
|
|
29
|
+
};
|
|
@@ -180,6 +180,7 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
function addWhereClauses(knex, dbQuery, filter, collection, logical = 'and') {
|
|
183
|
+
var _a, _b;
|
|
183
184
|
for (const [key, value] of Object.entries(filter)) {
|
|
184
185
|
if (key === '_or' || key === '_and') {
|
|
185
186
|
// If the _or array contains an empty object (full permissions), we should short-circuit and ignore all other
|
|
@@ -220,16 +221,25 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
220
221
|
if (relationType === 'o2a') {
|
|
221
222
|
pkField = knex.raw(`CAST(?? AS CHAR(255))`, [pkField]);
|
|
222
223
|
}
|
|
223
|
-
|
|
224
|
-
dbQuery[logical].whereIn(pkField, (subQueryKnex) => {
|
|
224
|
+
const subQueryBuilder = (filter) => (subQueryKnex) => {
|
|
225
225
|
const field = relation.field;
|
|
226
226
|
const collection = relation.collection;
|
|
227
227
|
const column = `${collection}.${field}`;
|
|
228
|
-
subQueryKnex
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
228
|
+
subQueryKnex
|
|
229
|
+
.select({ [field]: column })
|
|
230
|
+
.from(collection)
|
|
231
|
+
.whereNotNull(field);
|
|
232
|
+
applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema, true);
|
|
233
|
+
};
|
|
234
|
+
if (((_a = Object.keys(value)) === null || _a === void 0 ? void 0 : _a[0]) === '_none') {
|
|
235
|
+
dbQuery[logical].whereNotIn(pkField, subQueryBuilder(Object.values(value)[0]));
|
|
236
|
+
}
|
|
237
|
+
else if (((_b = Object.keys(value)) === null || _b === void 0 ? void 0 : _b[0]) === '_some') {
|
|
238
|
+
dbQuery[logical].whereIn(pkField, subQueryBuilder(Object.values(value)[0]));
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
dbQuery[logical].whereIn(pkField, subQueryBuilder(value));
|
|
242
|
+
}
|
|
233
243
|
}
|
|
234
244
|
}
|
|
235
245
|
function applyFilterToQuery(key, operator, compareValue, logical = 'and') {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Snapshot, SnapshotDiff } from '../types';
|
|
1
|
+
import { Snapshot, SnapshotDiff, SnapshotField } from '../types';
|
|
2
2
|
import { Knex } from 'knex';
|
|
3
|
+
import { Diff } from 'deep-diff';
|
|
3
4
|
import { SchemaOverview } from '@directus/shared/types';
|
|
4
5
|
export declare function applySnapshot(snapshot: Snapshot, options?: {
|
|
5
6
|
database?: Knex;
|
|
@@ -7,3 +8,4 @@ export declare function applySnapshot(snapshot: Snapshot, options?: {
|
|
|
7
8
|
current?: Snapshot;
|
|
8
9
|
diff?: SnapshotDiff;
|
|
9
10
|
}): Promise<void>;
|
|
11
|
+
export declare function isNestedMetaUpdate(diff: Diff<SnapshotField | undefined>): boolean;
|
|
@@ -3,7 +3,7 @@ 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.applySnapshot = void 0;
|
|
6
|
+
exports.isNestedMetaUpdate = exports.applySnapshot = void 0;
|
|
7
7
|
const get_snapshot_1 = require("./get-snapshot");
|
|
8
8
|
const get_snapshot_diff_1 = require("./get-snapshot-diff");
|
|
9
9
|
const database_1 = __importDefault(require("../database"));
|
|
@@ -34,7 +34,26 @@ async function applySnapshot(snapshot, options) {
|
|
|
34
34
|
// creating a collection without a primary key
|
|
35
35
|
const fields = snapshotDiff.fields
|
|
36
36
|
.filter((fieldDiff) => fieldDiff.collection === collection)
|
|
37
|
-
.map((fieldDiff) => fieldDiff.diff[0].rhs)
|
|
37
|
+
.map((fieldDiff) => fieldDiff.diff[0].rhs)
|
|
38
|
+
.map((fieldDiff) => {
|
|
39
|
+
// Casts field type to UUID when applying SQLite-based schema on other databases.
|
|
40
|
+
// This is needed because SQLite snapshots UUID fields as char with length 36, and
|
|
41
|
+
// it will fail when trying to create relation between char field to UUID field
|
|
42
|
+
if (!fieldDiff.schema ||
|
|
43
|
+
fieldDiff.schema.data_type !== 'char' ||
|
|
44
|
+
fieldDiff.schema.max_length !== 36 ||
|
|
45
|
+
!fieldDiff.schema.foreign_key_table ||
|
|
46
|
+
!fieldDiff.schema.foreign_key_column) {
|
|
47
|
+
return fieldDiff;
|
|
48
|
+
}
|
|
49
|
+
const matchingForeignKeyTable = schema.collections[fieldDiff.schema.foreign_key_table];
|
|
50
|
+
if (!matchingForeignKeyTable)
|
|
51
|
+
return fieldDiff;
|
|
52
|
+
const matchingForeignKeyField = matchingForeignKeyTable.fields[fieldDiff.schema.foreign_key_column];
|
|
53
|
+
if (!matchingForeignKeyField || matchingForeignKeyField.type !== 'uuid')
|
|
54
|
+
return fieldDiff;
|
|
55
|
+
return (0, lodash_1.merge)(fieldDiff, { type: 'uuid', schema: { data_type: 'uuid', max_length: null } });
|
|
56
|
+
});
|
|
38
57
|
try {
|
|
39
58
|
await collectionsService.createOne({
|
|
40
59
|
...diff[0].rhs,
|
|
@@ -66,7 +85,7 @@ async function applySnapshot(snapshot, options) {
|
|
|
66
85
|
}
|
|
67
86
|
const fieldsService = new services_1.FieldsService({ knex: trx, schema: await (0, get_schema_1.getSchema)({ database: trx }) });
|
|
68
87
|
for (const { collection, field, diff } of snapshotDiff.fields) {
|
|
69
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N') {
|
|
88
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
70
89
|
try {
|
|
71
90
|
await fieldsService.createField(collection, diff[0].rhs);
|
|
72
91
|
}
|
|
@@ -75,7 +94,7 @@ async function applySnapshot(snapshot, options) {
|
|
|
75
94
|
throw err;
|
|
76
95
|
}
|
|
77
96
|
}
|
|
78
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
|
|
97
|
+
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])) {
|
|
79
98
|
const newValues = snapshot.fields.find((snapshotField) => {
|
|
80
99
|
return snapshotField.collection === collection && snapshotField.field === field;
|
|
81
100
|
});
|
|
@@ -91,7 +110,7 @@ async function applySnapshot(snapshot, options) {
|
|
|
91
110
|
}
|
|
92
111
|
}
|
|
93
112
|
}
|
|
94
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
|
|
113
|
+
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
95
114
|
try {
|
|
96
115
|
await fieldsService.deleteField(collection, field);
|
|
97
116
|
}
|
|
@@ -146,3 +165,13 @@ async function applySnapshot(snapshot, options) {
|
|
|
146
165
|
});
|
|
147
166
|
}
|
|
148
167
|
exports.applySnapshot = applySnapshot;
|
|
168
|
+
function isNestedMetaUpdate(diff) {
|
|
169
|
+
if (!diff)
|
|
170
|
+
return false;
|
|
171
|
+
if (diff.kind !== 'N' && diff.kind !== 'D')
|
|
172
|
+
return false;
|
|
173
|
+
if (!diff.path || diff.path.length < 2 || diff.path[0] !== 'meta')
|
|
174
|
+
return false;
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
exports.isNestedMetaUpdate = isNestedMetaUpdate;
|
|
@@ -88,6 +88,7 @@ const localTypeMap = {
|
|
|
88
88
|
'time without time zone': 'time',
|
|
89
89
|
float4: 'float',
|
|
90
90
|
float8: 'float',
|
|
91
|
+
citext: 'text',
|
|
91
92
|
// Oracle
|
|
92
93
|
number: 'integer',
|
|
93
94
|
sdo_geometry: 'geometry',
|
|
@@ -109,6 +110,10 @@ function getLocalType(column, field) {
|
|
|
109
110
|
return 'csv';
|
|
110
111
|
if (special.includes('uuid') || special.includes('file'))
|
|
111
112
|
return 'uuid';
|
|
113
|
+
if (special.includes('cast-timestamp'))
|
|
114
|
+
return 'timestamp';
|
|
115
|
+
if (special.includes('cast-datetime'))
|
|
116
|
+
return 'dateTime';
|
|
112
117
|
if (type === null || type === void 0 ? void 0 : type.startsWith('geometry')) {
|
|
113
118
|
return special[0] || 'geometry';
|
|
114
119
|
}
|
package/dist/utils/jwt.js
CHANGED
|
@@ -31,7 +31,7 @@ function verifyAccessJWT(token, secret) {
|
|
|
31
31
|
}
|
|
32
32
|
catch (err) {
|
|
33
33
|
if (err instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
34
|
-
throw new exceptions_1.
|
|
34
|
+
throw new exceptions_1.TokenExpiredException();
|
|
35
35
|
}
|
|
36
36
|
else if (err instanceof jsonwebtoken_1.JsonWebTokenError) {
|
|
37
37
|
throw new exceptions_1.InvalidTokenException('Token invalid.');
|
|
@@ -47,21 +47,6 @@ function validateFilter(filter) {
|
|
|
47
47
|
else if (key.startsWith('_')) {
|
|
48
48
|
const value = nested;
|
|
49
49
|
switch (key) {
|
|
50
|
-
case '_eq':
|
|
51
|
-
case '_neq':
|
|
52
|
-
case '_contains':
|
|
53
|
-
case '_ncontains':
|
|
54
|
-
case '_starts_with':
|
|
55
|
-
case '_nstarts_with':
|
|
56
|
-
case '_ends_with':
|
|
57
|
-
case '_nends_with':
|
|
58
|
-
case '_gt':
|
|
59
|
-
case '_gte':
|
|
60
|
-
case '_lt':
|
|
61
|
-
case '_lte':
|
|
62
|
-
default:
|
|
63
|
-
validateFilterPrimitive(value, key);
|
|
64
|
-
break;
|
|
65
50
|
case '_in':
|
|
66
51
|
case '_nin':
|
|
67
52
|
case '_between':
|
|
@@ -80,6 +65,25 @@ function validateFilter(filter) {
|
|
|
80
65
|
case '_nintersects_bbox':
|
|
81
66
|
validateGeometry(value, key);
|
|
82
67
|
break;
|
|
68
|
+
case '_none':
|
|
69
|
+
case '_some':
|
|
70
|
+
validateFilter(nested);
|
|
71
|
+
break;
|
|
72
|
+
case '_eq':
|
|
73
|
+
case '_neq':
|
|
74
|
+
case '_contains':
|
|
75
|
+
case '_ncontains':
|
|
76
|
+
case '_starts_with':
|
|
77
|
+
case '_nstarts_with':
|
|
78
|
+
case '_ends_with':
|
|
79
|
+
case '_nends_with':
|
|
80
|
+
case '_gt':
|
|
81
|
+
case '_gte':
|
|
82
|
+
case '_lt':
|
|
83
|
+
case '_lte':
|
|
84
|
+
default:
|
|
85
|
+
validateFilterPrimitive(value, key);
|
|
86
|
+
break;
|
|
83
87
|
}
|
|
84
88
|
}
|
|
85
89
|
else if ((0, lodash_1.isPlainObject)(nested)) {
|
package/example.env
CHANGED
|
@@ -123,6 +123,10 @@ STORAGE_LOCAL_ROOT="./uploads"
|
|
|
123
123
|
# STORAGE_GOOGLE_KEY_FILENAME="abcdef"
|
|
124
124
|
# STORAGE_GOOGLE_BUCKET="my-files"
|
|
125
125
|
|
|
126
|
+
|
|
127
|
+
## CSV of additional metadata keys
|
|
128
|
+
# FILE_METADATA_ALLOW_LIST=
|
|
129
|
+
|
|
126
130
|
####################################################################################################
|
|
127
131
|
# Security
|
|
128
132
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.9.0",
|
|
4
4
|
"license": "GPL-3.0-only",
|
|
5
5
|
"homepage": "https://github.com/directus/directus#readme",
|
|
6
6
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content.",
|
|
@@ -78,16 +78,16 @@
|
|
|
78
78
|
],
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@aws-sdk/client-ses": "^3.40.0",
|
|
81
|
-
"@directus/app": "9.
|
|
82
|
-
"@directus/drive": "9.
|
|
83
|
-
"@directus/drive-azure": "9.
|
|
84
|
-
"@directus/drive-gcs": "9.
|
|
85
|
-
"@directus/drive-s3": "9.
|
|
86
|
-
"@directus/extensions-sdk": "9.
|
|
87
|
-
"@directus/format-title": "9.
|
|
88
|
-
"@directus/schema": "9.
|
|
89
|
-
"@directus/shared": "9.
|
|
90
|
-
"@directus/specs": "9.
|
|
81
|
+
"@directus/app": "9.9.0",
|
|
82
|
+
"@directus/drive": "9.9.0",
|
|
83
|
+
"@directus/drive-azure": "9.9.0",
|
|
84
|
+
"@directus/drive-gcs": "9.9.0",
|
|
85
|
+
"@directus/drive-s3": "9.9.0",
|
|
86
|
+
"@directus/extensions-sdk": "9.9.0",
|
|
87
|
+
"@directus/format-title": "9.9.0",
|
|
88
|
+
"@directus/schema": "9.9.0",
|
|
89
|
+
"@directus/shared": "9.9.0",
|
|
90
|
+
"@directus/specs": "9.9.0",
|
|
91
91
|
"@godaddy/terminus": "^4.9.0",
|
|
92
92
|
"@rollup/plugin-alias": "^3.1.9",
|
|
93
93
|
"@rollup/plugin-virtual": "^2.0.3",
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"resolve-cwd": "^3.0.0",
|
|
151
151
|
"rollup": "^2.67.3",
|
|
152
152
|
"sanitize-html": "^2.6.0",
|
|
153
|
-
"sharp": "^0.
|
|
153
|
+
"sharp": "^0.30.3",
|
|
154
154
|
"stream-json": "^1.7.1",
|
|
155
155
|
"supertest": "^6.1.6",
|
|
156
156
|
"tmp-promise": "^3.0.3",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"sqlite3": "^5.0.2",
|
|
174
174
|
"tedious": "^13.0.0"
|
|
175
175
|
},
|
|
176
|
-
"gitHead": "
|
|
176
|
+
"gitHead": "fb252ca4cef57de1aa8d1914db6bc85730902e81",
|
|
177
177
|
"devDependencies": {
|
|
178
178
|
"@types/async": "3.2.10",
|
|
179
179
|
"@types/body-parser": "1.19.2",
|
|
@@ -214,6 +214,7 @@
|
|
|
214
214
|
"@types/wellknown": "0.5.1",
|
|
215
215
|
"copyfiles": "2.4.1",
|
|
216
216
|
"cross-env": "7.0.3",
|
|
217
|
+
"form-data": "^4.0.0",
|
|
217
218
|
"jest": "27.5.1",
|
|
218
219
|
"knex-mock-client": "1.6.1",
|
|
219
220
|
"ts-jest": "27.1.3",
|