@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
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const { templateConfiguration, env } = require('@akemona-org/strapi-utils');
6
+
7
+ module.exports = (dir) => {
8
+ if (!fs.existsSync(dir)) return {};
9
+
10
+ return fs
11
+ .readdirSync(dir, { withFileTypes: true })
12
+ .filter((file) => file.isFile())
13
+ .reduce((acc, file) => {
14
+ const key = path.basename(file.name, path.extname(file.name));
15
+
16
+ acc[key] = loadFile(path.resolve(dir, file.name));
17
+
18
+ return acc;
19
+ }, {});
20
+ };
21
+
22
+ const loadFile = (file) => {
23
+ const ext = path.extname(file);
24
+
25
+ switch (ext) {
26
+ case '.js':
27
+ return loadJsFile(file);
28
+ case '.json':
29
+ return loadJSONFile(file);
30
+ default:
31
+ return {};
32
+ }
33
+ };
34
+
35
+ const loadJsFile = (file) => {
36
+ try {
37
+ const jsModule = require(file);
38
+
39
+ // call if function
40
+ if (typeof jsModule === 'function') {
41
+ return jsModule({ env });
42
+ }
43
+
44
+ return jsModule;
45
+ } catch (error) {
46
+ throw new Error(`Could not load js config file ${file}: ${error.message}`);
47
+ }
48
+ };
49
+
50
+ const loadJSONFile = (file) => {
51
+ try {
52
+ return templateConfiguration(JSON.parse(fs.readFileSync(file)));
53
+ } catch (error) {
54
+ throw new Error(`Could not load json config file ${file}: ${error.message}`);
55
+ }
56
+ };
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const _ = require('lodash');
5
+
6
+ module.exports = (initialConfig = {}) => {
7
+ assert(
8
+ typeof initialConfig === 'object' && initialConfig !== null,
9
+ 'Initial config must be an object'
10
+ );
11
+
12
+ const _config = _.cloneDeep(initialConfig);
13
+
14
+ return Object.assign(_config, {
15
+ get(path, defaultValue) {
16
+ return _.get(_config, path, defaultValue);
17
+ },
18
+
19
+ set(path, val) {
20
+ _.set(_config, path, val);
21
+ return this;
22
+ },
23
+
24
+ has(path) {
25
+ return _.has(_config, path);
26
+ },
27
+ });
28
+ };
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const _ = require('lodash');
6
+ const dotenv = require('dotenv');
7
+
8
+ dotenv.config({ path: process.env.ENV_PATH });
9
+
10
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
11
+
12
+ const getPrefixedDeps = require('../../utils/get-prefixed-dependencies');
13
+ const loadPolicies = require('../load-policies');
14
+ const loadFunctions = require('../load-functions');
15
+ const loadConfigDir = require('./config-loader');
16
+ const createConfigProvider = require('./config-provider');
17
+
18
+ const { version: strapiVersion } = require(path.join(__dirname, '../../../package.json'));
19
+
20
+ const CONFIG_PATHS = {
21
+ admin: 'admin',
22
+ api: 'api',
23
+ config: 'config',
24
+ controllers: 'controllers',
25
+ models: 'models',
26
+ plugins: 'plugins',
27
+ policies: 'policies',
28
+ tmp: '.tmp',
29
+ services: 'services',
30
+ static: 'public',
31
+ validators: 'validators',
32
+ views: 'views',
33
+ };
34
+
35
+ const defaultConfig = {
36
+ server: {
37
+ host: process.env.HOST || os.hostname() || 'localhost',
38
+ port: process.env.PORT || 1337,
39
+ proxy: false,
40
+ cron: { enabled: false },
41
+ admin: { autoOpen: false },
42
+ },
43
+ admin: {},
44
+ middleware: {
45
+ timeout: 1000,
46
+ load: {
47
+ before: ['responseTime', 'logger', 'cors', 'responses', 'gzip'],
48
+ order: [],
49
+ after: ['parser', 'router'],
50
+ },
51
+ settings: {},
52
+ },
53
+ hook: {
54
+ timeout: 1000,
55
+ load: { before: [], order: [], after: [] },
56
+ settings: {},
57
+ },
58
+ routes: {},
59
+ functions: {},
60
+ policies: {},
61
+ };
62
+
63
+ module.exports = (dir, initialConfig = {}) => {
64
+ const { autoReload = false, serveAdminPanel = true } = initialConfig;
65
+
66
+ const pkgJSON = require(path.resolve(dir, 'package.json'));
67
+
68
+ const configDir = path.resolve(dir || process.cwd(), 'config');
69
+
70
+ const rootConfig = {
71
+ launchedAt: Date.now(),
72
+ appPath: dir,
73
+ paths: CONFIG_PATHS,
74
+ serveAdminPanel,
75
+ autoReload,
76
+ environment: process.env.NODE_ENV,
77
+ uuid: _.get(pkgJSON, 'strapi.uuid'),
78
+ packageJsonStrapi: _.omit(_.get(pkgJSON, 'strapi', {}), 'uuid'),
79
+ info: {
80
+ ...pkgJSON,
81
+ strapi: strapiVersion,
82
+ },
83
+ installedPlugins: getPrefixedDeps('strapi-plugin', pkgJSON),
84
+ installedMiddlewares: getPrefixedDeps('strapi-middleware', pkgJSON),
85
+ installedHooks: getPrefixedDeps('strapi-hook', pkgJSON),
86
+ installedProviders: getPrefixedDeps('strapi-provider', pkgJSON),
87
+ };
88
+
89
+ const baseConfig = {
90
+ ...loadConfigDir(configDir),
91
+ policies: loadPolicies(path.resolve(configDir, 'policies')),
92
+ functions: loadFunctions(path.resolve(configDir, 'functions')),
93
+ };
94
+
95
+ const envDir = path.resolve(configDir, 'env', process.env.NODE_ENV);
96
+ const envConfig = loadConfigDir(envDir);
97
+
98
+ return createConfigProvider(_.merge(rootConfig, defaultConfig, baseConfig, envConfig));
99
+ };
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+ const { getConfigUrls, contentTypes: contentTypesUtils } = require('@akemona-org/strapi-utils');
5
+
6
+ const { createCoreApi } = require('../core-api');
7
+
8
+ module.exports = function (strapi) {
9
+ // Set connections.
10
+ strapi.connections = {};
11
+
12
+ const defaultConnection = strapi.config.get('database.defaultConnection');
13
+
14
+ // Set current connections.
15
+ strapi.config.connections = strapi.config.get('database.connections', {});
16
+
17
+ strapi.contentTypes = {};
18
+
19
+ // Set models.
20
+ strapi.models = Object.keys(strapi.api || []).reduce((acc, apiName) => {
21
+ const api = strapi.api[apiName];
22
+
23
+ for (let modelName in api.models) {
24
+ let model = strapi.api[apiName].models[modelName];
25
+
26
+ // mutate model
27
+ contentTypesUtils.createContentType(model, { modelName, defaultConnection }, { apiName });
28
+
29
+ strapi.contentTypes[model.uid] = model;
30
+
31
+ const { service, controller } = createCoreApi({ model, api, strapi });
32
+
33
+ _.set(strapi.api[apiName], ['services', modelName], service);
34
+ _.set(strapi.api[apiName], ['controllers', modelName], controller);
35
+
36
+ acc[modelName] = model;
37
+ }
38
+ return acc;
39
+ }, {});
40
+
41
+ // Set components
42
+ Object.keys(strapi.components).forEach((componentName) => {
43
+ const component = strapi.components[componentName];
44
+ component.connection = component.connection || defaultConnection;
45
+ });
46
+
47
+ // Set controllers.
48
+ strapi.controllers = Object.keys(strapi.api || []).reduce((acc, key) => {
49
+ for (let index in strapi.api[key].controllers) {
50
+ let controller = strapi.api[key].controllers[index];
51
+ controller.identity = controller.identity || _.upperFirst(index);
52
+ acc[index] = controller;
53
+ }
54
+
55
+ return acc;
56
+ }, {});
57
+
58
+ // Set services.
59
+ strapi.services = Object.keys(strapi.api || []).reduce((acc, key) => {
60
+ for (let index in strapi.api[key].services) {
61
+ acc[index] = strapi.api[key].services[index];
62
+ }
63
+
64
+ return acc;
65
+ }, {});
66
+
67
+ // Set routes.
68
+ strapi.config.routes = Object.keys(strapi.api || []).reduce((acc, key) => {
69
+ return acc.concat(_.get(strapi.api[key], 'config.routes') || {});
70
+ }, []);
71
+
72
+ // Init admin controllers.
73
+ Object.keys(strapi.admin.controllers || []).forEach((key) => {
74
+ if (!strapi.admin.controllers[key].identity) {
75
+ strapi.admin.controllers[key].identity = key;
76
+ }
77
+ });
78
+
79
+ // Init admin models.
80
+ Object.keys(strapi.admin.models || []).forEach((modelName) => {
81
+ let model = strapi.admin.models[modelName];
82
+
83
+ // mutate model
84
+ contentTypesUtils.createContentType(model, { modelName, defaultConnection });
85
+
86
+ strapi.contentTypes[model.uid] = model;
87
+ });
88
+
89
+ Object.keys(strapi.plugins).forEach((pluginName) => {
90
+ let plugin = strapi.plugins[pluginName];
91
+ Object.assign(plugin, {
92
+ controllers: plugin.controllers || [],
93
+ services: plugin.services || [],
94
+ models: plugin.models || [],
95
+ });
96
+
97
+ Object.keys(plugin.controllers).forEach((key) => {
98
+ let controller = plugin.controllers[key];
99
+
100
+ Object.assign(controller, {
101
+ identity: controller.identity || key,
102
+ });
103
+ });
104
+
105
+ Object.keys(plugin.models || []).forEach((modelName) => {
106
+ let model = plugin.models[modelName];
107
+
108
+ // mutate model
109
+ contentTypesUtils.createContentType(model, { modelName, defaultConnection }, { pluginName });
110
+
111
+ strapi.contentTypes[model.uid] = model;
112
+ });
113
+ });
114
+
115
+ // Preset config in alphabetical order.
116
+ strapi.config.middleware.settings = Object.keys(strapi.middleware).reduce((acc, current) => {
117
+ // Try to find the settings in the current environment, then in the main configurations.
118
+ const currentSettings = _.merge(
119
+ _.cloneDeep(_.get(strapi.middleware[current], ['defaults', current], {})),
120
+ strapi.config.get(['middleware', 'settings', current], {})
121
+ );
122
+
123
+ acc[current] = !_.isObject(currentSettings) ? {} : currentSettings;
124
+
125
+ // Ensure that enabled key exist by forcing to false.
126
+ _.defaults(acc[current], { enabled: false });
127
+
128
+ return acc;
129
+ }, {});
130
+
131
+ strapi.config.hook.settings = Object.keys(strapi.hook).reduce((acc, current) => {
132
+ // Try to find the settings in the current environment, then in the main configurations.
133
+ const currentSettings = _.merge(
134
+ _.cloneDeep(_.get(strapi.hook[current], ['defaults', current], {})),
135
+ strapi.config.get(['hook', 'settings', current], {})
136
+ );
137
+
138
+ acc[current] = !_.isObject(currentSettings) ? {} : currentSettings;
139
+
140
+ // Ensure that enabled key exist by forcing to false.
141
+ _.defaults(acc[current], { enabled: false });
142
+
143
+ return acc;
144
+ }, {});
145
+
146
+ // default settings
147
+ strapi.config.port = strapi.config.get('server.port') || strapi.config.port;
148
+ strapi.config.host = strapi.config.get('server.host') || strapi.config.host;
149
+
150
+ const { serverUrl, adminUrl, adminPath } = getConfigUrls(strapi.config.get('server'));
151
+
152
+ strapi.config.server = strapi.config.server || {};
153
+ strapi.config.server.url = serverUrl;
154
+ strapi.config.admin.url = adminUrl;
155
+ strapi.config.admin.path = adminPath;
156
+
157
+ // check if we should serve admin panel
158
+ const shouldServeAdmin = strapi.config.get(
159
+ 'server.admin.serveAdminPanel',
160
+ strapi.config.serveAdminPanel
161
+ );
162
+
163
+ if (!shouldServeAdmin) {
164
+ strapi.config.serveAdminPanel = false;
165
+ }
166
+ };
package/lib/core/fs.js ADDED
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fse = require('fs-extra');
5
+
6
+ /**
7
+ * create strapi fs layer
8
+ */
9
+ module.exports = strapi => {
10
+ function normalizePath(optPath) {
11
+ const filePath = Array.isArray(optPath) ? optPath.join('/') : optPath;
12
+
13
+ const normalizedPath = path.normalize(filePath).replace(/^(\/?\.\.?)+/, '');
14
+
15
+ return path.join(strapi.dir, normalizedPath);
16
+ }
17
+
18
+ const strapiFS = {
19
+ /**
20
+ * Writes a file in a strapi app
21
+ * @param {Array|string} optPath - file path
22
+ * @param {string} data - content
23
+ */
24
+ writeAppFile(optPath, data) {
25
+ const writePath = normalizePath(optPath);
26
+ return fse
27
+ .ensureFile(writePath)
28
+ .then(() => fse.writeFile(writePath, data));
29
+ },
30
+
31
+ /**
32
+ * Writes a file in a plugin extensions folder
33
+ * @param {string} plugin - plugin name
34
+ * @param {Array|string} optPath - path to file
35
+ * @param {string} data - content
36
+ */
37
+ writePluginFile(plugin, optPath, data) {
38
+ const newPath = ['extensions', plugin].concat(optPath).join('/');
39
+ return strapiFS.writeAppFile(newPath, data);
40
+ },
41
+
42
+ /**
43
+ * Removes a file in strapi app
44
+ */
45
+ removeAppFile(optPath) {
46
+ const removePath = normalizePath(optPath);
47
+ return fse.remove(removePath);
48
+ },
49
+ };
50
+
51
+ return strapiFS;
52
+ };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const loadApis = require('./load-apis');
4
+ const loadAdmin = require('./load-admin');
5
+ const loadPlugins = require('./load-plugins');
6
+ const loadMiddlewares = require('./load-middlewares');
7
+ const loadExtensions = require('./load-extensions');
8
+ const loadHooks = require('./load-hooks');
9
+ const bootstrap = require('./bootstrap');
10
+ const loadComponents = require('./load-components');
11
+
12
+ module.exports = {
13
+ loadApis,
14
+ loadAdmin,
15
+ loadPlugins,
16
+ loadMiddlewares,
17
+ loadHooks,
18
+ loadExtensions,
19
+ loadComponents,
20
+ bootstrap,
21
+ };
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ const findPackagePath = require('../load/package-path');
6
+ const loadFiles = require('../load/load-files');
7
+ const loadConfig = require('../load/load-config-files');
8
+
9
+ const mergeRoutes = (a, b, key) =>
10
+ _.isArray(a) && _.isArray(b) && key === 'routes' ? a.concat(b) : undefined;
11
+
12
+ module.exports = async strapi => {
13
+ const adminPath = findPackagePath('strapi-admin');
14
+ const [files, config] = await Promise.all([
15
+ loadFiles(adminPath, '!(config|node_modules|tests|ee|scripts)/*.*(js|json)'),
16
+ loadConfig(adminPath),
17
+ ]);
18
+
19
+ // set admin config in strapi.config.server.admin
20
+ const userAdminConfig = strapi.config.get('server.admin');
21
+ strapi.config.set('server.admin', _.merge(config.config, userAdminConfig));
22
+
23
+ // load ee files if they exist
24
+ let eeFiles = {};
25
+ let eeConfig = {};
26
+
27
+ if (process.env.STRAPI_DISABLE_EE !== 'true' && strapi.EE) {
28
+ const eeAdminPath = `${adminPath}/ee`;
29
+ [eeFiles, eeConfig] = await Promise.all([
30
+ loadFiles(eeAdminPath, '!(config|tests|test)/*.*(js|json)'),
31
+ loadConfig(eeAdminPath),
32
+ ]);
33
+ }
34
+
35
+ return _.mergeWith({}, files, eeFiles, config, eeConfig, mergeRoutes);
36
+ };
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const { join } = require('path');
4
+ const { existsSync } = require('fs-extra');
5
+ const _ = require('lodash');
6
+ const loadFiles = require('../load/load-files');
7
+ const loadConfig = require('../load/load-config-files');
8
+
9
+ module.exports = async ({ dir }) => {
10
+ const apiDir = join(dir, 'api');
11
+
12
+ if (!existsSync(apiDir)) {
13
+ throw new Error(
14
+ `Missing api folder. Please create one in your app root directory`
15
+ );
16
+ }
17
+
18
+ const apis = await loadFiles(apiDir, '*/!(config)/**/*.*(js|json)');
19
+ const apiConfigs = await loadConfig(apiDir, '*/config/**/*.*(js|json)');
20
+
21
+ return _.merge(apis, apiConfigs);
22
+ };
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ const { join } = require('path');
4
+ const _ = require('lodash');
5
+ const { exists } = require('fs-extra');
6
+ const loadFiles = require('../load/load-files');
7
+
8
+ module.exports = async strapi => {
9
+ const componentsDir = join(strapi.dir, 'components');
10
+
11
+ if (!(await exists(componentsDir))) {
12
+ return {};
13
+ }
14
+
15
+ const map = await loadFiles(componentsDir, '*/*.*(js|json)');
16
+
17
+ return Object.keys(map).reduce((acc, category) => {
18
+ Object.keys(map[category]).forEach(key => {
19
+ const schema = map[category][key];
20
+
21
+ const filePath = join(componentsDir, category, schema.__filename__);
22
+
23
+ if (!schema.collectionName) {
24
+ return strapi.stopWithError(
25
+ `Component ${key} is missing a "collectionName" property.\nVerify file ${filePath}.`
26
+ );
27
+ }
28
+
29
+ const uid = `${category}.${key}`;
30
+
31
+ acc[uid] = Object.assign(schema, {
32
+ __schema__: _.cloneDeep(schema),
33
+ uid,
34
+ category,
35
+ modelType: 'component',
36
+ modelName: key,
37
+ globalId: schema.globalId || _.upperFirst(_.camelCase(`component_${uid}`)),
38
+ });
39
+ });
40
+
41
+ return acc;
42
+ }, {});
43
+ };
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const { existsSync } = require('fs-extra');
5
+ const fse = require('fs-extra');
6
+ const _ = require('lodash');
7
+ const loadConfig = require('../load/load-config-files');
8
+ const loadFiles = require('../load/load-files');
9
+ const glob = require('../load/glob');
10
+ const filePathToPath = require('../load/filepath-to-prop-path');
11
+
12
+ /**
13
+ * Loads the extensions folder
14
+ */
15
+ module.exports = async function({ appPath }) {
16
+ const extensionsDir = path.resolve(appPath, 'extensions');
17
+
18
+ if (!existsSync(extensionsDir)) {
19
+ throw new Error(`Missing extensions folder. Please create one in your app root directory`);
20
+ }
21
+
22
+ const configs = await loadConfig(extensionsDir, '*/config/**/*.+(js|json)');
23
+ const controllersAndServices = await loadFiles(
24
+ extensionsDir,
25
+ '*/{controllers,services}/*.+(js|json)'
26
+ );
27
+
28
+ const overwrites = await loadOverwrites(extensionsDir);
29
+
30
+ return {
31
+ overwrites,
32
+ merges: _.merge({}, configs, controllersAndServices),
33
+ };
34
+ };
35
+
36
+ const OVERWRITABLE_FOLDERS_GLOB = 'models';
37
+ // returns a list of path and module to overwrite
38
+ const loadOverwrites = async extensionsDir => {
39
+ const files = await glob(`*/${OVERWRITABLE_FOLDERS_GLOB}/*.*(js|json)`, {
40
+ cwd: extensionsDir,
41
+ });
42
+
43
+ const overwrites = {};
44
+ files.forEach(file => {
45
+ const absolutePath = path.resolve(extensionsDir, file);
46
+
47
+ // load module
48
+ delete require.cache[absolutePath];
49
+ let mod;
50
+
51
+ if (path.extname(absolutePath) === '.json') {
52
+ mod = fse.readJsonSync(absolutePath);
53
+ } else {
54
+ mod = require(absolutePath);
55
+ }
56
+
57
+ const propPath = filePathToPath(file);
58
+ const strPath = propPath.join('.');
59
+
60
+ if (overwrites[strPath]) {
61
+ _.merge(overwrites[strPath], mod);
62
+ } else {
63
+ overwrites[strPath] = mod;
64
+ }
65
+ });
66
+
67
+ return Object.keys(overwrites).map(strPath => ({
68
+ path: strPath.split('.'),
69
+ mod: overwrites[strPath],
70
+ }));
71
+ };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const fse = require('fs-extra');
4
+
5
+ const walk = require('./walk');
6
+
7
+ const loadFunctions = dir => {
8
+ if (!fse.existsSync(dir)) return {};
9
+
10
+ return walk(dir, { loader: loadFunction });
11
+ };
12
+
13
+ const loadFunction = file => {
14
+ try {
15
+ return require(file);
16
+ } catch (error) {
17
+ throw `Could not load function ${file}: ${error.message}`;
18
+ }
19
+ };
20
+
21
+ module.exports = loadFunctions;