Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const path = require('path');
const fs = require('fs');
const { templateConfiguration, env } = require('@strapi/utils');
const jiti = require('jiti')(__dirname);

const loadJsFile = file => {
try {
Expand All @@ -19,6 +20,25 @@ const loadJsFile = file => {
}
};

const loadESModuleFile = file => {
try {
const esModule = jiti(file);

if (!esModule || !esModule.default) {
throw new Error(`The file has no default export`);
}

// call if function
if (typeof esModule.default === 'function') {
return esModule.default({ env });
}

return esModule.default;
} catch (error) {
throw new Error(`Could not load es/ts module config file ${file}: ${error.message}`);
}
};

const loadJSONFile = file => {
try {
return templateConfiguration(JSON.parse(fs.readFileSync(file)));
Expand All @@ -32,7 +52,11 @@ const loadFile = file => {

switch (ext) {
case '.js':
case '.cjs':
return loadJsFile(file);
case '.ts':
case '.mjs':
return loadESModuleFile(file);
case '.json':
return loadJSONFile(file);
default:
Expand Down
21 changes: 19 additions & 2 deletions packages/core/strapi/lib/core/loaders/apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { existsSync } = require('fs-extra');
const _ = require('lodash');
const fse = require('fs-extra');
const { isKebabCase } = require('@strapi/utils');
const jiti = require('jiti')(__dirname);

// to handle names with numbers in it we first check if it is already in kebabCase
const normalizeName = name => (isKebabCase(name) ? name : _.kebabCase(name));
Expand Down Expand Up @@ -97,8 +98,10 @@ const loadAPI = async dir => {
};

const loadIndex = async dir => {
if (await fse.pathExists(join(dir, 'index.js'))) {
return loadFile(join(dir, 'index.js'));
for (const file of ['index.js', 'index.ts', 'index.mjs', 'index.cjs']) {
if (await fse.pathExists(join(dir, file))) {
return loadFile(join(dir, file));
}
}
};

Expand Down Expand Up @@ -150,7 +153,21 @@ const loadFile = file => {

switch (ext) {
case '.js':
case '.cjs':
return require(file);
case '.ts':
case '.mjs':
try {
const esModule = jiti(file);

if (!esModule || !esModule.default) {
throw new Error(`The file has no default export`);
}

return esModule.default;
} catch (error) {
throw new Error(`Could not load es/ts module config file ${file}: ${error.message}`);
}
case '.json':
return fse.readJSON(file);
default:
Expand Down
2 changes: 1 addition & 1 deletion packages/core/strapi/lib/core/loaders/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = async strapi => {
return {};
}

const map = await loadFiles(strapi.dirs.components, '*/*.*(js|json)');
const map = await loadFiles(strapi.dirs.components, '*/*.*(js|ts|cjs|mjs|json)');

return Object.keys(map).reduce((acc, category) => {
Object.keys(map[category]).forEach(key => {
Expand Down
28 changes: 25 additions & 3 deletions packages/core/strapi/lib/core/loaders/middlewares.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { join, extname, basename } = require('path');
const fse = require('fs-extra');
const jiti = require('jiti')(__dirname);

// TODO:: allow folders with index.js inside for bigger policies
module.exports = async function loadMiddlewares(strapi) {
Expand All @@ -26,9 +27,30 @@ const loadLocalMiddlewares = async strapi => {
const { name } = fd;
const fullPath = join(dir, name);

if (fd.isFile() && extname(name) === '.js') {
const key = basename(name, '.js');
middlewares[key] = require(fullPath);
if (fd.isFile()) {
const ext = extname(name);
switch (ext) {
case '.js':
case '.cjs':
middlewares[basename(name, ext)] = require(fullPath);
break;
case '.mjs':
case '.ts':
try {
const esModule = jiti(fullPath);

if (!esModule || !esModule.default) {
throw new Error(`The file has no default export`);
}

middlewares[basename(name, ext)] = esModule.default;
} catch (error) {
throw new Error(
`Could not load es/ts module middleware file ${fullPath}: ${error.message}`
);
}
break;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,24 @@ const loadConfigFile = require('../../app-configuration/load-config-file');
* @return {Promise<{}>}
*/
const getUserPluginsConfig = async () => {
const globalUserConfigPath = join(strapi.dirs.config, 'plugins.js');
const currentEnvUserConfigPath = join(
strapi.dirs.config,
'env',
process.env.NODE_ENV,
'plugins.js'
);
let config = {};

// assign global user config if exists
if (await fse.pathExists(globalUserConfigPath)) {
config = loadConfigFile(globalUserConfigPath);
for (const file of ['plugins.js', 'plugins.ts', 'plugins.mjs', 'plugins.cjs']) {
const filepath = join(strapi.dirs.config, file);
if (await fse.pathExists(filepath)) {
config = loadConfigFile(filepath);
break;
}
}

// and merge user config by environment if exists
if (await fse.pathExists(currentEnvUserConfigPath)) {
config = merge(config, loadConfigFile(currentEnvUserConfigPath));
for (const file of ['plugins.js', 'plugins.ts', 'plugins.mjs', 'plugins.cjs']) {
let filepath = join(strapi.dirs.config, 'env', process.env.NODE_ENV, file);
if (await fse.pathExists(filepath)) {
config = merge(config, loadConfigFile(filepath));
break;
}
}

return config;
Expand Down
24 changes: 16 additions & 8 deletions packages/core/strapi/lib/core/loaders/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const applyUserExtension = async plugins => {
}

const extendedSchemas = await loadFiles(extensionsDir, '**/content-types/**/schema.json');
const strapiServers = await loadFiles(extensionsDir, '**/strapi-server.js');
const strapiServers = await loadFiles(extensionsDir, '**/strapi-server.(js|ts|cjs|mjs)');

for (const pluginName in plugins) {
const plugin = plugins[pluginName];
Expand Down Expand Up @@ -86,15 +86,23 @@ const loadPlugins = async strapi => {
for (const pluginName in enabledPlugins) {
const enabledPlugin = enabledPlugins[pluginName];

const serverEntrypointPath = join(enabledPlugin.pathToPlugin, 'strapi-server.js');
for (const file of [
'strapi-server.js',
'strapi-server.ts',
'strapi-server.mjs',
'strapi-server.cjs',
]) {
const serverEntrypointPath = join(enabledPlugin.pathToPlugin, file);

// only load plugins with a server entrypoint
if (!(await fse.pathExists(serverEntrypointPath))) {
continue;
}

// only load plugins with a server entrypoint
if (!(await fse.pathExists(serverEntrypointPath))) {
continue;
const pluginServer = loadConfigFile(serverEntrypointPath);
plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
break;
}

const pluginServer = loadConfigFile(serverEntrypointPath);
plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
}

// TODO: validate plugin format
Expand Down
26 changes: 23 additions & 3 deletions packages/core/strapi/lib/core/loaders/policies.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { join, extname, basename } = require('path');
const fse = require('fs-extra');
const jiti = require('jiti')(__dirname);

// TODO:: allow folders with index.js inside for bigger policies
module.exports = async function loadPolicies(strapi) {
Expand All @@ -18,9 +19,28 @@ module.exports = async function loadPolicies(strapi) {
const { name } = fd;
const fullPath = join(dir, name);

if (fd.isFile() && extname(name) === '.js') {
const key = basename(name, '.js');
policies[key] = require(fullPath);
if (fd.isFile()) {
const ext = extname(name);
switch (ext) {
case '.js':
case '.cjs':
policies[basename(name, ext)] = require(fullPath);
break;
case '.mjs':
case '.ts':
try {
const esModule = jiti(fullPath);

if (!esModule || !esModule.default) {
throw new Error(`The file has no default export`);
}

policies[basename(name, ext)] = esModule.default;
} catch (error) {
throw new Error(`Could not load es/ts module policy ${fullPath}: ${error.message}`);
}
break;
}
}
}

Expand Down
47 changes: 36 additions & 11 deletions packages/core/strapi/lib/core/loaders/src-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const { resolve } = require('path');
const { statSync, existsSync } = require('fs');
const { yup } = require('@strapi/utils');
const jiti = require('jiti')(__dirname);

const srcSchema = yup
.object()
Expand All @@ -22,18 +23,42 @@ module.exports = strapi => {
throw new Error('Missing src folder. Please create one at `./src`');
}

const pathToSrcIndex = resolve(strapi.dirs.src, 'index.js');
if (!existsSync(pathToSrcIndex) || statSync(pathToSrcIndex).isDirectory()) {
return {};
}
for (const ext of ['.js', '.ts', '.mjs', '.cjs']) {
const file = `index${ext}`;
const pathToSrcIndex = resolve(strapi.dirs.src, file);
if (!existsSync(pathToSrcIndex) || statSync(pathToSrcIndex).isDirectory()) {
continue;
}

const srcIndex = require(pathToSrcIndex);
let srcIndex;
switch (ext) {
case '.js':
case '.cjs':
srcIndex = require(pathToSrcIndex);
break;
case '.mjs':
case '.ts':
try {
const esModule = jiti(pathToSrcIndex);

try {
validateSrcIndex(srcIndex);
} catch (e) {
strapi.stopWithError({ message: `Invalid file \`./src/index.js\`: ${e.message}` });
}
if (!esModule || !esModule.default) {
throw new Error(`The file has no default export`);
}

srcIndex = esModule.default;
} catch (error) {
throw new Error(`Could not load es/ts module index ${pathToSrcIndex}: ${error.message}`);
}
break;
}

return srcIndex;
try {
validateSrcIndex(srcIndex);
} catch (e) {
strapi.stopWithError({ message: `Invalid file \`./src/index.js\`: ${e.message}` });
}

return srcIndex;
}
return {};
};
6 changes: 3 additions & 3 deletions packages/core/strapi/lib/factories.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ interface Router {
routes: Route[];
}

export function createCoreRouter(uid: string, cfg: RouterConfig): () => Router;
export function createCoreController(uid: string, cfg: ControllerConfig): () => Controller;
export function createCoreService(uid: string, cfg: ServiceConfig): () => Service;
export function createCoreRouter(uid: string, cfg?: Partial<RouterConfig>): () => Router;
export function createCoreController(uid: string, cfg?: Partial<ControllerConfig>): () => Controller;
export function createCoreService(uid: string, cfg?: Partial<ServiceConfig>): () => Service;
2 changes: 1 addition & 1 deletion packages/core/strapi/lib/load/filepath-to-prop-path.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = (filePath, useFileNameAsKey = true) => {
let cleanPath = filePath.startsWith('./') ? filePath.slice(2) : filePath;

const prop = cleanPath
.replace(/(\.settings|\.json|\.js)/g, '')
.replace(/(\.settings|\.json|\.js|\.cjs|\.mjs|\.ts)/g, '')
.toLowerCase()
.split('/')
.map(p => _.trimStart(p, '.'))
Expand Down
28 changes: 24 additions & 4 deletions packages/core/strapi/lib/load/load-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const path = require('path');
const _ = require('lodash');
const fse = require('fs-extra');
const jiti = require('jiti')(__dirname);
const glob = require('./glob');
const filePathToPath = require('./filepath-to-prop-path');

Expand All @@ -26,15 +27,34 @@ const loadFiles = async (

for (let file of files) {
const absolutePath = path.resolve(dir, file);
const ext = path.extname(absolutePath);

// load module
delete require.cache[absolutePath];
let mod;

if (path.extname(absolutePath) === '.json') {
mod = await fse.readJson(absolutePath);
} else {
mod = requireFn(absolutePath);
switch (ext) {
case '.js':
case '.cjs':
mod = requireFn(absolutePath);
break;
case '.ts':
case '.mjs':
try {
const esModule = jiti(absolutePath);

if (!esModule || !esModule.default) {
throw new Error(`The file has no default export`);
}

mod = esModule.default;
} catch (error) {
throw new Error(`Could not load es/ts module config file ${file}: ${error.message}`);
}
break;
case '.json':
mod = await fse.readJson(absolutePath);
break;
}

Object.defineProperty(mod, '__filename__', {
Expand Down
1 change: 1 addition & 0 deletions packages/core/strapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"dotenv": "10.0.0",
"execa": "5.1.1",
"fs-extra": "10.0.0",
"jiti": "1.12.15",
"glob": "7.2.0",
"http-errors": "1.8.0",
"inquirer": "8.2.0",
Expand Down
Loading