@akemona-org/strapi 3.7.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 (125) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +163 -0
  3. package/bin/strapi.js +239 -0
  4. package/index.d.ts +13 -0
  5. package/lib/Strapi.js +498 -0
  6. package/lib/commands/admin-reset.js +51 -0
  7. package/lib/commands/build.js +47 -0
  8. package/lib/commands/configurationDump.js +50 -0
  9. package/lib/commands/configurationRestore.js +160 -0
  10. package/lib/commands/console.js +26 -0
  11. package/lib/commands/develop.js +155 -0
  12. package/lib/commands/generate-template.js +97 -0
  13. package/lib/commands/generate.js +66 -0
  14. package/lib/commands/install.js +48 -0
  15. package/lib/commands/new.js +11 -0
  16. package/lib/commands/start.js +8 -0
  17. package/lib/commands/uninstall.js +68 -0
  18. package/lib/commands/watchAdmin.js +35 -0
  19. package/lib/core/app-configuration/config-loader.js +56 -0
  20. package/lib/core/app-configuration/config-provider.js +28 -0
  21. package/lib/core/app-configuration/index.js +99 -0
  22. package/lib/core/bootstrap.js +166 -0
  23. package/lib/core/fs.js +52 -0
  24. package/lib/core/index.js +21 -0
  25. package/lib/core/load-admin.js +36 -0
  26. package/lib/core/load-apis.js +22 -0
  27. package/lib/core/load-components.js +43 -0
  28. package/lib/core/load-extensions.js +71 -0
  29. package/lib/core/load-functions.js +21 -0
  30. package/lib/core/load-hooks.js +117 -0
  31. package/lib/core/load-middlewares.js +130 -0
  32. package/lib/core/load-modules.js +61 -0
  33. package/lib/core/load-plugins.js +68 -0
  34. package/lib/core/load-policies.js +36 -0
  35. package/lib/core/walk.js +27 -0
  36. package/lib/core-api/controller.js +158 -0
  37. package/lib/core-api/index.js +33 -0
  38. package/lib/core-api/service/collection-type.js +122 -0
  39. package/lib/core-api/service/index.js +81 -0
  40. package/lib/core-api/service/single-type.js +68 -0
  41. package/lib/hooks/index.js +97 -0
  42. package/lib/index.js +3 -0
  43. package/lib/load/check-reserved-filename.js +18 -0
  44. package/lib/load/filepath-to-prop-path.js +22 -0
  45. package/lib/load/glob.js +15 -0
  46. package/lib/load/index.js +9 -0
  47. package/lib/load/load-config-files.js +22 -0
  48. package/lib/load/load-files.js +56 -0
  49. package/lib/load/package-path.js +9 -0
  50. package/lib/load/require-file-parse.js +15 -0
  51. package/lib/middlewares/boom/defaults.json +5 -0
  52. package/lib/middlewares/boom/index.js +147 -0
  53. package/lib/middlewares/cors/index.js +66 -0
  54. package/lib/middlewares/cron/defaults.json +5 -0
  55. package/lib/middlewares/cron/index.js +43 -0
  56. package/lib/middlewares/csp/defaults.json +5 -0
  57. package/lib/middlewares/csp/index.js +26 -0
  58. package/lib/middlewares/favicon/defaults.json +7 -0
  59. package/lib/middlewares/favicon/index.js +35 -0
  60. package/lib/middlewares/gzip/defaults.json +6 -0
  61. package/lib/middlewares/gzip/index.js +19 -0
  62. package/lib/middlewares/hsts/defaults.json +7 -0
  63. package/lib/middlewares/hsts/index.js +30 -0
  64. package/lib/middlewares/index.js +120 -0
  65. package/lib/middlewares/ip/defaults.json +7 -0
  66. package/lib/middlewares/ip/index.js +25 -0
  67. package/lib/middlewares/language/defaults.json +9 -0
  68. package/lib/middlewares/language/index.js +40 -0
  69. package/lib/middlewares/logger/defaults.json +8 -0
  70. package/lib/middlewares/logger/index.js +63 -0
  71. package/lib/middlewares/p3p/defaults.json +6 -0
  72. package/lib/middlewares/p3p/index.js +29 -0
  73. package/lib/middlewares/parser/defaults.json +10 -0
  74. package/lib/middlewares/parser/index.js +71 -0
  75. package/lib/middlewares/poweredBy/defaults.json +5 -0
  76. package/lib/middlewares/poweredBy/index.js +16 -0
  77. package/lib/middlewares/public/assets/images/group_people_1.png +0 -0
  78. package/lib/middlewares/public/assets/images/group_people_2.png +0 -0
  79. package/lib/middlewares/public/assets/images/group_people_3.png +0 -0
  80. package/lib/middlewares/public/assets/images/logo_login.png +0 -0
  81. package/lib/middlewares/public/defaults.json +8 -0
  82. package/lib/middlewares/public/index.html +66 -0
  83. package/lib/middlewares/public/index.js +98 -0
  84. package/lib/middlewares/public/serve-static.js +23 -0
  85. package/lib/middlewares/responseTime/defaults.json +5 -0
  86. package/lib/middlewares/responseTime/index.js +25 -0
  87. package/lib/middlewares/responses/defaults.json +5 -0
  88. package/lib/middlewares/responses/index.js +18 -0
  89. package/lib/middlewares/router/defaults.json +7 -0
  90. package/lib/middlewares/router/index.js +64 -0
  91. package/lib/middlewares/router/utils/composeEndpoint.js +25 -0
  92. package/lib/middlewares/router/utils/routerChecker.js +92 -0
  93. package/lib/middlewares/session/defaults.json +18 -0
  94. package/lib/middlewares/session/index.js +140 -0
  95. package/lib/middlewares/xframe/defaults.json +6 -0
  96. package/lib/middlewares/xframe/index.js +33 -0
  97. package/lib/middlewares/xss/defaults.json +6 -0
  98. package/lib/middlewares/xss/index.js +30 -0
  99. package/lib/services/core-store.js +144 -0
  100. package/lib/services/entity-service.js +260 -0
  101. package/lib/services/entity-validator/index.js +199 -0
  102. package/lib/services/entity-validator/validators.js +125 -0
  103. package/lib/services/event-hub.js +15 -0
  104. package/lib/services/metrics/index.js +103 -0
  105. package/lib/services/metrics/is-truthy.js +9 -0
  106. package/lib/services/metrics/middleware.js +33 -0
  107. package/lib/services/metrics/rate-limiter.js +27 -0
  108. package/lib/services/metrics/sender.js +76 -0
  109. package/lib/services/metrics/stringify-deep.js +22 -0
  110. package/lib/services/utils/upload-files.js +70 -0
  111. package/lib/services/webhook-runner.js +159 -0
  112. package/lib/services/webhook-store.js +97 -0
  113. package/lib/services/worker-queue.js +58 -0
  114. package/lib/utils/addSlash.js +10 -0
  115. package/lib/utils/ee.js +123 -0
  116. package/lib/utils/get-prefixed-dependencies.js +7 -0
  117. package/lib/utils/index.js +25 -0
  118. package/lib/utils/openBrowser.js +145 -0
  119. package/lib/utils/resources/key.pub +9 -0
  120. package/lib/utils/resources/openChrome.applescript +83 -0
  121. package/lib/utils/run-checks.js +37 -0
  122. package/lib/utils/success.js +31 -0
  123. package/lib/utils/update-notifier/index.js +96 -0
  124. package/lib/utils/url-from-segments.js +13 -0
  125. package/package.json +143 -0
package/lib/Strapi.js ADDED
@@ -0,0 +1,498 @@
1
+ 'use strict';
2
+
3
+ const http = require('http');
4
+ const path = require('path');
5
+ const fse = require('fs-extra');
6
+ const Koa = require('koa');
7
+ const Router = require('koa-router');
8
+ const _ = require('lodash');
9
+ const chalk = require('chalk');
10
+ const CLITable = require('cli-table3');
11
+ const {
12
+ logger,
13
+ models,
14
+ getAbsoluteAdminUrl,
15
+ getAbsoluteServerUrl,
16
+ } = require('@akemona-org/strapi-utils');
17
+ const { createDatabaseManager } = require('@akemona-org/strapi-database');
18
+ const loadConfiguration = require('./core/app-configuration');
19
+
20
+ const utils = require('./utils');
21
+ const loadModules = require('./core/load-modules');
22
+ const bootstrap = require('./core/bootstrap');
23
+ const initializeMiddlewares = require('./middlewares');
24
+ const initializeHooks = require('./hooks');
25
+ const createStrapiFs = require('./core/fs');
26
+ const createEventHub = require('./services/event-hub');
27
+ const createWebhookRunner = require('./services/webhook-runner');
28
+ const { webhookModel, createWebhookStore } = require('./services/webhook-store');
29
+ const { createCoreStore, coreStoreModel } = require('./services/core-store');
30
+ const createEntityService = require('./services/entity-service');
31
+ const entityValidator = require('./services/entity-validator');
32
+ // const createTelemetry = require('./services/metrics');
33
+ const createUpdateNotifier = require('./utils/update-notifier');
34
+ const ee = require('./utils/ee');
35
+
36
+ const LIFECYCLES = {
37
+ REGISTER: 'register',
38
+ BOOTSTRAP: 'bootstrap',
39
+ };
40
+
41
+ /**
42
+ * Construct an Strapi instance.
43
+ *
44
+ * @constructor
45
+ */
46
+ class Strapi {
47
+ constructor(opts = {}) {
48
+ this.reload = this.reload();
49
+
50
+ // Expose `koa`.
51
+ this.app = new Koa();
52
+ this.router = new Router();
53
+
54
+ this.initServer();
55
+
56
+ // Logger.
57
+ this.log = logger;
58
+
59
+ // Utils.
60
+ this.utils = {
61
+ models,
62
+ };
63
+
64
+ this.dir = opts.dir || process.cwd();
65
+
66
+ this.admin = {};
67
+ this.plugins = {};
68
+ this.config = loadConfiguration(this.dir, opts);
69
+ this.app.proxy = this.config.get('server.proxy');
70
+
71
+ this.isLoaded = false;
72
+
73
+ // internal services.
74
+ this.fs = createStrapiFs(this);
75
+ this.eventHub = createEventHub();
76
+
77
+ this.requireProjectBootstrap();
78
+
79
+ createUpdateNotifier(this).notify();
80
+ }
81
+
82
+ get EE() {
83
+ return ee({ dir: this.dir, logger });
84
+ }
85
+
86
+ handleRequest(req, res) {
87
+ if (!this.requestHandler) {
88
+ this.requestHandler = this.app.callback();
89
+ }
90
+
91
+ return this.requestHandler(req, res);
92
+ }
93
+
94
+ requireProjectBootstrap() {
95
+ const bootstrapPath = path.resolve(this.dir, 'config/functions/bootstrap.js');
96
+
97
+ if (fse.existsSync(bootstrapPath)) {
98
+ require(bootstrapPath);
99
+ }
100
+ }
101
+
102
+ logStats() {
103
+ const columns = Math.min(process.stderr.columns, 80) - 2;
104
+ console.log();
105
+ console.log(chalk.black.bgWhite(_.padEnd(' Project information', columns)));
106
+ console.log();
107
+
108
+ const infoTable = new CLITable({
109
+ colWidths: [20, 50],
110
+ chars: { mid: '', 'left-mid': '', 'mid-mid': '', 'right-mid': '' },
111
+ });
112
+
113
+ const isEE = strapi.EE === true && ee.isEE === true;
114
+
115
+ infoTable.push(
116
+ [chalk.blue('Time'), `${new Date()}`],
117
+ [chalk.blue('Launched in'), Date.now() - this.config.launchedAt + ' ms'],
118
+ [chalk.blue('Environment'), this.config.environment],
119
+ [chalk.blue('Process PID'), process.pid],
120
+ [chalk.blue('Version'), `${this.config.info.strapi} (node ${process.version})`],
121
+ [chalk.blue('Edition'), isEE ? 'Enterprise' : 'Community']
122
+ );
123
+
124
+ console.log(infoTable.toString());
125
+ console.log();
126
+ console.log(chalk.black.bgWhite(_.padEnd(' Actions available', columns)));
127
+ console.log();
128
+ }
129
+
130
+ logFirstStartupMessage() {
131
+ this.logStats();
132
+
133
+ console.log(chalk.bold('One more thing...'));
134
+ console.log(
135
+ chalk.grey('Create your first administrator 💻 by going to the administration panel at:')
136
+ );
137
+ console.log();
138
+
139
+ const addressTable = new CLITable();
140
+
141
+ const adminUrl = getAbsoluteAdminUrl(strapi.config);
142
+ addressTable.push([chalk.bold(adminUrl)]);
143
+
144
+ console.log(`${addressTable.toString()}`);
145
+ console.log();
146
+ }
147
+
148
+ logStartupMessage() {
149
+ this.logStats();
150
+
151
+ console.log(chalk.bold('Welcome back!'));
152
+
153
+ if (this.config.serveAdminPanel === true) {
154
+ console.log(chalk.grey('To manage your project 🚀, go to the administration panel at:'));
155
+ const adminUrl = getAbsoluteAdminUrl(strapi.config);
156
+ console.log(chalk.bold(adminUrl));
157
+ console.log();
158
+ }
159
+
160
+ console.log(chalk.grey('To access the server ⚡️, go to:'));
161
+ const serverUrl = getAbsoluteServerUrl(strapi.config);
162
+ console.log(chalk.bold(serverUrl));
163
+ console.log();
164
+ }
165
+
166
+ initServer() {
167
+ this.server = http.createServer(this.handleRequest.bind(this));
168
+ // handle port in use cleanly
169
+ this.server.on('error', (err) => {
170
+ if (err.code === 'EADDRINUSE') {
171
+ return this.stopWithError(`The port ${err.port} is already used by another application.`);
172
+ }
173
+
174
+ this.log.error(err);
175
+ });
176
+
177
+ // Close current connections to fully destroy the server
178
+ const connections = {};
179
+
180
+ this.server.on('connection', (conn) => {
181
+ const key = conn.remoteAddress + ':' + conn.remotePort;
182
+ connections[key] = conn;
183
+
184
+ conn.on('close', function () {
185
+ delete connections[key];
186
+ });
187
+ });
188
+
189
+ this.server.destroy = (cb) => {
190
+ this.server.close(cb);
191
+
192
+ for (let key in connections) {
193
+ connections[key].destroy();
194
+ }
195
+ };
196
+ }
197
+
198
+ async start(cb) {
199
+ try {
200
+ if (!this.isLoaded) {
201
+ await this.load();
202
+ }
203
+
204
+ this.app.use(this.router.routes()).use(this.router.allowedMethods());
205
+
206
+ // Launch server.
207
+ this.listen(cb);
208
+ } catch (err) {
209
+ this.stopWithError(err);
210
+ }
211
+ }
212
+
213
+ async destroy() {
214
+ if (_.has(this, 'server.destroy')) {
215
+ await new Promise((res) => this.server.destroy(res));
216
+ }
217
+
218
+ await Promise.all(
219
+ Object.values(this.plugins).map((plugin) => {
220
+ if (_.has(plugin, 'destroy') && typeof plugin.destroy === 'function') {
221
+ return plugin.destroy();
222
+ }
223
+ })
224
+ );
225
+
226
+ if (_.has(this, 'admin')) {
227
+ await this.admin.destroy();
228
+ }
229
+
230
+ this.eventHub.removeAllListeners();
231
+
232
+ if (_.has(this, 'db')) {
233
+ await this.db.destroy();
234
+ }
235
+
236
+ // this.telemetry.destroy();
237
+
238
+ delete global.strapi;
239
+ }
240
+
241
+ /**
242
+ * Add behaviors to the server
243
+ */
244
+ async listen(cb) {
245
+ const onListen = async (err) => {
246
+ if (err) return this.stopWithError(err);
247
+
248
+ // Is the project initialised?
249
+ const isInitialised = await utils.isInitialised(this);
250
+
251
+ // Should the startup message be displayed?
252
+ const hideStartupMessage = process.env.STRAPI_HIDE_STARTUP_MESSAGE
253
+ ? process.env.STRAPI_HIDE_STARTUP_MESSAGE === 'true'
254
+ : false;
255
+
256
+ if (hideStartupMessage === false) {
257
+ if (!isInitialised) {
258
+ this.logFirstStartupMessage();
259
+ } else {
260
+ this.logStartupMessage();
261
+ }
262
+ }
263
+
264
+ // Get database clients
265
+ // const databaseClients = _.map(this.config.get('connections'), _.property('settings.client'));
266
+
267
+ // Emit started event.
268
+ // await this.telemetry.send('didStartServer', {
269
+ // database: databaseClients,
270
+ // plugins: this.config.installedPlugins,
271
+ // providers: this.config.installedProviders,
272
+ // });
273
+
274
+ if (cb && typeof cb === 'function') {
275
+ cb();
276
+ }
277
+
278
+ if (
279
+ (this.config.environment === 'development' &&
280
+ this.config.get('server.admin.autoOpen', true) !== false) ||
281
+ !isInitialised
282
+ ) {
283
+ await utils.openBrowser.call(this);
284
+ }
285
+ };
286
+
287
+ const listenSocket = this.config.get('server.socket');
288
+ const listenErrHandler = (err) => onListen(err).catch((err) => this.stopWithError(err));
289
+
290
+ if (listenSocket) {
291
+ this.server.listen(listenSocket, listenErrHandler);
292
+ } else {
293
+ this.server.listen(
294
+ this.config.get('server.port'),
295
+ this.config.get('server.host'),
296
+ listenErrHandler
297
+ );
298
+ }
299
+ }
300
+
301
+ stopWithError(err, customMessage) {
302
+ this.log.debug(`⛔️ Server wasn't able to start properly.`);
303
+ if (customMessage) {
304
+ this.log.error(customMessage);
305
+ }
306
+ this.log.error(err);
307
+ return this.stop();
308
+ }
309
+
310
+ stop(exitCode = 1) {
311
+ // Destroy server and available connections.
312
+ if (_.has(this, 'server.destroy')) {
313
+ this.server.destroy();
314
+ }
315
+
316
+ if (this.config.autoReload) {
317
+ process.send('stop');
318
+ }
319
+
320
+ // Kill process
321
+ process.exit(exitCode);
322
+ }
323
+
324
+ async load() {
325
+ this.app.use(async (ctx, next) => {
326
+ if (ctx.request.url === '/_health' && ['HEAD', 'GET'].includes(ctx.request.method)) {
327
+ ctx.set('strapi', 'You are so French!');
328
+ ctx.status = 204;
329
+ } else {
330
+ await next();
331
+ }
332
+ });
333
+
334
+ const modules = await loadModules(this);
335
+
336
+ this.api = modules.api;
337
+ this.admin = modules.admin;
338
+ this.components = modules.components;
339
+ this.plugins = modules.plugins;
340
+ this.middleware = modules.middlewares;
341
+ this.hook = modules.hook;
342
+
343
+ await bootstrap(this);
344
+
345
+ // init webhook runner
346
+ this.webhookRunner = createWebhookRunner({
347
+ eventHub: this.eventHub,
348
+ logger: this.log,
349
+ configuration: this.config.get('server.webhooks', {}),
350
+ });
351
+
352
+ // Init core store
353
+ this.models['core_store'] = coreStoreModel(this.config);
354
+ this.models['strapi_webhooks'] = webhookModel(this.config);
355
+
356
+ this.db = createDatabaseManager(this);
357
+
358
+ await this.runLifecyclesFunctions(LIFECYCLES.REGISTER);
359
+ await this.db.initialize();
360
+
361
+ this.store = createCoreStore({
362
+ environment: this.config.environment,
363
+ db: this.db,
364
+ });
365
+
366
+ this.webhookStore = createWebhookStore({ db: this.db });
367
+
368
+ await this.startWebhooks();
369
+
370
+ this.entityValidator = entityValidator;
371
+
372
+ this.entityService = createEntityService({
373
+ db: this.db,
374
+ eventHub: this.eventHub,
375
+ entityValidator: this.entityValidator,
376
+ });
377
+
378
+ // this.telemetry = createTelemetry(this);
379
+
380
+ // Initialize hooks and middlewares.
381
+ await initializeMiddlewares.call(this);
382
+ await initializeHooks.call(this);
383
+
384
+ await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP);
385
+ await this.freeze();
386
+
387
+ this.isLoaded = true;
388
+ return this;
389
+ }
390
+
391
+ async startWebhooks() {
392
+ const webhooks = await this.webhookStore.findWebhooks();
393
+ webhooks.forEach((webhook) => this.webhookRunner.add(webhook));
394
+ }
395
+
396
+ reload() {
397
+ const state = {
398
+ shouldReload: 0,
399
+ };
400
+
401
+ const reload = function () {
402
+ if (state.shouldReload > 0) {
403
+ // Reset the reloading state
404
+ state.shouldReload -= 1;
405
+ reload.isReloading = false;
406
+ return;
407
+ }
408
+
409
+ if (this.config.autoReload) {
410
+ this.server.close();
411
+ process.send('reload');
412
+ }
413
+ };
414
+
415
+ Object.defineProperty(reload, 'isWatching', {
416
+ configurable: true,
417
+ enumerable: true,
418
+ set: (value) => {
419
+ // Special state when the reloader is disabled temporarly (see GraphQL plugin example).
420
+ if (state.isWatching === false && value === true) {
421
+ state.shouldReload += 1;
422
+ }
423
+ state.isWatching = value;
424
+ },
425
+ get: () => {
426
+ return state.isWatching;
427
+ },
428
+ });
429
+
430
+ reload.isReloading = false;
431
+ reload.isWatching = true;
432
+
433
+ return reload;
434
+ }
435
+
436
+ async runLifecyclesFunctions(lifecycleName) {
437
+ const execLifecycle = async (fn) => {
438
+ if (!fn) {
439
+ return;
440
+ }
441
+
442
+ return fn();
443
+ };
444
+
445
+ const configPath = `functions.${lifecycleName}`;
446
+
447
+ // plugins
448
+ await Promise.all(
449
+ Object.keys(this.plugins).map((plugin) => {
450
+ const pluginFunc = _.get(this.plugins[plugin], `config.${configPath}`);
451
+
452
+ return execLifecycle(pluginFunc).catch((err) => {
453
+ strapi.log.error(`${lifecycleName} function in plugin "${plugin}" failed`);
454
+ strapi.log.error(err);
455
+ strapi.stop();
456
+ });
457
+ })
458
+ );
459
+
460
+ // user
461
+ await execLifecycle(_.get(this.config, configPath));
462
+
463
+ // admin
464
+ const adminFunc = _.get(this.admin.config, configPath);
465
+ return execLifecycle(adminFunc).catch((err) => {
466
+ strapi.log.error(`${lifecycleName} function in admin failed`);
467
+ strapi.log.error(err);
468
+ strapi.stop();
469
+ });
470
+ }
471
+
472
+ async freeze() {
473
+ Object.freeze(this.config);
474
+ Object.freeze(this.dir);
475
+ Object.freeze(this.admin);
476
+ Object.freeze(this.plugins);
477
+ Object.freeze(this.api);
478
+ }
479
+
480
+ getModel(modelKey, plugin) {
481
+ return this.db.getModel(modelKey, plugin);
482
+ }
483
+
484
+ /**
485
+ * Binds queries with a specific model
486
+ * @param {string} entity - entity name
487
+ * @param {string} plugin - plugin name or null
488
+ */
489
+ query(entity, plugin) {
490
+ return this.db.query(entity, plugin);
491
+ }
492
+ }
493
+
494
+ module.exports = (options) => {
495
+ const strapi = new Strapi(options);
496
+ global.strapi = strapi;
497
+ return strapi;
498
+ };
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+ const inquirer = require('inquirer');
5
+ const strapi = require('../index');
6
+
7
+ const promptQuestions = [
8
+ { type: 'input', name: 'email', message: 'User email?' },
9
+ { type: 'password', name: 'password', message: 'New password?' },
10
+ {
11
+ type: 'confirm',
12
+ name: 'confirm',
13
+ message: "Do you really want to reset this user's password?",
14
+ },
15
+ ];
16
+
17
+ /**
18
+ * Reset user's password
19
+ * @param {Object} cmdOptions - command options
20
+ * @param {string} cmdOptions.email - user's email
21
+ * @param {string} cmdOptions.password - user's new password
22
+ */
23
+ module.exports = async function(cmdOptions = {}) {
24
+ const { email, password } = cmdOptions;
25
+
26
+ if (_.isEmpty(email) && _.isEmpty(password) && process.stdin.isTTY) {
27
+ const inquiry = await inquirer.prompt(promptQuestions);
28
+
29
+ if (!inquiry.confirm) {
30
+ process.exit(0);
31
+ }
32
+
33
+ return changePassword(inquiry);
34
+ }
35
+
36
+ if (_.isEmpty(email) || _.isEmpty(password)) {
37
+ console.error('Missing required options `email` or `password`');
38
+ process.exit(1);
39
+ }
40
+
41
+ return changePassword({ email, password });
42
+ };
43
+
44
+ async function changePassword({ email, password }) {
45
+ const app = await strapi().load();
46
+
47
+ await app.admin.services.user.resetPasswordByEmail(email, password);
48
+
49
+ console.log(`Successfully reset user's password`);
50
+ process.exit(0);
51
+ }
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+ const { green } = require('chalk');
3
+
4
+ // eslint-disable-next-line node/no-extraneous-require
5
+ const strapiAdmin = require('@akemona-org/strapi-admin');
6
+ const { getConfigUrls } = require('@akemona-org/strapi-utils');
7
+ const loadConfiguration = require('../core/app-configuration');
8
+ const ee = require('../utils/ee');
9
+
10
+ const addSlash = require('../utils/addSlash');
11
+ /**
12
+ * `$ strapi build`
13
+ */
14
+ module.exports = async ({ clean, optimization }) => {
15
+ const dir = process.cwd();
16
+ const config = loadConfiguration(dir);
17
+
18
+ const { serverUrl, adminPath } = getConfigUrls(config.get('server'), true);
19
+
20
+ console.log(`Building your admin UI with ${green(config.environment)} configuration ...`);
21
+
22
+ if (clean) {
23
+ await strapiAdmin.clean({ dir });
24
+ }
25
+
26
+ ee({ dir });
27
+
28
+ return strapiAdmin
29
+ .build({
30
+ dir,
31
+ // front end build env is always production for now
32
+ env: 'production',
33
+ optimize: optimization,
34
+ options: {
35
+ backend: serverUrl,
36
+ publicPath: addSlash(adminPath),
37
+ features: ee.isEE ? ee.features.getEnabled() : [],
38
+ },
39
+ })
40
+ .then(() => {
41
+ process.exit();
42
+ })
43
+ .catch((err) => {
44
+ console.error(err);
45
+ process.exit(1);
46
+ });
47
+ };
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const strapi = require('../index');
5
+
6
+ const CHUNK_SIZE = 100;
7
+
8
+ /**
9
+ * Will dump configurations to a file or stdout
10
+ * @param {string} file filepath to use as output
11
+ */
12
+ module.exports = async function({ file: filePath, pretty }) {
13
+ const output = filePath ? fs.createWriteStream(filePath) : process.stdout;
14
+
15
+ const app = await strapi().load();
16
+
17
+ const count = await app.query('core_store').count();
18
+
19
+ const exportData = [];
20
+
21
+ const pageCount = Math.ceil(count / CHUNK_SIZE);
22
+
23
+ for (let page = 0; page < pageCount; page++) {
24
+ const results = await app
25
+ .query('core_store')
26
+ .find({ _limit: CHUNK_SIZE, _start: page * CHUNK_SIZE, _sort: 'key' });
27
+
28
+ results
29
+ .filter(result => result.key.startsWith('plugin_'))
30
+ .forEach(result => {
31
+ exportData.push({
32
+ key: result.key,
33
+ value: result.value,
34
+ type: result.type,
35
+ environment: result.environment,
36
+ tag: result.tag,
37
+ });
38
+ });
39
+ }
40
+
41
+ output.write(JSON.stringify(exportData, null, pretty ? 2 : null));
42
+ output.write('\n');
43
+ output.end();
44
+
45
+ // log success only when writting to file
46
+ if (filePath) {
47
+ console.log(`Successfully exported ${exportData.length} configuration entries`);
48
+ }
49
+ process.exit(0);
50
+ };