mirror of
https://github.com/strapi/strapi.git
synced 2025-11-08 14:19:40 +00:00
Migrate latest to ts
This commit is contained in:
parent
c779954631
commit
ddaa9e6775
@ -0,0 +1,14 @@
|
|||||||
|
import type { Utils } from '@strapi/strapi';
|
||||||
|
|
||||||
|
const expectExit = async (code: number, fn: Utils.Function.Any) => {
|
||||||
|
const exit = jest.spyOn(process, 'exit').mockImplementation((number) => {
|
||||||
|
throw new Error(`process.exit: ${number}`);
|
||||||
|
});
|
||||||
|
await expect(async () => {
|
||||||
|
await fn();
|
||||||
|
}).rejects.toThrow('process.exit');
|
||||||
|
expect(exit).toHaveBeenCalledWith(code);
|
||||||
|
exit.mockRestore();
|
||||||
|
};
|
||||||
|
|
||||||
|
export { expectExit };
|
||||||
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "testing",
|
|
||||||
"version": "0.0.0"
|
|
||||||
}
|
|
||||||
@ -1,509 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs/promises');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const {
|
|
||||||
loadPkg,
|
|
||||||
validatePkg,
|
|
||||||
validateExportsOrdering,
|
|
||||||
parseExports,
|
|
||||||
getExportExtensionMap,
|
|
||||||
} = require('../pkg');
|
|
||||||
|
|
||||||
const loggerMock = {
|
|
||||||
debug: jest.fn(),
|
|
||||||
info: jest.fn(),
|
|
||||||
warn: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('pkg', () => {
|
|
||||||
const tmpfolder = path.resolve(__dirname, '.tmp');
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.resetAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('loadPkg', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await fs.mkdir(tmpfolder);
|
|
||||||
await fs.copyFile(
|
|
||||||
path.resolve(__dirname, 'fixtures', 'test.pkg.json'),
|
|
||||||
path.resolve(tmpfolder, 'package.json')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
await fs.rm(tmpfolder, { recursive: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should succesfully load the package.json closest to the cwd provided & call the debug logger', async () => {
|
|
||||||
const pkg = await loadPkg({ cwd: tmpfolder, logger: loggerMock });
|
|
||||||
|
|
||||||
expect(pkg).toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"name": "testing",
|
|
||||||
"version": "0.0.0",
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
expect(loggerMock.debug).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if it cannot find a package.json', async () => {
|
|
||||||
await expect(
|
|
||||||
loadPkg({ cwd: '/', logger: loggerMock })
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"Could not find a package.json in the current directory"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('validatePkg', () => {
|
|
||||||
it("should return the validated package.json if it's valid", async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
};
|
|
||||||
|
|
||||||
const validatedPkg = await validatePkg({ pkg });
|
|
||||||
|
|
||||||
expect(validatedPkg).toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"name": "testing",
|
|
||||||
"version": "0.0.0",
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail if a required field is missing and call the error logger with the correct message', async () => {
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
version: '0.0.0',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'name' in 'package.json' is required as type '[35mstring[39m'"`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
name: 'testing',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'version' in 'package.json' is required as type '[35mstring[39m'"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail if a required field does not match the correct type and call the error logger with the correct message', async () => {
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
name: 'testing',
|
|
||||||
version: 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'version' in 'package.json' must be of type '[35mstring[39m' (recieved '[35mnumber[39m')"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should fail if the regex for a field doesn't match and call the error logger with the correct message", async () => {
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: {
|
|
||||||
apple: './apple.xyzx',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'exports.apple' in 'package.json' must be of type '[35m/^\\.\\/.*\\.json$/[39m' (recieved the value '[35m./apple.xyzx[39m')"`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
type: 'something',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'type' in 'package.json' must be of type '[35m/(commonjs|module)/[39m' (recieved the value '[35msomething[39m')"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail if the exports object does not match expectations', async () => {
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: 'hello',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'exports' in 'package.json' must be of type '[35mobject[39m' (recieved '[35mstring[39m')"`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
validatePkg({
|
|
||||||
pkg: {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
import: './admin/index.js',
|
|
||||||
something: 'xyz',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'exports["./admin"]' in 'package.json' contains the unknown key [35msomething[39m, for compatability only the following keys are allowed: [35m['types', 'source', 'import', 'require', 'default'][39m"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('validateExportsOrdering', () => {
|
|
||||||
it('should throw if there are no exports at all and log that error', async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
};
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
validateExportsOrdering({ pkg, logger: loggerMock })
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"'package.json' must contain a 'main' and 'module' property"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return the package if there is at least a 'main' or 'module' property", async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
main: './index.js',
|
|
||||||
};
|
|
||||||
|
|
||||||
const validatedPkg = await validateExportsOrdering({ pkg, logger: loggerMock });
|
|
||||||
|
|
||||||
expect(validatedPkg).toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"main": "./index.js",
|
|
||||||
"name": "testing",
|
|
||||||
"version": "0.0.0",
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the package if there is an exports property with a valid structure', async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.js',
|
|
||||||
require: './admin/index.cjs',
|
|
||||||
default: './admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const validatedPkg = await validateExportsOrdering({ pkg, logger: loggerMock });
|
|
||||||
|
|
||||||
expect(validatedPkg).toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"exports": {
|
|
||||||
"./admin": {
|
|
||||||
"default": "./admin/index.js",
|
|
||||||
"import": "./admin/index.js",
|
|
||||||
"require": "./admin/index.cjs",
|
|
||||||
"types": "./admin/index.d.ts",
|
|
||||||
},
|
|
||||||
"./package.json": "./package.json",
|
|
||||||
},
|
|
||||||
"name": "testing",
|
|
||||||
"version": "0.0.0",
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if the types property is not the first in an export object', async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: {
|
|
||||||
'./admin': {
|
|
||||||
import: './admin/index.js',
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
validateExportsOrdering({ pkg, logger: loggerMock })
|
|
||||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"exports["./admin"]: the 'types' property should be the first property"`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log a warning if the require property comes before the import property in an export object', async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: {
|
|
||||||
'./admin': {
|
|
||||||
require: './admin/index.cjs',
|
|
||||||
import: './admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await validateExportsOrdering({ pkg, logger: loggerMock });
|
|
||||||
|
|
||||||
expect(loggerMock.warn.mock.calls[0]).toMatchInlineSnapshot(`
|
|
||||||
[
|
|
||||||
"exports["./admin"]: the 'import' property should come before the 'require' property",
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log a warning if the import property comes the module property in an export object', async () => {
|
|
||||||
const pkg = {
|
|
||||||
name: 'testing',
|
|
||||||
version: '0.0.0',
|
|
||||||
exports: {
|
|
||||||
'./admin': {
|
|
||||||
import: './admin/index.js',
|
|
||||||
module: './admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await validateExportsOrdering({ pkg, logger: loggerMock });
|
|
||||||
|
|
||||||
expect(loggerMock.warn.mock.calls[0]).toMatchInlineSnapshot(`
|
|
||||||
[
|
|
||||||
"exports["./admin"]: the 'module' property should come before 'import' property",
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getExportExtensionMap', () => {
|
|
||||||
it('should just return the default mapping', async () => {
|
|
||||||
expect(getExportExtensionMap()).toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"commonjs": {
|
|
||||||
"cjs": ".js",
|
|
||||||
"es": ".mjs",
|
|
||||||
},
|
|
||||||
"module": {
|
|
||||||
"cjs": ".cjs",
|
|
||||||
"es": ".js",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parseExports', () => {
|
|
||||||
const extMap = getExportExtensionMap();
|
|
||||||
|
|
||||||
it('should by default return a root exports map using the standard export fields from the pkg.json', () => {
|
|
||||||
const pkg = {
|
|
||||||
types: './dist/index.d.ts',
|
|
||||||
main: './dist/index.js',
|
|
||||||
module: './dist/index.mjs',
|
|
||||||
source: './src/index.ts',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(parseExports({ pkg, extMap })).toMatchInlineSnapshot(`
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"_path": ".",
|
|
||||||
"default": "./dist/index.mjs",
|
|
||||||
"import": "./dist/index.mjs",
|
|
||||||
"require": "./dist/index.js",
|
|
||||||
"source": "./src/index.ts",
|
|
||||||
"types": "./dist/index.d.ts",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should not return anything if the standard export fields don't exist and there is no export map", () => {
|
|
||||||
const pkg = {};
|
|
||||||
|
|
||||||
expect(parseExports({ pkg, extMap })).toMatchInlineSnapshot(`[]`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a combination of the standard export fields and the export map if they both exist', () => {
|
|
||||||
const pkg = {
|
|
||||||
types: './dist/index.d.ts',
|
|
||||||
main: './dist/index.js',
|
|
||||||
module: './dist/index.mjs',
|
|
||||||
source: './src/index.ts',
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.mjs',
|
|
||||||
require: './admin/index.js',
|
|
||||||
default: './admin/index.js',
|
|
||||||
source: './src/admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(parseExports({ pkg, extMap })).toMatchInlineSnapshot(`
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"_path": ".",
|
|
||||||
"default": "./dist/index.mjs",
|
|
||||||
"import": "./dist/index.mjs",
|
|
||||||
"require": "./dist/index.js",
|
|
||||||
"source": "./src/index.ts",
|
|
||||||
"types": "./dist/index.d.ts",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_exported": true,
|
|
||||||
"_path": "./admin",
|
|
||||||
"default": "./admin/index.js",
|
|
||||||
"import": "./admin/index.mjs",
|
|
||||||
"require": "./admin/index.js",
|
|
||||||
"source": "./src/admin/index.js",
|
|
||||||
"types": "./admin/index.d.ts",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return just the exports map if there are no standard export fields and the export map exists', () => {
|
|
||||||
const pkg = {
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.mjs',
|
|
||||||
require: './admin/index.js',
|
|
||||||
default: './admin/index.js',
|
|
||||||
source: './src/admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(parseExports({ pkg, extMap })).toMatchInlineSnapshot(`
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"_exported": true,
|
|
||||||
"_path": "./admin",
|
|
||||||
"default": "./admin/index.js",
|
|
||||||
"import": "./admin/index.mjs",
|
|
||||||
"require": "./admin/index.js",
|
|
||||||
"source": "./src/admin/index.js",
|
|
||||||
"types": "./admin/index.d.ts",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if you try to use an exports map without supplying an export for the package.json file', () => {
|
|
||||||
const pkg = {
|
|
||||||
exports: {
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.mjs',
|
|
||||||
require: './admin/index.js',
|
|
||||||
default: './admin/index.js',
|
|
||||||
source: './src/admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() => parseExports({ pkg, extMap })).toThrowErrorMatchingInlineSnapshot(`
|
|
||||||
"
|
|
||||||
- package.json: \`exports["./package.json"] must be declared."
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if the pkg.json type is undefined and you try to export like a module', () => {
|
|
||||||
const pkg = {
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.js',
|
|
||||||
require: './admin/index.cjs',
|
|
||||||
default: './admin/index.cjs',
|
|
||||||
source: './src/admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() => parseExports({ pkg, extMap, type: 'module' }))
|
|
||||||
.toThrowErrorMatchingInlineSnapshot(`
|
|
||||||
"
|
|
||||||
- package.json with \`type: "undefined"\` - \`exports["./admin"].require\` must end with ".js"
|
|
||||||
- package.json with \`type: "undefined"\` - \`exports["./admin"].import\` must end with ".mjs""
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if the pkg.json type is commonjs and you try to export like a module', () => {
|
|
||||||
const pkg = {
|
|
||||||
type: 'commonjs',
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.js',
|
|
||||||
require: './admin/index.cjs',
|
|
||||||
default: './admin/index.cjs',
|
|
||||||
source: './src/admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() => parseExports({ pkg, extMap, type: 'module' }))
|
|
||||||
.toThrowErrorMatchingInlineSnapshot(`
|
|
||||||
"
|
|
||||||
- package.json with \`type: "commonjs"\` - \`exports["./admin"].require\` must end with ".js"
|
|
||||||
- package.json with \`type: "commonjs"\` - \`exports["./admin"].import\` must end with ".mjs""
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if the pkg.json type is module and you try to export like a commonjs', () => {
|
|
||||||
const pkg = {
|
|
||||||
type: 'module',
|
|
||||||
exports: {
|
|
||||||
'./package.json': './package.json',
|
|
||||||
'./admin': {
|
|
||||||
types: './admin/index.d.ts',
|
|
||||||
import: './admin/index.mjs',
|
|
||||||
require: './admin/index.js',
|
|
||||||
default: './admin/index.js',
|
|
||||||
source: './src/admin/index.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() => parseExports({ pkg, extMap, type: 'module' }))
|
|
||||||
.toThrowErrorMatchingInlineSnapshot(`
|
|
||||||
"
|
|
||||||
- package.json with \`type: "module"\` - \`exports["./admin"].require\` must end with ".cjs"
|
|
||||||
- package.json with \`type: "module"\` - \`exports["./admin"].import\` must end with ".js""
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { Command } = require('commander');
|
|
||||||
|
|
||||||
const strapiCommands = {
|
|
||||||
'admin/create-user': require('./actions/admin/create-user/command'),
|
|
||||||
'admin/reset-user-password': require('./actions/admin/reset-user-password/command'),
|
|
||||||
build: require('./actions/build-command/command'), // in 'build-command' to avoid problems with 'build' being commonly ignored
|
|
||||||
'components/list': require('./actions/components/list/command'),
|
|
||||||
'configuration/dump': require('./actions/configuration/dump/command'),
|
|
||||||
'configuration/restore': require('./actions/configuration/restore/command'),
|
|
||||||
console: require('./actions/console/command'),
|
|
||||||
'content-types/list': require('./actions/content-types/list/command'),
|
|
||||||
'controllers/list': require('./actions/controllers/list/command'),
|
|
||||||
develop: require('./actions/develop/command'),
|
|
||||||
export: require('./actions/export/command'),
|
|
||||||
generate: require('./actions/generate/command'),
|
|
||||||
'hooks/list': require('./actions/hooks/list/command'),
|
|
||||||
import: require('./actions/import/command'),
|
|
||||||
install: require('./actions/install/command'),
|
|
||||||
'middlewares/list': require('./actions/middlewares/list/command'),
|
|
||||||
new: require('./actions/new/command'),
|
|
||||||
'plugin/build': require('./actions/plugin/build-command/command'),
|
|
||||||
'policies/list': require('./actions/policies/list/command'),
|
|
||||||
report: require('./actions/report/command'),
|
|
||||||
'routes/list': require('./actions/routes/list/command'),
|
|
||||||
'services/list': require('./actions/services/list/command'),
|
|
||||||
start: require('./actions/start/command'),
|
|
||||||
'telemetry/disable': require('./actions/telemetry/disable/command'),
|
|
||||||
'telemetry/enable': require('./actions/telemetry/enable/command'),
|
|
||||||
'templates/generate': require('./actions/templates/generate/command'),
|
|
||||||
transfer: require('./actions/transfer/command'),
|
|
||||||
'ts/generate-types': require('./actions/ts/generate-types/command'),
|
|
||||||
uninstall: require('./actions/uninstall/command'),
|
|
||||||
version: require('./actions/version/command'),
|
|
||||||
'watch-admin': require('./actions/watch-admin/command'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildStrapiCommand = (argv, command = new Command()) => {
|
|
||||||
// Initial program setup
|
|
||||||
command.storeOptionsAsProperties(false).allowUnknownOption(true);
|
|
||||||
|
|
||||||
// Help command
|
|
||||||
command.helpOption('-h, --help', 'Display help for command');
|
|
||||||
command.addHelpCommand('help [command]', 'Display help for command');
|
|
||||||
|
|
||||||
// Load all commands
|
|
||||||
Object.keys(strapiCommands).forEach((name) => {
|
|
||||||
try {
|
|
||||||
// Add this command to the Commander command object
|
|
||||||
strapiCommands[name]({ command, argv });
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to load command ${name}`, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return command;
|
|
||||||
};
|
|
||||||
|
|
||||||
const runStrapiCommand = async (argv = process.argv, command = new Command()) => {
|
|
||||||
await buildStrapiCommand(argv, command).parseAsync(argv);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
runStrapiCommand,
|
|
||||||
buildStrapiCommand,
|
|
||||||
strapiCommands,
|
|
||||||
};
|
|
||||||
@ -1,453 +0,0 @@
|
|||||||
import type { Database } from '@strapi/database';
|
|
||||||
import type { Comomn, EntityService, Shared } from '@strapi/strapi';
|
|
||||||
|
|
||||||
// TODO move custom fields types to a separate file
|
|
||||||
interface CustomFieldServerOptions {
|
|
||||||
/**
|
|
||||||
* The name of the custom field
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the plugin creating the custom field
|
|
||||||
*/
|
|
||||||
pluginId?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The existing Strapi data type the custom field uses
|
|
||||||
*/
|
|
||||||
type: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Settings for the input size in the Admin UI
|
|
||||||
*/
|
|
||||||
inputSize?: {
|
|
||||||
default: 4 | 6 | 8 | 12;
|
|
||||||
isResizable: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CustomFields {
|
|
||||||
register: (customFields: CustomFieldServerOptions[] | CustomFieldServerOptions) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Strapi interface implemented by the main Strapi class.
|
|
||||||
*/
|
|
||||||
export interface Strapi {
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi enterprise edition configuration
|
|
||||||
*/
|
|
||||||
readonly EE: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi configuration container
|
|
||||||
*/
|
|
||||||
readonly config: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi admin container
|
|
||||||
*/
|
|
||||||
readonly admin: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi auth container
|
|
||||||
*/
|
|
||||||
readonly auth: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi content API container
|
|
||||||
*/
|
|
||||||
readonly contentAPI: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi sanitizers container
|
|
||||||
*/
|
|
||||||
readonly sanitizers: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi validators container
|
|
||||||
*/
|
|
||||||
readonly validators: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi services container
|
|
||||||
*
|
|
||||||
* It returns all the registered services
|
|
||||||
*/
|
|
||||||
readonly services: Shared.Services;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a service using its unique identifier
|
|
||||||
*/
|
|
||||||
service<TService extends Common.Service = Common.Service>(uid: string): TService | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi controllers container
|
|
||||||
*
|
|
||||||
* It returns all the registered controllers
|
|
||||||
*/
|
|
||||||
readonly controllers: Shared.Controllers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a controller using its unique identifier
|
|
||||||
*/
|
|
||||||
controller<TContentTypeUID extends Common.UID.Controller>(
|
|
||||||
uid: TContentTypeUID
|
|
||||||
): Shared.Controllers[TContentTypeUID];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi content types container
|
|
||||||
*
|
|
||||||
* It returns all the registered content types
|
|
||||||
*/
|
|
||||||
readonly contentTypes: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a content type using its unique identifier
|
|
||||||
*/
|
|
||||||
contentType(uid: string): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi component container
|
|
||||||
*
|
|
||||||
* It returns all the registered components
|
|
||||||
*/
|
|
||||||
readonly components: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The custom fields registry
|
|
||||||
*
|
|
||||||
* It returns the custom fields interface
|
|
||||||
*/
|
|
||||||
readonly customFields: CustomFields;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi policies container
|
|
||||||
*
|
|
||||||
* It returns all the registered policies
|
|
||||||
*/
|
|
||||||
readonly policies: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a policy using its name
|
|
||||||
*/
|
|
||||||
policy(name: string): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi middlewares container
|
|
||||||
*
|
|
||||||
* It returns all the registered middlewares
|
|
||||||
*/
|
|
||||||
readonly middlewares: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a middleware using its name
|
|
||||||
*/
|
|
||||||
middleware(): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi plugins container
|
|
||||||
*
|
|
||||||
* It returns all the registered plugins
|
|
||||||
*/
|
|
||||||
readonly plugins: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a plugin using its name
|
|
||||||
*/
|
|
||||||
plugin(name: string): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi hooks container
|
|
||||||
*
|
|
||||||
* It returns all the registered hooks
|
|
||||||
*/
|
|
||||||
readonly hooks: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a hook using its name
|
|
||||||
*/
|
|
||||||
hook(): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Strapi APIs container
|
|
||||||
*
|
|
||||||
* It returns all the registered APIs
|
|
||||||
*/
|
|
||||||
readonly api: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strapi Register Lifecycle.
|
|
||||||
*
|
|
||||||
* - Load
|
|
||||||
* - The user application
|
|
||||||
* - The plugins
|
|
||||||
* - The admin
|
|
||||||
* - The APIs
|
|
||||||
* - The components
|
|
||||||
* - The middlewares
|
|
||||||
* - The policies
|
|
||||||
* - Trigger Strapi internal bootstrap
|
|
||||||
* - Create the webhooks runner
|
|
||||||
* - Create the internal hooks registry.
|
|
||||||
* - Init the telemetry cron job and middleware
|
|
||||||
* - Run all the `register` lifecycle methods loaded by the user application or the enabled plugins
|
|
||||||
*/
|
|
||||||
register(): Promise<Strapi>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bootstraping phase.
|
|
||||||
*
|
|
||||||
* - Load all the content types
|
|
||||||
* - Initialize the database layer
|
|
||||||
* - Initialize the entity service
|
|
||||||
* - Run the schemas/database synchronization
|
|
||||||
* - Start the webhooks and initializing middlewares and routes
|
|
||||||
* - Run all the `bootstrap` lifecycle methods loaded by the
|
|
||||||
* user application or the enabled plugins
|
|
||||||
*/
|
|
||||||
bootstrap(): Promise<Strapi>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy phase
|
|
||||||
*
|
|
||||||
* - Destroy Strapi server
|
|
||||||
* - Run all the `destroy` lifecycle methods loaded by the
|
|
||||||
* user application or the enabled plugins
|
|
||||||
* - Cleanup the event hub
|
|
||||||
* - Gracefully stop the database
|
|
||||||
* - Stop the telemetry and cron instance
|
|
||||||
* - Cleanup the global scope by removing global.strapi
|
|
||||||
*/
|
|
||||||
destroy(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all functions registered for a given lifecycle. (Strapi core, user app, plugins)
|
|
||||||
*/
|
|
||||||
runLifecyclesFunctions<T extends Lifecycles[keyof Lifecycles]>(lifecycleName: T): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the application if needed and start the server
|
|
||||||
*/
|
|
||||||
start(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the server and provide a custom error and message
|
|
||||||
*/
|
|
||||||
stopWithError<TError = unknown>(error: TError, customMessage?: string): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gracefully stop the server
|
|
||||||
* Call the destroy method.
|
|
||||||
*/
|
|
||||||
stop(code?: number): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the server and the user application.
|
|
||||||
* It basically triggers the register and bootstrap phases
|
|
||||||
*/
|
|
||||||
load(): Promise<Strapi>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restart the server and reload all the configuration.
|
|
||||||
* It re-runs all the lifecycles phases.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ``` ts
|
|
||||||
* setImmediate(() => strapi.reload());
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
reload(): () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize and start all the webhooks registered in the webhook store
|
|
||||||
*/
|
|
||||||
startWebhooks(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method called when the server is fully initialized and listen to incomming requests.
|
|
||||||
* It handles tasks such as logging the startup message
|
|
||||||
* or automatically opening the administration panel.
|
|
||||||
*/
|
|
||||||
postListen(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start listening for incomming requests
|
|
||||||
*/
|
|
||||||
listen(): Promise<void | Error>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opent he administration panel in a browser if the option is enabled.
|
|
||||||
* You can disable it using the admin.autoOpen configuration variable.
|
|
||||||
*
|
|
||||||
* Note: It only works in development envs.
|
|
||||||
*/
|
|
||||||
openAdmin(options: { isInitialized: boolean }): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the admin panel server logic into the server code and initialize its configuration.
|
|
||||||
*/
|
|
||||||
loadAdmin(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve every enabled plugin and load them into the application.
|
|
||||||
*/
|
|
||||||
loadPlugins(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load every global policies in the policies container by
|
|
||||||
* reading from the `strapi.dirs.dist.policies` directory.
|
|
||||||
*/
|
|
||||||
loadPolicies(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load every APIs and their components (config, routes, controllers, services,
|
|
||||||
* policies, middlewares, content-types) in the API container.
|
|
||||||
*/
|
|
||||||
loadAPIs(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve every components in the user application and store them in `strapi.components`
|
|
||||||
*/
|
|
||||||
loadComponents(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load every global and core middlewares in the middlewares container by
|
|
||||||
* reading from the `strapi.dirs.dist.middlewares` and internal middlewares directory.
|
|
||||||
*/
|
|
||||||
loadMiddlewares(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the user application in the server by reading the `src/index.js` file.
|
|
||||||
*/
|
|
||||||
loadApp(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add internal hooks to the hooks container.
|
|
||||||
* Those hooks are meant for internal usage and might break in future releases.
|
|
||||||
*/
|
|
||||||
registerInternalHooks(): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a model (content-type, component) based on its unique identifier.
|
|
||||||
*/
|
|
||||||
getModel(uid: string): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds database queries for a specific model based on its unique identifier.
|
|
||||||
*/
|
|
||||||
query(uid: string): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main Strapi container holding all the registries and providers (config, content-types, services, policies, etc...)
|
|
||||||
*/
|
|
||||||
container: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References to all the directories handled by Strapi
|
|
||||||
*/
|
|
||||||
dirs: StrapiDirectories;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal flag used to check if the application has been loaded
|
|
||||||
*/
|
|
||||||
isLoaded: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully reload the application
|
|
||||||
*/
|
|
||||||
reload(): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds a reference to the Koa application and the http server used by Strapi
|
|
||||||
*/
|
|
||||||
server: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strapi util used to manage application files
|
|
||||||
*/
|
|
||||||
fs: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event hub used to send and receive events from anywhere in the application
|
|
||||||
*/
|
|
||||||
eventHub: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal util used to log stats and messages on application Startup
|
|
||||||
*/
|
|
||||||
startupLogger: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strapi logger used to send errors, warning or information messages
|
|
||||||
*/
|
|
||||||
log: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to manage cron within Strapi
|
|
||||||
*/
|
|
||||||
cron: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Telemetry util used to collect anonymous data on the application usage
|
|
||||||
*/
|
|
||||||
telemetry: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to access ctx from anywhere within the Strapi application
|
|
||||||
*/
|
|
||||||
requestContext: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strapi DB layer instance
|
|
||||||
*/
|
|
||||||
db: Database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Core Store accessor
|
|
||||||
*/
|
|
||||||
store: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity Validator instance
|
|
||||||
*/
|
|
||||||
entityValidator: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity Service instance
|
|
||||||
*/
|
|
||||||
entityService: EntityService.EntityService;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Lifecycles {
|
|
||||||
REGISTER: 'register';
|
|
||||||
BOOTSTRAP: 'bootstrap';
|
|
||||||
DESTROY: 'destroy';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StrapiDirectories {
|
|
||||||
static: {
|
|
||||||
public: string;
|
|
||||||
};
|
|
||||||
app: {
|
|
||||||
root: string;
|
|
||||||
src: string;
|
|
||||||
api: string;
|
|
||||||
components: string;
|
|
||||||
extensions: string;
|
|
||||||
policies: string;
|
|
||||||
middlewares: string;
|
|
||||||
config: string;
|
|
||||||
};
|
|
||||||
dist: {
|
|
||||||
root: string;
|
|
||||||
src: string;
|
|
||||||
api: string;
|
|
||||||
components: string;
|
|
||||||
extensions: string;
|
|
||||||
policies: string;
|
|
||||||
middlewares: string;
|
|
||||||
config: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,27 +1,24 @@
|
|||||||
'use strict';
|
import fs from 'fs/promises';
|
||||||
|
import boxen from 'boxen';
|
||||||
const fs = require('fs/promises');
|
import chalk from 'chalk';
|
||||||
const boxen = require('boxen');
|
import ora from 'ora';
|
||||||
const chalk = require('chalk');
|
import { createLogger } from '../../../utils/logger';
|
||||||
const ora = require('ora');
|
import { notifyExperimentalCommand } from '../../../utils/helpers';
|
||||||
const { createLogger } = require('../../../utils/logger');
|
import {
|
||||||
const { notifyExperimentalCommand } = require('../../../utils/helpers');
|
|
||||||
const {
|
|
||||||
loadPkg,
|
loadPkg,
|
||||||
validatePkg,
|
validatePkg,
|
||||||
validateExportsOrdering,
|
validateExportsOrdering,
|
||||||
getExportExtensionMap,
|
getExportExtensionMap,
|
||||||
} = require('../../../utils/pkg');
|
} from '../../../utils/pkg';
|
||||||
const { createBuildContext, createBuildTasks } = require('../../../builders/packages');
|
import { createBuildContext, createBuildTasks } from '../../../builders/packages';
|
||||||
const { buildTaskHandlers } = require('../../../builders/tasks');
|
import { buildTaskHandlers } from '../../../builders/tasks';
|
||||||
|
|
||||||
/**
|
interface ActionOptions {
|
||||||
*
|
force?: boolean;
|
||||||
* @param {object} args
|
debug?: boolean;
|
||||||
* @param {boolean} args.force
|
}
|
||||||
* @param {boolean} args.debug
|
|
||||||
*/
|
export default async ({ force, debug }: ActionOptions) => {
|
||||||
module.exports = async ({ force, debug }) => {
|
|
||||||
const logger = createLogger({ debug, timestamp: false });
|
const logger = createLogger({ debug, timestamp: false });
|
||||||
try {
|
try {
|
||||||
/**
|
/**
|
||||||
@ -106,13 +103,10 @@ module.exports = async ({ force, debug }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const task of buildTasks) {
|
for (const task of buildTasks) {
|
||||||
/**
|
const handler = buildTaskHandlers(task);
|
||||||
* @type {import('../../../builders/tasks').TaskHandler<any>}
|
|
||||||
*/
|
|
||||||
const handler = buildTaskHandlers[task.type];
|
|
||||||
handler.print(ctx, task);
|
handler.print(ctx, task);
|
||||||
|
|
||||||
await handler.run(ctx, task).catch((err) => {
|
await handler.run(ctx, task).catch((err: NodeJS.ErrnoException) => {
|
||||||
if (err instanceof Error) {
|
if (err instanceof Error) {
|
||||||
logger.error(err.message);
|
logger.error(err.message);
|
||||||
}
|
}
|
||||||
@ -124,6 +118,7 @@ module.exports = async ({ force, debug }) => {
|
|||||||
logger.error(
|
logger.error(
|
||||||
'There seems to be an unexpected error, try again with --debug for more information \n'
|
'There seems to be an unexpected error, try again with --debug for more information \n'
|
||||||
);
|
);
|
||||||
|
if (err instanceof Error && err.stack) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.red(
|
chalk.red(
|
||||||
boxen(err.stack, {
|
boxen(err.stack, {
|
||||||
@ -132,6 +127,7 @@ module.exports = async ({ force, debug }) => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,13 +1,11 @@
|
|||||||
'use strict';
|
import { forceOption } from '../../../utils/commander';
|
||||||
|
import { getLocalScript } from '../../../utils/helpers';
|
||||||
const { forceOption } = require('../../../utils/commander');
|
import type { StrapiCommand } from '../../../types';
|
||||||
const { getLocalScript } = require('../../../utils/helpers');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `$ strapi plugin:build`
|
* `$ strapi plugin:build`
|
||||||
* @param {import('../../../../types/core/commands').AddCommandOptions} options
|
|
||||||
*/
|
*/
|
||||||
module.exports = ({ command }) => {
|
const command: StrapiCommand = ({ command }) => {
|
||||||
command
|
command
|
||||||
.command('plugin:build')
|
.command('plugin:build')
|
||||||
.description('Bundle your strapi plugin for publishing.')
|
.description('Bundle your strapi plugin for publishing.')
|
||||||
@ -15,3 +13,5 @@ module.exports = ({ command }) => {
|
|||||||
.option('-d, --debug', 'Enable debugging mode with verbose logs', false)
|
.option('-d, --debug', 'Enable debugging mode with verbose logs', false)
|
||||||
.action(getLocalScript('plugin/build-command'));
|
.action(getLocalScript('plugin/build-command'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default command;
|
||||||
@ -1,35 +1,40 @@
|
|||||||
'use strict';
|
import path from 'path';
|
||||||
|
import browserslistToEsbuild from 'browserslist-to-esbuild';
|
||||||
|
import { parseExports, PackageJson, ExtMap, Export } from '../utils/pkg';
|
||||||
|
import type { Logger } from '../utils/logger';
|
||||||
|
import type { ViteTask } from './tasks/vite';
|
||||||
|
import type { DtsTask } from './tasks/dts';
|
||||||
|
|
||||||
const path = require('path');
|
interface BuildContextArgs {
|
||||||
const browserslistToEsbuild = require('browserslist-to-esbuild');
|
cwd: string;
|
||||||
|
extMap: ExtMap;
|
||||||
|
logger: Logger;
|
||||||
|
pkg: PackageJson;
|
||||||
|
}
|
||||||
|
|
||||||
const { parseExports } = require('../utils/pkg');
|
export type Target = 'node' | 'web' | '*';
|
||||||
|
|
||||||
/**
|
export type Targets = {
|
||||||
* @typedef {Object} BuildContextArgs
|
[target in Target]: string[];
|
||||||
* @property {string} cwd
|
};
|
||||||
* @property {import('../utils/pkg').ExtMap} extMap
|
|
||||||
* @property {import('../utils/logger').Logger} logger
|
|
||||||
* @property {import('../utils/pkg').PackageJson} pkg
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
export interface BuildContext {
|
||||||
* @typedef {Object} Targets
|
cwd: string;
|
||||||
* @property {string[]} node
|
exports: Record<string, Export>;
|
||||||
* @property {string[]} web
|
external: string[];
|
||||||
* @property {string[]} *
|
extMap: ExtMap;
|
||||||
*/
|
logger: Logger;
|
||||||
|
pkg: PackageJson;
|
||||||
|
targets: Targets;
|
||||||
|
distPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
export interface BuildTask {
|
||||||
* @typedef {Object} BuildContext
|
type: 'build:js' | 'build:dts';
|
||||||
* @property {string} cwd
|
entries: unknown[];
|
||||||
* @property {import('../utils/pkg').Export[]} exports
|
format?: 'cjs' | 'es';
|
||||||
* @property {string[]} external
|
[key: string]: unknown;
|
||||||
* @property {import('../utils/pkg').ExtMap} extMap
|
}
|
||||||
* @property {import('../utils/logger').Logger} logger
|
|
||||||
* @property {import('../utils/pkg').PackageJson} pkg
|
|
||||||
* @property {Targets} targets
|
|
||||||
*/
|
|
||||||
|
|
||||||
const DEFAULT_BROWSERS_LIST_CONFIG = [
|
const DEFAULT_BROWSERS_LIST_CONFIG = [
|
||||||
'last 3 major versions',
|
'last 3 major versions',
|
||||||
@ -43,30 +48,33 @@ const DEFAULT_BROWSERS_LIST_CONFIG = [
|
|||||||
* @description Create a build context for the pipeline we're creating,
|
* @description Create a build context for the pipeline we're creating,
|
||||||
* this is shared among tasks so they all use the same settings for core pieces
|
* this is shared among tasks so they all use the same settings for core pieces
|
||||||
* such as a target, distPath, externals etc.
|
* such as a target, distPath, externals etc.
|
||||||
*
|
|
||||||
* @type {(args: BuildContextArgs) => Promise<BuildContext>}
|
|
||||||
*/
|
*/
|
||||||
const createBuildContext = async ({ cwd, extMap, logger, pkg }) => {
|
const createBuildContext = async ({
|
||||||
|
cwd,
|
||||||
|
extMap,
|
||||||
|
logger,
|
||||||
|
pkg,
|
||||||
|
}: BuildContextArgs): Promise<BuildContext> => {
|
||||||
const targets = {
|
const targets = {
|
||||||
'*': browserslistToEsbuild(pkg.browserslist ?? DEFAULT_BROWSERS_LIST_CONFIG),
|
'*': browserslistToEsbuild(pkg.browserslist ?? DEFAULT_BROWSERS_LIST_CONFIG),
|
||||||
node: browserslistToEsbuild(['node 16.0.0']),
|
node: browserslistToEsbuild(['node 16.0.0']),
|
||||||
web: ['esnext'],
|
web: ['esnext'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const exports = parseExports({ extMap, pkg }).reduce((acc, x) => {
|
const exportsArray = parseExports({ extMap, pkg }).reduce((acc, x) => {
|
||||||
const { _path: exportPath, ...exportEntry } = x;
|
const { _path: exportPath, ...exportEntry } = x;
|
||||||
|
|
||||||
return { ...acc, [exportPath]: exportEntry };
|
return { ...acc, [exportPath]: exportEntry };
|
||||||
}, {});
|
}, {} as Record<string, Export>);
|
||||||
|
|
||||||
const external = [
|
const external = [
|
||||||
...(pkg.dependencies ? Object.keys(pkg.dependencies) : []),
|
...(pkg.dependencies ? Object.keys(pkg.dependencies) : []),
|
||||||
...(pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : []),
|
...(pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : []),
|
||||||
];
|
];
|
||||||
|
|
||||||
const outputPaths = Object.values(exports)
|
const outputPaths = Object.values(exportsArray)
|
||||||
.flatMap((exportEntry) => {
|
.flatMap((exportEntry) => {
|
||||||
return [exportEntry.import, exportEntry.require].filter(Boolean);
|
return [exportEntry.import, exportEntry.require].filter((v): v is string => Boolean(v));
|
||||||
})
|
})
|
||||||
.map((p) => path.resolve(cwd, p));
|
.map((p) => path.resolve(cwd, p));
|
||||||
|
|
||||||
@ -86,7 +94,7 @@ const createBuildContext = async ({ cwd, extMap, logger, pkg }) => {
|
|||||||
logger,
|
logger,
|
||||||
cwd,
|
cwd,
|
||||||
pkg,
|
pkg,
|
||||||
exports,
|
exports: exportsArray,
|
||||||
external,
|
external,
|
||||||
distPath,
|
distPath,
|
||||||
targets,
|
targets,
|
||||||
@ -94,17 +102,11 @@ const createBuildContext = async ({ cwd, extMap, logger, pkg }) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const pathContains = (containerPath: string, itemPath: string): boolean => {
|
||||||
* @type {(containerPath: string, itemPath: string) => boolean}
|
|
||||||
*/
|
|
||||||
const pathContains = (containerPath, itemPath) => {
|
|
||||||
return !path.relative(containerPath, itemPath).startsWith('..');
|
return !path.relative(containerPath, itemPath).startsWith('..');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const findCommonDirPath = (filePaths: string[]) => {
|
||||||
* @type {(filePaths: string[]) => string | undefined}
|
|
||||||
*/
|
|
||||||
const findCommonDirPath = (filePaths) => {
|
|
||||||
/**
|
/**
|
||||||
* @type {string | undefined}
|
* @type {string | undefined}
|
||||||
*/
|
*/
|
||||||
@ -138,38 +140,36 @@ const findCommonDirPath = (filePaths) => {
|
|||||||
return commonPath;
|
return commonPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
type Task = ViteTask | DtsTask;
|
||||||
* @typedef {import('./tasks/vite').ViteTask | import('./tasks/dts').DtsTask} BuildTask
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Create the build tasks for the pipeline, this
|
* @description Create the build tasks for the pipeline, this
|
||||||
* comes from the exports map we've created in the build context.
|
* comes from the exports map we've created in the build context.
|
||||||
* But handles each export line uniquely with space to add more
|
* But handles each export line uniquely with space to add more
|
||||||
* as the standard develops.
|
* as the standard develops.
|
||||||
*
|
|
||||||
* @type {(args: BuildContext) => Promise<BuildTask[]>}
|
|
||||||
*/
|
*/
|
||||||
const createBuildTasks = async (ctx) => {
|
const createBuildTasks = async (ctx: BuildContext): Promise<Task[]> => {
|
||||||
/**
|
const tasks: Task[] = [];
|
||||||
* @type {BuildTask[]}
|
|
||||||
*/
|
|
||||||
const tasks = [];
|
|
||||||
|
|
||||||
/**
|
const dtsTask: DtsTask = {
|
||||||
* @type {import('./tasks/dts').DtsTask}
|
|
||||||
*/
|
|
||||||
const dtsTask = {
|
|
||||||
type: 'build:dts',
|
type: 'build:dts',
|
||||||
entries: [],
|
entries: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const viteTasks: Record<string, ViteTask> = {};
|
||||||
* @type {Record<string, import('./tasks/vite').ViteTask>}
|
|
||||||
*/
|
|
||||||
const viteTasks = {};
|
|
||||||
|
|
||||||
const createViteTask = (format, runtime, { output, ...restEntry }) => {
|
const createViteTask = (
|
||||||
|
format: 'cjs' | 'es',
|
||||||
|
runtime: Target,
|
||||||
|
{
|
||||||
|
output,
|
||||||
|
...restEntry
|
||||||
|
}: {
|
||||||
|
output: string;
|
||||||
|
path: string;
|
||||||
|
entry: string;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
const buildId = `${format}:${output}`;
|
const buildId = `${format}:${output}`;
|
||||||
|
|
||||||
if (viteTasks[buildId]) {
|
if (viteTasks[buildId]) {
|
||||||
@ -208,11 +208,8 @@ const createBuildTasks = async (ctx) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {keyof Target}
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line no-nested-ternary
|
// eslint-disable-next-line no-nested-ternary
|
||||||
const runtime = exp._path.includes('strapi-admin')
|
const runtime: Target = exp._path.includes('strapi-admin')
|
||||||
? 'web'
|
? 'web'
|
||||||
: exp._path.includes('strapi-server')
|
: exp._path.includes('strapi-server')
|
||||||
? 'node'
|
? 'node'
|
||||||
@ -224,7 +221,7 @@ const createBuildTasks = async (ctx) => {
|
|||||||
*/
|
*/
|
||||||
createViteTask('cjs', runtime, {
|
createViteTask('cjs', runtime, {
|
||||||
path: exp._path,
|
path: exp._path,
|
||||||
entry: exp.source,
|
entry: exp.source ?? 'src/index.ts',
|
||||||
output: exp.require,
|
output: exp.require,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -235,7 +232,7 @@ const createBuildTasks = async (ctx) => {
|
|||||||
*/
|
*/
|
||||||
createViteTask('es', runtime, {
|
createViteTask('es', runtime, {
|
||||||
path: exp._path,
|
path: exp._path,
|
||||||
entry: exp.source,
|
entry: exp.source ?? 'src/index.ts',
|
||||||
output: exp.import,
|
output: exp.import,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -246,7 +243,4 @@ const createBuildTasks = async (ctx) => {
|
|||||||
return tasks;
|
return tasks;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export { createBuildContext, createBuildTasks };
|
||||||
createBuildContext,
|
|
||||||
createBuildTasks,
|
|
||||||
};
|
|
||||||
@ -1,18 +1,33 @@
|
|||||||
'use strict';
|
import path from 'path';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import ora from 'ora';
|
||||||
|
import ts from 'typescript';
|
||||||
|
import type { Logger } from '../../utils/logger';
|
||||||
|
import type { TaskHandler } from '.';
|
||||||
|
import type { BuildTask } from '../packages';
|
||||||
|
|
||||||
const path = require('path');
|
interface LoadTsConfigOptions {
|
||||||
const chalk = require('chalk');
|
cwd: string;
|
||||||
const ora = require('ora');
|
path: string;
|
||||||
const ts = require('typescript');
|
}
|
||||||
|
|
||||||
|
class TSConfigNotFoundError extends Error {
|
||||||
|
// eslint-disable-next-line no-useless-constructor
|
||||||
|
// constructor(message, options) {
|
||||||
|
// super(message, options);
|
||||||
|
// }
|
||||||
|
|
||||||
|
get code() {
|
||||||
|
return 'TS_CONFIG_NOT_FOUND';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Load a tsconfig.json file and return the parsed config
|
* @description Load a tsconfig.json file and return the parsed config
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @type {(args: { cwd: string; path: string }) => Promise<ts.ParsedCommandLine>)}
|
|
||||||
*/
|
*/
|
||||||
const loadTsConfig = async ({ cwd, path }) => {
|
const loadTsConfig = async ({ cwd, path }: LoadTsConfigOptions) => {
|
||||||
const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, path);
|
const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, path);
|
||||||
|
|
||||||
if (!configPath) {
|
if (!configPath) {
|
||||||
@ -24,25 +39,19 @@ const loadTsConfig = async ({ cwd, path }) => {
|
|||||||
return ts.parseJsonConfigFileContent(configFile.config, ts.sys, cwd);
|
return ts.parseJsonConfigFileContent(configFile.config, ts.sys, cwd);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TSConfigNotFoundError extends Error {
|
interface BuildTypesOptions {
|
||||||
// eslint-disable-next-line no-useless-constructor
|
cwd: string;
|
||||||
constructor(message, options) {
|
logger: Logger;
|
||||||
super(message, options);
|
outDir: string;
|
||||||
}
|
tsconfig: ts.ParsedCommandLine;
|
||||||
|
|
||||||
get code() {
|
|
||||||
return 'TS_CONFIG_NOT_FOUND';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @type {(args: { cwd: string; logger: import('../../utils/logger').Logger; outDir: string; tsconfig: ts.ParsedCommandLine }) => Promise<void>}
|
|
||||||
*/
|
*/
|
||||||
const buildTypes = ({ cwd, logger, outDir, tsconfig }) => {
|
const buildTypes = ({ cwd, logger, outDir, tsconfig }: BuildTypesOptions) => {
|
||||||
const compilerOptions = {
|
const compilerOptions = {
|
||||||
...tsconfig.options,
|
...tsconfig.options,
|
||||||
declaration: true,
|
declaration: true,
|
||||||
@ -102,23 +111,19 @@ const buildTypes = ({ cwd, logger, outDir, tsconfig }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export interface DtsTaskEntry {
|
||||||
* @typedef {Object} DtsTaskEntry
|
importId: string;
|
||||||
* @property {string} exportPath
|
exportPath: string;
|
||||||
* @property {string} sourcePath
|
sourcePath?: string;
|
||||||
* @property {string} targetPath
|
targetPath: string;
|
||||||
*/
|
}
|
||||||
|
|
||||||
/**
|
export interface DtsTask extends BuildTask {
|
||||||
* @typedef {Object} DtsTask
|
type: 'build:dts';
|
||||||
* @property {"build:dts"} type
|
entries: DtsTaskEntry[];
|
||||||
* @property {DtsTaskEntry[]} entries
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
const dtsTask: TaskHandler<DtsTask> = {
|
||||||
* @type {import('./index').TaskHandler<DtsTask>}
|
|
||||||
*/
|
|
||||||
const dtsTask = {
|
|
||||||
_spinner: null,
|
_spinner: null,
|
||||||
print(ctx, task) {
|
print(ctx, task) {
|
||||||
const entries = [
|
const entries = [
|
||||||
@ -146,7 +151,7 @@ const dtsTask = {
|
|||||||
* TODO: this will not scale and assumes all project sourcePaths are `src/index.ts`
|
* TODO: this will not scale and assumes all project sourcePaths are `src/index.ts`
|
||||||
* so we can go back to the "root" of the project...
|
* so we can go back to the "root" of the project...
|
||||||
*/
|
*/
|
||||||
cwd: path.join(ctx.cwd, entry.sourcePath, '..', '..'),
|
cwd: path.join(ctx.cwd, entry.sourcePath ?? 'src/index.ts', '..', '..'),
|
||||||
path: 'tsconfig.build.json',
|
path: 'tsconfig.build.json',
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (err instanceof TSConfigNotFoundError) {
|
if (err instanceof TSConfigNotFoundError) {
|
||||||
@ -187,13 +192,13 @@ const dtsTask = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async success() {
|
async success() {
|
||||||
this._spinner.succeed('Built type files');
|
this._spinner?.succeed('Built type files');
|
||||||
},
|
},
|
||||||
async fail(ctx, task, err) {
|
async fail(ctx, task, err) {
|
||||||
this._spinner.fail('Failed to build type files');
|
this._spinner?.fail('Failed to build type files');
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = { dtsTask };
|
export { dtsTask };
|
||||||
@ -1,29 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { dtsTask } = require('./dts');
|
|
||||||
const { viteTask } = require('./vite');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @template Task
|
|
||||||
* @param {Task}
|
|
||||||
* @returns {Task}
|
|
||||||
*
|
|
||||||
* @typedef {Object} TaskHandler
|
|
||||||
* @property {(ctx: import("../packages").BuildContext, task: Task) => import('ora').Ora} print
|
|
||||||
* @property {(ctx: import("../packages").BuildContext, task: Task) => Promise<void>} run
|
|
||||||
* @property {(ctx: import("../packages").BuildContext, task: Task) => Promise<void>} success
|
|
||||||
* @property {(ctx: import("../packages").BuildContext, task: Task, err: unknown) => Promise<void>} fail
|
|
||||||
* @property {import('ora').Ora | null} _spinner
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {{ "build:js": TaskHandler<import("./vite").ViteTask>; "build:dts": TaskHandler<import("./dts").DtsTask>; }}}
|
|
||||||
*/
|
|
||||||
const buildTaskHandlers = {
|
|
||||||
'build:js': viteTask,
|
|
||||||
'build:dts': dtsTask,
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
buildTaskHandlers,
|
|
||||||
};
|
|
||||||
23
packages/core/strapi/src/commands/builders/tasks/index.ts
Normal file
23
packages/core/strapi/src/commands/builders/tasks/index.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import type { Ora } from 'ora';
|
||||||
|
import { dtsTask, DtsTask } from './dts';
|
||||||
|
import { viteTask, ViteTask } from './vite';
|
||||||
|
import type { BuildContext, BuildTask } from '../packages';
|
||||||
|
|
||||||
|
export interface TaskHandler<Task extends BuildTask> {
|
||||||
|
print: (ctx: BuildContext, task: Task) => void;
|
||||||
|
run: (ctx: BuildContext, task: Task) => Promise<void>;
|
||||||
|
success: (ctx: BuildContext, task: Task) => Promise<void>;
|
||||||
|
fail: (ctx: BuildContext, task: Task, err: unknown) => Promise<void>;
|
||||||
|
_spinner: Ora | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlers = {
|
||||||
|
'build:js': viteTask,
|
||||||
|
'build:dts': dtsTask,
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildTaskHandlers = <T extends ViteTask | DtsTask>(t: T): TaskHandler<T> => {
|
||||||
|
return handlers[t.type] as TaskHandler<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { buildTaskHandlers };
|
||||||
@ -1,17 +1,18 @@
|
|||||||
'use strict';
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
|
import path from 'path';
|
||||||
|
// @ts-ignore
|
||||||
|
import { build, createLogger, InlineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import ora from 'ora';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
const path = require('path');
|
import type { TaskHandler } from '.';
|
||||||
const { build, createLogger } = require('vite');
|
import type { BuildContext, BuildTask, Target } from '../packages';
|
||||||
const react = require('@vitejs/plugin-react');
|
|
||||||
const ora = require('ora');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @type {(ctx: import('../packages').BuildContext, task: ViteTask) => import('vite').UserConfig}
|
|
||||||
*/
|
*/
|
||||||
const resolveViteConfig = (ctx, task) => {
|
const resolveViteConfig = (ctx: BuildContext, task: ViteTask): InlineConfig => {
|
||||||
const { cwd, distPath, targets, external, extMap, pkg } = ctx;
|
const { cwd, distPath, targets, external, extMap, pkg } = ctx;
|
||||||
const { entries, format, output, runtime } = task;
|
const { entries, format, output, runtime } = task;
|
||||||
const outputExt = extMap[pkg.type || 'commonjs'][format];
|
const outputExt = extMap[pkg.type || 'commonjs'][format];
|
||||||
@ -22,10 +23,7 @@ const resolveViteConfig = (ctx, task) => {
|
|||||||
customLogger.warnOnce = (msg) => ctx.logger.warn(msg);
|
customLogger.warnOnce = (msg) => ctx.logger.warn(msg);
|
||||||
customLogger.error = (msg) => ctx.logger.error(msg);
|
customLogger.error = (msg) => ctx.logger.error(msg);
|
||||||
|
|
||||||
/**
|
const config: InlineConfig = {
|
||||||
* @type {import('vite').InlineConfig}
|
|
||||||
*/
|
|
||||||
const config = {
|
|
||||||
configFile: false,
|
configFile: false,
|
||||||
root: cwd,
|
root: cwd,
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
@ -79,25 +77,20 @@ const resolveViteConfig = (ctx, task) => {
|
|||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
interface ViteTaskEntry {
|
||||||
* @typedef {Object} ViteTaskEntry
|
path: string;
|
||||||
* @property {string} path
|
entry: string;
|
||||||
* @property {string} entry
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
export interface ViteTask extends BuildTask {
|
||||||
* @typedef {Object} ViteTask
|
type: 'build:js';
|
||||||
* @property {"build:js"} type
|
entries: ViteTaskEntry[];
|
||||||
* @property {ViteTaskEntry[]} entries
|
format: 'cjs' | 'es';
|
||||||
* @property {string} format
|
output: string;
|
||||||
* @property {string} output
|
runtime: Target;
|
||||||
* @property {keyof import('../packages').Targets} runtime
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
const viteTask: TaskHandler<ViteTask> = {
|
||||||
* @type {import('./index').TaskHandler<ViteTask>}
|
|
||||||
*/
|
|
||||||
const viteTask = {
|
|
||||||
_spinner: null,
|
_spinner: null,
|
||||||
print(ctx, task) {
|
print(ctx, task) {
|
||||||
const targetLines = [
|
const targetLines = [
|
||||||
@ -130,15 +123,13 @@ const viteTask = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async success() {
|
async success() {
|
||||||
this._spinner.succeed('Built javascript files');
|
this._spinner?.succeed('Built javascript files');
|
||||||
},
|
},
|
||||||
async fail(ctx, task, err) {
|
async fail(ctx, task, err) {
|
||||||
this._spinner.fail('Failed to build javascript files');
|
this._spinner?.fail('Failed to build javascript files');
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export { viteTask };
|
||||||
viteTask,
|
|
||||||
};
|
|
||||||
@ -10,10 +10,8 @@ import consoleCommand from './actions/console/command';
|
|||||||
import listContentTypes from './actions/content-types/list/command';
|
import listContentTypes from './actions/content-types/list/command';
|
||||||
import listControllers from './actions/controllers/list/command';
|
import listControllers from './actions/controllers/list/command';
|
||||||
import developCommand from './actions/develop/command';
|
import developCommand from './actions/develop/command';
|
||||||
// import exportCommand from './actions/export/command';
|
|
||||||
import generateCommand from './actions/generate/command';
|
import generateCommand from './actions/generate/command';
|
||||||
import listHooks from './actions/hooks/list/command';
|
import listHooks from './actions/hooks/list/command';
|
||||||
// import importCommand from './actions/import/command';
|
|
||||||
import installCommand from './actions/install/command';
|
import installCommand from './actions/install/command';
|
||||||
import listMiddlewares from './actions/middlewares/list/command';
|
import listMiddlewares from './actions/middlewares/list/command';
|
||||||
import newCommand from './actions/new/command';
|
import newCommand from './actions/new/command';
|
||||||
@ -25,11 +23,11 @@ import startCommand from './actions/start/command';
|
|||||||
import disableTelemetry from './actions/telemetry/disable/command';
|
import disableTelemetry from './actions/telemetry/disable/command';
|
||||||
import enableTelemetry from './actions/telemetry/enable/command';
|
import enableTelemetry from './actions/telemetry/enable/command';
|
||||||
import generateTemplates from './actions/templates/generate/command';
|
import generateTemplates from './actions/templates/generate/command';
|
||||||
// import transferCommand from './actions/transfer/command';
|
|
||||||
import generateTsTypes from './actions/ts/generate-types/command';
|
import generateTsTypes from './actions/ts/generate-types/command';
|
||||||
import uninstallCommand from './actions/uninstall/command';
|
import uninstallCommand from './actions/uninstall/command';
|
||||||
import versionCommand from './actions/version/command';
|
import versionCommand from './actions/version/command';
|
||||||
import watchAdminCommand from './actions/watch-admin/command';
|
import watchAdminCommand from './actions/watch-admin/command';
|
||||||
|
import buildPluginCommand from './actions/plugin/build-command/command';
|
||||||
|
|
||||||
const strapiCommands = {
|
const strapiCommands = {
|
||||||
createAdminUser,
|
createAdminUser,
|
||||||
@ -59,6 +57,7 @@ const strapiCommands = {
|
|||||||
uninstallCommand,
|
uninstallCommand,
|
||||||
versionCommand,
|
versionCommand,
|
||||||
watchAdminCommand,
|
watchAdminCommand,
|
||||||
|
buildPluginCommand,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const buildStrapiCommand = (argv: string[], command = new Command()) => {
|
const buildStrapiCommand = (argv: string[], command = new Command()) => {
|
||||||
|
|||||||
@ -1,25 +1,14 @@
|
|||||||
<<<<<<< HEAD:packages/core/strapi/src/commands/utils/helpers.ts
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
import { yellow, red, green } from 'chalk';
|
import chalk, { yellow, red, green } from 'chalk';
|
||||||
import { has, isString, isArray } from 'lodash/fp';
|
import { has, isString, isArray } from 'lodash/fp';
|
||||||
import resolveCwd from 'resolve-cwd';
|
import resolveCwd from 'resolve-cwd';
|
||||||
|
import { prompt } from 'inquirer';
|
||||||
|
import boxen from 'boxen';
|
||||||
import type { Command } from 'commander';
|
import type { Command } from 'commander';
|
||||||
=======
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper functions for the Strapi CLI
|
* Helper functions for the Strapi CLI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { yellow, red, green } = require('chalk');
|
|
||||||
const { isString, isArray } = require('lodash/fp');
|
|
||||||
const resolveCwd = require('resolve-cwd');
|
|
||||||
const { has } = require('lodash/fp');
|
|
||||||
const { prompt } = require('inquirer');
|
|
||||||
const boxen = require('boxen');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
>>>>>>> main:packages/core/strapi/lib/commands/utils/helpers.js
|
|
||||||
|
|
||||||
const bytesPerKb = 1024;
|
const bytesPerKb = 1024;
|
||||||
const sizes = ['B ', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
const sizes = ['B ', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||||
|
|
||||||
@ -133,16 +122,11 @@ const assertCwdContainsStrapiProject = (name: string) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const pkgJSON = require(`${process.cwd()}/package.json`);
|
const pkgJSON = require(`${process.cwd()}/package.json`);
|
||||||
<<<<<<< HEAD:packages/core/strapi/src/commands/utils/helpers.ts
|
|
||||||
if (!has('dependencies.@strapi/strapi', pkgJSON)) {
|
|
||||||
logErrorAndExit();
|
|
||||||
=======
|
|
||||||
if (
|
if (
|
||||||
!has('dependencies.@strapi/strapi', pkgJSON) &&
|
!has('dependencies.@strapi/strapi', pkgJSON) &&
|
||||||
!has('devDependencies.@strapi/strapi', pkgJSON)
|
!has('devDependencies.@strapi/strapi', pkgJSON)
|
||||||
) {
|
) {
|
||||||
logErrorAndExit(name);
|
logErrorAndExit();
|
||||||
>>>>>>> main:packages/core/strapi/lib/commands/utils/helpers.js
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logErrorAndExit();
|
logErrorAndExit();
|
||||||
@ -176,9 +160,6 @@ const getLocalScript =
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
<<<<<<< HEAD:packages/core/strapi/src/commands/utils/helpers.ts
|
|
||||||
export {
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* @description Notify users this is an experimental command and get them to approve first
|
* @description Notify users this is an experimental command and get them to approve first
|
||||||
* this can be opted out by passing `yes` as a property of the args object.
|
* this can be opted out by passing `yes` as a property of the args object.
|
||||||
@ -194,7 +175,7 @@ export {
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
const notifyExperimentalCommand = async ({ force } = {}) => {
|
const notifyExperimentalCommand = async ({ force }: { force?: boolean } = {}) => {
|
||||||
console.log(
|
console.log(
|
||||||
boxen(
|
boxen(
|
||||||
`The ${chalk.bold(
|
`The ${chalk.bold(
|
||||||
@ -224,8 +205,7 @@ const notifyExperimentalCommand = async ({ force } = {}) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export {
|
||||||
>>>>>>> main:packages/core/strapi/lib/commands/utils/helpers.js
|
|
||||||
exitWith,
|
exitWith,
|
||||||
assertUrlHasProtocol,
|
assertUrlHasProtocol,
|
||||||
ifOptions,
|
ifOptions,
|
||||||
|
|||||||
@ -1,26 +1,22 @@
|
|||||||
'use strict';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
const chalk = require('chalk');
|
export interface LoggerOptions {
|
||||||
|
silent?: boolean;
|
||||||
|
debug?: boolean;
|
||||||
|
timestamp?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
export interface Logger {
|
||||||
* @typedef {{ silent?: boolean; debug?: boolean; timestamp?: boolean; }} LoggerOptions
|
warnings: number;
|
||||||
*/
|
errors: number;
|
||||||
|
debug: (...args: unknown[]) => void;
|
||||||
|
info: (...args: unknown[]) => void;
|
||||||
|
warn: (...args: unknown[]) => void;
|
||||||
|
error: (...args: unknown[]) => void;
|
||||||
|
log: (...args: unknown[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const createLogger = (options: LoggerOptions = {}): Logger => {
|
||||||
* @typedef {object} Logger
|
|
||||||
* @property {number} warnings
|
|
||||||
* @property {number} errors
|
|
||||||
* @property {(...args: any[]) => void} debug
|
|
||||||
* @property {(...args: any[]) => void} info
|
|
||||||
* @property {(...args: any[]) => void} warn
|
|
||||||
* @property {(...args: any[]) => void} error
|
|
||||||
* @property {(...args: any[]) => void} log
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {(options: LoggerOptions) => Logger}
|
|
||||||
*/
|
|
||||||
const createLogger = (options = {}) => {
|
|
||||||
const { silent = false, debug = false, timestamp = true } = options;
|
const { silent = false, debug = false, timestamp = true } = options;
|
||||||
|
|
||||||
const state = { errors: 0, warning: 0 };
|
const state = { errors: 0, warning: 0 };
|
||||||
@ -92,6 +88,4 @@ const createLogger = (options = {}) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export { createLogger };
|
||||||
createLogger,
|
|
||||||
};
|
|
||||||
@ -1,9 +1,36 @@
|
|||||||
'use strict';
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import * as yup from 'yup';
|
||||||
|
import type { Logger } from './logger';
|
||||||
|
|
||||||
const fs = require('fs/promises');
|
export interface PackageJson extends Omit<yup.Asserts<typeof packageJsonSchema>, 'exports'> {
|
||||||
const path = require('path');
|
type: Extensions;
|
||||||
const chalk = require('chalk');
|
exports?: {
|
||||||
const yup = require('yup');
|
[key: string]: Export | string;
|
||||||
|
};
|
||||||
|
browserslist?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Extensions = 'commonjs' | 'module';
|
||||||
|
export type ExtMap = {
|
||||||
|
[key in Extensions]: {
|
||||||
|
cjs: string;
|
||||||
|
es: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Export {
|
||||||
|
types?: string;
|
||||||
|
source?: string;
|
||||||
|
require?: string;
|
||||||
|
import?: string;
|
||||||
|
default?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExportWithMeta extends Export {
|
||||||
|
_path: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility functions for loading and validating package.json
|
* Utility functions for loading and validating package.json
|
||||||
@ -18,14 +45,19 @@ const yup = require('yup');
|
|||||||
const packageJsonSchema = yup.object({
|
const packageJsonSchema = yup.object({
|
||||||
name: yup.string().required(),
|
name: yup.string().required(),
|
||||||
version: yup.string().required(),
|
version: yup.string().required(),
|
||||||
type: yup.string().matches(/(commonjs|module)/),
|
type: yup.mixed().oneOf(['commonjs', 'module']),
|
||||||
license: yup.string(),
|
license: yup.string(),
|
||||||
bin: yup.mixed().oneOf([
|
bin: yup.lazy((value) =>
|
||||||
yup.string(),
|
typeof value === 'object'
|
||||||
yup.object({
|
? yup.object(
|
||||||
[yup.string()]: yup.string(),
|
Object.entries(value).reduce((acc, [key]) => {
|
||||||
}),
|
acc[key] = yup.string().required();
|
||||||
]),
|
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, yup.SchemaOf<string>>)
|
||||||
|
)
|
||||||
|
: yup.string()
|
||||||
|
),
|
||||||
main: yup.string(),
|
main: yup.string(),
|
||||||
module: yup.string(),
|
module: yup.string(),
|
||||||
source: yup.string(),
|
source: yup.string(),
|
||||||
@ -52,7 +84,7 @@ const packageJsonSchema = yup.object({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {} as Record<string, yup.SchemaOf<string> | yup.SchemaOf<Export>>)
|
||||||
: undefined
|
: undefined
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -64,18 +96,18 @@ const packageJsonSchema = yup.object({
|
|||||||
engines: yup.object(),
|
engines: yup.object(),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
interface LoadPkgOptions {
|
||||||
* @typedef {import('yup').Asserts<typeof packageJsonSchema>} PackageJson
|
cwd: string;
|
||||||
*/
|
logger: Logger;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description being a task to load the package.json starting from the current working directory
|
* @description being a task to load the package.json starting from the current working directory
|
||||||
* using a shallow find for the package.json and `fs` to read the file. If no package.json is found,
|
* using a shallow find for the package.json and `fs` to read the file. If no package.json is found,
|
||||||
* the process will throw with an appropriate error message.
|
* the process will throw with an appropriate error message.
|
||||||
*
|
*
|
||||||
* @type {(args: { cwd: string, logger: import('./logger').Logger }) => Promise<object>}
|
|
||||||
*/
|
*/
|
||||||
const loadPkg = async ({ cwd, logger }) => {
|
const loadPkg = async ({ cwd, logger }: LoadPkgOptions): Promise<PackageJson> => {
|
||||||
const directory = path.resolve(cwd);
|
const directory = path.resolve(cwd);
|
||||||
|
|
||||||
const pkgPath = path.join(directory, 'package.json');
|
const pkgPath = path.join(directory, 'package.json');
|
||||||
@ -95,10 +127,8 @@ const loadPkg = async ({ cwd, logger }) => {
|
|||||||
/**
|
/**
|
||||||
* @description validate the package.json against a standardised schema using `yup`.
|
* @description validate the package.json against a standardised schema using `yup`.
|
||||||
* If the validation fails, the process will throw with an appropriate error message.
|
* If the validation fails, the process will throw with an appropriate error message.
|
||||||
*
|
|
||||||
* @type {(args: { pkg: object }) => Promise<PackageJson | null>}
|
|
||||||
*/
|
*/
|
||||||
const validatePkg = async ({ pkg }) => {
|
const validatePkg = async ({ pkg }: { pkg: PackageJson }) => {
|
||||||
try {
|
try {
|
||||||
const validatedPkg = await packageJsonSchema.validate(pkg, {
|
const validatedPkg = await packageJsonSchema.validate(pkg, {
|
||||||
strict: true,
|
strict: true,
|
||||||
@ -111,14 +141,14 @@ const validatePkg = async ({ pkg }) => {
|
|||||||
case 'required':
|
case 'required':
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`'${err.path}' in 'package.json' is required as type '${chalk.magenta(
|
`'${err.path}' in 'package.json' is required as type '${chalk.magenta(
|
||||||
yup.reach(packageJsonSchema, err.path).type
|
yup.reach(packageJsonSchema, err.path ?? '').type
|
||||||
)}'`
|
)}'`
|
||||||
);
|
);
|
||||||
case 'matches':
|
case 'matches':
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`'${err.path}' in 'package.json' must be of type '${chalk.magenta(
|
`'${err.path}' in 'package.json' must be of type '${chalk.magenta(
|
||||||
err.params.regex
|
err.params?.regex
|
||||||
)}' (recieved the value '${chalk.magenta(err.params.value)}')`
|
)}' (recieved the value '${chalk.magenta(err.params?.value)}')`
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
* This will only be thrown if there are keys in the export map
|
* This will only be thrown if there are keys in the export map
|
||||||
@ -127,7 +157,7 @@ const validatePkg = async ({ pkg }) => {
|
|||||||
case 'noUnknown':
|
case 'noUnknown':
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`'${err.path}' in 'package.json' contains the unknown key ${chalk.magenta(
|
`'${err.path}' in 'package.json' contains the unknown key ${chalk.magenta(
|
||||||
err.params.unknown
|
err.params?.unknown
|
||||||
)}, for compatability only the following keys are allowed: ${chalk.magenta(
|
)}, for compatability only the following keys are allowed: ${chalk.magenta(
|
||||||
"['types', 'source', 'import', 'require', 'default']"
|
"['types', 'source', 'import', 'require', 'default']"
|
||||||
)}`
|
)}`
|
||||||
@ -135,8 +165,8 @@ const validatePkg = async ({ pkg }) => {
|
|||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`'${err.path}' in 'package.json' must be of type '${chalk.magenta(
|
`'${err.path}' in 'package.json' must be of type '${chalk.magenta(
|
||||||
err.params.type
|
err.params?.type
|
||||||
)}' (recieved '${chalk.magenta(typeof err.params.value)}')`
|
)}' (recieved '${chalk.magenta(typeof err.params?.value)}')`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,15 +175,21 @@ const validatePkg = async ({ pkg }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface ValidateExportsOrderingOptions {
|
||||||
|
pkg: PackageJson;
|
||||||
|
logger: Logger;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description validate the `exports` property of the package.json against a set of rules.
|
* @description validate the `exports` property of the package.json against a set of rules.
|
||||||
* If the validation fails, the process will throw with an appropriate error message. If
|
* If the validation fails, the process will throw with an appropriate error message. If
|
||||||
* there is no `exports` property we check the standard export-like properties on the root
|
* there is no `exports` property we check the standard export-like properties on the root
|
||||||
* of the package.json.
|
* of the package.json.
|
||||||
*
|
|
||||||
* @type {(args: { pkg: object, logger: import('./logger').Logger }) => Promise<PackageJson>}
|
|
||||||
*/
|
*/
|
||||||
const validateExportsOrdering = async ({ pkg, logger }) => {
|
const validateExportsOrdering = async ({
|
||||||
|
pkg,
|
||||||
|
logger,
|
||||||
|
}: ValidateExportsOrderingOptions): Promise<PackageJson> => {
|
||||||
if (pkg.exports) {
|
if (pkg.exports) {
|
||||||
const exports = Object.entries(pkg.exports);
|
const exports = Object.entries(pkg.exports);
|
||||||
|
|
||||||
@ -195,7 +231,7 @@ const validateExportsOrdering = async ({ pkg, logger }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
function assertFirst(key, arr) {
|
function assertFirst(key: string, arr: string[]) {
|
||||||
const aIdx = arr.indexOf(key);
|
const aIdx = arr.indexOf(key);
|
||||||
|
|
||||||
// if not found, then we don't care
|
// if not found, then we don't care
|
||||||
@ -207,7 +243,7 @@ function assertFirst(key, arr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
function assertLast(key, arr) {
|
function assertLast(key: string, arr: string[]) {
|
||||||
const aIdx = arr.indexOf(key);
|
const aIdx = arr.indexOf(key);
|
||||||
|
|
||||||
// if not found, then we don't care
|
// if not found, then we don't care
|
||||||
@ -219,7 +255,7 @@ function assertLast(key, arr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
function assertOrder(keyA, keyB, arr) {
|
function assertOrder(keyA: string, keyB: string, arr: string[]) {
|
||||||
const aIdx = arr.indexOf(keyA);
|
const aIdx = arr.indexOf(keyA);
|
||||||
const bIdx = arr.indexOf(keyB);
|
const bIdx = arr.indexOf(keyB);
|
||||||
|
|
||||||
@ -231,24 +267,10 @@ function assertOrder(keyA, keyB, arr) {
|
|||||||
return aIdx < bIdx;
|
return aIdx < bIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Extensions
|
|
||||||
* @property {string} commonjs
|
|
||||||
* @property {string} esm
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ExtMap
|
|
||||||
* @property {Extensions} commonjs
|
|
||||||
* @property {Extensions} esm
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @type {ExtMap}
|
|
||||||
*/
|
*/
|
||||||
const DEFAULT_PKG_EXT_MAP = {
|
const DEFAULT_PKG_EXT_MAP: ExtMap = {
|
||||||
// pkg.type: "commonjs"
|
// pkg.type: "commonjs"
|
||||||
commonjs: {
|
commonjs: {
|
||||||
cjs: '.js',
|
cjs: '.js',
|
||||||
@ -266,21 +288,24 @@ const DEFAULT_PKG_EXT_MAP = {
|
|||||||
* We potentially might need to support legacy exports or as package
|
* We potentially might need to support legacy exports or as package
|
||||||
* development continues we have space to tweak this.
|
* development continues we have space to tweak this.
|
||||||
*
|
*
|
||||||
* @type {() => ExtMap}
|
|
||||||
*/
|
*/
|
||||||
const getExportExtensionMap = () => {
|
const getExportExtensionMap = (): ExtMap => {
|
||||||
return DEFAULT_PKG_EXT_MAP;
|
return DEFAULT_PKG_EXT_MAP;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface ValidateExportsOptions {
|
||||||
|
extMap: ExtMap;
|
||||||
|
pkg: PackageJson;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
* @description validate the `require` and `import` properties of a given exports maps from the package.json
|
* @description validate the `require` and `import` properties of a given exports maps from the package.json
|
||||||
* returning if any errors are found.
|
* returning if any errors are found.
|
||||||
*
|
*
|
||||||
* @type {(_exports: unknown, options: {extMap: ExtMap; pkg: PackageJson}) => string[]}
|
|
||||||
*/
|
*/
|
||||||
const validateExports = (_exports, options) => {
|
const validateExports = (_exports: ExportWithMeta[], options: ValidateExportsOptions): string[] => {
|
||||||
const { extMap, pkg } = options;
|
const { extMap, pkg } = options;
|
||||||
const ext = extMap[pkg.type || 'commonjs'];
|
const ext = extMap[pkg.type || 'commonjs'];
|
||||||
|
|
||||||
@ -303,27 +328,17 @@ const validateExports = (_exports, options) => {
|
|||||||
return errors;
|
return errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
interface ParseExportsOptions {
|
||||||
* @typedef {Object} Export
|
extMap: ExtMap;
|
||||||
* @property {string} _path the path of the export, `.` for the root.
|
pkg: PackageJson;
|
||||||
* @property {string=} types the path to the types file
|
}
|
||||||
* @property {string} source the path to the source file
|
|
||||||
* @property {string=} require the path to the commonjs require file
|
|
||||||
* @property {string=} import the path to the esm import file
|
|
||||||
* @property {string=} default the path to the default file
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description parse the exports map from the package.json into a standardised
|
* @description parse the exports map from the package.json into a standardised
|
||||||
* format that we can use to generate build tasks from.
|
* format that we can use to generate build tasks from.
|
||||||
*
|
|
||||||
* @type {(args: { extMap: ExtMap, pkg: PackageJson }) => Export[]}
|
|
||||||
*/
|
*/
|
||||||
const parseExports = ({ extMap, pkg }) => {
|
const parseExports = ({ extMap, pkg }: ParseExportsOptions): ExportWithMeta[] => {
|
||||||
/**
|
const rootExport: ExportWithMeta = {
|
||||||
* @type {Export}
|
|
||||||
*/
|
|
||||||
const rootExport = {
|
|
||||||
_path: '.',
|
_path: '.',
|
||||||
types: pkg.types,
|
types: pkg.types,
|
||||||
source: pkg.source,
|
source: pkg.source,
|
||||||
@ -332,15 +347,9 @@ const parseExports = ({ extMap, pkg }) => {
|
|||||||
default: pkg.module || pkg.main,
|
default: pkg.module || pkg.main,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const extraExports: ExportWithMeta[] = [];
|
||||||
* @type {Export[]}
|
|
||||||
*/
|
|
||||||
const extraExports = [];
|
|
||||||
|
|
||||||
/**
|
const errors: string[] = [];
|
||||||
* @type {string[]}
|
|
||||||
*/
|
|
||||||
const errors = [];
|
|
||||||
|
|
||||||
if (pkg.exports) {
|
if (pkg.exports) {
|
||||||
if (!pkg.exports['./package.json']) {
|
if (!pkg.exports['./package.json']) {
|
||||||
@ -394,14 +403,14 @@ const parseExports = ({ extMap, pkg }) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const _exports = [
|
const _exports: ExportWithMeta[] = [
|
||||||
/**
|
/**
|
||||||
* In the case of strapi plugins, we don't have a root export because we
|
* In the case of strapi plugins, we don't have a root export because we
|
||||||
* ship a server side and client side package. So this can be completely omitted.
|
* ship a server side and client side package. So this can be completely omitted.
|
||||||
*/
|
*/
|
||||||
Object.values(rootExport).some((exp) => exp !== rootExport._path && Boolean(exp)) && rootExport,
|
Object.values(rootExport).some((exp) => exp !== rootExport._path && Boolean(exp)) && rootExport,
|
||||||
...extraExports,
|
...extraExports,
|
||||||
].filter(Boolean);
|
].filter((v): v is ExportWithMeta => Boolean(v));
|
||||||
|
|
||||||
errors.push(...validateExports(_exports, { extMap, pkg }));
|
errors.push(...validateExports(_exports, { extMap, pkg }));
|
||||||
|
|
||||||
@ -412,10 +421,4 @@ const parseExports = ({ extMap, pkg }) => {
|
|||||||
return _exports;
|
return _exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export { loadPkg, validatePkg, validateExportsOrdering, getExportExtensionMap, parseExports };
|
||||||
loadPkg,
|
|
||||||
validatePkg,
|
|
||||||
validateExportsOrdering,
|
|
||||||
getExportExtensionMap,
|
|
||||||
parseExports,
|
|
||||||
};
|
|
||||||
@ -2,7 +2,7 @@ import type { Attribute, Common, Utils } from '../../../../../types';
|
|||||||
|
|
||||||
import type * as Operator from './operators';
|
import type * as Operator from './operators';
|
||||||
import type * as AttributeUtils from '../attributes';
|
import type * as AttributeUtils from '../attributes';
|
||||||
import type Params from '../index';
|
import type * as Params from '../index';
|
||||||
|
|
||||||
export { Operator };
|
export { Operator };
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json.schemastore.org/tsconfig",
|
"$schema": "http://json.schemastore.org/tsconfig",
|
||||||
"extends": "./base.json",
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "ESNext",
|
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"target": "es2015",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noEmit": true
|
"noEmit": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user