@strapi/strapi 4.10.0-beta.1 → 4.10.1-experimental.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 (193) hide show
  1. package/bin/strapi.js +2 -468
  2. package/coverage/clover.xml +1613 -0
  3. package/coverage/coverage-final.json +48 -0
  4. package/coverage/lcov-report/base.css +224 -0
  5. package/coverage/lcov-report/block-navigation.js +87 -0
  6. package/coverage/lcov-report/commands/__tests__/data-transfer/shared/index.html +116 -0
  7. package/coverage/lcov-report/commands/__tests__/data-transfer/shared/transfer.test.utils.js.html +133 -0
  8. package/coverage/lcov-report/commands/admin-create.js.html +424 -0
  9. package/coverage/lcov-report/commands/admin-reset.js.html +241 -0
  10. package/coverage/lcov-report/commands/generate-template.js.html +373 -0
  11. package/coverage/lcov-report/commands/index.html +146 -0
  12. package/coverage/lcov-report/commands/transfer/export.js.html +619 -0
  13. package/coverage/lcov-report/commands/transfer/import.js.html +562 -0
  14. package/coverage/lcov-report/commands/transfer/index.html +146 -0
  15. package/coverage/lcov-report/commands/transfer/transfer.js.html +532 -0
  16. package/coverage/lcov-report/commands/utils/helpers.js.html +430 -0
  17. package/coverage/lcov-report/commands/utils/index.html +116 -0
  18. package/coverage/lcov-report/core/registries/custom-fields.js.html +301 -0
  19. package/coverage/lcov-report/core/registries/index.html +116 -0
  20. package/coverage/lcov-report/core-api/controller/collection-type.js.html +418 -0
  21. package/coverage/lcov-report/core-api/controller/index.html +161 -0
  22. package/coverage/lcov-report/core-api/controller/index.js.html +220 -0
  23. package/coverage/lcov-report/core-api/controller/single-type.js.html +274 -0
  24. package/coverage/lcov-report/core-api/controller/transform.js.html +376 -0
  25. package/coverage/lcov-report/core-api/service/collection-type.js.html +325 -0
  26. package/coverage/lcov-report/core-api/service/index.html +161 -0
  27. package/coverage/lcov-report/core-api/service/index.js.html +220 -0
  28. package/coverage/lcov-report/core-api/service/pagination.js.html +460 -0
  29. package/coverage/lcov-report/core-api/service/single-type.js.html +301 -0
  30. package/coverage/lcov-report/favicon.png +0 -0
  31. package/coverage/lcov-report/index.html +386 -0
  32. package/coverage/lcov-report/load/filepath-to-prop-path.js.html +151 -0
  33. package/coverage/lcov-report/load/index.html +116 -0
  34. package/coverage/lcov-report/prettify.css +1 -0
  35. package/coverage/lcov-report/prettify.js +2 -0
  36. package/coverage/lcov-report/services/content-api/index.html +116 -0
  37. package/coverage/lcov-report/services/content-api/index.js.html +307 -0
  38. package/coverage/lcov-report/services/content-api/permissions/engine.js.html +100 -0
  39. package/coverage/lcov-report/services/content-api/permissions/index.html +131 -0
  40. package/coverage/lcov-report/services/content-api/permissions/index.js.html +529 -0
  41. package/coverage/lcov-report/services/content-api/permissions/providers/action.js.html +142 -0
  42. package/coverage/lcov-report/services/content-api/permissions/providers/condition.js.html +142 -0
  43. package/coverage/lcov-report/services/content-api/permissions/providers/index.html +146 -0
  44. package/coverage/lcov-report/services/content-api/permissions/providers/index.js.html +112 -0
  45. package/coverage/lcov-report/services/core-store.js.html +520 -0
  46. package/coverage/lcov-report/services/entity-service/attributes/index.html +131 -0
  47. package/coverage/lcov-report/services/entity-service/attributes/index.js.html +178 -0
  48. package/coverage/lcov-report/services/entity-service/attributes/transforms.js.html +145 -0
  49. package/coverage/lcov-report/services/entity-service/components.js.html +1246 -0
  50. package/coverage/lcov-report/services/entity-service/index.html +146 -0
  51. package/coverage/lcov-report/services/entity-service/index.js.html +1120 -0
  52. package/coverage/lcov-report/services/entity-service/params.js.html +112 -0
  53. package/coverage/lcov-report/services/entity-validator/__tests__/relations/utils/index.html +116 -0
  54. package/coverage/lcov-report/services/entity-validator/__tests__/relations/utils/relations.testdata.js.html +544 -0
  55. package/coverage/lcov-report/services/entity-validator/index.html +131 -0
  56. package/coverage/lcov-report/services/entity-validator/index.js.html +1231 -0
  57. package/coverage/lcov-report/services/entity-validator/validators.js.html +733 -0
  58. package/coverage/lcov-report/services/event-hub.js.html +319 -0
  59. package/coverage/lcov-report/services/fs.js.html +259 -0
  60. package/coverage/lcov-report/services/index.html +161 -0
  61. package/coverage/lcov-report/services/metrics/admin-user-hash.js.html +148 -0
  62. package/coverage/lcov-report/services/metrics/index.html +206 -0
  63. package/coverage/lcov-report/services/metrics/index.js.html +265 -0
  64. package/coverage/lcov-report/services/metrics/is-truthy.js.html +112 -0
  65. package/coverage/lcov-report/services/metrics/middleware.js.html +184 -0
  66. package/coverage/lcov-report/services/metrics/rate-limiter.js.html +166 -0
  67. package/coverage/lcov-report/services/metrics/sender.js.html +394 -0
  68. package/coverage/lcov-report/services/metrics/stringify-deep.js.html +151 -0
  69. package/coverage/lcov-report/services/utils/index.html +116 -0
  70. package/coverage/lcov-report/services/utils/upload-files.js.html +322 -0
  71. package/coverage/lcov-report/services/worker-queue.js.html +262 -0
  72. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  73. package/coverage/lcov-report/sorter.js +196 -0
  74. package/coverage/lcov-report/utils/convert-custom-field-type.js.html +151 -0
  75. package/coverage/lcov-report/utils/index.html +146 -0
  76. package/coverage/lcov-report/utils/machine-id.js.html +127 -0
  77. package/coverage/lcov-report/utils/url-from-segments.js.html +121 -0
  78. package/ee/LICENSE.txt +21 -0
  79. package/ee/index.js +3 -1
  80. package/ee/license.js +8 -7
  81. package/lib/Strapi.js +3 -0
  82. package/lib/commands/__tests__/commands.test.js +20 -0
  83. package/lib/commands/__tests__/commands.test.utils.js +16 -0
  84. package/lib/commands/actions/admin/create-user/__tests__/admin.create-user.test.js +450 -0
  85. package/lib/commands/{admin-create.js → actions/admin/create-user/action.js} +2 -2
  86. package/lib/commands/actions/admin/create-user/command.js +19 -0
  87. package/lib/commands/actions/admin/reset-user-password/__tests__/admin.reset-user-password.test.js +145 -0
  88. package/lib/commands/{admin-reset.js → actions/admin/reset-user-password/action.js} +2 -2
  89. package/lib/commands/actions/admin/reset-user-password/command.js +17 -0
  90. package/lib/commands/{build.js → actions/build/action.js} +2 -2
  91. package/lib/commands/actions/build/command.js +15 -0
  92. package/lib/commands/{configurationDump.js → actions/configuration/dump/action.js} +1 -1
  93. package/lib/commands/actions/configuration/dump/command.js +17 -0
  94. package/lib/commands/{configurationRestore.js → actions/configuration/restore/action.js} +1 -1
  95. package/lib/commands/actions/configuration/restore/command.js +17 -0
  96. package/lib/commands/{console.js → actions/console/action.js} +2 -2
  97. package/lib/commands/actions/console/command.js +14 -0
  98. package/lib/commands/{content-types/list.js → actions/content-types/list/action.js} +2 -2
  99. package/lib/commands/actions/content-types/list/command.js +14 -0
  100. package/lib/commands/{controllers/list.js → actions/controllers/list/action.js} +2 -2
  101. package/lib/commands/actions/controllers/list/command.js +14 -0
  102. package/lib/commands/{develop.js → actions/develop/action.js} +3 -3
  103. package/lib/commands/actions/develop/command.js +19 -0
  104. package/lib/commands/actions/export/__tests__/export.test.js +175 -0
  105. package/lib/commands/{transfer/export.js → actions/export/action.js} +3 -2
  106. package/lib/commands/actions/export/command.js +45 -0
  107. package/lib/commands/actions/generate/command.js +18 -0
  108. package/lib/commands/{hooks/list.js → actions/hooks/list/action.js} +2 -2
  109. package/lib/commands/actions/hooks/list/command.js +14 -0
  110. package/lib/commands/actions/import/__tests__/import.test.js +143 -0
  111. package/lib/commands/{transfer/import.js → actions/import/action.js} +2 -2
  112. package/lib/commands/actions/import/command.js +97 -0
  113. package/lib/commands/{install.js → actions/install/action.js} +1 -1
  114. package/lib/commands/actions/install/command.js +14 -0
  115. package/lib/commands/{middlewares/list.js → actions/middlewares/list/action.js} +2 -2
  116. package/lib/commands/actions/middlewares/list/command.js +14 -0
  117. package/lib/commands/{new.js → actions/new/action.js} +1 -1
  118. package/lib/commands/actions/new/command.js +35 -0
  119. package/lib/commands/{policies/list.js → actions/policies/list/action.js} +2 -2
  120. package/lib/commands/actions/policies/list/command.js +14 -0
  121. package/lib/commands/{report.js → actions/report/action.js} +1 -1
  122. package/lib/commands/actions/report/command.js +17 -0
  123. package/lib/commands/{routes/list.js → actions/routes/list/action.js} +2 -2
  124. package/lib/commands/actions/routes/list/command.js +14 -0
  125. package/lib/commands/{services/list.js → actions/services/list/action.js} +2 -2
  126. package/lib/commands/actions/services/list/command.js +14 -0
  127. package/lib/commands/{start.js → actions/start/action.js} +1 -1
  128. package/lib/commands/actions/start/command.js +14 -0
  129. package/lib/commands/{opt-out-telemetry.js → actions/telemetry/disable/action.js} +1 -1
  130. package/lib/commands/actions/telemetry/disable/command.js +14 -0
  131. package/lib/commands/{opt-in-telemetry.js → actions/telemetry/enable/action.js} +1 -1
  132. package/lib/commands/actions/telemetry/enable/command.js +14 -0
  133. package/lib/commands/actions/templates/generate/__tests__/templates.generate.js +118 -0
  134. package/lib/commands/actions/templates/generate/command.js +14 -0
  135. package/lib/commands/actions/transfer/__tests__/transfer.test.js +178 -0
  136. package/lib/commands/{transfer/transfer.js → actions/transfer/action.js} +2 -2
  137. package/lib/commands/actions/transfer/command.js +115 -0
  138. package/lib/commands/{ts/generate-types.js → actions/ts/generate-types/action.js} +2 -2
  139. package/lib/commands/actions/ts/generate-types/command.js +21 -0
  140. package/lib/commands/{uninstall.js → actions/uninstall/action.js} +1 -1
  141. package/lib/commands/actions/uninstall/command.js +15 -0
  142. package/lib/commands/actions/version/command.js +19 -0
  143. package/lib/commands/{watchAdmin.js → actions/watch-admin/action.js} +4 -4
  144. package/lib/commands/actions/watch-admin/command.js +15 -0
  145. package/lib/commands/index.js +66 -0
  146. package/lib/commands/{transfer/utils.js → utils/data-transfer.js} +2 -2
  147. package/lib/commands/utils/helpers.js +54 -3
  148. package/lib/core/registries/__tests__/custom-fields.test.js +152 -0
  149. package/lib/core/registries/custom-fields.js +19 -2
  150. package/lib/core-api/__tests__/controller.test.js +39 -0
  151. package/lib/core-api/controller/__tests__/transform.test.js +226 -0
  152. package/lib/core-api/service/__tests__/index.test.js +127 -0
  153. package/lib/core-api/service/__tests__/pagination.test.js +275 -0
  154. package/lib/load/__tests__/filepath-to-prop-path.test.js +30 -0
  155. package/lib/middlewares/__tests__/errors.test.js +21 -0
  156. package/lib/services/__tests__/content-api-permissions.test.js +291 -0
  157. package/lib/services/__tests__/core-store.test.js +148 -0
  158. package/lib/services/__tests__/event-hub.test.js +126 -0
  159. package/lib/services/__tests__/fs.test.js +78 -0
  160. package/lib/services/__tests__/worker-queue.test.js +47 -0
  161. package/lib/services/entity-service/__tests__/entity-service-events.test.js +117 -0
  162. package/lib/services/entity-service/__tests__/entity-service.test.js +587 -0
  163. package/lib/services/entity-validator/__tests__/biginteger-validators.test.js +220 -0
  164. package/lib/services/entity-validator/__tests__/date-validators.test.js +183 -0
  165. package/lib/services/entity-validator/__tests__/datetime-validators.test.js +183 -0
  166. package/lib/services/entity-validator/__tests__/email-validators.test.js +56 -0
  167. package/lib/services/entity-validator/__tests__/enumeration-validators.test.js +43 -0
  168. package/lib/services/entity-validator/__tests__/float-validators.test.js +278 -0
  169. package/lib/services/entity-validator/__tests__/index.test.js +609 -0
  170. package/lib/services/entity-validator/__tests__/integer-validators.test.js +278 -0
  171. package/lib/services/entity-validator/__tests__/relations/attribute-level.test.js +123 -0
  172. package/lib/services/entity-validator/__tests__/relations/component-level.test.js +275 -0
  173. package/lib/services/entity-validator/__tests__/relations/dynamic-zone-level.test.js +159 -0
  174. package/lib/services/entity-validator/__tests__/relations/media-level.test.js +74 -0
  175. package/lib/services/entity-validator/__tests__/relations/utils/relations.testdata.js +153 -0
  176. package/lib/services/entity-validator/__tests__/string-validators.test.js +374 -0
  177. package/lib/services/entity-validator/__tests__/time-validators.test.js +183 -0
  178. package/lib/services/entity-validator/__tests__/timestamp-validators.test.js +204 -0
  179. package/lib/services/entity-validator/__tests__/uid-validators.test.js +229 -0
  180. package/lib/services/metrics/__tests__/admin-user-hash.test.js +41 -0
  181. package/lib/services/metrics/__tests__/index.test.js +157 -0
  182. package/lib/services/metrics/__tests__/is-truthy.js +33 -0
  183. package/lib/services/metrics/__tests__/middleware.test.js +60 -0
  184. package/lib/services/metrics/__tests__/rate-limiter.test.js +50 -0
  185. package/lib/services/metrics/__tests__/stringify-deep.test.js +27 -0
  186. package/lib/services/metrics/sender.js +1 -2
  187. package/lib/services/webhook-runner.js +4 -4
  188. package/lib/types/core/commands/index.d.ts +6 -0
  189. package/lib/utils/__tests__/convert-custom-field-type.test.js +69 -0
  190. package/lib/utils/__tests__/url-from-segments.test.js +40 -0
  191. package/lib/utils/fetch.js +23 -0
  192. package/package.json +17 -16
  193. /package/lib/commands/{generate-template.js → actions/templates/generate/action.js} +0 -0
@@ -0,0 +1,178 @@
1
+ 'use strict';
2
+
3
+ const { expectExit } = require('../../../__tests__/commands.test.utils');
4
+
5
+ describe('Transfer', () => {
6
+ // command utils
7
+ const mockUtils = {
8
+ getTransferTelemetryPayload: jest.fn().mockReturnValue({}),
9
+ loadersFactory: jest.fn().mockReturnValue({ updateLoader: jest.fn() }),
10
+ formatDiagnostic: jest.fn(),
11
+ createStrapiInstance() {
12
+ return {
13
+ telemetry: {
14
+ send: jest.fn(),
15
+ },
16
+ };
17
+ },
18
+ getDefaultExportName: jest.fn(() => 'default'),
19
+ buildTransferTable: jest.fn(() => {
20
+ return {
21
+ toString() {
22
+ return 'table';
23
+ },
24
+ };
25
+ }),
26
+ exitMessageText: jest.fn(),
27
+ };
28
+ jest.mock(
29
+ '../../../utils/data-transfer.js',
30
+ () => {
31
+ return mockUtils;
32
+ },
33
+ { virtual: true }
34
+ );
35
+
36
+ const mockDataTransfer = {
37
+ strapi: {
38
+ providers: {
39
+ createLocalStrapiSourceProvider: jest.fn().mockReturnValue({ name: 'testLocalSource' }),
40
+ createLocalStrapiDestinationProvider: jest
41
+ .fn()
42
+ .mockReturnValue({ name: 'testLocalDestination' }),
43
+ createRemoteStrapiDestinationProvider: jest
44
+ .fn()
45
+ .mockReturnValue({ name: 'testRemoteDest' }),
46
+ },
47
+ },
48
+ engine: {
49
+ ...jest.requireActual('@strapi/data-transfer').engine,
50
+ createTransferEngine() {
51
+ return {
52
+ transfer: jest.fn(() => {
53
+ return {
54
+ engine: {},
55
+ };
56
+ }),
57
+ progress: {
58
+ on: jest.fn(),
59
+ stream: {
60
+ on: jest.fn(),
61
+ },
62
+ },
63
+ sourceProvider: { name: 'testSource' },
64
+ destinationProvider: { name: 'testDestination' },
65
+ diagnostics: {
66
+ on: jest.fn().mockReturnThis(),
67
+ onDiagnostic: jest.fn().mockReturnThis(),
68
+ },
69
+ };
70
+ },
71
+ },
72
+ };
73
+
74
+ jest.mock('@strapi/data-transfer', () => mockDataTransfer);
75
+
76
+ const transferAction = require('../action');
77
+
78
+ // console spies
79
+ jest.spyOn(console, 'log').mockImplementation(() => {});
80
+ jest.spyOn(console, 'warn').mockImplementation(() => {});
81
+ jest.spyOn(console, 'info').mockImplementation(() => {});
82
+ jest.spyOn(console, 'error').mockImplementation(() => {});
83
+
84
+ const destinationUrl = new URL('http://one.localhost/admin');
85
+ const destinationToken = 'test-token';
86
+
87
+ const sourceUrl = new URL('http://two.localhost/admin');
88
+
89
+ beforeEach(() => {
90
+ jest.clearAllMocks();
91
+ });
92
+
93
+ it('exits with error when no --to or --from is provided', async () => {
94
+ await expectExit(1, async () => {
95
+ await transferAction({ from: undefined, to: undefined });
96
+ });
97
+
98
+ expect(console.error).toHaveBeenCalledWith(expect.stringMatching(/one source/i));
99
+
100
+ expect(
101
+ mockDataTransfer.strapi.providers.createRemoteStrapiDestinationProvider
102
+ ).not.toHaveBeenCalled();
103
+ });
104
+
105
+ it('exits with error when both --to and --from are provided', async () => {
106
+ await expectExit(1, async () => {
107
+ await transferAction({ from: sourceUrl, to: destinationUrl });
108
+ });
109
+
110
+ expect(console.error).toHaveBeenCalledWith(expect.stringMatching(/one source/i));
111
+
112
+ expect(
113
+ mockDataTransfer.strapi.providers.createRemoteStrapiDestinationProvider
114
+ ).not.toHaveBeenCalled();
115
+ });
116
+
117
+ describe('--to', () => {
118
+ it('exits with error when auth is not provided', async () => {
119
+ await expectExit(1, async () => {
120
+ await transferAction({ from: undefined, to: destinationUrl });
121
+ });
122
+
123
+ expect(console.error).toHaveBeenCalledWith(expect.stringMatching(/missing token/i));
124
+
125
+ expect(
126
+ mockDataTransfer.strapi.providers.createRemoteStrapiDestinationProvider
127
+ ).not.toHaveBeenCalled();
128
+ });
129
+
130
+ it('uses destination url and token provided by user', async () => {
131
+ await expectExit(0, async () => {
132
+ await transferAction({ from: undefined, to: destinationUrl, toToken: destinationToken });
133
+ });
134
+
135
+ expect(console.error).not.toHaveBeenCalled();
136
+ expect(
137
+ mockDataTransfer.strapi.providers.createRemoteStrapiDestinationProvider
138
+ ).toHaveBeenCalledWith(
139
+ expect.objectContaining({
140
+ url: destinationUrl,
141
+ auth: {
142
+ type: 'token',
143
+ token: destinationToken,
144
+ },
145
+ })
146
+ );
147
+ });
148
+
149
+ it('uses local Strapi source when from is not specified', async () => {
150
+ await expectExit(0, async () => {
151
+ await transferAction({ from: undefined, to: destinationUrl, toToken: destinationToken });
152
+ });
153
+
154
+ expect(console.error).not.toHaveBeenCalled();
155
+ expect(mockDataTransfer.strapi.providers.createLocalStrapiSourceProvider).toHaveBeenCalled();
156
+ expect(
157
+ mockDataTransfer.strapi.providers.createRemoteStrapiDestinationProvider
158
+ ).toHaveBeenCalled();
159
+ });
160
+ });
161
+
162
+ it.todo('uses local Strapi destination when to is not specified');
163
+
164
+ it('uses restore as the default strategy', async () => {
165
+ await expectExit(0, async () => {
166
+ await transferAction({ from: undefined, to: destinationUrl, toToken: destinationToken });
167
+ });
168
+
169
+ expect(console.error).not.toHaveBeenCalled();
170
+ expect(
171
+ mockDataTransfer.strapi.providers.createRemoteStrapiDestinationProvider
172
+ ).toHaveBeenCalledWith(
173
+ expect.objectContaining({
174
+ strategy: 'restore',
175
+ })
176
+ );
177
+ });
178
+ });
@@ -22,8 +22,8 @@ const {
22
22
  exitMessageText,
23
23
  abortTransfer,
24
24
  getTransferTelemetryPayload,
25
- } = require('./utils');
26
- const { exitWith } = require('../utils/helpers');
25
+ } = require('../../utils/data-transfer');
26
+ const { exitWith } = require('../../utils/helpers');
27
27
 
28
28
  /**
29
29
  * @typedef TransferCommandOptions Options given to the CLI transfer command
@@ -0,0 +1,115 @@
1
+ 'use strict';
2
+
3
+ const inquirer = require('inquirer');
4
+ const { Option } = require('commander');
5
+ const { confirmMessage, forceOption, parseURL } = require('../../utils/commander');
6
+ const {
7
+ getLocalScript,
8
+ exitWith,
9
+ assertUrlHasProtocol,
10
+ ifOptions,
11
+ } = require('../../utils/helpers');
12
+ const {
13
+ excludeOption,
14
+ onlyOption,
15
+ throttleOption,
16
+ validateExcludeOnly,
17
+ } = require('../../utils/data-transfer');
18
+
19
+ /**
20
+ * `$ strapi transfer`
21
+ * @param {import('../../../types/core/commands').AddCommandOptions} options
22
+ */
23
+ module.exports = ({ command }) => {
24
+ command
25
+ .command('transfer')
26
+ .description('Transfer data from one source to another')
27
+ .allowExcessArguments(false)
28
+ .addOption(
29
+ new Option(
30
+ '--from <sourceURL>',
31
+ `URL of the remote Strapi instance to get data from`
32
+ ).argParser(parseURL)
33
+ )
34
+ .addOption(new Option('--from-token <token>', `Transfer token for the remote Strapi source`))
35
+ .addOption(
36
+ new Option(
37
+ '--to <destinationURL>',
38
+ `URL of the remote Strapi instance to send data to`
39
+ ).argParser(parseURL)
40
+ )
41
+ .addOption(new Option('--to-token <token>', `Transfer token for the remote Strapi destination`))
42
+ .addOption(forceOption)
43
+ .addOption(excludeOption)
44
+ .addOption(onlyOption)
45
+ .addOption(throttleOption)
46
+ .hook('preAction', validateExcludeOnly)
47
+ .hook(
48
+ 'preAction',
49
+ ifOptions(
50
+ (opts) => !(opts.from || opts.to) || (opts.from && opts.to),
51
+ () =>
52
+ exitWith(
53
+ 1,
54
+ 'Exactly one remote source (from) or destination (to) option must be provided'
55
+ )
56
+ )
57
+ )
58
+ // If --from is used, validate the URL and token
59
+ .hook(
60
+ 'preAction',
61
+ ifOptions(
62
+ (opts) => opts.from,
63
+ async (thisCommand) => {
64
+ assertUrlHasProtocol(thisCommand.opts().from, ['https:', 'http:']);
65
+ if (!thisCommand.opts().fromToken) {
66
+ const answers = await inquirer.prompt([
67
+ {
68
+ type: 'password',
69
+ message: 'Please enter your transfer token for the remote Strapi source',
70
+ name: 'fromToken',
71
+ },
72
+ ]);
73
+ if (!answers.fromToken?.length) {
74
+ exitWith(1, 'No token provided for remote source, aborting transfer.');
75
+ }
76
+ thisCommand.opts().fromToken = answers.fromToken;
77
+ }
78
+
79
+ await confirmMessage(
80
+ 'The transfer will delete all the local Strapi assets and its database. Are you sure you want to proceed?',
81
+ { failMessage: 'Transfer process aborted' }
82
+ )(thisCommand);
83
+ }
84
+ )
85
+ )
86
+ // If --to is used, validate the URL, token, and confirm restore
87
+ .hook(
88
+ 'preAction',
89
+ ifOptions(
90
+ (opts) => opts.to,
91
+ async (thisCommand) => {
92
+ assertUrlHasProtocol(thisCommand.opts().to, ['https:', 'http:']);
93
+ if (!thisCommand.opts().toToken) {
94
+ const answers = await inquirer.prompt([
95
+ {
96
+ type: 'password',
97
+ message: 'Please enter your transfer token for the remote Strapi destination',
98
+ name: 'toToken',
99
+ },
100
+ ]);
101
+ if (!answers.toToken?.length) {
102
+ exitWith(1, 'No token provided for remote destination, aborting transfer.');
103
+ }
104
+ thisCommand.opts().toToken = answers.toToken;
105
+ }
106
+
107
+ await confirmMessage(
108
+ 'The transfer will delete all the remote Strapi assets and its database. Are you sure you want to proceed?',
109
+ { failMessage: 'Transfer process aborted' }
110
+ )(thisCommand);
111
+ }
112
+ )
113
+ )
114
+ .action(getLocalScript('transfer'));
115
+ };
@@ -2,9 +2,9 @@
2
2
 
3
3
  const tsUtils = require('@strapi/typescript-utils');
4
4
 
5
- const strapi = require('../../index');
5
+ const strapi = require('../../../../index');
6
6
 
7
- module.exports = async function ({ outDir, file, verbose, silent }) {
7
+ module.exports = async ({ outDir, file, verbose, silent }) => {
8
8
  if (verbose && silent) {
9
9
  console.error('You cannot enable verbose and silent flags at the same time, exiting...');
10
10
  process.exit(1);
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const { getLocalScript } = require('../../../utils/helpers');
4
+
5
+ /**
6
+ * `$ strapi ts:generate-types`
7
+ * @param {import('../../../../types/core/commands').AddCommandOptions} options
8
+ */
9
+ module.exports = ({ command }) => {
10
+ command
11
+ .command('ts:generate-types')
12
+ .description(`Generate TypeScript typings for your schemas`)
13
+ .option(
14
+ '-o, --out-dir <outDir>',
15
+ 'Specify a relative directory in which the schemas definitions will be generated'
16
+ )
17
+ .option('-f, --file <file>', 'Specify a filename to store the schemas definitions')
18
+ .option('--verbose', `Display more information about the types generation`, false)
19
+ .option('-s, --silent', `Run the generation silently, without any output`, false)
20
+ .action(getLocalScript('ts/generate-types'));
21
+ };
@@ -5,7 +5,7 @@ const { existsSync, removeSync } = require('fs-extra');
5
5
  const ora = require('ora');
6
6
  const execa = require('execa');
7
7
  const inquirer = require('inquirer');
8
- const findPackagePath = require('../load/package-path');
8
+ const findPackagePath = require('../../../load/package-path');
9
9
 
10
10
  module.exports = async (plugins, { deleteFiles }) => {
11
11
  const answers = await inquirer.prompt([
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const { getLocalScript } = require('../../utils/helpers');
4
+
5
+ /**
6
+ * `$ strapi uninstall`
7
+ * @param {import('../../../types/core/commands').AddCommandOptions} options
8
+ */
9
+ module.exports = ({ command }) => {
10
+ command
11
+ .command('uninstall [plugins...]')
12
+ .description('Uninstall a Strapi plugin')
13
+ .option('-d, --delete-files', 'Delete files', false)
14
+ .action(getLocalScript('uninstall'));
15
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * `$ strapi version`
5
+ * @param {import('../../../types/core/commands').AddCommandOptions} options
6
+ */
7
+ module.exports = ({ command }) => {
8
+ // load the Strapi package.json to get version and other information
9
+ const packageJSON = require('../../../../package.json');
10
+
11
+ command.version(packageJSON.version, '-v, --version', 'Output the version number');
12
+ command
13
+ .command('version')
14
+ .description('Output the version of Strapi')
15
+ .action(() => {
16
+ process.stdout.write(`${packageJSON.version}\n`);
17
+ process.exit(0);
18
+ });
19
+ };
@@ -3,11 +3,11 @@
3
3
  const strapiAdmin = require('@strapi/admin');
4
4
  const { getConfigUrls, getAbsoluteServerUrl } = require('@strapi/utils');
5
5
 
6
- const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins');
7
- const addSlash = require('../utils/addSlash');
8
- const strapi = require('../index');
6
+ const getEnabledPlugins = require('../../../core/loaders/plugins/get-enabled-plugins');
7
+ const addSlash = require('../../../utils/addSlash');
8
+ const strapi = require('../../../index');
9
9
 
10
- module.exports = async function ({ browser }) {
10
+ module.exports = async ({ browser }) => {
11
11
  const appContext = await strapi.compile();
12
12
 
13
13
  const strapiInstance = strapi({
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const { getLocalScript } = require('../../utils/helpers');
4
+
5
+ /**
6
+ * `$ strapi watch-admin`
7
+ * @param {import('../../../types/core/commands').AddCommandOptions} options
8
+ */
9
+ module.exports = ({ command }) => {
10
+ command
11
+ .command('watch-admin')
12
+ .option('--browser <name>', 'Open the browser', true)
13
+ .description('Start the admin development server')
14
+ .action(getLocalScript('watch-admin'));
15
+ };
@@ -0,0 +1,66 @@
1
+ 'use strict';
2
+
3
+ const { Command } = require('commander');
4
+
5
+ const strapiCommands = {
6
+ 'admin/create-user': require('./actions/admin/create-user/command'),
7
+ 'admin/reset-user-password': require('./actions/admin/reset-user-password/command'),
8
+ build: require('./actions/build/command'),
9
+ 'configuration/dump': require('./actions/configuration/dump/command'),
10
+ 'configuration/restore': require('./actions/configuration/restore/command'),
11
+ console: require('./actions/console/command'),
12
+ 'content-types/list': require('./actions/content-types/list/command'),
13
+ 'controllers/list': require('./actions/controllers/list/command'),
14
+ develop: require('./actions/develop/command'),
15
+ export: require('./actions/export/command'),
16
+ generate: require('./actions/generate/command'),
17
+ 'hooks/list': require('./actions/hooks/list/command'),
18
+ import: require('./actions/import/command'),
19
+ install: require('./actions/install/command'),
20
+ 'middlewares/list': require('./actions/middlewares/list/command'),
21
+ new: require('./actions/new/command'),
22
+ 'policies/list': require('./actions/policies/list/command'),
23
+ report: require('./actions/report/command'),
24
+ 'routes/list': require('./actions/routes/list/command'),
25
+ 'services/list': require('./actions/services/list/command'),
26
+ start: require('./actions/start/command'),
27
+ 'telemetry/disable': require('./actions/telemetry/disable/command'),
28
+ 'telemetry/enable': require('./actions/telemetry/enable/command'),
29
+ 'templates/generate': require('./actions/templates/generate/command'),
30
+ transfer: require('./actions/transfer/command'),
31
+ 'ts/generate-types': require('./actions/ts/generate-types/command'),
32
+ uninstall: require('./actions/uninstall/command'),
33
+ version: require('./actions/version/command'),
34
+ 'watch-admin': require('./actions/watch-admin/command'),
35
+ };
36
+
37
+ const buildStrapiCommand = (argv, command = new Command()) => {
38
+ // Initial program setup
39
+ command.storeOptionsAsProperties(false).allowUnknownOption(true);
40
+
41
+ // Help command
42
+ command.helpOption('-h, --help', 'Display help for command');
43
+ command.addHelpCommand('help [command]', 'Display help for command');
44
+
45
+ // Load all commands
46
+ Object.keys(strapiCommands).forEach((name) => {
47
+ try {
48
+ // Add this command to the Commander command object
49
+ strapiCommands[name]({ command, argv });
50
+ } catch (e) {
51
+ console.error(`Failed to load command ${name}`, e);
52
+ }
53
+ });
54
+
55
+ return command;
56
+ };
57
+
58
+ const runStrapiCommand = async (argv = process.argv, command = new Command()) => {
59
+ await buildStrapiCommand(argv, command).parseAsync(argv);
60
+ };
61
+
62
+ module.exports = {
63
+ runStrapiCommand,
64
+ buildStrapiCommand,
65
+ strapiCommands,
66
+ };
@@ -12,9 +12,9 @@ const {
12
12
  createLogger,
13
13
  } = require('@strapi/logger');
14
14
  const ora = require('ora');
15
- const { readableBytes, exitWith } = require('../utils/helpers');
15
+ const { readableBytes, exitWith } = require('./helpers');
16
16
  const strapi = require('../../index');
17
- const { getParseListWithChoices, parseInteger } = require('../utils/commander');
17
+ const { getParseListWithChoices, parseInteger } = require('./commander');
18
18
 
19
19
  const exitMessageText = (process, error = false) => {
20
20
  const processCapitalized = process[0].toUpperCase() + process.slice(1);
@@ -4,8 +4,10 @@
4
4
  * Helper functions for the Strapi CLI
5
5
  */
6
6
 
7
- const chalk = require('chalk');
7
+ const { yellow, red, green } = require('chalk');
8
8
  const { isString, isArray } = require('lodash/fp');
9
+ const resolveCwd = require('resolve-cwd');
10
+ const { has } = require('lodash/fp');
9
11
 
10
12
  const bytesPerKb = 1024;
11
13
  const sizes = ['B ', 'KB', 'MB', 'GB', 'TB', 'PB'];
@@ -46,9 +48,9 @@ const exitWith = (code, message = undefined, options = {}) => {
46
48
 
47
49
  const log = (message) => {
48
50
  if (code === 0) {
49
- logger.log(chalk.green(message));
51
+ logger.log(green(message));
50
52
  } else {
51
- logger.error(chalk.red(message));
53
+ logger.error(red(message));
52
54
  }
53
55
  };
54
56
 
@@ -107,9 +109,58 @@ const ifOptions = (conditionCallback, isMetCallback = () => {}, isNotMetCallback
107
109
  };
108
110
  };
109
111
 
112
+ const assertCwdContainsStrapiProject = (name) => {
113
+ const logErrorAndExit = () => {
114
+ console.log(
115
+ `You need to run ${yellow(
116
+ `strapi ${name}`
117
+ )} in a Strapi project. Make sure you are in the right directory.`
118
+ );
119
+ process.exit(1);
120
+ };
121
+
122
+ try {
123
+ const pkgJSON = require(`${process.cwd()}/package.json`);
124
+ if (!has('dependencies.@strapi/strapi', pkgJSON)) {
125
+ logErrorAndExit(name);
126
+ }
127
+ } catch (err) {
128
+ logErrorAndExit(name);
129
+ }
130
+ };
131
+
132
+ const getLocalScript =
133
+ (name) =>
134
+ (...args) => {
135
+ assertCwdContainsStrapiProject(name);
136
+
137
+ const cmdPath = resolveCwd.silent(`@strapi/strapi/lib/commands/actions/${name}/action`);
138
+ if (!cmdPath) {
139
+ console.log(
140
+ `Error loading the local ${yellow(
141
+ name
142
+ )} command. Strapi might not be installed in your "node_modules". You may need to run "yarn install".`
143
+ );
144
+ process.exit(1);
145
+ }
146
+
147
+ const script = require(cmdPath);
148
+
149
+ Promise.resolve()
150
+ .then(() => {
151
+ return script(...args);
152
+ })
153
+ .catch((error) => {
154
+ console.error(error);
155
+ process.exit(1);
156
+ });
157
+ };
158
+
110
159
  module.exports = {
111
160
  exitWith,
112
161
  assertUrlHasProtocol,
113
162
  ifOptions,
114
163
  readableBytes,
164
+ getLocalScript,
165
+ assertCwdContainsStrapiProject,
115
166
  };