directus 9.4.1 → 9.5.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 (133) hide show
  1. package/README.md +1 -1
  2. package/dist/app.js +20 -1
  3. package/dist/auth/auth.d.ts +2 -1
  4. package/dist/auth/drivers/ldap.js +2 -1
  5. package/dist/auth/drivers/local.js +2 -1
  6. package/dist/auth/drivers/oauth2.js +12 -21
  7. package/dist/auth/drivers/openid.js +14 -3
  8. package/dist/cache.js +1 -3
  9. package/dist/cli/commands/init/questions.d.ts +3 -0
  10. package/dist/cli/commands/init/questions.js +2 -0
  11. package/dist/cli/index.js +1 -1
  12. package/dist/cli/utils/create-db-connection.d.ts +1 -1
  13. package/dist/cli/utils/create-db-connection.js +11 -1
  14. package/dist/cli/utils/drivers.d.ts +1 -0
  15. package/dist/cli/utils/drivers.js +2 -1
  16. package/dist/controllers/activity.js +2 -1
  17. package/dist/controllers/auth.js +5 -4
  18. package/dist/controllers/extensions.js +1 -1
  19. package/dist/controllers/files.js +3 -0
  20. package/dist/controllers/utils.js +2 -0
  21. package/dist/database/helpers/date/index.d.ts +1 -0
  22. package/dist/database/helpers/date/index.js +3 -1
  23. package/dist/database/helpers/geometry/index.d.ts +1 -0
  24. package/dist/database/helpers/geometry/index.js +3 -1
  25. package/dist/database/helpers/index.d.ts +2 -0
  26. package/dist/database/helpers/index.js +2 -0
  27. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +16 -0
  28. package/dist/database/helpers/schema/dialects/cockroachdb.js +16 -0
  29. package/dist/database/helpers/schema/dialects/default.d.ts +3 -0
  30. package/dist/database/helpers/schema/dialects/default.js +7 -0
  31. package/dist/database/helpers/schema/dialects/oracle.d.ts +12 -0
  32. package/dist/database/helpers/schema/dialects/oracle.js +13 -0
  33. package/dist/database/helpers/schema/index.d.ts +7 -0
  34. package/dist/database/helpers/schema/index.js +17 -0
  35. package/dist/database/helpers/schema/types.d.ts +25 -0
  36. package/dist/database/helpers/schema/types.js +89 -0
  37. package/dist/database/index.d.ts +1 -1
  38. package/dist/database/index.js +66 -17
  39. package/dist/database/migrations/20201105B-change-webhook-url-type.js +6 -25
  40. package/dist/database/migrations/20210312A-webhooks-collections-text.js +6 -25
  41. package/dist/database/migrations/20210415A-make-filesize-nullable.js +9 -4
  42. package/dist/database/migrations/20210506A-rename-interfaces.js +1 -1
  43. package/dist/database/migrations/20210510A-restructure-relations.js +12 -4
  44. package/dist/database/migrations/20210525A-add-insights.js +2 -2
  45. package/dist/database/migrations/20210626A-change-filesize-bigint.js +5 -7
  46. package/dist/database/migrations/20210903A-add-auth-provider.js +11 -2
  47. package/dist/database/migrations/20210907A-webhooks-collections-not-null.js +6 -20
  48. package/dist/database/migrations/20210920A-webhooks-url-not-null.js +10 -14
  49. package/dist/database/migrations/20211211A-add-shares.js +2 -2
  50. package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +3 -0
  51. package/dist/database/migrations/20211230A-add-project-descriptor.js +15 -0
  52. package/dist/database/migrations/run.js +1 -1
  53. package/dist/database/run-ast.d.ts +1 -1
  54. package/dist/database/seeds/01-collections.yaml +1 -0
  55. package/dist/database/seeds/02-roles.yaml +1 -0
  56. package/dist/database/seeds/03-users.yaml +1 -0
  57. package/dist/database/system-data/fields/settings.yaml +11 -1
  58. package/dist/database/system-data/relations/index.d.ts +1 -1
  59. package/dist/emitter.d.ts +3 -4
  60. package/dist/emitter.js +2 -8
  61. package/dist/env.js +3 -0
  62. package/dist/exceptions/database/translate.js +1 -0
  63. package/dist/exceptions/index.d.ts +1 -0
  64. package/dist/exceptions/index.js +1 -0
  65. package/dist/exceptions/unsupported-media-type.d.ts +4 -0
  66. package/dist/exceptions/unsupported-media-type.js +10 -0
  67. package/dist/extensions.d.ts +14 -8
  68. package/dist/extensions.js +136 -69
  69. package/dist/logger.js +22 -1
  70. package/dist/middleware/authenticate.js +2 -1
  71. package/dist/middleware/extract-token.js +1 -1
  72. package/dist/middleware/rate-limiter.js +2 -1
  73. package/dist/services/assets.js +3 -3
  74. package/dist/services/authentication.d.ts +2 -2
  75. package/dist/services/authentication.js +7 -2
  76. package/dist/services/authorization.d.ts +2 -3
  77. package/dist/services/collections.d.ts +2 -2
  78. package/dist/services/collections.js +18 -18
  79. package/dist/services/fields.d.ts +2 -3
  80. package/dist/services/fields.js +19 -15
  81. package/dist/services/graphql.d.ts +3 -2
  82. package/dist/services/graphql.js +31 -5
  83. package/dist/services/import.d.ts +2 -2
  84. package/dist/services/import.js +2 -1
  85. package/dist/services/items.d.ts +2 -2
  86. package/dist/services/items.js +22 -18
  87. package/dist/services/mail/index.d.ts +2 -2
  88. package/dist/services/meta.d.ts +2 -2
  89. package/dist/services/payload.d.ts +2 -2
  90. package/dist/services/payload.js +7 -3
  91. package/dist/services/relations.d.ts +2 -2
  92. package/dist/services/server.d.ts +2 -2
  93. package/dist/services/server.js +1 -0
  94. package/dist/services/specifications.d.ts +2 -2
  95. package/dist/services/users.d.ts +2 -3
  96. package/dist/services/utils.d.ts +2 -2
  97. package/dist/types/ast.d.ts +1 -2
  98. package/dist/types/auth.d.ts +1 -3
  99. package/dist/types/index.d.ts +0 -3
  100. package/dist/types/index.js +0 -3
  101. package/dist/types/services.d.ts +1 -3
  102. package/dist/types/snapshot.d.ts +1 -2
  103. package/dist/utils/apply-query.d.ts +1 -2
  104. package/dist/utils/apply-query.js +1 -1
  105. package/dist/utils/apply-snapshot.d.ts +2 -1
  106. package/dist/utils/get-ast-from-query.d.ts +2 -3
  107. package/dist/utils/get-ip-from-req.d.ts +2 -0
  108. package/dist/utils/get-ip-from-req.js +24 -0
  109. package/dist/utils/get-local-type.js +1 -1
  110. package/dist/utils/get-permissions.d.ts +1 -2
  111. package/dist/utils/get-permissions.js +1 -1
  112. package/dist/utils/get-relation-type.d.ts +1 -1
  113. package/dist/utils/get-schema.d.ts +1 -2
  114. package/dist/utils/get-snapshot.d.ts +2 -1
  115. package/dist/utils/md.js +1 -1
  116. package/dist/utils/merge-permissions-for-share.d.ts +1 -2
  117. package/dist/utils/reduce-schema.d.ts +1 -2
  118. package/example.env +8 -0
  119. package/package.json +22 -15
  120. package/dist/cli/index.test.d.ts +0 -1
  121. package/dist/cli/index.test.js +0 -58
  122. package/dist/middleware/cache.test.d.ts +0 -1
  123. package/dist/middleware/cache.test.js +0 -62
  124. package/dist/tests/database/migrations/run.test.d.ts +0 -1
  125. package/dist/tests/database/migrations/run.test.js +0 -29
  126. package/dist/types/extensions.d.ts +0 -43
  127. package/dist/types/extensions.js +0 -2
  128. package/dist/types/relation.d.ts +0 -21
  129. package/dist/types/relation.js +0 -2
  130. package/dist/types/schema.d.ts +0 -32
  131. package/dist/types/schema.js +0 -2
  132. package/dist/utils/get-cache-key.test.d.ts +0 -1
  133. package/dist/utils/get-cache-key.test.js +0 -53
@@ -3,15 +3,12 @@ export * from './assets';
3
3
  export * from './ast';
4
4
  export * from './auth';
5
5
  export * from './collection';
6
- export * from './extensions';
7
6
  export * from './files';
8
7
  export * from './graphql';
9
8
  export * from './items';
10
9
  export * from './meta';
11
10
  export * from './migration';
12
- export * from './relation';
13
11
  export * from './revision';
14
- export * from './schema';
15
12
  export * from './services';
16
13
  export * from './snapshot';
17
14
  export * from './webhooks';
@@ -15,15 +15,12 @@ __exportStar(require("./assets"), exports);
15
15
  __exportStar(require("./ast"), exports);
16
16
  __exportStar(require("./auth"), exports);
17
17
  __exportStar(require("./collection"), exports);
18
- __exportStar(require("./extensions"), exports);
19
18
  __exportStar(require("./files"), exports);
20
19
  __exportStar(require("./graphql"), exports);
21
20
  __exportStar(require("./items"), exports);
22
21
  __exportStar(require("./meta"), exports);
23
22
  __exportStar(require("./migration"), exports);
24
- __exportStar(require("./relation"), exports);
25
23
  __exportStar(require("./revision"), exports);
26
- __exportStar(require("./schema"), exports);
27
24
  __exportStar(require("./services"), exports);
28
25
  __exportStar(require("./snapshot"), exports);
29
26
  __exportStar(require("./webhooks"), exports);
@@ -1,8 +1,6 @@
1
1
  import { Knex } from 'knex';
2
- import { SchemaOverview } from '../types';
3
- import { Accountability } from '@directus/shared/types';
2
+ import { Accountability, Query, SchemaOverview } from '@directus/shared/types';
4
3
  import { Item, PrimaryKey } from './items';
5
- import { Query } from '@directus/shared/types';
6
4
  export declare type AbstractServiceOptions = {
7
5
  knex?: Knex;
8
6
  accountability?: Accountability | null;
@@ -1,6 +1,5 @@
1
1
  import { Collection } from './collection';
2
- import { Relation, RelationMeta } from './relation';
3
- import { Field, FieldMeta } from '@directus/shared/types';
2
+ import { Relation, RelationMeta, Field, FieldMeta } from '@directus/shared/types';
4
3
  import { Diff } from 'deep-diff';
5
4
  export declare type Snapshot = {
6
5
  version: number;
@@ -1,6 +1,5 @@
1
1
  import { Knex } from 'knex';
2
- import { SchemaOverview } from '../types';
3
- import { Aggregate, Filter, Query } from '@directus/shared/types';
2
+ import { Aggregate, Filter, Query, SchemaOverview } from '@directus/shared/types';
4
3
  /**
5
4
  * Apply the Query to a given Knex query builder instance
6
5
  */
@@ -177,7 +177,7 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
177
177
  if (relationType === 'o2m' && (subQuery === true || parentAlias !== undefined)) {
178
178
  dbQuery.leftJoin({ [alias]: relation.collection }, `${parentAlias || parentCollection}.${schema.collections[relation.related_collection].primary}`, `${alias}.${relation.field}`);
179
179
  }
180
- if (relationType === 'm2o' || subQuery === true) {
180
+ if (relationType === 'm2o' || subQuery === true || (relationType === 'o2m' && parentAlias !== undefined)) {
181
181
  let parent;
182
182
  if (relationType === 'm2o') {
183
183
  parent = relation.related_collection;
@@ -1,5 +1,6 @@
1
- import { Snapshot, SnapshotDiff, SchemaOverview } from '../types';
1
+ import { Snapshot, SnapshotDiff } from '../types';
2
2
  import { Knex } from 'knex';
3
+ import { SchemaOverview } from '@directus/shared/types';
3
4
  export declare function applySnapshot(snapshot: Snapshot, options?: {
4
5
  database?: Knex;
5
6
  schema?: SchemaOverview;
@@ -2,9 +2,8 @@
2
2
  * Generate an AST based on a given collection and query
3
3
  */
4
4
  import { Knex } from 'knex';
5
- import { Accountability } from '@directus/shared/types';
6
- import { AST, SchemaOverview } from '../types';
7
- import { Query, PermissionsAction } from '@directus/shared/types';
5
+ import { AST } from '../types';
6
+ import { Query, PermissionsAction, Accountability, SchemaOverview } from '@directus/shared/types';
8
7
  declare type GetASTOptions = {
9
8
  accountability?: Accountability | null;
10
9
  action?: PermissionsAction;
@@ -0,0 +1,2 @@
1
+ import { Request } from 'express';
2
+ export declare function getIPFromReq(req: Request): string;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getIPFromReq = void 0;
7
+ const net_1 = require("net");
8
+ const env_1 = __importDefault(require("../env"));
9
+ const logger_1 = __importDefault(require("../logger"));
10
+ function getIPFromReq(req) {
11
+ let ip = req.ip;
12
+ if (env_1.default.IP_CUSTOM_HEADER) {
13
+ const customIPHeaderValue = req.get(env_1.default.IP_CUSTOM_HEADER);
14
+ if (typeof customIPHeaderValue === 'string' && (0, net_1.isIP)(customIPHeaderValue) !== 0) {
15
+ ip = customIPHeaderValue;
16
+ }
17
+ else {
18
+ logger_1.default.warn(`Custom IP header didn't return valid IP address: ${JSON.stringify(customIPHeaderValue)}`);
19
+ }
20
+ }
21
+ // IP addresses starting with ::ffff: are IPv4 addresses in IPv6 format. We can strip the prefix to get back to IPv4
22
+ return ip.startsWith('::ffff:') ? ip.substring(7) : ip;
23
+ }
24
+ exports.getIPFromReq = getIPFromReq;
@@ -107,7 +107,7 @@ function getLocalType(column, field) {
107
107
  return 'hash';
108
108
  if (special.includes('csv'))
109
109
  return 'csv';
110
- if (special.includes('uuid'))
110
+ if (special.includes('uuid') || special.includes('file'))
111
111
  return 'uuid';
112
112
  if (type === null || type === void 0 ? void 0 : type.startsWith('geometry')) {
113
113
  return special[0] || 'geometry';
@@ -1,3 +1,2 @@
1
- import { Permission, Accountability } from '@directus/shared/types';
2
- import { SchemaOverview } from '../types';
1
+ import { Permission, Accountability, SchemaOverview } from '@directus/shared/types';
3
2
  export declare function getPermissions(accountability: Accountability, schema: SchemaOverview): Promise<Permission[]>;
@@ -145,7 +145,7 @@ function processPermissions(accountability, permissions, filterContext) {
145
145
  return permissions.map((permission) => {
146
146
  permission.permissions = (0, utils_1.parseFilter)(permission.permissions, accountability, filterContext);
147
147
  permission.validation = (0, utils_1.parseFilter)(permission.validation, accountability, filterContext);
148
- permission.presets = (0, utils_1.parseFilter)(permission.presets, accountability, filterContext);
148
+ permission.presets = (0, utils_1.parsePreset)(permission.presets, accountability, filterContext);
149
149
  return permission;
150
150
  });
151
151
  }
@@ -1,4 +1,4 @@
1
- import { Relation } from '../types';
1
+ import { Relation } from '@directus/shared/types';
2
2
  export declare function getRelationType(getRelationOptions: {
3
3
  relation: Relation;
4
4
  collection: string | null;
@@ -1,6 +1,5 @@
1
1
  import { Knex } from 'knex';
2
- import { SchemaOverview } from '../types';
3
- import { Accountability } from '@directus/shared/types';
2
+ import { Accountability, SchemaOverview } from '@directus/shared/types';
4
3
  export declare function getSchema(options?: {
5
4
  accountability?: Accountability;
6
5
  database?: Knex;
@@ -1,5 +1,6 @@
1
- import { SchemaOverview, Snapshot } from '../types';
1
+ import { Snapshot } from '../types';
2
2
  import { Knex } from 'knex';
3
+ import { SchemaOverview } from '@directus/shared/types';
3
4
  export declare function getSnapshot(options?: {
4
5
  database?: Knex;
5
6
  schema?: SchemaOverview;
package/dist/utils/md.js CHANGED
@@ -10,6 +10,6 @@ const sanitize_html_1 = __importDefault(require("sanitize-html"));
10
10
  * Render and sanitize a markdown string
11
11
  */
12
12
  function md(str) {
13
- return (0, sanitize_html_1.default)((0, marked_1.parse)(str));
13
+ return (0, sanitize_html_1.default)((0, marked_1.marked)(str));
14
14
  }
15
15
  exports.md = md;
@@ -1,5 +1,4 @@
1
- import { Permission, Accountability, Filter } from '@directus/shared/types';
2
- import { SchemaOverview } from '../types';
1
+ import { Permission, Accountability, Filter, SchemaOverview } from '@directus/shared/types';
3
2
  export declare function mergePermissionsForShare(currentPermissions: Permission[], accountability: Accountability, schema: SchemaOverview): Permission[];
4
3
  export declare function traverse(schema: SchemaOverview, rootItemPrimaryKeyField: string, rootItemPrimaryKey: string, currentCollection: string, parentCollections?: string[], path?: string[]): Partial<Permission>[];
5
4
  export declare function getFilterForPath(type: 'o2m' | 'm2o' | 'a2o', path: string[], rootPrimaryKeyField: string, rootPrimaryKey: string): Filter;
@@ -1,5 +1,4 @@
1
- import { SchemaOverview } from '../types';
2
- import { Permission, PermissionsAction } from '@directus/shared/types';
1
+ import { Permission, PermissionsAction, SchemaOverview } from '@directus/shared/types';
3
2
  /**
4
3
  * Reduces the schema based on the included permissions. The resulting object is the schema structure, but with only
5
4
  * the allowed collections/fields/relations included based on the permissions.
package/example.env CHANGED
@@ -19,6 +19,14 @@ DB_DATABASE="directus"
19
19
  DB_USER="postgres"
20
20
  DB_PASSWORD="secret"
21
21
 
22
+ ## CockroachDB
23
+ # DB_CLIENT="cockroachdb"
24
+ # DB_HOST="localhost"
25
+ # DB_PORT=5113
26
+ # DB_DATABASE="directus"
27
+ # DB_USER="root"
28
+ # DB_PASSWORD=""
29
+
22
30
  ## MySQL 8
23
31
  # DB_CLIENT="mysql"
24
32
  # DB_HOST="localhost"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus",
3
- "version": "9.4.1",
3
+ "version": "9.5.1",
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.",
@@ -18,6 +18,7 @@
18
18
  "cms",
19
19
  "mysql",
20
20
  "postgresql",
21
+ "cockroachdb",
21
22
  "sqlite",
22
23
  "framework",
23
24
  "vue"
@@ -62,7 +63,8 @@
62
63
  "cleanup": "rimraf dist",
63
64
  "dev": "cross-env NODE_ENV=development SERVE_APP=false ts-node-dev --files --transpile-only --respawn --watch \".env\" --inspect=0 --exit-child -- src/start.ts",
64
65
  "cli": "cross-env NODE_ENV=development SERVE_APP=false ts-node --script-mode --transpile-only src/cli/run.ts",
65
- "test": "jest --coverage",
66
+ "test": "jest",
67
+ "test:coverage": "jest --coverage",
66
68
  "test:watch": "jest --watchAll"
67
69
  },
68
70
  "engines": {
@@ -76,16 +78,16 @@
76
78
  ],
77
79
  "dependencies": {
78
80
  "@aws-sdk/client-ses": "^3.40.0",
79
- "@directus/app": "9.4.1",
80
- "@directus/drive": "9.4.1",
81
- "@directus/drive-azure": "9.4.1",
82
- "@directus/drive-gcs": "9.4.1",
83
- "@directus/drive-s3": "9.4.1",
84
- "@directus/extensions-sdk": "9.4.1",
85
- "@directus/format-title": "9.4.1",
86
- "@directus/schema": "9.4.1",
87
- "@directus/shared": "9.4.1",
88
- "@directus/specs": "9.4.1",
81
+ "@directus/app": "9.5.1",
82
+ "@directus/drive": "9.5.1",
83
+ "@directus/drive-azure": "9.5.1",
84
+ "@directus/drive-gcs": "9.5.1",
85
+ "@directus/drive-s3": "9.5.1",
86
+ "@directus/extensions-sdk": "9.5.1",
87
+ "@directus/format-title": "9.5.1",
88
+ "@directus/schema": "9.5.1",
89
+ "@directus/shared": "9.5.1",
90
+ "@directus/specs": "9.5.1",
89
91
  "@godaddy/terminus": "^4.9.0",
90
92
  "@rollup/plugin-alias": "^3.1.2",
91
93
  "@rollup/plugin-virtual": "^2.0.3",
@@ -97,6 +99,7 @@
97
99
  "busboy": "^0.3.1",
98
100
  "camelcase": "^6.2.0",
99
101
  "chalk": "^4.1.1",
102
+ "chokidar": "^3.5.2",
100
103
  "commander": "^8.0.0",
101
104
  "cookie-parser": "^1.4.5",
102
105
  "cors": "^2.8.5",
@@ -114,6 +117,7 @@
114
117
  "fs-extra": "^10.0.0",
115
118
  "graphql": "^15.5.0",
116
119
  "graphql-compose": "^9.0.1",
120
+ "helmet": "^4.6.0",
117
121
  "inquirer": "^8.1.1",
118
122
  "joi": "^17.3.0",
119
123
  "js-yaml": "^4.1.0",
@@ -121,8 +125,8 @@
121
125
  "json2csv": "^5.0.3",
122
126
  "jsonwebtoken": "^8.5.1",
123
127
  "keyv": "^4.0.3",
124
- "knex": "^0.95.11",
125
- "knex-schema-inspector": "1.6.6",
128
+ "knex": "^0.95.14",
129
+ "knex-schema-inspector": "1.7.3",
126
130
  "ldapjs": "^2.3.1",
127
131
  "liquidjs": "^9.25.0",
128
132
  "lodash": "^4.17.21",
@@ -169,7 +173,7 @@
169
173
  "sqlite3": "^5.0.2",
170
174
  "tedious": "^13.0.0"
171
175
  },
172
- "gitHead": "4991ba858bdde8bdf03aee475d77a218da6e46ab",
176
+ "gitHead": "c0c412d30b116bd38a2690b62463f775d37db79c",
173
177
  "devDependencies": {
174
178
  "@types/async": "3.2.10",
175
179
  "@types/atob": "2.1.2",
@@ -192,12 +196,15 @@
192
196
  "@types/keyv": "3.1.3",
193
197
  "@types/ldapjs": "2.2.2",
194
198
  "@types/lodash": "4.14.177",
199
+ "@types/marked": "4.0.1",
195
200
  "@types/mime-types": "2.1.1",
196
201
  "@types/ms": "0.7.31",
197
202
  "@types/node": "16.11.9",
198
203
  "@types/node-cron": "2.0.5",
199
204
  "@types/nodemailer": "6.4.4",
200
205
  "@types/object-hash": "2.2.1",
206
+ "@types/pino": "6.3.12",
207
+ "@types/pino-http": "5.8.0",
201
208
  "@types/qs": "6.9.7",
202
209
  "@types/sanitize-html": "2.5.0",
203
210
  "@types/sharp": "0.29.4",
@@ -1 +0,0 @@
1
- export {};
@@ -1,58 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const index_1 = require("./index");
4
- jest.mock('../env', () => ({
5
- ...jest.requireActual('../env').default,
6
- EXTENSIONS_PATH: '',
7
- SERVE_APP: false,
8
- DB_CLIENT: 'pg',
9
- DB_HOST: 'localhost',
10
- DB_PORT: 5432,
11
- DB_DATABASE: 'directus',
12
- DB_USER: 'postgres',
13
- DB_PASSWORD: 'psql1234',
14
- }));
15
- jest.mock('@directus/shared/utils/node/get-extensions', () => ({
16
- getPackageExtensions: jest.fn(() => Promise.resolve([])),
17
- getLocalExtensions: jest.fn(() => Promise.resolve([customCliExtension])),
18
- }));
19
- jest.mock(`/hooks/custom-cli/index.js`, () => customCliHook, { virtual: true });
20
- const customCliExtension = {
21
- path: `/hooks/custom-cli`,
22
- name: 'custom-cli',
23
- type: 'hook',
24
- entrypoint: 'index.js',
25
- local: true,
26
- };
27
- const beforeHook = jest.fn();
28
- const afterAction = jest.fn();
29
- const afterHook = jest.fn(({ program }) => {
30
- program.command('custom').action(afterAction);
31
- });
32
- const customCliHook = ({ init }) => {
33
- init('cli.before', beforeHook);
34
- init('cli.after', afterHook);
35
- };
36
- const writeOut = jest.fn();
37
- const writeErr = jest.fn();
38
- const setup = async () => {
39
- const program = await (0, index_1.createCli)();
40
- program.exitOverride();
41
- program.configureOutput({ writeOut, writeErr });
42
- return program;
43
- };
44
- beforeEach(jest.clearAllMocks);
45
- describe('cli hooks', () => {
46
- test('should call hooks before and after creating the cli', async () => {
47
- const program = await setup();
48
- expect(beforeHook).toHaveBeenCalledTimes(1);
49
- expect(beforeHook).toHaveBeenCalledWith({ program });
50
- expect(afterHook).toHaveBeenCalledTimes(1);
51
- expect(afterHook).toHaveBeenCalledWith({ program });
52
- });
53
- test('should be able to add a custom cli command', async () => {
54
- const program = await setup();
55
- program.parseAsync(['custom'], { from: 'user' });
56
- expect(afterAction).toHaveBeenCalledTimes(1);
57
- });
58
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,62 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const express_1 = __importDefault(require("express"));
7
- const supertest_1 = __importDefault(require("supertest"));
8
- const cache_1 = __importDefault(require("./cache"));
9
- jest.mock('../cache');
10
- jest.mock('../env', () => ({
11
- CACHE_ENABLED: true,
12
- CACHE_NAMESPACE: 'test',
13
- CACHE_STORE: 'memory',
14
- CACHE_TTL: '5s',
15
- CACHE_CONTROL_S_MAXAGE: true,
16
- }));
17
- const { cache } = jest.requireMock('../cache');
18
- const env = jest.requireMock('../env');
19
- const handler = jest.fn((req, res) => res.json({ data: 'Uncached value' }));
20
- const setup = () => (0, express_1.default)().use(cache_1.default).all('/items/test', handler);
21
- beforeEach(jest.clearAllMocks);
22
- describe('cache middleware', () => {
23
- test('should return the cached response for a request', async () => {
24
- cache.get.mockResolvedValueOnce({ data: 'Cached value' });
25
- cache.get.mockResolvedValueOnce(new Date().getTime() + 1000 * 60);
26
- const res = await (0, supertest_1.default)(setup()).get('/items/test').send();
27
- expect(res.body.data).toBe('Cached value');
28
- expect(res.headers['vary']).toBe('Origin, Cache-Control');
29
- expect(res.headers['cache-control']).toMatch(/public, max-age=\d+, s-maxage=\d+/);
30
- expect(handler).not.toHaveBeenCalled();
31
- });
32
- test('should call the handler when there is no cached value', async () => {
33
- cache.get.mockResolvedValueOnce(undefined);
34
- const res = await (0, supertest_1.default)(setup()).get('/items/test').send();
35
- expect(res.body.data).toBe('Uncached value');
36
- expect(cache.get).toHaveBeenCalledTimes(1);
37
- expect(handler).toHaveBeenCalledTimes(1);
38
- });
39
- test('should not cache requests then the cache is disabled', async () => {
40
- env.CACHE_ENABLED = false;
41
- const res = await (0, supertest_1.default)(setup()).get('/items/test').send();
42
- expect(res.body.data).toBe('Uncached value');
43
- expect(cache.get).not.toHaveBeenCalled();
44
- expect(handler).toHaveBeenCalledTimes(1);
45
- env.CACHE_ENABLED = true;
46
- });
47
- test('should not use cache when the "Cache-Control" header is set to "no-store"', async () => {
48
- const res = await (0, supertest_1.default)(setup()).get('/items/test').set('Cache-Control', 'no-store').send();
49
- expect(res.body.data).toBe('Uncached value');
50
- expect(cache.get).not.toHaveBeenCalled();
51
- expect(handler).toHaveBeenCalledTimes(1);
52
- });
53
- test('should only cache get requests', async () => {
54
- const app = setup();
55
- await (0, supertest_1.default)(app).post('/items/test').send();
56
- await (0, supertest_1.default)(app).put('/items/test').send();
57
- await (0, supertest_1.default)(app).patch('/items/test').send();
58
- await (0, supertest_1.default)(app).delete('/items/test').send();
59
- expect(cache.get).not.toHaveBeenCalled();
60
- expect(handler).toHaveBeenCalledTimes(4);
61
- });
62
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,29 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const knex_1 = __importDefault(require("knex"));
7
- const knex_mock_client_1 = require("knex-mock-client");
8
- const run_1 = __importDefault(require("../../../database/migrations/run"));
9
- describe('run', () => {
10
- let db;
11
- let tracker;
12
- beforeAll(() => {
13
- db = (0, knex_1.default)({ client: knex_mock_client_1.MockClient });
14
- tracker = (0, knex_mock_client_1.getTracker)();
15
- });
16
- afterEach(() => {
17
- tracker.reset();
18
- });
19
- describe('when passed the argument up', () => {
20
- it('returns "Nothing To Updage" if no directus_migrations', async () => {
21
- // note the difference between an empty array and ['Empty']
22
- tracker.on.select('directus_migrations').response(['Empty']);
23
- await (0, run_1.default)(db, 'up').catch((e) => {
24
- expect(e).toBeInstanceOf(Error);
25
- expect(e.message).toBe('Nothing to upgrade');
26
- });
27
- });
28
- });
29
- });
@@ -1,43 +0,0 @@
1
- import { Accountability } from '@directus/shared/types';
2
- import { Router } from 'express';
3
- import { Knex } from 'knex';
4
- import { Logger } from 'pino';
5
- import env from '../env';
6
- import * as exceptions from '../exceptions';
7
- import * as services from '../services';
8
- import { Emitter } from '../emitter';
9
- import { getSchema } from '../utils/get-schema';
10
- import { SchemaOverview } from './schema';
11
- export declare type ExtensionContext = {
12
- services: typeof services;
13
- exceptions: typeof exceptions;
14
- database: Knex;
15
- env: typeof env;
16
- emitter: Emitter;
17
- logger: Logger;
18
- getSchema: typeof getSchema;
19
- };
20
- export declare type HookContext = {
21
- database: Knex;
22
- schema: SchemaOverview | null;
23
- accountability: Accountability | null;
24
- };
25
- export declare type FilterHandler = (payload: any, meta: Record<string, any>, context: HookContext) => any | Promise<any>;
26
- export declare type ActionHandler = (meta: Record<string, any>, context: HookContext) => void | Promise<void>;
27
- export declare type InitHandler = (meta: Record<string, any>) => void | Promise<void>;
28
- export declare type ScheduleHandler = () => void | Promise<void>;
29
- declare type RegisterFunctions = {
30
- filter: (event: string, handler: FilterHandler) => void;
31
- action: (event: string, handler: ActionHandler) => void;
32
- init: (event: string, handler: InitHandler) => void;
33
- schedule: (cron: string, handler: ScheduleHandler) => void;
34
- };
35
- declare type HookHandlerFunction = (register: RegisterFunctions, context: ExtensionContext) => void;
36
- export declare type HookConfig = HookHandlerFunction;
37
- declare type EndpointHandlerFunction = (router: Router, context: ExtensionContext) => void;
38
- interface EndpointAdvancedConfig {
39
- id: string;
40
- handler: EndpointHandlerFunction;
41
- }
42
- export declare type EndpointConfig = EndpointHandlerFunction | EndpointAdvancedConfig;
43
- export {};
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,21 +0,0 @@
1
- import { ForeignKey } from 'knex-schema-inspector/dist/types/foreign-key';
2
- export declare type RelationMeta = {
3
- id: number;
4
- many_collection: string;
5
- many_field: string;
6
- one_collection: string | null;
7
- one_field: string | null;
8
- one_collection_field: string | null;
9
- one_allowed_collections: string[] | null;
10
- one_deselect_action: 'nullify' | 'delete';
11
- junction_field: string | null;
12
- sort_field: string | null;
13
- system?: boolean;
14
- };
15
- export declare type Relation = {
16
- collection: string;
17
- field: string;
18
- related_collection: string | null;
19
- schema: ForeignKey | null;
20
- meta: RelationMeta | null;
21
- };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,32 +0,0 @@
1
- import { Type } from '@directus/shared/types';
2
- import { Relation } from './relation';
3
- export declare type FieldOverview = {
4
- field: string;
5
- defaultValue: any;
6
- nullable: boolean;
7
- generated: boolean;
8
- type: Type | 'unknown' | 'alias';
9
- dbType: string | null;
10
- precision: number | null;
11
- scale: number | null;
12
- special: string[];
13
- note: string | null;
14
- alias: boolean;
15
- };
16
- export declare type CollectionsOverview = {
17
- [name: string]: {
18
- collection: string;
19
- primary: string;
20
- singleton: boolean;
21
- sortField: string | null;
22
- note: string | null;
23
- accountability: 'all' | 'activity' | null;
24
- fields: {
25
- [name: string]: FieldOverview;
26
- };
27
- };
28
- };
29
- export declare type SchemaOverview = {
30
- collections: CollectionsOverview;
31
- relations: Relation[];
32
- };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1 +0,0 @@
1
- export {};