directus 9.12.0 → 9.13.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/app.js +11 -1
- package/dist/auth/drivers/index.js +5 -1
- package/dist/auth/drivers/ldap.js +5 -1
- package/dist/auth/drivers/oauth2.js +15 -23
- package/dist/auth/drivers/openid.js +16 -24
- package/dist/cli/commands/bootstrap/index.js +5 -1
- package/dist/cli/commands/schema/apply.js +7 -3
- package/dist/cli/commands/schema/snapshot.d.ts +1 -1
- package/dist/cli/commands/schema/snapshot.js +33 -25
- package/dist/cli/index.js +1 -1
- package/dist/cli/utils/create-env/env-stub.liquid +11 -11
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +5 -1
- package/dist/controllers/assets.js +5 -5
- package/dist/controllers/dashboards.js +4 -1
- package/dist/controllers/files.js +8 -5
- package/dist/controllers/flows.js +4 -1
- package/dist/controllers/folders.js +4 -1
- package/dist/controllers/items.js +4 -1
- package/dist/controllers/notifications.js +4 -1
- package/dist/controllers/operations.js +4 -1
- package/dist/controllers/panels.js +4 -1
- package/dist/controllers/permissions.js +4 -1
- package/dist/controllers/presets.js +4 -1
- package/dist/controllers/roles.js +4 -1
- package/dist/controllers/shares.js +4 -1
- package/dist/controllers/users.js +75 -3
- package/dist/controllers/utils.js +3 -3
- package/dist/database/helpers/date/dialects/sqlite.js +3 -0
- package/dist/database/helpers/fn/dialects/oracle.d.ts +9 -9
- package/dist/database/helpers/fn/dialects/oracle.js +22 -16
- package/dist/database/helpers/fn/dialects/sqlite.d.ts +9 -9
- package/dist/database/helpers/fn/dialects/sqlite.js +46 -16
- package/dist/database/helpers/fn/types.d.ts +12 -9
- package/dist/database/helpers/index.js +5 -1
- package/dist/database/index.js +2 -0
- package/dist/database/migrations/20210225A-add-relations-sort-field.js +2 -2
- package/dist/database/migrations/20210506A-rename-interfaces.js +2 -2
- package/dist/database/migrations/20210802A-replace-groups.js +2 -2
- package/dist/database/migrations/20210805A-update-groups.js +2 -2
- package/dist/database/migrations/20210805B-change-image-metadata-structure.js +3 -3
- package/dist/database/migrations/20211007A-update-presets.js +5 -5
- package/dist/database/migrations/20220429A-add-flows.js +1 -2
- package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.d.ts +3 -0
- package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.js +11 -0
- package/dist/database/system-data/fields/dashboards.yaml +1 -0
- package/dist/database/system-data/fields/flows.yaml +1 -1
- package/dist/env.d.ts +1 -1
- package/dist/env.js +8 -3
- package/dist/exceptions/database/translate.js +5 -1
- package/dist/exceptions/index.js +5 -1
- package/dist/extensions.d.ts +2 -1
- package/dist/extensions.js +31 -23
- package/dist/flows.d.ts +5 -0
- package/dist/flows.js +66 -40
- package/dist/index.js +5 -1
- package/dist/logger.js +5 -1
- package/dist/messenger.js +2 -2
- package/dist/middleware/graphql.js +2 -2
- package/dist/middleware/respond.js +10 -1
- package/dist/middleware/validate-batch.js +3 -1
- package/dist/operations/item-create/index.js +1 -2
- package/dist/operations/item-delete/index.d.ts +1 -0
- package/dist/operations/item-delete/index.js +8 -7
- package/dist/operations/item-read/index.js +7 -6
- package/dist/operations/item-update/index.d.ts +1 -0
- package/dist/operations/item-update/index.js +9 -8
- package/dist/operations/log/index.js +1 -2
- package/dist/operations/notification/index.js +1 -2
- package/dist/operations/request/index.d.ts +4 -1
- package/dist/operations/request/index.js +5 -1
- package/dist/operations/transform/index.js +1 -2
- package/dist/operations/trigger/index.js +1 -2
- package/dist/server.js +5 -1
- package/dist/services/assets.js +5 -1
- package/dist/services/collections.js +5 -1
- package/dist/services/fields.d.ts +3 -3
- package/dist/services/fields.js +25 -17
- package/dist/services/files.js +5 -1
- package/dist/services/flows.d.ts +1 -2
- package/dist/services/flows.js +19 -8
- package/dist/services/{graphql.d.ts → graphql/index.d.ts} +3 -5
- package/dist/services/{graphql.js → graphql/index.js} +115 -102
- package/dist/services/graphql/types/date.d.ts +2 -0
- package/dist/services/graphql/types/date.js +9 -0
- package/dist/services/graphql/types/geojson.d.ts +2 -0
- package/dist/services/graphql/types/geojson.js +10 -0
- package/dist/services/graphql/types/string-or-float.d.ts +5 -0
- package/dist/services/graphql/types/string-or-float.js +34 -0
- package/dist/services/graphql/types/void.d.ts +2 -0
- package/dist/services/graphql/types/void.js +17 -0
- package/dist/services/graphql/utils/add-path-to-validation-error.d.ts +2 -0
- package/dist/services/graphql/utils/add-path-to-validation-error.js +20 -0
- package/dist/services/import-export.js +13 -10
- package/dist/services/index.js +5 -1
- package/dist/services/items.d.ts +5 -1
- package/dist/services/items.js +22 -2
- package/dist/services/mail/index.js +8 -6
- package/dist/services/operations.d.ts +1 -2
- package/dist/services/operations.js +19 -8
- package/dist/services/payload.js +2 -3
- package/dist/services/permissions.d.ts +1 -0
- package/dist/services/permissions.js +5 -0
- package/dist/services/relations.js +5 -1
- package/dist/services/roles.d.ts +1 -0
- package/dist/services/roles.js +9 -0
- package/dist/services/server.js +5 -1
- package/dist/services/users.d.ts +1 -0
- package/dist/services/users.js +22 -0
- package/dist/types/index.js +5 -1
- package/dist/utils/apply-query.js +24 -15
- package/dist/utils/apply-snapshot.js +3 -0
- package/dist/utils/calculate-field-depth.d.ts +33 -0
- package/dist/utils/calculate-field-depth.js +75 -0
- package/dist/utils/get-column.js +1 -1
- package/dist/utils/get-default-value.js +3 -13
- package/dist/utils/get-graphql-type.js +4 -3
- package/dist/utils/get-local-type.d.ts +6 -3
- package/dist/utils/get-permissions.js +3 -4
- package/dist/utils/get-schema.js +1 -2
- package/dist/utils/get-string-byte-size.d.ts +4 -0
- package/dist/utils/get-string-byte-size.js +10 -0
- package/dist/utils/job-queue.d.ts +9 -0
- package/dist/utils/job-queue.js +24 -0
- package/dist/utils/jwt.js +5 -1
- package/dist/utils/sanitize-query.js +4 -5
- package/dist/utils/validate-query.js +50 -0
- package/dist/webhooks.js +5 -1
- package/package.json +75 -74
- package/dist/utils/operation-options.d.ts +0 -3
- package/dist/utils/operation-options.js +0 -45
- package/dist/utils/parse-json.d.ts +0 -5
- package/dist/utils/parse-json.js +0 -19
|
@@ -3,70 +3,56 @@ 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.GraphQLService =
|
|
6
|
+
exports.GraphQLService = void 0;
|
|
7
7
|
const types_1 = require("@directus/shared/types");
|
|
8
8
|
const argon2_1 = __importDefault(require("argon2"));
|
|
9
9
|
const graphql_1 = require("graphql");
|
|
10
10
|
const graphql_compose_1 = require("graphql-compose");
|
|
11
11
|
const lodash_1 = require("lodash");
|
|
12
12
|
const ms_1 = __importDefault(require("ms"));
|
|
13
|
-
const cache_1 = require("
|
|
14
|
-
const constants_1 = require("
|
|
15
|
-
const database_1 = __importDefault(require("
|
|
16
|
-
const env_1 = __importDefault(require("
|
|
17
|
-
const exceptions_1 = require("
|
|
18
|
-
const extensions_1 = require("
|
|
19
|
-
const generate_hash_1 = require("
|
|
20
|
-
const get_graphql_type_1 = require("
|
|
21
|
-
const reduce_schema_1 = require("
|
|
22
|
-
const sanitize_query_1 = require("
|
|
23
|
-
const validate_query_1 = require("
|
|
24
|
-
const activity_1 = require("
|
|
25
|
-
const authentication_1 = require("
|
|
26
|
-
const collections_1 = require("
|
|
27
|
-
const fields_1 = require("
|
|
28
|
-
const files_1 = require("
|
|
29
|
-
const flows_1 = require("
|
|
30
|
-
const folders_1 = require("
|
|
31
|
-
const items_1 = require("
|
|
32
|
-
const notifications_1 = require("
|
|
33
|
-
const operations_1 = require("
|
|
34
|
-
const permissions_1 = require("
|
|
35
|
-
const presets_1 = require("
|
|
36
|
-
const relations_1 = require("
|
|
37
|
-
const revisions_1 = require("
|
|
38
|
-
const roles_1 = require("
|
|
39
|
-
const server_1 = require("
|
|
40
|
-
const settings_1 = require("
|
|
41
|
-
const shares_1 = require("
|
|
42
|
-
const specifications_1 = require("
|
|
43
|
-
const tfa_1 = require("
|
|
44
|
-
const users_1 = require("
|
|
45
|
-
const utils_1 = require("
|
|
46
|
-
const webhooks_1 = require("
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
parseLiteral() {
|
|
57
|
-
return null;
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
exports.GraphQLGeoJSON = new graphql_1.GraphQLScalarType({
|
|
61
|
-
...graphql_compose_1.GraphQLJSON,
|
|
62
|
-
name: 'GraphQLGeoJSON',
|
|
63
|
-
description: 'GeoJSON value',
|
|
64
|
-
});
|
|
65
|
-
exports.GraphQLDate = new graphql_1.GraphQLScalarType({
|
|
66
|
-
...graphql_1.GraphQLString,
|
|
67
|
-
name: 'Date',
|
|
68
|
-
description: 'ISO8601 Date values',
|
|
69
|
-
});
|
|
13
|
+
const cache_1 = require("../../cache");
|
|
14
|
+
const constants_1 = require("../../constants");
|
|
15
|
+
const database_1 = __importDefault(require("../../database"));
|
|
16
|
+
const env_1 = __importDefault(require("../../env"));
|
|
17
|
+
const exceptions_1 = require("../../exceptions");
|
|
18
|
+
const extensions_1 = require("../../extensions");
|
|
19
|
+
const generate_hash_1 = require("../../utils/generate-hash");
|
|
20
|
+
const get_graphql_type_1 = require("../../utils/get-graphql-type");
|
|
21
|
+
const reduce_schema_1 = require("../../utils/reduce-schema");
|
|
22
|
+
const sanitize_query_1 = require("../../utils/sanitize-query");
|
|
23
|
+
const validate_query_1 = require("../../utils/validate-query");
|
|
24
|
+
const activity_1 = require("../activity");
|
|
25
|
+
const authentication_1 = require("../authentication");
|
|
26
|
+
const collections_1 = require("../collections");
|
|
27
|
+
const fields_1 = require("../fields");
|
|
28
|
+
const files_1 = require("../files");
|
|
29
|
+
const flows_1 = require("../flows");
|
|
30
|
+
const folders_1 = require("../folders");
|
|
31
|
+
const items_1 = require("../items");
|
|
32
|
+
const notifications_1 = require("../notifications");
|
|
33
|
+
const operations_1 = require("../operations");
|
|
34
|
+
const permissions_1 = require("../permissions");
|
|
35
|
+
const presets_1 = require("../presets");
|
|
36
|
+
const relations_1 = require("../relations");
|
|
37
|
+
const revisions_1 = require("../revisions");
|
|
38
|
+
const roles_1 = require("../roles");
|
|
39
|
+
const server_1 = require("../server");
|
|
40
|
+
const settings_1 = require("../settings");
|
|
41
|
+
const shares_1 = require("../shares");
|
|
42
|
+
const specifications_1 = require("../specifications");
|
|
43
|
+
const tfa_1 = require("../tfa");
|
|
44
|
+
const users_1 = require("../users");
|
|
45
|
+
const utils_1 = require("../utils");
|
|
46
|
+
const webhooks_1 = require("../webhooks");
|
|
47
|
+
const date_1 = require("./types/date");
|
|
48
|
+
const geojson_1 = require("./types/geojson");
|
|
49
|
+
const string_or_float_1 = require("./types/string-or-float");
|
|
50
|
+
const void_1 = require("./types/void");
|
|
51
|
+
const add_path_to_validation_error_1 = require("./utils/add-path-to-validation-error");
|
|
52
|
+
const validationRules = Array.from(graphql_1.specifiedRules);
|
|
53
|
+
if (env_1.default.GRAPHQL_INTROSPECTION === false) {
|
|
54
|
+
validationRules.push(graphql_1.NoSchemaIntrospectionCustomRule);
|
|
55
|
+
}
|
|
70
56
|
/**
|
|
71
57
|
* These should be ignored in the context of GraphQL, and/or are replaced by a custom resolver (for non-standard structures)
|
|
72
58
|
*/
|
|
@@ -91,16 +77,7 @@ class GraphQLService {
|
|
|
91
77
|
async execute({ document, variables, operationName, contextValue, }) {
|
|
92
78
|
var _a;
|
|
93
79
|
const schema = this.getSchema();
|
|
94
|
-
const validationErrors = (0, graphql_1.validate)(schema, document,
|
|
95
|
-
...graphql_1.specifiedRules,
|
|
96
|
-
(context) => ({
|
|
97
|
-
Field(node) {
|
|
98
|
-
if (env_1.default.GRAPHQL_INTROSPECTION === false && (node.name.value === '__schema' || node.name.value === '__type')) {
|
|
99
|
-
context.reportError(new graphql_1.GraphQLError('GraphQL introspection is not allowed. The query contained __schema or __type.', [node]));
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
}),
|
|
103
|
-
]);
|
|
80
|
+
const validationErrors = (0, graphql_1.validate)(schema, document, validationRules).map((validationError) => (0, add_path_to_validation_error_1.addPathToValidationError)(validationError));
|
|
104
81
|
if (validationErrors.length > 0) {
|
|
105
82
|
throw new exceptions_1.GraphQLValidationException({ graphqlErrors: validationErrors });
|
|
106
83
|
}
|
|
@@ -180,7 +157,7 @@ class GraphQLService {
|
|
|
180
157
|
else {
|
|
181
158
|
schemaComposer.Query.addFields({
|
|
182
159
|
_empty: {
|
|
183
|
-
type: GraphQLVoid,
|
|
160
|
+
type: void_1.GraphQLVoid,
|
|
184
161
|
description: "There's no data to query.",
|
|
185
162
|
},
|
|
186
163
|
});
|
|
@@ -209,6 +186,7 @@ class GraphQLService {
|
|
|
209
186
|
}
|
|
210
187
|
else {
|
|
211
188
|
acc[`update_${collectionName}_items`] = UpdateCollectionTypes[collection.collection].getResolver(`update_${collection.collection}_items`);
|
|
189
|
+
acc[`update_${collectionName}_batch`] = UpdateCollectionTypes[collection.collection].getResolver(`update_${collection.collection}_batch`);
|
|
212
190
|
acc[`update_${collectionName}_item`] = UpdateCollectionTypes[collection.collection].getResolver(`update_${collection.collection}_item`);
|
|
213
191
|
}
|
|
214
192
|
return acc;
|
|
@@ -512,32 +490,33 @@ class GraphQLService {
|
|
|
512
490
|
},
|
|
513
491
|
},
|
|
514
492
|
});
|
|
493
|
+
// Uses StringOrFloat rather than Float to support api dynamic variables (like `$NOW`)
|
|
515
494
|
const NumberFilterOperators = schemaComposer.createInputTC({
|
|
516
495
|
name: 'number_filter_operators',
|
|
517
496
|
fields: {
|
|
518
497
|
_eq: {
|
|
519
|
-
type:
|
|
498
|
+
type: string_or_float_1.GraphQLStringOrFloat,
|
|
520
499
|
},
|
|
521
500
|
_neq: {
|
|
522
|
-
type:
|
|
501
|
+
type: string_or_float_1.GraphQLStringOrFloat,
|
|
523
502
|
},
|
|
524
503
|
_in: {
|
|
525
|
-
type: new graphql_1.GraphQLList(
|
|
504
|
+
type: new graphql_1.GraphQLList(string_or_float_1.GraphQLStringOrFloat),
|
|
526
505
|
},
|
|
527
506
|
_nin: {
|
|
528
|
-
type: new graphql_1.GraphQLList(
|
|
507
|
+
type: new graphql_1.GraphQLList(string_or_float_1.GraphQLStringOrFloat),
|
|
529
508
|
},
|
|
530
509
|
_gt: {
|
|
531
|
-
type:
|
|
510
|
+
type: string_or_float_1.GraphQLStringOrFloat,
|
|
532
511
|
},
|
|
533
512
|
_gte: {
|
|
534
|
-
type:
|
|
513
|
+
type: string_or_float_1.GraphQLStringOrFloat,
|
|
535
514
|
},
|
|
536
515
|
_lt: {
|
|
537
|
-
type:
|
|
516
|
+
type: string_or_float_1.GraphQLStringOrFloat,
|
|
538
517
|
},
|
|
539
518
|
_lte: {
|
|
540
|
-
type:
|
|
519
|
+
type: string_or_float_1.GraphQLStringOrFloat,
|
|
541
520
|
},
|
|
542
521
|
_null: {
|
|
543
522
|
type: graphql_1.GraphQLBoolean,
|
|
@@ -551,22 +530,22 @@ class GraphQLService {
|
|
|
551
530
|
name: 'geometry_filter_operators',
|
|
552
531
|
fields: {
|
|
553
532
|
_eq: {
|
|
554
|
-
type:
|
|
533
|
+
type: geojson_1.GraphQLGeoJSON,
|
|
555
534
|
},
|
|
556
535
|
_neq: {
|
|
557
|
-
type:
|
|
536
|
+
type: geojson_1.GraphQLGeoJSON,
|
|
558
537
|
},
|
|
559
538
|
_intersects: {
|
|
560
|
-
type:
|
|
539
|
+
type: geojson_1.GraphQLGeoJSON,
|
|
561
540
|
},
|
|
562
541
|
_nintersects: {
|
|
563
|
-
type:
|
|
542
|
+
type: geojson_1.GraphQLGeoJSON,
|
|
564
543
|
},
|
|
565
544
|
_intersects_bbox: {
|
|
566
|
-
type:
|
|
545
|
+
type: geojson_1.GraphQLGeoJSON,
|
|
567
546
|
},
|
|
568
547
|
_nintersects_bbox: {
|
|
569
|
-
type:
|
|
548
|
+
type: geojson_1.GraphQLGeoJSON,
|
|
570
549
|
},
|
|
571
550
|
},
|
|
572
551
|
});
|
|
@@ -637,10 +616,10 @@ class GraphQLService {
|
|
|
637
616
|
case graphql_1.GraphQLFloat:
|
|
638
617
|
filterOperatorType = NumberFilterOperators;
|
|
639
618
|
break;
|
|
640
|
-
case
|
|
619
|
+
case date_1.GraphQLDate:
|
|
641
620
|
filterOperatorType = DateFilterOperators;
|
|
642
621
|
break;
|
|
643
|
-
case
|
|
622
|
+
case geojson_1.GraphQLGeoJSON:
|
|
644
623
|
filterOperatorType = GeometryFilterOperators;
|
|
645
624
|
break;
|
|
646
625
|
default:
|
|
@@ -782,7 +761,7 @@ class GraphQLService {
|
|
|
782
761
|
},
|
|
783
762
|
type: collection.singleton
|
|
784
763
|
? ReadCollectionTypes[collection.collection]
|
|
785
|
-
:
|
|
764
|
+
: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(ReadCollectionTypes[collection.collection].getType()))),
|
|
786
765
|
resolve: async ({ info, context }) => {
|
|
787
766
|
const result = await self.resolveQuery(info);
|
|
788
767
|
context.data = result;
|
|
@@ -791,7 +770,7 @@ class GraphQLService {
|
|
|
791
770
|
});
|
|
792
771
|
ReadCollectionTypes[collection.collection].addResolver({
|
|
793
772
|
name: `${collection.collection}_aggregated`,
|
|
794
|
-
type:
|
|
773
|
+
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(AggregatedFunctions[collection.collection].getType()))),
|
|
795
774
|
args: {
|
|
796
775
|
groupBy: new graphql_1.GraphQLList(graphql_1.GraphQLString),
|
|
797
776
|
filter: ReadableCollectionFilterTypes[collection.collection],
|
|
@@ -901,7 +880,9 @@ class GraphQLService {
|
|
|
901
880
|
if (Object.keys(creatableFields).length > 0) {
|
|
902
881
|
CreateCollectionTypes[collection.collection].addResolver({
|
|
903
882
|
name: `create_${collection.collection}_items`,
|
|
904
|
-
type: collectionIsReadable
|
|
883
|
+
type: collectionIsReadable
|
|
884
|
+
? new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(ReadCollectionTypes[collection.collection].getType())))
|
|
885
|
+
: graphql_1.GraphQLBoolean,
|
|
905
886
|
args: collectionIsReadable
|
|
906
887
|
? ReadCollectionTypes[collection.collection].getResolver(collection.collection).getArgs()
|
|
907
888
|
: undefined,
|
|
@@ -949,9 +930,26 @@ class GraphQLService {
|
|
|
949
930
|
});
|
|
950
931
|
}
|
|
951
932
|
else {
|
|
933
|
+
UpdateCollectionTypes[collection.collection].addResolver({
|
|
934
|
+
name: `update_${collection.collection}_batch`,
|
|
935
|
+
type: collectionIsReadable
|
|
936
|
+
? new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(ReadCollectionTypes[collection.collection].getType())))
|
|
937
|
+
: graphql_1.GraphQLBoolean,
|
|
938
|
+
args: {
|
|
939
|
+
...(collectionIsReadable
|
|
940
|
+
? ReadCollectionTypes[collection.collection].getResolver(collection.collection).getArgs()
|
|
941
|
+
: {}),
|
|
942
|
+
data: [
|
|
943
|
+
(0, graphql_compose_1.toInputObjectType)(UpdateCollectionTypes[collection.collection]).setTypeName(`update_${collection.collection}_input`).NonNull,
|
|
944
|
+
],
|
|
945
|
+
},
|
|
946
|
+
resolve: async ({ args, info }) => await self.resolveMutation(args, info),
|
|
947
|
+
});
|
|
952
948
|
UpdateCollectionTypes[collection.collection].addResolver({
|
|
953
949
|
name: `update_${collection.collection}_items`,
|
|
954
|
-
type: collectionIsReadable
|
|
950
|
+
type: collectionIsReadable
|
|
951
|
+
? new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(ReadCollectionTypes[collection.collection].getType())))
|
|
952
|
+
: graphql_1.GraphQLBoolean,
|
|
955
953
|
args: {
|
|
956
954
|
...(collectionIsReadable
|
|
957
955
|
? ReadCollectionTypes[collection.collection].getResolver(collection.collection).getArgs()
|
|
@@ -1065,10 +1063,14 @@ class GraphQLService {
|
|
|
1065
1063
|
collection = `directus_${collection}`;
|
|
1066
1064
|
const selections = this.replaceFragmentsInSelections((_b = (_a = info.fieldNodes[0]) === null || _a === void 0 ? void 0 : _a.selectionSet) === null || _b === void 0 ? void 0 : _b.selections, info.fragments);
|
|
1067
1065
|
const query = this.getQuery(args, selections || [], info.variableValues);
|
|
1068
|
-
const singleton = collection.endsWith('
|
|
1066
|
+
const singleton = collection.endsWith('_batch') === false &&
|
|
1067
|
+
collection.endsWith('_items') === false &&
|
|
1069
1068
|
collection.endsWith('_item') === false &&
|
|
1070
1069
|
collection in this.schema.collections;
|
|
1071
|
-
const single = collection.endsWith('_items') === false;
|
|
1070
|
+
const single = collection.endsWith('_items') === false && collection.endsWith('_batch') === false;
|
|
1071
|
+
const batchUpdate = action === 'update' && collection.endsWith('_batch');
|
|
1072
|
+
if (collection.endsWith('_batch'))
|
|
1073
|
+
collection = collection.slice(0, -6);
|
|
1072
1074
|
if (collection.endsWith('_items'))
|
|
1073
1075
|
collection = collection.slice(0, -6);
|
|
1074
1076
|
if (collection.endsWith('_item'))
|
|
@@ -1099,7 +1101,13 @@ class GraphQLService {
|
|
|
1099
1101
|
return hasQuery ? await service.readMany(keys, query) : true;
|
|
1100
1102
|
}
|
|
1101
1103
|
if (action === 'update') {
|
|
1102
|
-
const keys =
|
|
1104
|
+
const keys = [];
|
|
1105
|
+
if (batchUpdate) {
|
|
1106
|
+
keys.push(...(await service.updateBatch(args.data)));
|
|
1107
|
+
}
|
|
1108
|
+
else {
|
|
1109
|
+
keys.push(...(await service.updateMany(args.ids, args.data)));
|
|
1110
|
+
}
|
|
1103
1111
|
return hasQuery ? await service.readMany(keys, query) : true;
|
|
1104
1112
|
}
|
|
1105
1113
|
if (action === 'delete') {
|
|
@@ -1167,7 +1175,12 @@ class GraphQLService {
|
|
|
1167
1175
|
values.push(this.parseArgs(valueNode.fields, variableValues));
|
|
1168
1176
|
}
|
|
1169
1177
|
else {
|
|
1170
|
-
|
|
1178
|
+
if (valueNode.kind === 'Variable') {
|
|
1179
|
+
values.push(variableValues[valueNode.name.value]);
|
|
1180
|
+
}
|
|
1181
|
+
else {
|
|
1182
|
+
values.push(valueNode.value);
|
|
1183
|
+
}
|
|
1171
1184
|
}
|
|
1172
1185
|
}
|
|
1173
1186
|
argsObject[argument.name.value] = values;
|
|
@@ -1227,7 +1240,7 @@ class GraphQLService {
|
|
|
1227
1240
|
if (selection.selectionSet) {
|
|
1228
1241
|
if (!query.deep)
|
|
1229
1242
|
query.deep = {};
|
|
1230
|
-
(0, lodash_1.set)(query.deep, parent, (0, lodash_1.merge)((0, lodash_1.get)(query.deep, parent), { _alias: { [selection.alias.value]: selection.name.value } }));
|
|
1243
|
+
(0, lodash_1.set)(query.deep, parent, (0, lodash_1.merge)({}, (0, lodash_1.get)(query.deep, parent), { _alias: { [selection.alias.value]: selection.name.value } }));
|
|
1231
1244
|
}
|
|
1232
1245
|
}
|
|
1233
1246
|
}
|
|
@@ -1256,7 +1269,7 @@ class GraphQLService {
|
|
|
1256
1269
|
if (!query.deep)
|
|
1257
1270
|
query.deep = {};
|
|
1258
1271
|
const args = this.parseArgs(selection.arguments, variableValues);
|
|
1259
|
-
(0, lodash_1.set)(query.deep, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current, (0, lodash_1.merge)((0, lodash_1.get)(query.deep, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current), (0, lodash_1.mapKeys)((0, sanitize_query_1.sanitizeQuery)(args, this.accountability), (value, key) => `_${key}`)));
|
|
1272
|
+
(0, lodash_1.set)(query.deep, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current, (0, lodash_1.merge)({}, (0, lodash_1.get)(query.deep, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current), (0, lodash_1.mapKeys)((0, sanitize_query_1.sanitizeQuery)(args, this.accountability), (value, key) => `_${key}`)));
|
|
1260
1273
|
}
|
|
1261
1274
|
}
|
|
1262
1275
|
}
|
|
@@ -1302,7 +1315,7 @@ class GraphQLService {
|
|
|
1302
1315
|
continue;
|
|
1303
1316
|
const aggregateProperty = aggregationGroup.name.value;
|
|
1304
1317
|
query.aggregate[aggregateProperty] =
|
|
1305
|
-
(_b = (_a = aggregationGroup.selectionSet) === null || _a === void 0 ? void 0 : _a.selections.filter((selectionNode) =>
|
|
1318
|
+
(_b = (_a = aggregationGroup.selectionSet) === null || _a === void 0 ? void 0 : _a.selections.filter((selectionNode) => !(selectionNode === null || selectionNode === void 0 ? void 0 : selectionNode.name.value.startsWith('__'))).map((selectionNode) => {
|
|
1306
1319
|
selectionNode = selectionNode;
|
|
1307
1320
|
return selectionNode.name.value;
|
|
1308
1321
|
})) !== null && _b !== void 0 ? _b : [];
|
|
@@ -1803,7 +1816,7 @@ class GraphQLService {
|
|
|
1803
1816
|
},
|
|
1804
1817
|
},
|
|
1805
1818
|
utils_cache_clear: {
|
|
1806
|
-
type: GraphQLVoid,
|
|
1819
|
+
type: void_1.GraphQLVoid,
|
|
1807
1820
|
resolve: async () => {
|
|
1808
1821
|
var _a;
|
|
1809
1822
|
if (((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) !== true) {
|
|
@@ -1854,7 +1867,7 @@ class GraphQLService {
|
|
|
1854
1867
|
});
|
|
1855
1868
|
schemaComposer.Query.addFields({
|
|
1856
1869
|
collections: {
|
|
1857
|
-
type:
|
|
1870
|
+
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Collection.getType()))),
|
|
1858
1871
|
resolve: async () => {
|
|
1859
1872
|
const collectionsService = new collections_1.CollectionsService({
|
|
1860
1873
|
accountability: this.accountability,
|
|
@@ -1915,7 +1928,7 @@ class GraphQLService {
|
|
|
1915
1928
|
});
|
|
1916
1929
|
schemaComposer.Query.addFields({
|
|
1917
1930
|
fields: {
|
|
1918
|
-
type:
|
|
1931
|
+
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Field.getType()))),
|
|
1919
1932
|
resolve: async () => {
|
|
1920
1933
|
const service = new fields_1.FieldsService({
|
|
1921
1934
|
accountability: this.accountability,
|
|
@@ -1925,7 +1938,7 @@ class GraphQLService {
|
|
|
1925
1938
|
},
|
|
1926
1939
|
},
|
|
1927
1940
|
fields_in_collection: {
|
|
1928
|
-
type:
|
|
1941
|
+
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Field.getType()))),
|
|
1929
1942
|
args: {
|
|
1930
1943
|
collection: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
|
|
1931
1944
|
},
|
|
@@ -1983,7 +1996,7 @@ class GraphQLService {
|
|
|
1983
1996
|
});
|
|
1984
1997
|
schemaComposer.Query.addFields({
|
|
1985
1998
|
relations: {
|
|
1986
|
-
type:
|
|
1999
|
+
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Relation.getType()))),
|
|
1987
2000
|
resolve: async () => {
|
|
1988
2001
|
const service = new relations_1.RelationsService({
|
|
1989
2002
|
accountability: this.accountability,
|
|
@@ -1993,7 +2006,7 @@ class GraphQLService {
|
|
|
1993
2006
|
},
|
|
1994
2007
|
},
|
|
1995
2008
|
relations_in_collection: {
|
|
1996
|
-
type:
|
|
2009
|
+
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Relation.getType()))),
|
|
1997
2010
|
args: {
|
|
1998
2011
|
collection: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
|
|
1999
2012
|
},
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GraphQLDate = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
exports.GraphQLDate = new graphql_1.GraphQLScalarType({
|
|
6
|
+
...graphql_1.GraphQLString,
|
|
7
|
+
name: 'Date',
|
|
8
|
+
description: 'ISO8601 Date values',
|
|
9
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GraphQLGeoJSON = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const graphql_compose_1 = require("graphql-compose");
|
|
6
|
+
exports.GraphQLGeoJSON = new graphql_1.GraphQLScalarType({
|
|
7
|
+
...graphql_compose_1.GraphQLJSON,
|
|
8
|
+
name: 'GraphQLGeoJSON',
|
|
9
|
+
description: 'GeoJSON value',
|
|
10
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GraphQLStringOrFloat = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
/**
|
|
6
|
+
* Adopted from https://kamranicus.com/handling-multiple-scalar-types-in-graphql/
|
|
7
|
+
*/
|
|
8
|
+
exports.GraphQLStringOrFloat = new graphql_1.GraphQLScalarType({
|
|
9
|
+
name: 'GraphQLStringOrFloat',
|
|
10
|
+
description: 'A Float or a String',
|
|
11
|
+
serialize(value) {
|
|
12
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
13
|
+
throw new Error('Value must be either a String or a Float');
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
},
|
|
17
|
+
parseValue(value) {
|
|
18
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
19
|
+
throw new Error('Value must be either a String or a Float');
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
},
|
|
23
|
+
parseLiteral(ast) {
|
|
24
|
+
switch (ast.kind) {
|
|
25
|
+
case graphql_1.Kind.INT:
|
|
26
|
+
case graphql_1.Kind.FLOAT:
|
|
27
|
+
return Number(ast.value);
|
|
28
|
+
case graphql_1.Kind.STRING:
|
|
29
|
+
return ast.value;
|
|
30
|
+
default:
|
|
31
|
+
throw new Error('Value must be either a String or a Float');
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GraphQLVoid = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
exports.GraphQLVoid = new graphql_1.GraphQLScalarType({
|
|
6
|
+
name: 'Void',
|
|
7
|
+
description: 'Represents NULL values',
|
|
8
|
+
serialize() {
|
|
9
|
+
return null;
|
|
10
|
+
},
|
|
11
|
+
parseValue() {
|
|
12
|
+
return null;
|
|
13
|
+
},
|
|
14
|
+
parseLiteral() {
|
|
15
|
+
return null;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addPathToValidationError = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
function addPathToValidationError(validationError) {
|
|
6
|
+
var _a, _b, _c;
|
|
7
|
+
const token = (_c = (_b = (_a = validationError.nodes) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.loc) === null || _c === void 0 ? void 0 : _c.startToken;
|
|
8
|
+
if (!token)
|
|
9
|
+
return validationError;
|
|
10
|
+
let prev = token;
|
|
11
|
+
const queryRegex = /query_[A-Za-z0-9]{8}/;
|
|
12
|
+
while (prev) {
|
|
13
|
+
if (prev.kind === 'Name' && prev.value && queryRegex.test(prev.value)) {
|
|
14
|
+
return (0, graphql_1.locatedError)(validationError, validationError.nodes, [prev.value]);
|
|
15
|
+
}
|
|
16
|
+
prev = prev.prev;
|
|
17
|
+
}
|
|
18
|
+
return (0, graphql_1.locatedError)(validationError, validationError.nodes);
|
|
19
|
+
}
|
|
20
|
+
exports.addPathToValidationError = addPathToValidationError;
|
|
@@ -20,7 +20,6 @@ const env_1 = __importDefault(require("../env"));
|
|
|
20
20
|
const exceptions_1 = require("../exceptions");
|
|
21
21
|
const logger_1 = __importDefault(require("../logger"));
|
|
22
22
|
const get_date_formatted_1 = require("../utils/get-date-formatted");
|
|
23
|
-
const parse_json_1 = require("../utils/parse-json");
|
|
24
23
|
const files_1 = require("./files");
|
|
25
24
|
const items_1 = require("./items");
|
|
26
25
|
const notifications_1 = require("./notifications");
|
|
@@ -31,12 +30,12 @@ class ImportService {
|
|
|
31
30
|
this.schema = options.schema;
|
|
32
31
|
}
|
|
33
32
|
async import(collection, mimetype, stream) {
|
|
34
|
-
var _a, _b, _c, _d, _e;
|
|
35
|
-
if (collection.startsWith('directus_'))
|
|
33
|
+
var _a, _b, _c, _d, _e, _f;
|
|
34
|
+
if (((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) !== true && collection.startsWith('directus_'))
|
|
36
35
|
throw new exceptions_1.ForbiddenException();
|
|
37
|
-
const createPermissions = (
|
|
38
|
-
const updatePermissions = (
|
|
39
|
-
if (((
|
|
36
|
+
const createPermissions = (_c = (_b = this.accountability) === null || _b === void 0 ? void 0 : _b.permissions) === null || _c === void 0 ? void 0 : _c.find((permission) => permission.collection === collection && permission.action === 'create');
|
|
37
|
+
const updatePermissions = (_e = (_d = this.accountability) === null || _d === void 0 ? void 0 : _d.permissions) === null || _e === void 0 ? void 0 : _e.find((permission) => permission.collection === collection && permission.action === 'update');
|
|
38
|
+
if (((_f = this.accountability) === null || _f === void 0 ? void 0 : _f.admin) !== true && (!createPermissions || !updatePermissions)) {
|
|
40
39
|
throw new exceptions_1.ForbiddenException();
|
|
41
40
|
}
|
|
42
41
|
switch (mimetype) {
|
|
@@ -102,7 +101,7 @@ class ImportService {
|
|
|
102
101
|
}
|
|
103
102
|
else {
|
|
104
103
|
try {
|
|
105
|
-
const parsedJson = (0,
|
|
104
|
+
const parsedJson = (0, utils_1.parseJSON)(value);
|
|
106
105
|
(0, lodash_1.set)(result, key, parsedJson);
|
|
107
106
|
}
|
|
108
107
|
catch {
|
|
@@ -169,7 +168,7 @@ class ExportService {
|
|
|
169
168
|
const requestedLimit = (_a = query.limit) !== null && _a !== void 0 ? _a : -1;
|
|
170
169
|
const batchesRequired = Math.ceil(count / env_1.default.EXPORT_BATCH_SIZE);
|
|
171
170
|
let readCount = 0;
|
|
172
|
-
for (let batch = 0; batch
|
|
171
|
+
for (let batch = 0; batch < batchesRequired; batch++) {
|
|
173
172
|
let limit = env_1.default.EXPORT_BATCH_SIZE;
|
|
174
173
|
if (requestedLimit > 0 && env_1.default.EXPORT_BATCH_SIZE > requestedLimit - readCount) {
|
|
175
174
|
limit = requestedLimit - readCount;
|
|
@@ -177,7 +176,7 @@ class ExportService {
|
|
|
177
176
|
const result = await service.readByQuery({
|
|
178
177
|
...query,
|
|
179
178
|
limit,
|
|
180
|
-
|
|
179
|
+
offset: batch * env_1.default.EXPORT_BATCH_SIZE,
|
|
181
180
|
});
|
|
182
181
|
readCount += result.length;
|
|
183
182
|
if (result.length) {
|
|
@@ -265,7 +264,11 @@ class ExportService {
|
|
|
265
264
|
transforms: [json2csv_1.transforms.flatten({ separator: '.' })],
|
|
266
265
|
header: (options === null || options === void 0 ? void 0 : options.includeHeader) !== false,
|
|
267
266
|
});
|
|
268
|
-
|
|
267
|
+
let string = parser.parse(input);
|
|
268
|
+
if ((options === null || options === void 0 ? void 0 : options.includeHeader) === false) {
|
|
269
|
+
string = '\n' + string;
|
|
270
|
+
}
|
|
271
|
+
return string;
|
|
269
272
|
}
|
|
270
273
|
throw new exceptions_1.ServiceUnavailableException(`Illegal export type used: "${format}"`, { service: 'export' });
|
|
271
274
|
}
|
package/dist/services/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/dist/services/items.d.ts
CHANGED
|
@@ -44,7 +44,11 @@ export declare class ItemsService<Item extends AnyItem = AnyItem> implements Abs
|
|
|
44
44
|
*/
|
|
45
45
|
updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
46
46
|
/**
|
|
47
|
-
* Update
|
|
47
|
+
* Update multiple items in a single transaction
|
|
48
|
+
*/
|
|
49
|
+
updateBatch(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
50
|
+
/**
|
|
51
|
+
* Update many items by primary key, setting all items to the same change
|
|
48
52
|
*/
|
|
49
53
|
updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
50
54
|
/**
|