@directus/api 13.2.0 → 14.0.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 (109) hide show
  1. package/dist/__utils__/snapshots.js +9 -0
  2. package/dist/app.js +2 -0
  3. package/dist/cli/index.js +3 -4
  4. package/dist/cli/load-extensions.d.ts +1 -0
  5. package/dist/cli/load-extensions.js +19 -0
  6. package/dist/controllers/extensions.js +28 -19
  7. package/dist/controllers/versions.d.ts +2 -0
  8. package/dist/controllers/versions.js +188 -0
  9. package/dist/database/migrations/20230823A-add-content-versioning.d.ts +3 -0
  10. package/dist/database/migrations/20230823A-add-content-versioning.js +36 -0
  11. package/dist/database/migrations/20230927A-themes.d.ts +3 -0
  12. package/dist/database/migrations/20230927A-themes.js +49 -0
  13. package/dist/database/migrations/20231009B-update-panel-options.d.ts +3 -0
  14. package/dist/database/migrations/20231009B-update-panel-options.js +77 -0
  15. package/dist/database/migrations/20231010A-add-extensions.d.ts +3 -0
  16. package/dist/database/migrations/20231010A-add-extensions.js +9 -0
  17. package/dist/database/run-ast.js +1 -1
  18. package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +5 -1
  19. package/dist/database/system-data/collections/collections.yaml +6 -0
  20. package/dist/database/system-data/fields/activity.yaml +4 -4
  21. package/dist/database/system-data/fields/collections.yaml +19 -0
  22. package/dist/database/system-data/fields/extensions.yaml +10 -0
  23. package/dist/database/system-data/fields/revisions.yaml +3 -0
  24. package/dist/database/system-data/fields/settings.yaml +73 -17
  25. package/dist/database/system-data/fields/users.yaml +50 -12
  26. package/dist/database/system-data/fields/versions.yaml +38 -0
  27. package/dist/database/system-data/fields/webhooks.yaml +9 -9
  28. package/dist/database/system-data/relations/relations.yaml +88 -20
  29. package/dist/emitter.d.ts +2 -2
  30. package/dist/env.js +4 -0
  31. package/dist/extensions/lib/get-extensions-settings.d.ts +7 -0
  32. package/dist/extensions/lib/get-extensions-settings.js +39 -0
  33. package/dist/extensions/lib/get-extensions.d.ts +1 -0
  34. package/dist/extensions/lib/get-extensions.js +11 -0
  35. package/dist/extensions/{get-shared-deps-mapping.js → lib/get-shared-deps-mapping.js} +3 -3
  36. package/dist/extensions/lib/sandbox/generate-api-extensions-sandbox-entrypoint.d.ts +31 -0
  37. package/dist/extensions/lib/sandbox/generate-api-extensions-sandbox-entrypoint.js +80 -0
  38. package/dist/extensions/lib/sandbox/generate-host-function-reference.d.ts +11 -0
  39. package/dist/extensions/lib/sandbox/generate-host-function-reference.js +28 -0
  40. package/dist/extensions/lib/sandbox/register/action.d.ts +6 -0
  41. package/dist/extensions/lib/sandbox/register/action.js +18 -0
  42. package/dist/extensions/lib/sandbox/register/call-reference.d.ts +5 -0
  43. package/dist/extensions/lib/sandbox/register/call-reference.js +20 -0
  44. package/dist/extensions/lib/sandbox/register/filter.d.ts +6 -0
  45. package/dist/extensions/lib/sandbox/register/filter.js +21 -0
  46. package/dist/extensions/lib/sandbox/register/index.d.ts +5 -0
  47. package/dist/extensions/lib/sandbox/register/index.js +5 -0
  48. package/dist/extensions/lib/sandbox/register/operation.d.ts +6 -0
  49. package/dist/extensions/lib/sandbox/register/operation.js +19 -0
  50. package/dist/extensions/lib/sandbox/register/route.d.ts +17 -0
  51. package/dist/extensions/lib/sandbox/register/route.js +44 -0
  52. package/dist/extensions/lib/sandbox/sdk/generators/index.d.ts +3 -0
  53. package/dist/extensions/lib/sandbox/sdk/generators/index.js +3 -0
  54. package/dist/extensions/lib/sandbox/sdk/generators/log.d.ts +3 -0
  55. package/dist/extensions/lib/sandbox/sdk/generators/log.js +11 -0
  56. package/dist/extensions/lib/sandbox/sdk/generators/request.d.ts +12 -0
  57. package/dist/extensions/lib/sandbox/sdk/generators/request.js +49 -0
  58. package/dist/extensions/lib/sandbox/sdk/generators/sleep.d.ts +3 -0
  59. package/dist/extensions/lib/sandbox/sdk/generators/sleep.js +11 -0
  60. package/dist/extensions/lib/sandbox/sdk/index.d.ts +2 -0
  61. package/dist/extensions/lib/sandbox/sdk/index.js +2 -0
  62. package/dist/extensions/lib/sandbox/sdk/instantiate.d.ts +11 -0
  63. package/dist/extensions/lib/sandbox/sdk/instantiate.js +28 -0
  64. package/dist/extensions/lib/sandbox/sdk/sdk.d.ts +20 -0
  65. package/dist/extensions/lib/sandbox/sdk/sdk.js +11 -0
  66. package/dist/extensions/lib/sandbox/sdk/utils/index.d.ts +1 -0
  67. package/dist/extensions/lib/sandbox/sdk/utils/index.js +1 -0
  68. package/dist/extensions/lib/sandbox/sdk/utils/wrap.d.ts +11 -0
  69. package/dist/extensions/lib/sandbox/sdk/utils/wrap.js +17 -0
  70. package/dist/extensions/manager.d.ts +128 -14
  71. package/dist/extensions/manager.js +310 -136
  72. package/dist/extensions/types.d.ts +1 -5
  73. package/dist/flows.d.ts +1 -1
  74. package/dist/flows.js +6 -6
  75. package/dist/middleware/respond.js +12 -0
  76. package/dist/server.js +2 -1
  77. package/dist/services/assets.js +1 -1
  78. package/dist/services/extensions.d.ts +31 -0
  79. package/dist/services/extensions.js +136 -0
  80. package/dist/services/graphql/index.d.ts +1 -1
  81. package/dist/services/graphql/index.js +87 -24
  82. package/dist/services/index.d.ts +2 -0
  83. package/dist/services/index.js +2 -0
  84. package/dist/services/server.js +3 -1
  85. package/dist/services/users.js +2 -0
  86. package/dist/services/versions.d.ts +21 -0
  87. package/dist/services/versions.js +238 -0
  88. package/dist/types/collection.d.ts +1 -0
  89. package/dist/utils/apply-query.d.ts +1 -1
  90. package/dist/utils/apply-query.js +30 -2
  91. package/dist/utils/delete-from-require-cache.d.ts +1 -0
  92. package/dist/utils/delete-from-require-cache.js +5 -0
  93. package/dist/utils/get-service.js +3 -1
  94. package/dist/utils/import-file-url.d.ts +5 -0
  95. package/dist/utils/import-file-url.js +6 -0
  96. package/dist/utils/job-queue.d.ts +2 -3
  97. package/dist/utils/redact-object.d.ts +1 -1
  98. package/dist/utils/redact-object.js +37 -24
  99. package/dist/utils/sanitize-query.js +3 -0
  100. package/dist/utils/validate-query.js +1 -0
  101. package/dist/worker-pool.js +8 -0
  102. package/package.json +28 -27
  103. package/dist/extensions/get-extensions.d.ts +0 -47
  104. package/dist/extensions/get-extensions.js +0 -9
  105. package/dist/extensions/normalize-extension-info.d.ts +0 -5
  106. package/dist/extensions/normalize-extension-info.js +0 -30
  107. /package/dist/extensions/{get-shared-deps-mapping.d.ts → lib/get-shared-deps-mapping.d.ts} +0 -0
  108. /package/dist/extensions/{wrap-embeds.d.ts → lib/wrap-embeds.d.ts} +0 -0
  109. /package/dist/extensions/{wrap-embeds.js → lib/wrap-embeds.js} +0 -0
@@ -114,8 +114,27 @@ fields:
114
114
  interface: system-display-template
115
115
  options:
116
116
  collectionField: collection
117
+ injectVersionField: true
117
118
  width: full
118
119
 
120
+ - field: content_versioning_divider
121
+ special:
122
+ - alias
123
+ - no-data
124
+ interface: presentation-divider
125
+ options:
126
+ icon: published_with_changes
127
+ title: $t:field_options.directus_collections.content_versioning_divider
128
+ width: full
129
+
130
+ - field: versioning
131
+ interface: boolean
132
+ special:
133
+ - cast-boolean
134
+ options:
135
+ label: $t:field_options.directus_collections.enable_versioning
136
+ width: half
137
+
119
138
  - field: archive_divider
120
139
  special:
121
140
  - alias
@@ -0,0 +1,10 @@
1
+ table: directus_extensions
2
+
3
+ fields:
4
+ - collection: directus_extensions
5
+ field: name
6
+
7
+ - collection: directus_extensions
8
+ field: enabled
9
+ special:
10
+ - cast-boolean
@@ -25,3 +25,6 @@ fields:
25
25
 
26
26
  - field: parent
27
27
  width: half
28
+
29
+ - field: version
30
+ width: half
@@ -32,6 +32,13 @@ fields:
32
32
  placeholder: en-US
33
33
  width: half
34
34
 
35
+ - field: theming_group
36
+ interface: group-raw
37
+ special:
38
+ - alias
39
+ - no-data
40
+ - group
41
+
35
42
  - field: branding_divider
36
43
  interface: presentation-divider
37
44
  options:
@@ -41,32 +48,96 @@ fields:
41
48
  - alias
42
49
  - no-data
43
50
  width: full
51
+ group: theming_group
44
52
 
45
53
  - field: project_color
46
54
  interface: select-color
47
55
  note: $t:field_options.directus_settings.project_color_note
48
56
  width: half
57
+ group: theming_group
49
58
 
50
59
  - field: project_logo
51
60
  interface: file
52
61
  note: $t:field_options.directus_settings.project_logo_note
53
62
  width: half
63
+ group: theming_group
54
64
 
55
65
  - field: public_foreground
56
66
  interface: file
57
67
  width: half
68
+ group: theming_group
58
69
 
59
70
  - field: public_background
60
71
  interface: file
61
- translations:
62
72
  width: half
73
+ group: theming_group
74
+
75
+ - field: public_favicon
76
+ interface: file
77
+ note: $t:field_options.directus_settings.project_favicon_note
78
+ width: half
79
+ group: theming_group
63
80
 
64
81
  - field: public_note
65
82
  interface: input
66
83
  options:
67
84
  placeholder: $t:field_options.directus_settings.public_note_placeholder
68
85
  iconRight: info
86
+ width: half
87
+ group: theming_group
88
+
89
+ - field: default_appearance
90
+ interface: select-dropdown
91
+ options:
92
+ choices:
93
+ - value: auto
94
+ text: $t:appearance_auto
95
+ - value: light
96
+ text: $t:appearance_light
97
+ - value: dark
98
+ text: $t:appearance_dark
99
+ group: theming_group
100
+
101
+ - field: theming_divider
102
+ interface: presentation-divider
103
+ options:
104
+ icon: palette
105
+ title: $t:fields.directus_settings.theming
106
+ special:
107
+ - alias
108
+ - no-data
69
109
  width: full
110
+ group: theming_group
111
+
112
+ - field: default_theme_light
113
+ width: full
114
+ interface: system-theme
115
+ options:
116
+ appearance: light
117
+ group: theming_group
118
+ hidden: true
119
+
120
+ - field: theme_light_overrides
121
+ width: full
122
+ interface: system-theme-overrides
123
+ group: theming_group
124
+ special:
125
+ - cast-json
126
+
127
+ - field: default_theme_dark
128
+ width: full
129
+ interface: system-theme
130
+ options:
131
+ appearance: dark
132
+ group: theming_group
133
+ hidden: true
134
+
135
+ - field: theme_dark_overrides
136
+ width: full
137
+ interface: system-theme-overrides
138
+ group: theming_group
139
+ special:
140
+ - cast-json
70
141
 
71
142
  - field: custom_css
72
143
  interface: input-code
@@ -75,26 +146,11 @@ fields:
75
146
  lineNumber: true
76
147
  template: |
77
148
  #app, #main-content, body {
78
- --primary-alt: #F0ECFF !important;
79
- --primary-10: #F0ECFF !important;
80
- --primary-25: #D9D0FF !important;
81
- --primary-50: #B3A1FF !important;
82
- --primary-75: #8C73FF !important;
83
- --primary-90: #7557FF !important;
84
-
85
- --primary: #6644FF !important;
86
-
87
- --primary-110: #5E41EC !important;
88
- --primary-125: #523DCF !important;
89
- --primary-150: #3E369F !important;
90
- --primary-175: #2B3070 !important;
91
- --primary-190: #1F2C53 !important;
92
-
93
149
  --v-button-background-color: #6644FF !important;
94
150
  --v-button-background-color-hover: #5E41EC !important;
95
- --sidebar-detail-color-active: #5E41EC !important;
96
151
  }
97
152
  width: full
153
+ group: theming_group
98
154
 
99
155
  - field: modules_divider
100
156
  interface: presentation-divider
@@ -78,36 +78,74 @@ fields:
78
78
  options:
79
79
  includeProjectDefault: true
80
80
 
81
- - field: theme
81
+ - field: tfa_secret
82
+ interface: system-mfa-setup
83
+ special:
84
+ - conceal
85
+ width: half
86
+
87
+ - field: email_notifications
88
+ interface: boolean
89
+ width: half
90
+ special:
91
+ - cast-boolean
92
+
93
+ - field: theming_divider
94
+ interface: presentation-divider
95
+ options:
96
+ icon: palette
97
+ title: $t:theme
98
+ special:
99
+ - alias
100
+ - no-data
101
+ width: full
102
+
103
+ - field: appearance
82
104
  interface: select-dropdown
83
105
  options:
84
106
  choices:
107
+ - value: null
108
+ text: $t:appearance_global
85
109
  - value: auto
86
- text: $t:fields.directus_users.theme_auto
110
+ text: $t:appearance_auto
87
111
  - value: light
88
- text: $t:fields.directus_users.theme_light
112
+ text: $t:appearance_light
89
113
  - value: dark
90
- text: $t:fields.directus_users.theme_dark
114
+ text: $t:appearance_dark
91
115
  width: half
92
116
 
93
- - field: tfa_secret
94
- interface: system-mfa-setup
95
- special:
96
- - conceal
117
+ - field: theme_light
97
118
  width: half
119
+ interface: system-theme
120
+ options:
121
+ appearance: light
122
+ hidden: true
98
123
 
99
- - field: email_notifications
100
- interface: boolean
124
+ - field: theme_dark
101
125
  width: half
126
+ interface: system-theme
127
+ options:
128
+ appearance: dark
129
+ hidden: true
130
+
131
+ - field: theme_light_overrides
132
+ width: full
133
+ interface: system-theme-overrides
102
134
  special:
103
- - cast-boolean
135
+ - cast-json
136
+
137
+ - field: theme_dark_overrides
138
+ width: full
139
+ interface: system-theme-overrides
140
+ special:
141
+ - cast-json
104
142
 
105
143
  - field: admin_divider
106
144
  interface: presentation-divider
107
145
  options:
108
146
  icon: verified_user
109
147
  title: $t:fields.directus_users.admin_options
110
- color: 'var(--danger)'
148
+ color: 'var(--theme--danger)'
111
149
  special:
112
150
  - alias
113
151
  - no-data
@@ -0,0 +1,38 @@
1
+ table: directus_versions
2
+
3
+ fields:
4
+ - field: id
5
+ special:
6
+ - uuid
7
+ readonly: true
8
+ hidden: true
9
+
10
+ - field: key
11
+
12
+ - field: name
13
+
14
+ - field: collection
15
+
16
+ - field: item
17
+
18
+ - field: hash
19
+ readonly: true
20
+ hidden: true
21
+
22
+ - field: date_created
23
+ special:
24
+ - date-created
25
+ - cast-timestamp
26
+
27
+ - field: date_updated
28
+ special:
29
+ - date-updated
30
+ - cast-timestamp
31
+
32
+ - field: user_created
33
+ special:
34
+ - user-created
35
+
36
+ - field: user_updated
37
+ special:
38
+ - user-updated
@@ -16,10 +16,10 @@ fields:
16
16
  display_options:
17
17
  choices:
18
18
  - value: POST
19
- foreground: 'var(--primary)'
20
- background: 'var(--primary-25)'
19
+ foreground: 'var(--theme--primary)'
20
+ background: 'var(--theme--primary-subdued)'
21
21
  - value: GET
22
- foreground: 'var(--secondary)'
22
+ foreground: 'var(--theme--secondary)'
23
23
  background: 'var(--secondary-25)'
24
24
  format: false
25
25
  options:
@@ -42,11 +42,11 @@ fields:
42
42
  choices:
43
43
  - text: $t:field_options.directus_webhooks.status_options_active
44
44
  value: active
45
- foreground: 'var(--primary-10)'
46
- background: 'var(--primary)'
45
+ foreground: 'var(--theme--primary-background)'
46
+ background: 'var(--theme--primary)'
47
47
  - text: $t:field_options.directus_webhooks.status_options_inactive
48
48
  value: inactive
49
- foreground: 'var(--foreground-normal)'
49
+ foreground: 'var(--theme--foreground)'
50
50
  background: 'var(--background-normal-alt)'
51
51
  options:
52
52
  choices:
@@ -115,15 +115,15 @@ fields:
115
115
  choices:
116
116
  - text: $t:create
117
117
  value: create
118
- foreground: 'var(--primary)'
119
- background: 'var(--primary-25)'
118
+ foreground: 'var(--theme--primary)'
119
+ background: 'var(--theme--primary-subdued)'
120
120
  - text: $t:update
121
121
  value: update
122
122
  foreground: 'var(--blue)'
123
123
  background: 'var(--blue-25)'
124
124
  - text: $t:delete_label
125
125
  value: delete
126
- foreground: 'var(--danger)'
126
+ foreground: 'var(--theme--danger)'
127
127
  background: 'var(--danger-25)'
128
128
  - text: $t:login
129
129
  value: login
@@ -12,114 +12,182 @@ defaults:
12
12
  sort_field: null
13
13
 
14
14
  data:
15
+ ### Collections
15
16
  - many_collection: directus_collections
16
17
  many_field: group
17
18
  one_collection: directus_collections
19
+
20
+ ### Users
18
21
  - many_collection: directus_users
19
22
  many_field: role
20
23
  one_collection: directus_roles
21
24
  one_field: users
25
+
22
26
  - many_collection: directus_users
23
27
  many_field: avatar
24
28
  one_collection: directus_files
29
+
30
+ ### Revisions
25
31
  - many_collection: directus_revisions
26
32
  many_field: activity
27
33
  one_collection: directus_activity
28
34
  one_field: revisions
35
+
36
+ - many_collection: directus_revisions
37
+ many_field: parent
38
+ one_collection: directus_revisions
39
+
40
+ - many_collection: directus_revisions
41
+ many_field: version
42
+ one_collection: directus_versions
43
+
44
+ ### Presets
29
45
  - many_collection: directus_presets
30
46
  many_field: user
31
47
  one_collection: directus_users
48
+
32
49
  - many_collection: directus_presets
33
50
  many_field: role
34
51
  one_collection: directus_roles
52
+
53
+ ### Folders
35
54
  - many_collection: directus_folders
36
55
  many_field: parent
37
56
  one_collection: directus_folders
57
+
58
+ ### Files
38
59
  - many_collection: directus_files
39
60
  many_field: folder
40
61
  one_collection: directus_folders
62
+
41
63
  - many_collection: directus_files
42
64
  many_field: uploaded_by
43
65
  one_collection: directus_users
66
+
67
+ - many_collection: directus_files
68
+ many_field: modified_by
69
+ one_collection: directus_users
70
+
71
+ ### Fields
44
72
  - many_collection: directus_fields
45
73
  many_field: collection
46
74
  one_collection: directus_collections
47
75
  one_field: fields
76
+
77
+ - many_collection: directus_fields
78
+ many_field: group
79
+ one_collection: directus_fields
80
+
81
+ ### Activity
48
82
  - many_collection: directus_activity
49
83
  many_field: user
50
84
  one_collection: directus_users
85
+
86
+ ### Settings
51
87
  - many_collection: directus_settings
52
88
  many_field: project_logo
53
89
  one_collection: directus_files
90
+
54
91
  - many_collection: directus_settings
55
92
  many_field: public_foreground
56
93
  one_collection: directus_files
94
+
57
95
  - many_collection: directus_settings
58
96
  many_field: public_background
59
97
  one_collection: directus_files
98
+
99
+ - many_collection: directus_settings
100
+ many_field: storage_default_folder
101
+ one_collection: directus_folders
102
+
103
+ ### Panels
60
104
  - many_collection: directus_panels
61
105
  many_field: dashboard
62
106
  one_collection: directus_dashboards
63
107
  one_field: panels
108
+
109
+ - many_collection: directus_panels
110
+ many_field: user_created
111
+ one_collection: directus_users
112
+
113
+ ### Flows
64
114
  - many_collection: directus_flows
65
115
  many_field: operation
66
116
  one_collection: directus_operations
117
+
118
+ - many_collection: directus_flows
119
+ many_field: user_created
120
+ one_collection: directus_users
121
+
122
+ ### Operations
67
123
  - many_collection: directus_operations
68
124
  many_field: flow
69
125
  one_collection: directus_flows
70
126
  one_field: operations
71
127
  one_deselect_action: delete
128
+
72
129
  - many_collection: directus_operations
73
130
  many_field: resolve
74
131
  one_collection: directus_operations
132
+
75
133
  - many_collection: directus_operations
76
134
  many_field: reject
77
135
  one_collection: directus_operations
78
- - many_collection: directus_files
79
- many_field: modified_by
136
+
137
+ - many_collection: directus_operations
138
+ many_field: user_created
80
139
  one_collection: directus_users
81
- - many_collection: directus_fields
82
- many_field: group
83
- one_collection: directus_fields
140
+
141
+ ### Permissions
84
142
  - many_collection: directus_permissions
85
143
  many_field: role
86
144
  one_collection: directus_roles
87
- - many_collection: directus_revisions
88
- many_field: parent
89
- one_collection: directus_revisions
145
+
146
+ ### Sessions
90
147
  - many_collection: directus_sessions
91
148
  many_field: user
92
149
  one_collection: directus_users
150
+
93
151
  - many_collection: directus_sessions
94
152
  many_field: share
95
153
  one_collection: directus_shares
96
- - many_collection: directus_settings
97
- many_field: storage_default_folder
98
- one_collection: directus_folders
154
+
155
+ ### Dashboards
99
156
  - many_collection: directus_dashboards
100
157
  many_field: user_created
101
158
  one_collection: directus_users
102
- - many_collection: directus_panels
103
- many_field: user_created
104
- one_collection: directus_users
105
- - many_collection: directus_flows
106
- many_field: user_created
107
- one_collection: directus_users
108
- - many_collection: directus_operations
109
- many_field: user_created
110
- one_collection: directus_users
159
+
160
+ ### Notifications
111
161
  - many_collection: directus_notifications
112
162
  many_field: recipient
113
163
  one_collection: directus_users
164
+
114
165
  - many_collection: directus_notifications
115
166
  many_field: sender
116
167
  one_collection: directus_users
168
+
169
+ ### Shares
117
170
  - many_collection: directus_shares
118
171
  many_field: role
119
172
  one_collection: directus_roles
173
+
120
174
  - many_collection: directus_shares
121
175
  many_field: collection
122
176
  one_collection: directus_collections
177
+
123
178
  - many_collection: directus_shares
124
179
  many_field: user_created
125
180
  one_collection: directus_users
181
+
182
+ ### Versions
183
+ - many_collection: directus_versions
184
+ many_field: collection
185
+ one_collection: directus_collections
186
+
187
+ - many_collection: directus_versions
188
+ many_field: user_created
189
+ one_collection: directus_users
190
+
191
+ - many_collection: directus_versions
192
+ many_field: user_updated
193
+ one_collection: directus_users
package/dist/emitter.d.ts CHANGED
@@ -8,10 +8,10 @@ export declare class Emitter {
8
8
  emitFilter<T>(event: string | string[], payload: T, meta: Record<string, any>, context?: EventContext | null): Promise<T>;
9
9
  emitAction(event: string | string[], meta: Record<string, any>, context?: EventContext | null): void;
10
10
  emitInit(event: string, meta: Record<string, any>): Promise<void>;
11
- onFilter(event: string, handler: FilterHandler): void;
11
+ onFilter<T = unknown>(event: string, handler: FilterHandler<T>): void;
12
12
  onAction(event: string, handler: ActionHandler): void;
13
13
  onInit(event: string, handler: InitHandler): void;
14
- offFilter(event: string, handler: FilterHandler): void;
14
+ offFilter<T = unknown>(event: string, handler: FilterHandler<T>): void;
15
15
  offAction(event: string, handler: ActionHandler): void;
16
16
  offInit(event: string, handler: InitHandler): void;
17
17
  offAll(): void;
package/dist/env.js CHANGED
@@ -159,6 +159,8 @@ const allowedEnvironmentVars = [
159
159
  'EXTENSIONS_PATH',
160
160
  'EXTENSIONS_AUTO_RELOAD',
161
161
  'EXTENSIONS_CACHE_TTL',
162
+ 'EXTENSIONS_SANDBOX_MEMORY',
163
+ 'EXTENSIONS_SANDBOX_TIMEOUT',
162
164
  // messenger
163
165
  'MESSENGER_STORE',
164
166
  'MESSENGER_NAMESPACE',
@@ -255,6 +257,8 @@ const defaults = {
255
257
  PACKAGE_FILE_LOCATION: '.',
256
258
  EXTENSIONS_PATH: './extensions',
257
259
  EXTENSIONS_AUTO_RELOAD: false,
260
+ EXTENSIONS_SANDBOX_MEMORY: 100,
261
+ EXTENSIONS_SANDBOX_TIMEOUT: 1000,
258
262
  EMAIL_FROM: 'no-reply@example.com',
259
263
  EMAIL_VERIFY_SETUP: true,
260
264
  EMAIL_TRANSPORT: 'sendmail',
@@ -0,0 +1,7 @@
1
+ import type { Extension } from '@directus/extensions';
2
+ /**
3
+ * Loads stored settings for all extensions. Creates empty new rows in extensions tables for
4
+ * extensions that don't have settings yet, and remove any settings for extensions that are no
5
+ * longer installed.
6
+ */
7
+ export declare const getExtensionsSettings: (extensions: Extension[]) => Promise<import("@directus/extensions").ExtensionSettings[]>;
@@ -0,0 +1,39 @@
1
+ import { difference } from 'lodash-es';
2
+ import getDatabase from '../../database/index.js';
3
+ import { ExtensionsService } from '../../services/extensions.js';
4
+ import { getSchema } from '../../utils/get-schema.js';
5
+ /**
6
+ * Loads stored settings for all extensions. Creates empty new rows in extensions tables for
7
+ * extensions that don't have settings yet, and remove any settings for extensions that are no
8
+ * longer installed.
9
+ */
10
+ export const getExtensionsSettings = async (extensions) => {
11
+ const database = getDatabase();
12
+ const service = new ExtensionsService({
13
+ knex: database,
14
+ schema: await getSchema(),
15
+ });
16
+ const settings = await service.extensionsItemService.readByQuery({ limit: -1 });
17
+ const extensionNames = extensions
18
+ .map((extension) => {
19
+ if (extension.type === 'bundle') {
20
+ return [extension.name, ...extension.entries.map((entry) => `${extension.name}/${entry.name}`)];
21
+ }
22
+ return extension.name;
23
+ })
24
+ .flat();
25
+ const extensionSettingNames = settings.map(({ name }) => name);
26
+ const missing = difference(extensionNames, extensionSettingNames);
27
+ if (missing.length > 0) {
28
+ const missingRows = missing.map((name) => ({ name, enabled: true }));
29
+ await database.insert(missingRows).into('directus_extensions');
30
+ settings.push(...missingRows);
31
+ }
32
+ /**
33
+ * Silently ignore settings for extensions that have been manually removed from the extensions
34
+ * folder. Having them automatically synced feels dangerous, as it's a destructive action. In the
35
+ * edge case you'd deploy / start with the extensions folder misconfigured, it would remove all
36
+ * previous options on startup, without an option to undo.
37
+ */
38
+ return settings.filter(({ name }) => extensionNames.includes(name));
39
+ };
@@ -0,0 +1 @@
1
+ export declare const getExtensions: () => Promise<import("@directus/extensions/node").Extension[]>;
@@ -0,0 +1,11 @@
1
+ import { getLocalExtensions, getPackageExtensions, resolvePackageExtensions } from '@directus/extensions/node';
2
+ import env from '../../env.js';
3
+ export const getExtensions = async () => {
4
+ const localExtensions = await getLocalExtensions(env['EXTENSIONS_PATH']);
5
+ const loadedNames = localExtensions.map(({ name }) => name);
6
+ const filterDuplicates = ({ name }) => loadedNames.includes(name) === false;
7
+ const localPackageExtensions = (await resolvePackageExtensions(env['EXTENSIONS_PATH'])).filter((extension) => filterDuplicates(extension));
8
+ loadedNames.push(...localPackageExtensions.map(({ name }) => name));
9
+ const packageExtensions = (await getPackageExtensions(env['PACKAGE_FILE_LOCATION'])).filter((extension) => filterDuplicates(extension));
10
+ return [...packageExtensions, ...localPackageExtensions, ...localExtensions];
11
+ };
@@ -2,9 +2,9 @@ import { resolvePackage } from '@directus/utils/node';
2
2
  import { escapeRegExp } from 'lodash-es';
3
3
  import { readdir } from 'node:fs/promises';
4
4
  import path from 'path';
5
- import env from '../env.js';
6
- import logger from '../logger.js';
7
- import { Url } from '../utils/url.js';
5
+ import env from '../../env.js';
6
+ import logger from '../../logger.js';
7
+ import { Url } from '../../utils/url.js';
8
8
  import { dirname } from 'node:path';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  const __dirname = dirname(fileURLToPath(import.meta.url));