@directus/api 15.0.0 → 16.0.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.
Files changed (169) hide show
  1. package/dist/app.js +6 -4
  2. package/dist/auth/drivers/ldap.js +7 -4
  3. package/dist/auth/drivers/local.js +3 -2
  4. package/dist/auth/drivers/oauth2.js +9 -2
  5. package/dist/auth/drivers/openid.js +9 -2
  6. package/dist/auth/drivers/saml.js +6 -4
  7. package/dist/auth.js +7 -4
  8. package/dist/bus/index.d.ts +1 -0
  9. package/dist/bus/index.js +1 -0
  10. package/dist/bus/lib/use-bus.d.ts +9 -0
  11. package/dist/bus/lib/use-bus.js +21 -0
  12. package/dist/cache.js +9 -9
  13. package/dist/cli/commands/bootstrap/index.js +6 -2
  14. package/dist/cli/commands/count/index.js +2 -1
  15. package/dist/cli/commands/database/install.js +2 -1
  16. package/dist/cli/commands/database/migrate.js +2 -1
  17. package/dist/cli/commands/roles/create.js +2 -1
  18. package/dist/cli/commands/schema/apply.js +2 -1
  19. package/dist/cli/commands/schema/snapshot.js +6 -5
  20. package/dist/cli/commands/users/create.js +4 -3
  21. package/dist/cli/commands/users/passwd.js +5 -4
  22. package/dist/cli/load-extensions.js +4 -2
  23. package/dist/cli/utils/create-env/env-stub.liquid +1 -1
  24. package/dist/constants.d.ts +1 -1
  25. package/dist/constants.js +4 -1
  26. package/dist/controllers/assets.js +5 -3
  27. package/dist/controllers/auth.js +5 -4
  28. package/dist/controllers/extensions.js +18 -6
  29. package/dist/controllers/files.js +3 -3
  30. package/dist/controllers/schema.js +3 -2
  31. package/dist/controllers/shares.js +3 -3
  32. package/dist/database/helpers/index.d.ts +1 -1
  33. package/dist/database/index.js +9 -2
  34. package/dist/database/migrations/20210518A-add-foreign-key-constraints.js +3 -1
  35. package/dist/database/migrations/20210519A-add-system-fk-triggers.js +3 -1
  36. package/dist/database/migrations/20210802A-replace-groups.js +2 -1
  37. package/dist/database/migrations/20230721A-require-shares-fields.js +2 -1
  38. package/dist/database/migrations/20231215A-add-focalpoints.d.ts +3 -0
  39. package/dist/database/migrations/20231215A-add-focalpoints.js +12 -0
  40. package/dist/database/migrations/run.js +2 -1
  41. package/dist/database/run-ast.js +5 -2
  42. package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +0 -7
  43. package/dist/database/system-data/fields/files.yaml +16 -0
  44. package/dist/emitter.js +3 -1
  45. package/dist/extensions/lib/get-extensions-path.d.ts +1 -1
  46. package/dist/extensions/lib/get-extensions-path.js +2 -1
  47. package/dist/extensions/lib/get-extensions.d.ts +1 -1
  48. package/dist/extensions/lib/get-extensions.js +32 -8
  49. package/dist/extensions/lib/get-shared-deps-mapping.js +6 -4
  50. package/dist/extensions/lib/sandbox/register/call-reference.js +4 -2
  51. package/dist/extensions/lib/sandbox/sdk/generators/log.js +2 -1
  52. package/dist/extensions/lib/sync-extensions.js +6 -4
  53. package/dist/extensions/manager.js +43 -19
  54. package/dist/flows.js +13 -7
  55. package/dist/logger.d.ts +7 -7
  56. package/dist/logger.js +116 -92
  57. package/dist/mailer.js +4 -2
  58. package/dist/middleware/cache.js +4 -2
  59. package/dist/middleware/check-ip.js +25 -6
  60. package/dist/middleware/cors.js +2 -1
  61. package/dist/middleware/error-handler.js +5 -5
  62. package/dist/middleware/rate-limiter-global.js +4 -2
  63. package/dist/middleware/rate-limiter-ip.js +2 -1
  64. package/dist/middleware/respond.js +4 -2
  65. package/dist/operations/log/index.js +2 -1
  66. package/dist/rate-limiter.d.ts +2 -1
  67. package/dist/rate-limiter.js +5 -2
  68. package/dist/redis/index.d.ts +3 -2
  69. package/dist/redis/index.js +3 -2
  70. package/dist/redis/{create-redis.js → lib/create-redis.js} +2 -2
  71. package/dist/redis/utils/redis-config-available.d.ts +4 -0
  72. package/dist/redis/utils/redis-config-available.js +8 -0
  73. package/dist/request/request-interceptor.js +7 -5
  74. package/dist/request/response-interceptor.js +2 -2
  75. package/dist/request/validate-ip.d.ts +1 -1
  76. package/dist/request/validate-ip.js +23 -7
  77. package/dist/server.js +11 -7
  78. package/dist/services/activity.js +5 -4
  79. package/dist/services/assets.d.ts +2 -0
  80. package/dist/services/assets.js +9 -4
  81. package/dist/services/authentication.js +17 -9
  82. package/dist/services/collections.js +5 -4
  83. package/dist/services/extensions.d.ts +15 -9
  84. package/dist/services/extensions.js +74 -39
  85. package/dist/services/fields.js +9 -4
  86. package/dist/services/files.d.ts +2 -2
  87. package/dist/services/files.js +22 -14
  88. package/dist/services/graphql/index.js +46 -3
  89. package/dist/services/graphql/subscription.js +2 -2
  90. package/dist/services/graphql/types/bigint.js +16 -5
  91. package/dist/services/graphql/utils/process-error.d.ts +4 -1
  92. package/dist/services/graphql/utils/process-error.js +10 -8
  93. package/dist/services/import-export/index.js +5 -3
  94. package/dist/services/items.js +12 -8
  95. package/dist/services/mail/index.js +4 -2
  96. package/dist/services/notifications.js +7 -3
  97. package/dist/services/relations.js +19 -10
  98. package/dist/services/server.js +5 -4
  99. package/dist/services/shares.js +3 -2
  100. package/dist/services/specifications.js +2 -1
  101. package/dist/services/users.js +20 -9
  102. package/dist/services/versions.js +6 -5
  103. package/dist/services/webhooks.d.ts +2 -2
  104. package/dist/services/webhooks.js +2 -2
  105. package/dist/services/websocket.d.ts +1 -1
  106. package/dist/services/websocket.js +4 -3
  107. package/dist/storage/register-drivers.js +2 -1
  108. package/dist/storage/register-locations.js +2 -1
  109. package/dist/synchronization.js +3 -1
  110. package/dist/telemetry/lib/get-report.js +1 -1
  111. package/dist/telemetry/lib/init-telemetry.js +2 -2
  112. package/dist/telemetry/lib/send-report.js +1 -1
  113. package/dist/telemetry/lib/track.js +2 -3
  114. package/dist/telemetry/utils/get-user-count.js +1 -1
  115. package/dist/types/assets.d.ts +2 -0
  116. package/dist/utils/apply-diff.js +2 -1
  117. package/dist/utils/apply-query.js +0 -11
  118. package/dist/utils/delete-from-require-cache.js +2 -1
  119. package/dist/utils/get-accountability-for-token.js +3 -2
  120. package/dist/utils/get-auth-providers.js +2 -1
  121. package/dist/utils/get-cache-headers.js +5 -2
  122. package/dist/utils/get-config-from-env.js +2 -1
  123. package/dist/utils/get-default-value.js +4 -3
  124. package/dist/utils/get-ip-from-req.js +4 -2
  125. package/dist/utils/get-permissions.js +5 -3
  126. package/dist/utils/get-schema.js +5 -2
  127. package/dist/utils/get-snapshot-diff.js +7 -9
  128. package/dist/utils/get-snapshot.js +4 -4
  129. package/dist/utils/ip-in-networks.d.ts +6 -0
  130. package/dist/utils/ip-in-networks.js +13 -0
  131. package/dist/utils/is-url-allowed.js +2 -1
  132. package/dist/utils/job-queue.d.ts +1 -0
  133. package/dist/utils/job-queue.js +3 -0
  134. package/dist/utils/sanitize-query.js +7 -2
  135. package/dist/utils/sanitize-schema.d.ts +1 -1
  136. package/dist/utils/should-clear-cache.js +2 -1
  137. package/dist/utils/should-skip-cache.js +2 -1
  138. package/dist/utils/transformations.js +95 -12
  139. package/dist/utils/validate-env.js +4 -2
  140. package/dist/utils/validate-query.js +7 -3
  141. package/dist/utils/validate-storage.js +4 -2
  142. package/dist/webhooks.js +4 -3
  143. package/dist/websocket/controllers/base.js +12 -6
  144. package/dist/websocket/controllers/graphql.js +4 -2
  145. package/dist/websocket/controllers/hooks.js +3 -2
  146. package/dist/websocket/controllers/index.js +4 -2
  147. package/dist/websocket/controllers/rest.js +4 -2
  148. package/dist/websocket/errors.js +2 -1
  149. package/dist/websocket/handlers/heartbeat.js +4 -3
  150. package/dist/websocket/handlers/subscribe.d.ts +2 -2
  151. package/dist/websocket/handlers/subscribe.js +5 -4
  152. package/package.json +57 -57
  153. package/dist/__utils__/items-utils.d.ts +0 -2
  154. package/dist/__utils__/items-utils.js +0 -31
  155. package/dist/__utils__/mock-env.d.ts +0 -18
  156. package/dist/__utils__/mock-env.js +0 -41
  157. package/dist/__utils__/schemas.d.ts +0 -13
  158. package/dist/__utils__/schemas.js +0 -301
  159. package/dist/__utils__/snapshots.d.ts +0 -5
  160. package/dist/__utils__/snapshots.js +0 -903
  161. package/dist/env.d.ts +0 -14
  162. package/dist/env.js +0 -511
  163. package/dist/messenger.d.ts +0 -24
  164. package/dist/messenger.js +0 -64
  165. package/dist/utils/to-boolean.d.ts +0 -4
  166. package/dist/utils/to-boolean.js +0 -6
  167. /package/dist/redis/{create-redis.d.ts → lib/create-redis.d.ts} +0 -0
  168. /package/dist/redis/{use-redis.d.ts → lib/use-redis.d.ts} +0 -0
  169. /package/dist/redis/{use-redis.js → lib/use-redis.js} +0 -0
package/dist/env.d.ts DELETED
@@ -1,14 +0,0 @@
1
- /**
2
- * @NOTE
3
- * For all possible keys, see: https://docs.directus.io/self-hosted/config-options/
4
- */
5
- export declare const defaults: Record<string, any>;
6
- declare let env: Record<string, any>;
7
- export default env;
8
- export declare const useEnv: () => Record<string, any>;
9
- /**
10
- * When changes have been made during runtime, like in the CLI, we can refresh the env object with
11
- * the newly created variables
12
- */
13
- export declare function refreshEnv(): Promise<void>;
14
- export declare function processValues(env: Record<string, any>): Record<string, any>;
package/dist/env.js DELETED
@@ -1,511 +0,0 @@
1
- /**
2
- * @NOTE
3
- * For all possible keys, see: https://docs.directus.io/self-hosted/config-options/
4
- */
5
- import { JAVASCRIPT_FILE_EXTS } from '@directus/constants';
6
- import { parseJSON, toArray } from '@directus/utils';
7
- import dotenv from 'dotenv';
8
- import fs from 'fs';
9
- import { clone, toNumber, toString } from 'lodash-es';
10
- import { createRequire } from 'node:module';
11
- import { pathToFileURL } from 'node:url';
12
- import path from 'path';
13
- import getModuleDefault from './utils/get-module-default.js';
14
- import { requireYAML } from './utils/require-yaml.js';
15
- import { toBoolean } from './utils/to-boolean.js';
16
- const require = createRequire(import.meta.url);
17
- // keeping this here for now to prevent a circular import to constants.ts
18
- const allowedEnvironmentVars = [
19
- // general
20
- 'CONFIG_PATH',
21
- 'HOST',
22
- 'PORT',
23
- 'PUBLIC_URL',
24
- 'LOG_LEVEL',
25
- 'LOG_STYLE',
26
- 'LOG_HTTP_IGNORE_PATHS',
27
- 'MAX_PAYLOAD_SIZE',
28
- 'ROOT_REDIRECT',
29
- 'SERVE_APP',
30
- 'GRAPHQL_INTROSPECTION',
31
- 'MAX_BATCH_MUTATION',
32
- 'LOGGER_.+',
33
- 'QUERY_LIMIT_MAX',
34
- 'QUERY_LIMIT_DEFAULT',
35
- 'ROBOTS_TXT',
36
- 'TEMP_PATH',
37
- // server
38
- 'SERVER_.+',
39
- // database
40
- 'DB_.+',
41
- // security
42
- 'KEY',
43
- 'SECRET',
44
- 'ACCESS_TOKEN_TTL',
45
- 'REFRESH_TOKEN_TTL',
46
- 'REFRESH_TOKEN_COOKIE_DOMAIN',
47
- 'REFRESH_TOKEN_COOKIE_SECURE',
48
- 'REFRESH_TOKEN_COOKIE_SAME_SITE',
49
- 'REFRESH_TOKEN_COOKIE_NAME',
50
- 'REDIS',
51
- 'REDIS_HOST',
52
- 'REDIS_PORT',
53
- 'REDIS_USERNAME',
54
- 'REDIS_PASSWORD',
55
- 'REDIS_DB',
56
- 'LOGIN_STALL_TIME',
57
- 'PASSWORD_RESET_URL_ALLOW_LIST',
58
- 'USER_INVITE_URL_ALLOW_LIST',
59
- 'IP_TRUST_PROXY',
60
- 'IP_CUSTOM_HEADER',
61
- 'ASSETS_CONTENT_SECURITY_POLICY',
62
- 'IMPORT_IP_DENY_LIST',
63
- 'CONTENT_SECURITY_POLICY_.+',
64
- 'HSTS_.+',
65
- // hashing
66
- 'HASH_.+',
67
- // cors
68
- 'CORS_ENABLED',
69
- 'CORS_ORIGIN',
70
- 'CORS_METHODS',
71
- 'CORS_ALLOWED_HEADERS',
72
- 'CORS_EXPOSED_HEADERS',
73
- 'CORS_CREDENTIALS',
74
- 'CORS_MAX_AGE',
75
- // rate limiting
76
- 'RATE_LIMITER_GLOBAL_.+',
77
- 'RATE_LIMITER_.+',
78
- // cache
79
- 'CACHE_ENABLED',
80
- 'CACHE_TTL',
81
- 'CACHE_CONTROL_S_MAXAGE',
82
- 'CACHE_AUTO_PURGE',
83
- 'CACHE_AUTO_PURGE_IGNORE_LIST',
84
- 'CACHE_SYSTEM_TTL',
85
- 'CACHE_SCHEMA',
86
- 'CACHE_PERMISSIONS',
87
- 'CACHE_NAMESPACE',
88
- 'CACHE_STORE',
89
- 'CACHE_STATUS_HEADER',
90
- 'CACHE_VALUE_MAX_SIZE',
91
- 'CACHE_SKIP_ALLOWED',
92
- 'CACHE_HEALTHCHECK_THRESHOLD',
93
- // storage
94
- 'STORAGE_LOCATIONS',
95
- 'STORAGE_.+_DRIVER',
96
- 'STORAGE_.+_ROOT',
97
- 'STORAGE_.+_KEY',
98
- 'STORAGE_.+_SECRET',
99
- 'STORAGE_.+_BUCKET',
100
- 'STORAGE_.+_REGION',
101
- 'STORAGE_.+_ENDPOINT',
102
- 'STORAGE_.+_ACL',
103
- 'STORAGE_.+_CONTAINER_NAME',
104
- 'STORAGE_.+_SERVER_SIDE_ENCRYPTION',
105
- 'STORAGE_.+_ACCOUNT_NAME',
106
- 'STORAGE_.+_ACCOUNT_KEY',
107
- 'STORAGE_.+_ENDPOINT',
108
- 'STORAGE_.+_KEY_FILENAME',
109
- 'STORAGE_.+_BUCKET',
110
- 'STORAGE_.+_HEALTHCHECK_THRESHOLD',
111
- // metadata
112
- 'FILE_METADATA_ALLOW_LIST',
113
- // files
114
- 'FILES_MAX_UPLOAD_SIZE',
115
- 'FILES_CONTENT_TYPE_ALLOW_LIST',
116
- // assets
117
- 'ASSETS_CACHE_TTL',
118
- 'ASSETS_TRANSFORM_MAX_CONCURRENT',
119
- 'ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION',
120
- 'ASSETS_TRANSFORM_MAX_OPERATIONS',
121
- 'ASSETS_TRANSFORM_TIMEOUT',
122
- 'ASSETS_CONTENT_SECURITY_POLICY',
123
- 'ASSETS_INVALID_IMAGE_SENSITIVITY_LEVEL',
124
- // auth
125
- 'AUTH_PROVIDERS',
126
- 'AUTH_DISABLE_DEFAULT',
127
- 'AUTH_.+_DRIVER',
128
- 'AUTH_.+_CLIENT_ID',
129
- 'AUTH_.+_CLIENT_SECRET',
130
- 'AUTH_.+_SCOPE',
131
- 'AUTH_.+_AUTHORIZE_URL',
132
- 'AUTH_.+_ACCESS_URL',
133
- 'AUTH_.+_PROFILE_URL',
134
- 'AUTH_.+_IDENTIFIER_KEY',
135
- 'AUTH_.+_EMAIL_KEY',
136
- 'AUTH_.+_FIRST_NAME_KEY',
137
- 'AUTH_.+_LAST_NAME_KEY',
138
- 'AUTH_.+_ALLOW_PUBLIC_REGISTRATION',
139
- 'AUTH_.+_DEFAULT_ROLE_ID',
140
- 'AUTH_.+_ICON',
141
- 'AUTH_.+_LABEL',
142
- 'AUTH_.+_PARAMS',
143
- 'AUTH_.+_ISSUER_URL',
144
- 'AUTH_.+_AUTH_REQUIRE_VERIFIED_EMAIL',
145
- 'AUTH_.+_CLIENT_URL',
146
- 'AUTH_.+_BIND_DN',
147
- 'AUTH_.+_BIND_PASSWORD',
148
- 'AUTH_.+_USER_DN',
149
- 'AUTH_.+_USER_ATTRIBUTE',
150
- 'AUTH_.+_USER_SCOPE',
151
- 'AUTH_.+_MAIL_ATTRIBUTE',
152
- 'AUTH_.+_FIRST_NAME_ATTRIBUTE',
153
- 'AUTH_.+_LAST_NAME_ATTRIBUTE',
154
- 'AUTH_.+_GROUP_DN',
155
- 'AUTH_.+_GROUP_ATTRIBUTE',
156
- 'AUTH_.+_GROUP_SCOPE',
157
- 'AUTH_.+_IDP.+',
158
- 'AUTH_.+_SP.+',
159
- // extensions
160
- 'PACKAGE_FILE_LOCATION',
161
- 'EXTENSIONS_LOCATION',
162
- 'EXTENSIONS_PATH',
163
- 'EXTENSIONS_MUST_LOAD',
164
- 'EXTENSIONS_AUTO_RELOAD',
165
- 'EXTENSIONS_CACHE_TTL',
166
- 'EXTENSIONS_SANDBOX_MEMORY',
167
- 'EXTENSIONS_SANDBOX_TIMEOUT',
168
- // messenger
169
- 'MESSENGER_STORE',
170
- 'MESSENGER_NAMESPACE',
171
- // synchronization
172
- 'SYNCHRONIZATION_STORE',
173
- 'SYNCHRONIZATION_NAMESPACE',
174
- // emails
175
- 'EMAIL_FROM',
176
- 'EMAIL_TRANSPORT',
177
- 'EMAIL_VERIFY_SETUP',
178
- 'EMAIL_SENDMAIL_NEW_LINE',
179
- 'EMAIL_SENDMAIL_PATH',
180
- 'EMAIL_SMTP_NAME',
181
- 'EMAIL_SMTP_HOST',
182
- 'EMAIL_SMTP_PORT',
183
- 'EMAIL_SMTP_USER',
184
- 'EMAIL_SMTP_PASSWORD',
185
- 'EMAIL_SMTP_POOL',
186
- 'EMAIL_SMTP_SECURE',
187
- 'EMAIL_SMTP_IGNORE_TLS',
188
- 'EMAIL_MAILGUN_API_KEY',
189
- 'EMAIL_MAILGUN_DOMAIN',
190
- 'EMAIL_MAILGUN_HOST',
191
- 'EMAIL_SENDGRID_API_KEY',
192
- 'EMAIL_SES_CREDENTIALS__ACCESS_KEY_ID',
193
- 'EMAIL_SES_CREDENTIALS__SECRET_ACCESS_KEY',
194
- 'EMAIL_SES_REGION',
195
- // admin account
196
- 'ADMIN_EMAIL',
197
- 'ADMIN_PASSWORD',
198
- // telemetry
199
- 'TELEMETRY',
200
- 'TELEMETRY_URL',
201
- 'TELEMETRY_AUTHORIZATION',
202
- // limits & optimization
203
- 'RELATIONAL_BATCH_SIZE',
204
- 'EXPORT_BATCH_SIZE',
205
- // flows
206
- 'FLOWS_ENV_ALLOW_LIST',
207
- 'FLOWS_RUN_SCRIPT_MAX_MEMORY',
208
- 'FLOWS_RUN_SCRIPT_TIMEOUT',
209
- // websockets
210
- 'WEBSOCKETS_.+',
211
- ].map((name) => new RegExp(`^${name}$`));
212
- const acceptedEnvTypes = ['string', 'number', 'regex', 'array', 'json'];
213
- export const defaults = {
214
- CONFIG_PATH: path.resolve(process.cwd(), '.env'),
215
- HOST: '0.0.0.0',
216
- PORT: 8055,
217
- PUBLIC_URL: '/',
218
- MAX_PAYLOAD_SIZE: '1mb',
219
- MAX_RELATIONAL_DEPTH: 10,
220
- QUERY_LIMIT_DEFAULT: 100,
221
- MAX_BATCH_MUTATION: Infinity,
222
- ROBOTS_TXT: 'User-agent: *\nDisallow: /',
223
- TEMP_PATH: './node_modules/.directus',
224
- DB_EXCLUDE_TABLES: 'spatial_ref_sys,sysdiagrams',
225
- STORAGE_LOCATIONS: 'local',
226
- STORAGE_LOCAL_DRIVER: 'local',
227
- STORAGE_LOCAL_ROOT: './uploads',
228
- RATE_LIMITER_ENABLED: false,
229
- RATE_LIMITER_POINTS: 50,
230
- RATE_LIMITER_DURATION: 1,
231
- RATE_LIMITER_STORE: 'memory',
232
- RATE_LIMITER_GLOBAL_ENABLED: false,
233
- RATE_LIMITER_GLOBAL_POINTS: 1000,
234
- RATE_LIMITER_GLOBAL_DURATION: 1,
235
- RATE_LIMITER_GLOBAL_STORE: 'memory',
236
- ACCESS_TOKEN_TTL: '15m',
237
- REFRESH_TOKEN_TTL: '7d',
238
- REFRESH_TOKEN_COOKIE_SECURE: false,
239
- REFRESH_TOKEN_COOKIE_SAME_SITE: 'lax',
240
- REFRESH_TOKEN_COOKIE_NAME: 'directus_refresh_token',
241
- LOGIN_STALL_TIME: 500,
242
- SERVER_SHUTDOWN_TIMEOUT: 1000,
243
- ROOT_REDIRECT: './admin',
244
- CORS_ENABLED: false,
245
- CORS_ORIGIN: false,
246
- CORS_METHODS: 'GET,POST,PATCH,DELETE',
247
- CORS_ALLOWED_HEADERS: 'Content-Type,Authorization',
248
- CORS_EXPOSED_HEADERS: 'Content-Range',
249
- CORS_CREDENTIALS: true,
250
- CORS_MAX_AGE: 18000,
251
- CACHE_ENABLED: false,
252
- CACHE_STORE: 'memory',
253
- CACHE_TTL: '5m',
254
- CACHE_NAMESPACE: 'system-cache',
255
- CACHE_AUTO_PURGE: false,
256
- CACHE_AUTO_PURGE_IGNORE_LIST: 'directus_activity,directus_presets',
257
- CACHE_CONTROL_S_MAXAGE: '0',
258
- CACHE_SCHEMA: true,
259
- CACHE_PERMISSIONS: true,
260
- CACHE_VALUE_MAX_SIZE: false,
261
- CACHE_SKIP_ALLOWED: false,
262
- AUTH_PROVIDERS: '',
263
- AUTH_DISABLE_DEFAULT: false,
264
- PACKAGE_FILE_LOCATION: '.',
265
- EXTENSIONS_PATH: './extensions',
266
- EXTENSIONS_MUST_LOAD: false,
267
- EXTENSIONS_AUTO_RELOAD: false,
268
- EXTENSIONS_SANDBOX_MEMORY: 100,
269
- EXTENSIONS_SANDBOX_TIMEOUT: 1000,
270
- EMAIL_FROM: 'no-reply@example.com',
271
- EMAIL_VERIFY_SETUP: true,
272
- EMAIL_TRANSPORT: 'sendmail',
273
- EMAIL_SENDMAIL_NEW_LINE: 'unix',
274
- EMAIL_SENDMAIL_PATH: '/usr/sbin/sendmail',
275
- TELEMETRY: true,
276
- TELEMETRY_URL: 'https://telemetry.directus.io',
277
- ASSETS_CACHE_TTL: '30d',
278
- ASSETS_TRANSFORM_MAX_CONCURRENT: 25,
279
- ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION: 6000,
280
- ASSETS_TRANSFORM_MAX_OPERATIONS: 5,
281
- ASSETS_TRANSFORM_TIMEOUT: '7500ms',
282
- ASSETS_INVALID_IMAGE_SENSITIVITY_LEVEL: 'warning',
283
- IP_TRUST_PROXY: true,
284
- IP_CUSTOM_HEADER: false,
285
- IMPORT_IP_DENY_LIST: ['0.0.0.0', '169.254.169.254'],
286
- SERVE_APP: true,
287
- RELATIONAL_BATCH_SIZE: 25000,
288
- EXPORT_BATCH_SIZE: 5000,
289
- FILE_METADATA_ALLOW_LIST: 'ifd0.Make,ifd0.Model,exif.FNumber,exif.ExposureTime,exif.FocalLength,exif.ISO',
290
- GRAPHQL_INTROSPECTION: true,
291
- WEBSOCKETS_ENABLED: false,
292
- WEBSOCKETS_REST_ENABLED: true,
293
- WEBSOCKETS_REST_AUTH: 'handshake',
294
- WEBSOCKETS_REST_AUTH_TIMEOUT: 10,
295
- WEBSOCKETS_REST_PATH: '/websocket',
296
- WEBSOCKETS_GRAPHQL_ENABLED: true,
297
- WEBSOCKETS_GRAPHQL_AUTH: 'handshake',
298
- WEBSOCKETS_GRAPHQL_AUTH_TIMEOUT: 10,
299
- WEBSOCKETS_GRAPHQL_PATH: '/graphql',
300
- WEBSOCKETS_HEARTBEAT_ENABLED: true,
301
- WEBSOCKETS_HEARTBEAT_PERIOD: 30,
302
- FLOWS_ENV_ALLOW_LIST: false,
303
- FLOWS_RUN_SCRIPT_MAX_MEMORY: 32,
304
- FLOWS_RUN_SCRIPT_TIMEOUT: 10000,
305
- PRESSURE_LIMITER_ENABLED: true,
306
- PRESSURE_LIMITER_SAMPLE_INTERVAL: 250,
307
- PRESSURE_LIMITER_MAX_EVENT_LOOP_UTILIZATION: 0.99,
308
- PRESSURE_LIMITER_MAX_EVENT_LOOP_DELAY: 500,
309
- PRESSURE_LIMITER_MAX_MEMORY_RSS: false,
310
- PRESSURE_LIMITER_MAX_MEMORY_HEAP_USED: false,
311
- PRESSURE_LIMITER_RETRY_AFTER: false,
312
- FILES_MIME_TYPE_ALLOW_LIST: '*/*',
313
- };
314
- /**
315
- * Allows us to force certain environment variable into a type, instead of relying
316
- * on the auto-parsed type in processValues.
317
- */
318
- const typeMap = {
319
- HOST: 'string',
320
- PORT: 'string',
321
- DB_NAME: 'string',
322
- DB_USER: 'string',
323
- DB_PASSWORD: 'string',
324
- DB_DATABASE: 'string',
325
- DB_PORT: 'number',
326
- DB_EXCLUDE_TABLES: 'array',
327
- CACHE_SKIP_ALLOWED: 'boolean',
328
- CACHE_AUTO_PURGE_IGNORE_LIST: 'array',
329
- IMPORT_IP_DENY_LIST: 'array',
330
- FILE_METADATA_ALLOW_LIST: 'array',
331
- GRAPHQL_INTROSPECTION: 'boolean',
332
- MAX_BATCH_MUTATION: 'number',
333
- SERVER_SHUTDOWN_TIMEOUT: 'number',
334
- LOG_HTTP_IGNORE_PATHS: 'array',
335
- };
336
- let env = {
337
- ...defaults,
338
- ...process.env,
339
- ...(await processConfiguration()),
340
- };
341
- process.env = env;
342
- env = processValues(env);
343
- export default env;
344
- export const useEnv = () => env;
345
- /**
346
- * When changes have been made during runtime, like in the CLI, we can refresh the env object with
347
- * the newly created variables
348
- */
349
- export async function refreshEnv() {
350
- env = {
351
- ...defaults,
352
- ...process.env,
353
- ...(await processConfiguration()),
354
- };
355
- process.env = env;
356
- env = processValues(env);
357
- }
358
- async function processConfiguration() {
359
- const configPath = path.resolve(process.env['CONFIG_PATH'] || defaults['CONFIG_PATH']);
360
- if (fs.existsSync(configPath) === false)
361
- return {};
362
- const fileExt = path.extname(configPath).toLowerCase().substring(1);
363
- if (JAVASCRIPT_FILE_EXTS.includes(fileExt)) {
364
- const data = await import(pathToFileURL(configPath).toString());
365
- const config = getModuleDefault(data);
366
- if (typeof config === 'function') {
367
- return config(process.env);
368
- }
369
- else if (typeof config === 'object') {
370
- return config;
371
- }
372
- throw new Error(`Invalid JS configuration file export type. Requires one of "function", "object", received: "${typeof config}"`);
373
- }
374
- if (fileExt === 'json') {
375
- return require(configPath);
376
- }
377
- if (fileExt === 'yaml' || fileExt === 'yml') {
378
- const data = requireYAML(configPath);
379
- if (typeof data === 'object') {
380
- return data;
381
- }
382
- throw new Error('Invalid YAML configuration. Root has to be an object.');
383
- }
384
- // Default to env vars plain text files
385
- return dotenv.parse(fs.readFileSync(configPath, { encoding: 'utf8' }));
386
- }
387
- function getVariableType(variable) {
388
- return variable.split(':').slice(0, -1)[0];
389
- }
390
- function getEnvVariableValue(variableValue, variableType) {
391
- return variableValue.split(`${variableType}:`)[1];
392
- }
393
- function getEnvironmentValueWithPrefix(envArray) {
394
- return envArray.map((item) => {
395
- if (isEnvSyntaxPrefixPresent(item)) {
396
- return getEnvironmentValueByType(item);
397
- }
398
- return item;
399
- });
400
- }
401
- function getEnvironmentValueByType(envVariableString) {
402
- const variableType = getVariableType(envVariableString);
403
- const envVariableValue = getEnvVariableValue(envVariableString, variableType);
404
- switch (variableType) {
405
- case 'number':
406
- return toNumber(envVariableValue);
407
- case 'array':
408
- return getEnvironmentValueWithPrefix(toArray(envVariableValue));
409
- case 'regex':
410
- return new RegExp(envVariableValue);
411
- case 'string':
412
- return envVariableValue;
413
- case 'json':
414
- return tryJSON(envVariableValue);
415
- }
416
- }
417
- function isEnvSyntaxPrefixPresent(value) {
418
- return acceptedEnvTypes.some((envType) => value.includes(`${envType}:`));
419
- }
420
- export function processValues(env) {
421
- env = clone(env);
422
- for (let [key, value] of Object.entries(env)) {
423
- // If key ends with '_FILE', try to get the value from the file defined in this variable
424
- // and store it in the variable with the same name but without '_FILE' at the end
425
- let newKey;
426
- if (key.length > 5 && key.endsWith('_FILE')) {
427
- newKey = key.slice(0, -5);
428
- if (allowedEnvironmentVars.some((pattern) => pattern.test(newKey))) {
429
- if (newKey in env && !(newKey in defaults && env[newKey] === defaults[newKey])) {
430
- throw new Error(`Duplicate environment variable encountered: you can't use "${newKey}" and "${key}" simultaneously.`);
431
- }
432
- try {
433
- value = fs.readFileSync(value, { encoding: 'utf8' });
434
- key = newKey;
435
- }
436
- catch {
437
- throw new Error(`Failed to read value from file "${value}", defined in environment variable "${key}".`);
438
- }
439
- }
440
- }
441
- // Convert values with a type prefix
442
- // (see https://docs.directus.io/reference/environment-variables/#environment-syntax-prefix)
443
- if (typeof value === 'string' && isEnvSyntaxPrefixPresent(value)) {
444
- env[key] = getEnvironmentValueByType(value);
445
- continue;
446
- }
447
- // Convert values where the key is defined in typeMap
448
- if (typeMap[key]) {
449
- switch (typeMap[key]) {
450
- case 'number':
451
- env[key] = toNumber(value);
452
- break;
453
- case 'string':
454
- env[key] = toString(value);
455
- break;
456
- case 'array':
457
- env[key] = toArray(value);
458
- break;
459
- case 'json':
460
- env[key] = tryJSON(value);
461
- break;
462
- case 'boolean':
463
- env[key] = toBoolean(value);
464
- }
465
- continue;
466
- }
467
- // Try to convert remaining values:
468
- // - boolean values to boolean
469
- // - 'null' to null
470
- // - number values (> 0 <= Number.MAX_SAFE_INTEGER) to number
471
- if (value === 'true') {
472
- env[key] = true;
473
- continue;
474
- }
475
- if (value === 'false') {
476
- env[key] = false;
477
- continue;
478
- }
479
- if (value === 'null') {
480
- env[key] = null;
481
- continue;
482
- }
483
- if (String(value).startsWith('0') === false &&
484
- isNaN(value) === false &&
485
- value.length > 0 &&
486
- value <= Number.MAX_SAFE_INTEGER) {
487
- env[key] = Number(value);
488
- continue;
489
- }
490
- if (String(value).includes(',')) {
491
- env[key] = toArray(value);
492
- continue;
493
- }
494
- // Try converting the value to a JS object. This allows JSON objects to be passed for nested
495
- // config flags, or custom param names (that aren't camelCased)
496
- env[key] = tryJSON(value);
497
- // If '_FILE' variable hasn't been processed yet, store it as it is (string)
498
- if (newKey) {
499
- env[key] = value;
500
- }
501
- }
502
- return env;
503
- }
504
- function tryJSON(value) {
505
- try {
506
- return parseJSON(value);
507
- }
508
- catch {
509
- return value;
510
- }
511
- }
@@ -1,24 +0,0 @@
1
- import { Redis } from 'ioredis';
2
- export type MessengerSubscriptionCallback = (payload: Record<string, any>) => void;
3
- export interface Messenger {
4
- publish: (channel: string, payload: Record<string, any>) => void;
5
- subscribe: (channel: string, callback: MessengerSubscriptionCallback) => void;
6
- unsubscribe: (channel: string, callback?: MessengerSubscriptionCallback) => void;
7
- }
8
- export declare class MessengerMemory implements Messenger {
9
- handlers: Record<string, Set<MessengerSubscriptionCallback>>;
10
- constructor();
11
- publish(channel: string, payload: Record<string, any>): void;
12
- subscribe(channel: string, callback: MessengerSubscriptionCallback): void;
13
- unsubscribe(channel: string, callback?: MessengerSubscriptionCallback): void;
14
- }
15
- export declare class MessengerRedis implements Messenger {
16
- namespace: string;
17
- pub: Redis;
18
- sub: Redis;
19
- constructor();
20
- publish(channel: string, payload: Record<string, any>): void;
21
- subscribe(channel: string, callback: MessengerSubscriptionCallback): void;
22
- unsubscribe(channel: string): void;
23
- }
24
- export declare function getMessenger(): Messenger;
package/dist/messenger.js DELETED
@@ -1,64 +0,0 @@
1
- import { parseJSON } from '@directus/utils';
2
- import { Redis } from 'ioredis';
3
- import env from './env.js';
4
- import { getConfigFromEnv } from './utils/get-config-from-env.js';
5
- export class MessengerMemory {
6
- handlers;
7
- constructor() {
8
- this.handlers = {};
9
- }
10
- publish(channel, payload) {
11
- this.handlers[channel]?.forEach((callback) => callback(payload));
12
- }
13
- subscribe(channel, callback) {
14
- if (!this.handlers[channel])
15
- this.handlers[channel] = new Set();
16
- this.handlers[channel]?.add(callback);
17
- }
18
- unsubscribe(channel, callback) {
19
- if (!callback) {
20
- delete this.handlers[channel];
21
- }
22
- else {
23
- this.handlers[channel]?.delete(callback);
24
- }
25
- }
26
- }
27
- export class MessengerRedis {
28
- namespace;
29
- pub;
30
- sub;
31
- constructor() {
32
- const config = getConfigFromEnv('REDIS');
33
- this.pub = new Redis(env['REDIS'] ?? config);
34
- this.sub = new Redis(env['REDIS'] ?? config);
35
- this.namespace = env['MESSENGER_NAMESPACE'] ?? 'directus-messenger';
36
- }
37
- publish(channel, payload) {
38
- this.pub.publish(`${this.namespace}:${channel}`, JSON.stringify(payload));
39
- }
40
- subscribe(channel, callback) {
41
- this.sub.subscribe(`${this.namespace}:${channel}`);
42
- this.sub.on('message', (messageChannel, payloadString) => {
43
- const payload = parseJSON(payloadString);
44
- if (messageChannel === `${this.namespace}:${channel}`) {
45
- callback(payload);
46
- }
47
- });
48
- }
49
- unsubscribe(channel) {
50
- this.sub.unsubscribe(`${this.namespace}:${channel}`);
51
- }
52
- }
53
- let messenger;
54
- export function getMessenger() {
55
- if (messenger)
56
- return messenger;
57
- if (env['MESSENGER_STORE'] === 'redis') {
58
- messenger = new MessengerRedis();
59
- }
60
- else {
61
- messenger = new MessengerMemory();
62
- }
63
- return messenger;
64
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * Convert environment variable to Boolean
3
- */
4
- export declare function toBoolean(value: any): boolean;
@@ -1,6 +0,0 @@
1
- /**
2
- * Convert environment variable to Boolean
3
- */
4
- export function toBoolean(value) {
5
- return value === 'true' || value === true || value === '1' || value === 1;
6
- }
File without changes