@strapi/strapi 4.0.0-next.11 → 4.0.0-next.15

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 (51) hide show
  1. package/bin/strapi.js +1 -4
  2. package/lib/Strapi.js +82 -28
  3. package/lib/commands/console.js +1 -1
  4. package/lib/commands/develop.js +4 -3
  5. package/lib/core/domain/content-type/index.js +3 -7
  6. package/lib/core/domain/module/index.js +2 -2
  7. package/lib/core/loaders/apis.js +4 -6
  8. package/lib/core/loaders/components.js +3 -5
  9. package/lib/core/loaders/index.js +1 -0
  10. package/lib/core/loaders/middlewares.js +1 -1
  11. package/lib/core/loaders/plugins/get-enabled-plugins.js +2 -2
  12. package/lib/core/loaders/plugins/index.js +7 -7
  13. package/lib/core/loaders/policies.js +1 -1
  14. package/lib/core/loaders/src-index.js +38 -0
  15. package/lib/core/registries/hooks.js +37 -0
  16. package/lib/core/registries/services.js +7 -7
  17. package/lib/core-api/controller/collection-type.js +5 -5
  18. package/lib/core-api/controller/single-type.js +3 -3
  19. package/lib/core-api/controller/transform.js +28 -3
  20. package/lib/core-api/service/collection-type.js +18 -19
  21. package/lib/core-api/service/single-type.js +10 -14
  22. package/lib/index.d.ts +9 -31
  23. package/lib/middlewares/cors/index.js +1 -1
  24. package/lib/middlewares/{boom → error}/defaults.json +1 -1
  25. package/lib/middlewares/{boom → error}/index.js +1 -1
  26. package/lib/middlewares/favicon/index.js +1 -2
  27. package/lib/middlewares/index.js +1 -1
  28. package/lib/middlewares/public/index.js +2 -2
  29. package/lib/middlewares/responses/index.js +2 -1
  30. package/lib/middlewares/router/index.js +5 -3
  31. package/lib/migrations/draft-publish.js +57 -0
  32. package/lib/services/auth/index.js +2 -2
  33. package/lib/services/core-store.js +64 -49
  34. package/lib/services/cron.js +54 -0
  35. package/lib/services/entity-service/components.js +37 -12
  36. package/lib/services/entity-service/index.d.ts +91 -0
  37. package/lib/services/entity-service/index.js +52 -50
  38. package/lib/services/entity-service/params.js +74 -57
  39. package/lib/services/fs.js +1 -1
  40. package/lib/services/metrics/index.js +1 -1
  41. package/lib/services/server/policy.js +15 -4
  42. package/lib/services/webhook-runner.js +1 -1
  43. package/lib/utils/ee.js +3 -3
  44. package/lib/utils/get-dirs.js +15 -0
  45. package/lib/utils/index.js +2 -0
  46. package/lib/utils/update-notifier/index.js +2 -1
  47. package/package.json +88 -98
  48. package/lib/middlewares/cron/defaults.json +0 -5
  49. package/lib/middlewares/cron/index.js +0 -43
  50. package/lib/middlewares/language/defaults.json +0 -9
  51. package/lib/middlewares/language/index.js +0 -40
package/bin/strapi.js CHANGED
@@ -58,10 +58,7 @@ const getLocalScript = name => (...args) => {
58
58
  };
59
59
 
60
60
  // Initial program setup
61
- program
62
- .storeOptionsAsProperties(false)
63
- .passCommandToAction(false)
64
- .allowUnknownOption(true);
61
+ program.storeOptionsAsProperties(false).allowUnknownOption(true);
65
62
 
66
63
  program.helpOption('-h, --help', 'Display help for command');
67
64
  program.addHelpCommand('help [command]', 'Display help for command');
package/lib/Strapi.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const _ = require('lodash');
4
4
  const { createLogger } = require('@strapi/logger');
5
5
  const { Database } = require('@strapi/database');
6
+ const { createAsyncParallelHook } = require('@strapi/utils').hooks;
6
7
 
7
8
  const loadConfiguration = require('./core/app-configuration');
8
9
 
@@ -16,6 +17,7 @@ const createWebhookRunner = require('./services/webhook-runner');
16
17
  const { webhookModel, createWebhookStore } = require('./services/webhook-store');
17
18
  const { createCoreStore, coreStoreModel } = require('./services/core-store');
18
19
  const createEntityService = require('./services/entity-service');
20
+ const createCronService = require('./services/cron');
19
21
  const entityValidator = require('./services/entity-validator');
20
22
  const createTelemetry = require('./services/metrics');
21
23
  const createAuth = require('./services/auth');
@@ -26,6 +28,7 @@ const contentTypesRegistry = require('./core/registries/content-types');
26
28
  const servicesRegistry = require('./core/registries/services');
27
29
  const policiesRegistry = require('./core/registries/policies');
28
30
  const middlewaresRegistry = require('./core/registries/middlewares');
31
+ const hooksRegistry = require('./core/registries/hooks');
29
32
  const controllersRegistry = require('./core/registries/controllers');
30
33
  const modulesRegistry = require('./core/registries/modules');
31
34
  const pluginsRegistry = require('./core/registries/plugins');
@@ -34,6 +37,9 @@ const apisRegistry = require('./core/registries/apis');
34
37
  const bootstrap = require('./core/bootstrap');
35
38
  const loaders = require('./core/loaders');
36
39
 
40
+ // TODO: move somewhere else
41
+ const draftAndPublishSync = require('./migrations/draft-publish');
42
+
37
43
  const LIFECYCLES = {
38
44
  REGISTER: 'register',
39
45
  BOOTSTRAP: 'bootstrap',
@@ -41,14 +47,15 @@ const LIFECYCLES = {
41
47
 
42
48
  class Strapi {
43
49
  constructor(opts = {}) {
44
- this.dir = opts.dir || process.cwd();
45
- const appConfig = loadConfiguration(this.dir, opts);
50
+ this.dirs = utils.getDirs(opts.dir || process.cwd());
51
+ const appConfig = loadConfiguration(this.dirs.root, opts);
46
52
  this.container = createContainer(this);
47
53
  this.container.register('config', createConfigProvider(appConfig));
48
54
  this.container.register('content-types', contentTypesRegistry(this));
49
55
  this.container.register('services', servicesRegistry(this));
50
56
  this.container.register('policies', policiesRegistry(this));
51
57
  this.container.register('middlewares', middlewaresRegistry(this));
58
+ this.container.register('hooks', hooksRegistry(this));
52
59
  this.container.register('controllers', controllersRegistry(this));
53
60
  this.container.register('modules', modulesRegistry(this));
54
61
  this.container.register('plugins', pluginsRegistry(this));
@@ -63,6 +70,7 @@ class Strapi {
63
70
  this.eventHub = createEventHub();
64
71
  this.startupLogger = createStartupLogger(this);
65
72
  this.log = createLogger(this.config.get('logger', {}));
73
+ this.cron = createCronService();
66
74
 
67
75
  createUpdateNotifier(this).notify();
68
76
  }
@@ -72,7 +80,7 @@ class Strapi {
72
80
  }
73
81
 
74
82
  get EE() {
75
- return ee({ dir: this.dir, logger: this.log });
83
+ return ee({ dir: this.dirs.root, logger: this.log });
76
84
  }
77
85
 
78
86
  service(uid) {
@@ -107,6 +115,14 @@ class Strapi {
107
115
  return this.container.get('plugins').getAll();
108
116
  }
109
117
 
118
+ hook(name) {
119
+ return this.container.get('hooks').get(name);
120
+ }
121
+
122
+ get hooks() {
123
+ return this.container.get('hooks');
124
+ }
125
+
110
126
  // api(name) {
111
127
  // return this.container.get('apis').get(name);
112
128
  // }
@@ -115,6 +131,10 @@ class Strapi {
115
131
  return this.container.get('apis').getAll();
116
132
  }
117
133
 
134
+ get auth() {
135
+ return this.container.get('auth');
136
+ }
137
+
118
138
  async start() {
119
139
  try {
120
140
  if (!this.isLoaded) {
@@ -151,6 +171,7 @@ class Strapi {
151
171
  }
152
172
 
153
173
  this.telemetry.destroy();
174
+ this.cron.destroy();
154
175
 
155
176
  delete global.strapi;
156
177
  }
@@ -173,7 +194,7 @@ class Strapi {
173
194
  this.config.get('environment') === 'development' &&
174
195
  this.config.get('server.admin.autoOpen', true) !== false;
175
196
 
176
- if (shouldOpenAdmin || !isInitialized) {
197
+ if (shouldOpenAdmin && !isInitialized) {
177
198
  await utils.openBrowser(this.config);
178
199
  }
179
200
  }
@@ -262,8 +283,21 @@ class Strapi {
262
283
  this.middleware = await loaders.loadMiddlewares(this);
263
284
  }
264
285
 
286
+ async loadApp() {
287
+ this.app = await loaders.loadSrcIndex(this);
288
+ }
289
+
290
+ registerInternalHooks() {
291
+ this.hooks.set('strapi::content-types.beforeSync', createAsyncParallelHook());
292
+ this.hooks.set('strapi::content-types.afterSync', createAsyncParallelHook());
293
+
294
+ this.hook('strapi::content-types.beforeSync').register(draftAndPublishSync.disable);
295
+ this.hook('strapi::content-types.afterSync').register(draftAndPublishSync.enable);
296
+ }
297
+
265
298
  async load() {
266
299
  await Promise.all([
300
+ this.loadApp(),
267
301
  this.loadPlugins(),
268
302
  this.loadAdmin(),
269
303
  this.loadAPIs(),
@@ -281,6 +315,8 @@ class Strapi {
281
315
  configuration: this.config.get('server.webhooks', {}),
282
316
  });
283
317
 
318
+ this.registerInternalHooks();
319
+
284
320
  await this.runLifecyclesFunctions(LIFECYCLES.REGISTER);
285
321
 
286
322
  const contentTypes = [
@@ -295,19 +331,10 @@ class Strapi {
295
331
  models: Database.transformContentTypes(contentTypes),
296
332
  });
297
333
 
298
- await this.db.schema.sync();
299
-
300
- this.store = createCoreStore({
301
- environment: this.config.get('environment'),
302
- db: this.db,
303
- });
304
-
334
+ this.store = createCoreStore({ db: this.db });
305
335
  this.webhookStore = createWebhookStore({ db: this.db });
306
336
 
307
- await this.startWebhooks();
308
-
309
337
  this.entityValidator = entityValidator;
310
-
311
338
  this.entityService = createEntityService({
312
339
  strapi: this,
313
340
  db: this.db,
@@ -315,13 +342,48 @@ class Strapi {
315
342
  entityValidator: this.entityValidator,
316
343
  });
317
344
 
345
+ const cronTasks = this.config.get('server.cron.tasks', {});
346
+ this.cron.add(cronTasks);
347
+
318
348
  this.telemetry = createTelemetry(this);
319
349
 
350
+ let oldContentTypes;
351
+ if (await this.db.connection.schema.hasTable(coreStoreModel.collectionName)) {
352
+ oldContentTypes = await this.store.get({
353
+ type: 'strapi',
354
+ name: 'content_types',
355
+ key: 'schema',
356
+ });
357
+ }
358
+
359
+ await this.hook('strapi::content-types.beforeSync').call({
360
+ oldContentTypes,
361
+ contentTypes: strapi.contentTypes,
362
+ });
363
+
364
+ await this.db.schema.sync();
365
+
366
+ await this.hook('strapi::content-types.afterSync').call({
367
+ oldContentTypes,
368
+ contentTypes: strapi.contentTypes,
369
+ });
370
+
371
+ await this.store.set({
372
+ type: 'strapi',
373
+ name: 'content_types',
374
+ key: 'schema',
375
+ value: strapi.contentTypes,
376
+ });
377
+
378
+ await this.startWebhooks();
379
+
320
380
  // Initialize middlewares.
321
381
  await initializeMiddlewares(this);
322
382
 
323
383
  await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP);
324
384
 
385
+ this.cron.start();
386
+
325
387
  this.isLoaded = true;
326
388
 
327
389
  return this;
@@ -354,14 +416,14 @@ class Strapi {
354
416
  Object.defineProperty(reload, 'isWatching', {
355
417
  configurable: true,
356
418
  enumerable: true,
357
- set: value => {
419
+ set(value) {
358
420
  // Special state when the reloader is disabled temporarly (see GraphQL plugin example).
359
421
  if (state.isWatching === false && value === true) {
360
422
  state.shouldReload += 1;
361
423
  }
362
424
  state.isWatching = value;
363
425
  },
364
- get: () => {
426
+ get() {
365
427
  return state.isWatching;
366
428
  },
367
429
  });
@@ -373,21 +435,14 @@ class Strapi {
373
435
  }
374
436
 
375
437
  async runLifecyclesFunctions(lifecycleName) {
376
- const execLifecycle = async fn => {
377
- if (!fn) {
378
- return;
379
- }
380
-
381
- return fn({ strapi: this });
382
- };
383
-
384
- const configPath = `functions.${lifecycleName}`;
385
-
386
438
  // plugins
387
439
  await this.container.get('modules')[lifecycleName]();
388
440
 
389
441
  // user
390
- await execLifecycle(this.config.get(configPath));
442
+ const lifecycleFunction = this.app[lifecycleName];
443
+ if (lifecycleFunction) {
444
+ await lifecycleFunction({ strapi: this });
445
+ }
391
446
 
392
447
  // admin
393
448
  await this.admin[lifecycleName](this);
@@ -400,7 +455,6 @@ class Strapi {
400
455
  /**
401
456
  * Binds queries with a specific model
402
457
  * @param {string} uid
403
- * @returns {}
404
458
  */
405
459
  query(uid) {
406
460
  return this.db.query(uid);
@@ -10,7 +10,7 @@ module.exports = () => {
10
10
  // Now load up the Strapi framework for real.
11
11
  const app = strapi();
12
12
 
13
- app.start(() => {
13
+ app.start().then(() => {
14
14
  const repl = REPL.start(app.config.info.name + ' > ' || 'strapi > '); // eslint-disable-line prefer-template
15
15
 
16
16
  repl.on('exit', function(err) {
@@ -27,8 +27,9 @@ module.exports = async function({ build, watchAdmin, polling, browser }) {
27
27
  // Don't run the build process if the admin is in watch mode
28
28
  if (build && !watchAdmin && serveAdminPanel && !buildExists) {
29
29
  try {
30
- execa.shellSync('npm run -s build -- --no-optimization', {
30
+ execa.sync('npm run -s build -- --no-optimization', {
31
31
  stdio: 'inherit',
32
+ shell: true,
32
33
  });
33
34
  } catch (err) {
34
35
  process.exit(1);
@@ -124,8 +125,8 @@ function watchFileChanges({ dir, strapiInstance, watchIgnoreFiles, polling }) {
124
125
  /tmp/,
125
126
  '**/admin',
126
127
  '**/admin/**',
127
- 'extensions/**/admin',
128
- 'extensions/**/admin/**',
128
+ 'src/extensions/**/admin',
129
+ 'src/extensions/**/admin/**',
129
130
  '**/documentation',
130
131
  '**/documentation/**',
131
132
  '**/node_modules',
@@ -68,12 +68,10 @@ const createContentType = (uid, definition) => {
68
68
  Object.assign(schema.attributes, {
69
69
  [CREATED_AT_ATTRIBUTE]: {
70
70
  type: 'datetime',
71
- default: () => new Date(),
72
71
  },
73
72
  // TODO: handle on edit set to new date
74
73
  [UPDATED_AT_ATTRIBUTE]: {
75
74
  type: 'datetime',
76
- default: () => new Date(),
77
75
  },
78
76
  });
79
77
 
@@ -110,11 +108,9 @@ const createContentType = (uid, definition) => {
110
108
  private: isPrivate,
111
109
  };
112
110
 
113
- return {
114
- ...schema,
115
- actions: actions,
116
- lifecycles: lifecycles,
117
- };
111
+ Object.assign(schema, { actions, lifecycles });
112
+
113
+ return schema;
118
114
  };
119
115
 
120
116
  const getGlobalId = (model, modelName, prefix) => {
@@ -62,8 +62,8 @@ const createModule = (namespace, rawModule, strapi) => {
62
62
  strapi.container.get('config').set(uidToPath(namespace), rawModule.config);
63
63
  },
64
64
  routes: rawModule.routes,
65
- config(path) {
66
- return strapi.container.get('config').get(`${uidToPath(namespace)}.${path}`);
65
+ config(path, defaultValue) {
66
+ return strapi.container.get('config').get(`${uidToPath(namespace)}.${path}`, defaultValue);
67
67
  },
68
68
  contentType(ctName) {
69
69
  return strapi.container.get('content-types').get(`${namespace}.${ctName}`);
@@ -14,20 +14,18 @@ const DEFAULT_CONTENT_TYPE = {
14
14
  };
15
15
 
16
16
  module.exports = async strapi => {
17
- const apisDir = join(strapi.dir, 'api');
18
-
19
- if (!existsSync(apisDir)) {
20
- throw new Error(`Missing api folder. Please create one in your app root directory`);
17
+ if (!existsSync(strapi.dirs.api)) {
18
+ throw new Error('Missing api folder. Please create one at `./src/api`');
21
19
  }
22
20
 
23
- const apisFDs = await fse.readdir(apisDir, { withFileTypes: true });
21
+ const apisFDs = await fse.readdir(strapi.dirs.api, { withFileTypes: true });
24
22
  const apis = {};
25
23
 
26
24
  // only load folders
27
25
  for (const apiFD of apisFDs) {
28
26
  if (apiFD.isDirectory()) {
29
27
  const apiName = normalizeName(apiFD.name);
30
- const api = await loadAPI(join(apisDir, apiFD.name));
28
+ const api = await loadAPI(join(strapi.dirs.api, apiFD.name));
31
29
 
32
30
  apis[apiName] = api;
33
31
  }
@@ -6,19 +6,17 @@ const { pathExists } = require('fs-extra');
6
6
  const loadFiles = require('../../load/load-files');
7
7
 
8
8
  module.exports = async strapi => {
9
- const componentsDir = join(strapi.dir, 'components');
10
-
11
- if (!(await pathExists(componentsDir))) {
9
+ if (!(await pathExists(strapi.dirs.components))) {
12
10
  return {};
13
11
  }
14
12
 
15
- const map = await loadFiles(componentsDir, '*/*.*(js|json)');
13
+ const map = await loadFiles(strapi.dirs.components, '*/*.*(js|json)');
16
14
 
17
15
  return Object.keys(map).reduce((acc, category) => {
18
16
  Object.keys(map[category]).forEach(key => {
19
17
  const schema = map[category][key];
20
18
 
21
- const filePath = join(componentsDir, category, schema.__filename__);
19
+ const filePath = join(strapi.dirs.components, category, schema.__filename__);
22
20
 
23
21
  if (!schema.collectionName) {
24
22
  return strapi.stopWithError(
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  module.exports = {
4
+ loadSrcIndex: require('./src-index'),
4
5
  loadAPIs: require('./apis'),
5
6
  loadMiddlewares: require('./middlewares'),
6
7
  loadComponents: require('./components'),
@@ -45,7 +45,7 @@ const createLoaders = strapi => {
45
45
  loadMiddlewaresInDir(path.resolve(__dirname, '..', '..', 'middlewares'), middlewares);
46
46
 
47
47
  const loadLocalMiddlewares = (appPath, middlewares) =>
48
- loadMiddlewaresInDir(path.resolve(appPath, 'middlewares'), middlewares);
48
+ loadMiddlewaresInDir(path.resolve(appPath, 'src', 'middlewares'), middlewares);
49
49
 
50
50
  const loadMiddlewareDependencies = async (packages, middlewares) => {
51
51
  for (let packageName of packages) {
@@ -32,7 +32,7 @@ const toDetailedDeclaration = declaration => {
32
32
  try {
33
33
  pathToPlugin = dirname(require.resolve(declaration.resolve));
34
34
  } catch (e) {
35
- pathToPlugin = resolve(strapi.dir, declaration.resolve);
35
+ pathToPlugin = resolve(strapi.dirs.root, declaration.resolve);
36
36
 
37
37
  if (!existsSync(pathToPlugin) || !statSync(pathToPlugin).isDirectory()) {
38
38
  throw new Error(`${declaration.resolve} couldn't be resolved`);
@@ -72,7 +72,7 @@ const getEnabledPlugins = async strapi => {
72
72
  }
73
73
 
74
74
  const declaredPlugins = {};
75
- const userPluginConfigPath = join(strapi.dir, 'config', 'plugins.js');
75
+ const userPluginConfigPath = join(strapi.dirs.config, 'plugins.js');
76
76
  const userPluginsConfig = existsSync(userPluginConfigPath)
77
77
  ? loadConfigFile(userPluginConfigPath)
78
78
  : {};
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { join, resolve } = require('path');
3
+ const { join } = require('path');
4
4
  const { existsSync } = require('fs');
5
5
  const { defaultsDeep, getOr, get } = require('lodash/fp');
6
6
  const { env } = require('@strapi/utils');
@@ -9,12 +9,12 @@ const loadFiles = require('../../../load/load-files');
9
9
  const getEnabledPlugins = require('./get-enabled-plugins');
10
10
 
11
11
  const defaultPlugin = {
12
- bootstrap: () => {},
13
- destroy: () => {},
14
- register: () => {},
12
+ bootstrap() {},
13
+ destroy() {},
14
+ register() {},
15
15
  config: {
16
16
  default: {},
17
- validator: () => {},
17
+ validator() {},
18
18
  },
19
19
  routes: [],
20
20
  controllers: {},
@@ -25,7 +25,7 @@ const defaultPlugin = {
25
25
  };
26
26
 
27
27
  const applyUserExtension = async plugins => {
28
- const extensionsDir = resolve(strapi.dir, 'extensions');
28
+ const extensionsDir = strapi.dirs.extensions;
29
29
  if (!existsSync(extensionsDir)) {
30
30
  return;
31
31
  }
@@ -62,7 +62,7 @@ const formatContentTypes = plugins => {
62
62
  };
63
63
 
64
64
  const applyUserConfig = plugins => {
65
- const userPluginConfigPath = join(strapi.dir, 'config', 'plugins.js');
65
+ const userPluginConfigPath = join(strapi.dirs.config, 'plugins.js');
66
66
  const userPluginsConfig = existsSync(userPluginConfigPath)
67
67
  ? loadConfigFile(userPluginConfigPath)
68
68
  : {};
@@ -5,7 +5,7 @@ const fse = require('fs-extra');
5
5
 
6
6
  // TODO:: allow folders with index.js inside for bigger policies
7
7
  module.exports = async function loadPolicies(strapi) {
8
- const dir = join(strapi.dir, 'policies');
8
+ const dir = strapi.dirs.policies;
9
9
 
10
10
  if (!(await fse.pathExists(dir))) {
11
11
  return;
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const { resolve } = require('path');
4
+ const { statSync, existsSync } = require('fs');
5
+ const { yup } = require('@strapi/utils');
6
+
7
+ const srcSchema = yup
8
+ .object()
9
+ .shape({
10
+ bootstrap: yup.mixed().isFunction(),
11
+ register: yup.mixed().isFunction(),
12
+ })
13
+ .noUnknown();
14
+
15
+ const validateSrcIndex = srcIndex => {
16
+ return srcSchema.validateSync(srcIndex, { strict: true, abortEarly: false });
17
+ };
18
+
19
+ module.exports = strapi => {
20
+ if (!existsSync(strapi.dirs.src)) {
21
+ throw new Error('Missing src folder. Please create one at `./src`');
22
+ }
23
+
24
+ const pathToSrcIndex = resolve(strapi.dirs.src, 'index.js');
25
+ if (!existsSync(pathToSrcIndex) || statSync(pathToSrcIndex).isDirectory()) {
26
+ return {};
27
+ }
28
+
29
+ const srcIndex = require(pathToSrcIndex);
30
+
31
+ try {
32
+ validateSrcIndex(srcIndex);
33
+ } catch (e) {
34
+ strapi.stopWithError({ message: `Invalid file \`./src/index.js\`: ${e.message}` });
35
+ }
36
+
37
+ return srcIndex;
38
+ };
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ const { pickBy, has } = require('lodash/fp');
4
+ const { addNamespace, hasNamespace } = require('../utils');
5
+
6
+ const hooksRegistry = () => {
7
+ const hooks = {};
8
+
9
+ return {
10
+ get(hookUID) {
11
+ return hooks[hookUID];
12
+ },
13
+ getAll(namespace) {
14
+ return pickBy((_, uid) => hasNamespace(uid, namespace))(hooks);
15
+ },
16
+ set(uid, hook) {
17
+ if (has(uid, hooks)) {
18
+ throw new Error(`hook ${uid} has already been registered.`);
19
+ }
20
+
21
+ hooks[uid] = hook;
22
+ return this;
23
+ },
24
+ add(namespace, hooks) {
25
+ for (const hookName in hooks) {
26
+ const hook = hooks[hookName];
27
+ const uid = addNamespace(hookName, namespace);
28
+
29
+ this.set(uid, hook);
30
+ }
31
+
32
+ return this;
33
+ },
34
+ };
35
+ };
36
+
37
+ module.exports = hooksRegistry;
@@ -6,18 +6,18 @@ const { addNamespace, hasNamespace } = require('../utils');
6
6
 
7
7
  const servicesRegistry = strapi => {
8
8
  const services = {};
9
- const instanciatedServices = {};
9
+ const instantiatedServices = {};
10
10
 
11
11
  return {
12
12
  get(uid) {
13
- if (instanciatedServices[uid]) {
14
- return instanciatedServices[uid];
13
+ if (instantiatedServices[uid]) {
14
+ return instantiatedServices[uid];
15
15
  }
16
16
 
17
17
  const service = services[uid];
18
18
  if (service) {
19
- instanciatedServices[uid] = service({ strapi });
20
- return instanciatedServices[uid];
19
+ instantiatedServices[uid] = service({ strapi });
20
+ return instantiatedServices[uid];
21
21
  }
22
22
 
23
23
  return undefined;
@@ -28,7 +28,7 @@ const servicesRegistry = strapi => {
28
28
  return _.mapValues(filteredServices, (service, serviceUID) => this.get(serviceUID));
29
29
  },
30
30
  set(uid, value) {
31
- instanciatedServices[uid] = value;
31
+ instantiatedServices[uid] = value;
32
32
  return this;
33
33
  },
34
34
  add(namespace, newServices) {
@@ -50,7 +50,7 @@ const servicesRegistry = strapi => {
50
50
  throw new Error(`Service ${serviceUID} doesn't exist`);
51
51
  }
52
52
  const newService = extendFn(currentService);
53
- instanciatedServices[serviceUID] = newService;
53
+ instantiatedServices[serviceUID] = newService;
54
54
  },
55
55
  };
56
56
  };
@@ -16,7 +16,7 @@ const createCollectionTypeController = ({ service, sanitize, transformResponse }
16
16
  async find(ctx) {
17
17
  const { query } = ctx;
18
18
 
19
- const { results, pagination } = await service.find({ params: query });
19
+ const { results, pagination } = await service.find(query);
20
20
 
21
21
  return transformResponse(sanitize(results), { pagination });
22
22
  },
@@ -30,7 +30,7 @@ const createCollectionTypeController = ({ service, sanitize, transformResponse }
30
30
  const { id } = ctx.params;
31
31
  const { query } = ctx;
32
32
 
33
- const entity = await service.findOne(id, { params: query });
33
+ const entity = await service.findOne(id, query);
34
34
 
35
35
  return transformResponse(sanitize(entity));
36
36
  },
@@ -45,7 +45,7 @@ const createCollectionTypeController = ({ service, sanitize, transformResponse }
45
45
 
46
46
  const { data, files } = parseBody(ctx);
47
47
 
48
- const entity = await service.create({ params: query, data, files });
48
+ const entity = await service.create({ ...query, data, files });
49
49
 
50
50
  return transformResponse(sanitize(entity));
51
51
  },
@@ -61,7 +61,7 @@ const createCollectionTypeController = ({ service, sanitize, transformResponse }
61
61
 
62
62
  const { data, files } = parseBody(ctx);
63
63
 
64
- const entity = await service.update(id, { params: query, data, files });
64
+ const entity = await service.update(id, { ...query, data, files });
65
65
 
66
66
  return transformResponse(sanitize(entity));
67
67
  },
@@ -75,7 +75,7 @@ const createCollectionTypeController = ({ service, sanitize, transformResponse }
75
75
  const { id } = ctx.params;
76
76
  const { query } = ctx;
77
77
 
78
- const entity = await service.delete(id, { params: query });
78
+ const entity = await service.delete(id, query);
79
79
  return transformResponse(sanitize(entity));
80
80
  },
81
81
  };
@@ -14,7 +14,7 @@ const createSingleTypeController = ({ service, sanitize, transformResponse }) =>
14
14
  */
15
15
  async find(ctx) {
16
16
  const { query } = ctx;
17
- const entity = await service.find({ params: query });
17
+ const entity = await service.find(query);
18
18
  return transformResponse(sanitize(entity));
19
19
  },
20
20
 
@@ -27,7 +27,7 @@ const createSingleTypeController = ({ service, sanitize, transformResponse }) =>
27
27
  const { query } = ctx.request;
28
28
  const { data, files } = parseBody(ctx);
29
29
 
30
- const entity = await service.createOrUpdate({ params: query, data, files });
30
+ const entity = await service.createOrUpdate({ ...query, data, files });
31
31
 
32
32
  return transformResponse(sanitize(entity));
33
33
  },
@@ -35,7 +35,7 @@ const createSingleTypeController = ({ service, sanitize, transformResponse }) =>
35
35
  async delete(ctx) {
36
36
  const { query } = ctx;
37
37
 
38
- const entity = await service.delete({ params: query });
38
+ const entity = await service.delete(query);
39
39
  return transformResponse(sanitize(entity));
40
40
  },
41
41
  };