directus 9.12.2 → 9.14.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.
Files changed (120) hide show
  1. package/dist/app.js +14 -5
  2. package/dist/auth/drivers/index.js +5 -1
  3. package/dist/auth/drivers/ldap.js +5 -1
  4. package/dist/auth/drivers/oauth2.js +15 -23
  5. package/dist/auth/drivers/openid.js +20 -25
  6. package/dist/cli/commands/bootstrap/index.js +5 -1
  7. package/dist/cli/commands/schema/apply.js +7 -3
  8. package/dist/cli/commands/schema/snapshot.d.ts +1 -1
  9. package/dist/cli/commands/schema/snapshot.js +33 -25
  10. package/dist/cli/index.js +1 -1
  11. package/dist/cli/utils/create-env/env-stub.liquid +11 -11
  12. package/dist/controllers/assets.js +5 -5
  13. package/dist/controllers/dashboards.js +4 -1
  14. package/dist/controllers/files.js +8 -5
  15. package/dist/controllers/flows.js +4 -1
  16. package/dist/controllers/folders.js +4 -1
  17. package/dist/controllers/items.js +4 -1
  18. package/dist/controllers/notifications.js +4 -1
  19. package/dist/controllers/operations.js +4 -1
  20. package/dist/controllers/panels.js +4 -1
  21. package/dist/controllers/permissions.js +4 -1
  22. package/dist/controllers/presets.js +4 -1
  23. package/dist/controllers/roles.js +4 -1
  24. package/dist/controllers/shares.js +4 -1
  25. package/dist/controllers/users.js +75 -3
  26. package/dist/controllers/utils.js +3 -3
  27. package/dist/database/helpers/date/dialects/sqlite.js +3 -0
  28. package/dist/database/helpers/index.js +5 -1
  29. package/dist/database/index.js +2 -0
  30. package/dist/database/migrations/20210225A-add-relations-sort-field.js +2 -2
  31. package/dist/database/migrations/20210506A-rename-interfaces.js +2 -2
  32. package/dist/database/migrations/20210802A-replace-groups.js +2 -2
  33. package/dist/database/migrations/20210805A-update-groups.js +2 -2
  34. package/dist/database/migrations/20210805B-change-image-metadata-structure.js +3 -3
  35. package/dist/database/migrations/20211007A-update-presets.js +5 -5
  36. package/dist/database/migrations/20220429A-add-flows.js +1 -2
  37. package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.d.ts +3 -0
  38. package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.js +11 -0
  39. package/dist/database/system-data/fields/dashboards.yaml +1 -0
  40. package/dist/emitter.js +12 -7
  41. package/dist/env.d.ts +1 -1
  42. package/dist/env.js +8 -3
  43. package/dist/exceptions/database/translate.js +5 -1
  44. package/dist/exceptions/index.js +5 -1
  45. package/dist/extensions.js +5 -1
  46. package/dist/flows.js +15 -11
  47. package/dist/index.js +5 -1
  48. package/dist/logger.js +5 -1
  49. package/dist/messenger.js +2 -2
  50. package/dist/middleware/graphql.js +2 -2
  51. package/dist/middleware/respond.js +10 -1
  52. package/dist/middleware/validate-batch.js +3 -1
  53. package/dist/operations/item-create/index.js +1 -2
  54. package/dist/operations/item-delete/index.d.ts +1 -0
  55. package/dist/operations/item-delete/index.js +8 -7
  56. package/dist/operations/item-read/index.d.ts +1 -0
  57. package/dist/operations/item-read/index.js +8 -7
  58. package/dist/operations/item-update/index.d.ts +1 -0
  59. package/dist/operations/item-update/index.js +9 -8
  60. package/dist/operations/log/index.js +1 -2
  61. package/dist/operations/notification/index.js +1 -2
  62. package/dist/operations/transform/index.js +1 -2
  63. package/dist/operations/trigger/index.js +1 -2
  64. package/dist/server.js +5 -1
  65. package/dist/services/assets.js +5 -1
  66. package/dist/services/collections.js +5 -1
  67. package/dist/services/fields.d.ts +3 -3
  68. package/dist/services/fields.js +25 -17
  69. package/dist/services/files.js +5 -1
  70. package/dist/services/flows.d.ts +1 -0
  71. package/dist/services/flows.js +6 -0
  72. package/dist/services/{graphql.d.ts → graphql/index.d.ts} +3 -5
  73. package/dist/services/{graphql.js → graphql/index.js} +109 -101
  74. package/dist/services/graphql/types/date.d.ts +2 -0
  75. package/dist/services/graphql/types/date.js +9 -0
  76. package/dist/services/graphql/types/geojson.d.ts +2 -0
  77. package/dist/services/graphql/types/geojson.js +10 -0
  78. package/dist/services/graphql/types/string-or-float.d.ts +5 -0
  79. package/dist/services/graphql/types/string-or-float.js +34 -0
  80. package/dist/services/graphql/types/void.d.ts +2 -0
  81. package/dist/services/graphql/types/void.js +17 -0
  82. package/dist/services/graphql/utils/add-path-to-validation-error.d.ts +2 -0
  83. package/dist/services/graphql/utils/add-path-to-validation-error.js +20 -0
  84. package/dist/services/import-export.js +12 -8
  85. package/dist/services/index.js +5 -1
  86. package/dist/services/items.d.ts +6 -1
  87. package/dist/services/items.js +43 -19
  88. package/dist/services/mail/index.js +8 -6
  89. package/dist/services/notifications.js +22 -11
  90. package/dist/services/operations.d.ts +1 -0
  91. package/dist/services/operations.js +6 -0
  92. package/dist/services/payload.js +13 -11
  93. package/dist/services/permissions.d.ts +1 -0
  94. package/dist/services/permissions.js +5 -0
  95. package/dist/services/relations.js +5 -1
  96. package/dist/services/roles.d.ts +1 -0
  97. package/dist/services/roles.js +9 -0
  98. package/dist/services/server.js +5 -1
  99. package/dist/services/users.d.ts +1 -0
  100. package/dist/services/users.js +17 -0
  101. package/dist/types/index.js +5 -1
  102. package/dist/utils/apply-query.js +24 -15
  103. package/dist/utils/calculate-field-depth.d.ts +33 -0
  104. package/dist/utils/calculate-field-depth.js +75 -0
  105. package/dist/utils/get-default-value.js +3 -13
  106. package/dist/utils/get-graphql-type.js +4 -3
  107. package/dist/utils/get-local-type.d.ts +6 -3
  108. package/dist/utils/get-permissions.js +3 -4
  109. package/dist/utils/get-schema.js +1 -2
  110. package/dist/utils/get-string-byte-size.d.ts +4 -0
  111. package/dist/utils/get-string-byte-size.js +10 -0
  112. package/dist/utils/jwt.js +5 -1
  113. package/dist/utils/sanitize-query.js +4 -5
  114. package/dist/utils/validate-query.js +50 -0
  115. package/dist/webhooks.js +5 -1
  116. package/package.json +74 -73
  117. package/dist/utils/operation-options.d.ts +0 -3
  118. package/dist/utils/operation-options.js +0 -45
  119. package/dist/utils/parse-json.d.ts +0 -5
  120. package/dist/utils/parse-json.js +0 -19
@@ -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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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];
@@ -6,6 +6,7 @@ export declare class FlowsService extends ItemsService<FlowRaw> {
6
6
  createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
7
7
  createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
8
8
  updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
9
+ updateBatch(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
9
10
  updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
10
11
  deleteOne(key: PrimaryKey, opts?: MutationOptions): Promise<PrimaryKey>;
11
12
  deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
@@ -25,6 +25,12 @@ class FlowsService extends items_1.ItemsService {
25
25
  await flowManager.reload();
26
26
  return result;
27
27
  }
28
+ async updateBatch(data, opts) {
29
+ const flowManager = (0, flows_1.getFlowManager)();
30
+ const result = await super.updateBatch(data, opts);
31
+ await flowManager.reload();
32
+ return result;
33
+ }
28
34
  async updateMany(keys, data, opts) {
29
35
  const flowManager = (0, flows_1.getFlowManager)();
30
36
  const result = await super.updateMany(keys, data, opts);
@@ -1,12 +1,10 @@
1
1
  import { BaseException } from '@directus/shared/exceptions';
2
2
  import { Accountability, Query, SchemaOverview } from '@directus/shared/types';
3
- import { ArgumentNode, FormattedExecutionResult, FragmentDefinitionNode, GraphQLError, GraphQLResolveInfo, GraphQLScalarType, GraphQLSchema, ObjectFieldNode, SelectionNode } from 'graphql';
3
+ import { ArgumentNode, FormattedExecutionResult, FragmentDefinitionNode, GraphQLError, GraphQLResolveInfo, GraphQLSchema, ObjectFieldNode, SelectionNode } from 'graphql';
4
4
  import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose';
5
5
  import { Knex } from 'knex';
6
- import { AbstractServiceOptions, GraphQLParams, Item } from '../types';
7
- import { ItemsService } from './items';
8
- export declare const GraphQLGeoJSON: GraphQLScalarType;
9
- export declare const GraphQLDate: GraphQLScalarType;
6
+ import { AbstractServiceOptions, GraphQLParams, Item } from '../../types';
7
+ import { ItemsService } from '../items';
10
8
  export declare class GraphQLService {
11
9
  accountability: Accountability | null;
12
10
  knex: Knex;
@@ -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 = exports.GraphQLDate = exports.GraphQLGeoJSON = void 0;
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("../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 GraphQLVoid = new graphql_1.GraphQLScalarType({
48
- name: 'Void',
49
- description: 'Represents NULL values',
50
- serialize() {
51
- return null;
52
- },
53
- parseValue() {
54
- return null;
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: graphql_1.GraphQLFloat,
498
+ type: string_or_float_1.GraphQLStringOrFloat,
520
499
  },
521
500
  _neq: {
522
- type: graphql_1.GraphQLFloat,
501
+ type: string_or_float_1.GraphQLStringOrFloat,
523
502
  },
524
503
  _in: {
525
- type: new graphql_1.GraphQLList(graphql_1.GraphQLFloat),
504
+ type: new graphql_1.GraphQLList(string_or_float_1.GraphQLStringOrFloat),
526
505
  },
527
506
  _nin: {
528
- type: new graphql_1.GraphQLList(graphql_1.GraphQLFloat),
507
+ type: new graphql_1.GraphQLList(string_or_float_1.GraphQLStringOrFloat),
529
508
  },
530
509
  _gt: {
531
- type: graphql_1.GraphQLFloat,
510
+ type: string_or_float_1.GraphQLStringOrFloat,
532
511
  },
533
512
  _gte: {
534
- type: graphql_1.GraphQLFloat,
513
+ type: string_or_float_1.GraphQLStringOrFloat,
535
514
  },
536
515
  _lt: {
537
- type: graphql_1.GraphQLFloat,
516
+ type: string_or_float_1.GraphQLStringOrFloat,
538
517
  },
539
518
  _lte: {
540
- type: graphql_1.GraphQLFloat,
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: exports.GraphQLGeoJSON,
533
+ type: geojson_1.GraphQLGeoJSON,
555
534
  },
556
535
  _neq: {
557
- type: exports.GraphQLGeoJSON,
536
+ type: geojson_1.GraphQLGeoJSON,
558
537
  },
559
538
  _intersects: {
560
- type: exports.GraphQLGeoJSON,
539
+ type: geojson_1.GraphQLGeoJSON,
561
540
  },
562
541
  _nintersects: {
563
- type: exports.GraphQLGeoJSON,
542
+ type: geojson_1.GraphQLGeoJSON,
564
543
  },
565
544
  _intersects_bbox: {
566
- type: exports.GraphQLGeoJSON,
545
+ type: geojson_1.GraphQLGeoJSON,
567
546
  },
568
547
  _nintersects_bbox: {
569
- type: exports.GraphQLGeoJSON,
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 exports.GraphQLDate:
619
+ case date_1.GraphQLDate:
641
620
  filterOperatorType = DateFilterOperators;
642
621
  break;
643
- case exports.GraphQLGeoJSON:
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
- : [ReadCollectionTypes[collection.collection]],
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: [AggregatedFunctions[collection.collection]],
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 ? [ReadCollectionTypes[collection.collection]] : graphql_1.GraphQLBoolean,
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 ? [ReadCollectionTypes[collection.collection]] : graphql_1.GraphQLBoolean,
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('_items') === false &&
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 = await service.updateMany(args.ids, args.data);
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') {
@@ -1232,7 +1240,7 @@ class GraphQLService {
1232
1240
  if (selection.selectionSet) {
1233
1241
  if (!query.deep)
1234
1242
  query.deep = {};
1235
- (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 } }));
1236
1244
  }
1237
1245
  }
1238
1246
  }
@@ -1261,7 +1269,7 @@ class GraphQLService {
1261
1269
  if (!query.deep)
1262
1270
  query.deep = {};
1263
1271
  const args = this.parseArgs(selection.arguments, variableValues);
1264
- (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}`)));
1265
1273
  }
1266
1274
  }
1267
1275
  }
@@ -1307,7 +1315,7 @@ class GraphQLService {
1307
1315
  continue;
1308
1316
  const aggregateProperty = aggregationGroup.name.value;
1309
1317
  query.aggregate[aggregateProperty] =
1310
- (_b = (_a = aggregationGroup.selectionSet) === null || _a === void 0 ? void 0 : _a.selections.filter((selectionNode) => { var _a; return !((_a = selectionNode) === null || _a === void 0 ? void 0 : _a.name.value.startsWith('__')); }).map((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) => {
1311
1319
  selectionNode = selectionNode;
1312
1320
  return selectionNode.name.value;
1313
1321
  })) !== null && _b !== void 0 ? _b : [];
@@ -1808,7 +1816,7 @@ class GraphQLService {
1808
1816
  },
1809
1817
  },
1810
1818
  utils_cache_clear: {
1811
- type: GraphQLVoid,
1819
+ type: void_1.GraphQLVoid,
1812
1820
  resolve: async () => {
1813
1821
  var _a;
1814
1822
  if (((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) !== true) {
@@ -1859,7 +1867,7 @@ class GraphQLService {
1859
1867
  });
1860
1868
  schemaComposer.Query.addFields({
1861
1869
  collections: {
1862
- type: [Collection],
1870
+ type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Collection.getType()))),
1863
1871
  resolve: async () => {
1864
1872
  const collectionsService = new collections_1.CollectionsService({
1865
1873
  accountability: this.accountability,
@@ -1920,7 +1928,7 @@ class GraphQLService {
1920
1928
  });
1921
1929
  schemaComposer.Query.addFields({
1922
1930
  fields: {
1923
- type: [Field],
1931
+ type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Field.getType()))),
1924
1932
  resolve: async () => {
1925
1933
  const service = new fields_1.FieldsService({
1926
1934
  accountability: this.accountability,
@@ -1930,7 +1938,7 @@ class GraphQLService {
1930
1938
  },
1931
1939
  },
1932
1940
  fields_in_collection: {
1933
- type: [Field],
1941
+ type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Field.getType()))),
1934
1942
  args: {
1935
1943
  collection: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
1936
1944
  },
@@ -1988,7 +1996,7 @@ class GraphQLService {
1988
1996
  });
1989
1997
  schemaComposer.Query.addFields({
1990
1998
  relations: {
1991
- type: [Relation],
1999
+ type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Relation.getType()))),
1992
2000
  resolve: async () => {
1993
2001
  const service = new relations_1.RelationsService({
1994
2002
  accountability: this.accountability,
@@ -1998,7 +2006,7 @@ class GraphQLService {
1998
2006
  },
1999
2007
  },
2000
2008
  relations_in_collection: {
2001
- type: [Relation],
2009
+ type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(Relation.getType()))),
2002
2010
  args: {
2003
2011
  collection: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
2004
2012
  },
@@ -0,0 +1,2 @@
1
+ import { GraphQLScalarType } from 'graphql';
2
+ export declare const GraphQLDate: GraphQLScalarType;
@@ -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,2 @@
1
+ import { GraphQLScalarType } from 'graphql';
2
+ export declare const GraphQLGeoJSON: GraphQLScalarType;
@@ -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,5 @@
1
+ import { GraphQLScalarType } from 'graphql';
2
+ /**
3
+ * Adopted from https://kamranicus.com/handling-multiple-scalar-types-in-graphql/
4
+ */
5
+ export declare const GraphQLStringOrFloat: GraphQLScalarType;
@@ -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,2 @@
1
+ import { GraphQLScalarType } from 'graphql';
2
+ export declare const GraphQLVoid: GraphQLScalarType;
@@ -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,2 @@
1
+ import { GraphQLError } from 'graphql';
2
+ export declare function addPathToValidationError(validationError: GraphQLError): GraphQLError;
@@ -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 = (_b = (_a = this.accountability) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.find((permission) => permission.collection === collection && permission.action === 'create');
38
- const updatePermissions = (_d = (_c = this.accountability) === null || _c === void 0 ? void 0 : _c.permissions) === null || _d === void 0 ? void 0 : _d.find((permission) => permission.collection === collection && permission.action === 'update');
39
- if (((_e = this.accountability) === null || _e === void 0 ? void 0 : _e.admin) !== true && (!createPermissions || !updatePermissions)) {
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,8 +101,13 @@ class ImportService {
102
101
  }
103
102
  else {
104
103
  try {
105
- const parsedJson = (0, parse_json_1.parseJSON)(value);
106
- (0, lodash_1.set)(result, key, parsedJson);
104
+ const parsedJson = (0, utils_1.parseJSON)(value);
105
+ if (typeof parsedJson === 'number') {
106
+ (0, lodash_1.set)(result, key, value);
107
+ }
108
+ else {
109
+ (0, lodash_1.set)(result, key, parsedJson);
110
+ }
107
111
  }
108
112
  catch {
109
113
  (0, lodash_1.set)(result, key, value);
@@ -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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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];