mirror of
https://github.com/directus/directus.git
synced 2026-01-27 22:57:56 -05:00
Configure build command based on extension manifest (#6706)
* Add simple logger to extension-sdk CLI * Configure build command based on extension manifest The configuration can be overwritten by command line options. Adds a "force" option to ignore if there is no package.json in the cwd.
This commit is contained in:
committed by
GitHub
parent
ff393eab3b
commit
f64ad3335c
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import fse from 'fs-extra';
|
||||
@@ -11,37 +9,56 @@ import { terser } from 'rollup-plugin-terser';
|
||||
import styles from 'rollup-plugin-styles';
|
||||
import vue from 'rollup-plugin-vue';
|
||||
import { APP_EXTENSION_TYPES, EXTENSION_PKG_KEY, SHARED_DEPS } from '@directus/shared/constants';
|
||||
import { AppExtensionType } from '@directus/shared/types';
|
||||
import log from '../utils/logger';
|
||||
import validateExtensionPackage from '../utils/validate-extension-package';
|
||||
|
||||
export default async function build(options: { input: string; output: string }): Promise<void> {
|
||||
type BuildOptions = { type: AppExtensionType; input: string; output: string; force: boolean };
|
||||
|
||||
export default async function build(options: BuildOptions): Promise<void> {
|
||||
const packagePath = path.resolve('package.json');
|
||||
let packageManifest: Record<string, any> = {};
|
||||
|
||||
if (!(await fse.pathExists(packagePath))) {
|
||||
console.log(`${chalk.bold.red('[Error]')} Current directory is not a package.`);
|
||||
log(`Current directory is not a package.`, !options.force ? 'error' : 'warn');
|
||||
if (!options.force) process.exit(1);
|
||||
} else {
|
||||
packageManifest = await fse.readJSON(packagePath);
|
||||
|
||||
if (!packageManifest[EXTENSION_PKG_KEY] || !validateExtensionPackage(packageManifest[EXTENSION_PKG_KEY])) {
|
||||
log(`Current directory is not a Directus extension.`, !options.force ? 'error' : 'warn');
|
||||
if (!options.force) process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const type = options.type || packageManifest[EXTENSION_PKG_KEY]?.type;
|
||||
const input = options.input || packageManifest[EXTENSION_PKG_KEY]?.source;
|
||||
const output = options.output || packageManifest[EXTENSION_PKG_KEY]?.path;
|
||||
|
||||
if (!APP_EXTENSION_TYPES.includes(type)) {
|
||||
log(
|
||||
`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${APP_EXTENSION_TYPES.map((t) =>
|
||||
chalk.bold.magenta(t)
|
||||
).join(', ')}.`,
|
||||
!options.force ? 'error' : 'warn'
|
||||
);
|
||||
if (!options.force) process.exit(1);
|
||||
}
|
||||
|
||||
if (!(await fse.pathExists(input)) || !(await fse.stat(input)).isFile()) {
|
||||
log(`Entrypoint ${chalk.bold(input)} does not exist.`, 'error');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const packageManifest = await fse.readJSON(packagePath);
|
||||
|
||||
if (!packageManifest[EXTENSION_PKG_KEY] || !packageManifest[EXTENSION_PKG_KEY].type) {
|
||||
console.log(`${chalk.bold.yellow('[Warn]')} Current directory is not a Directus extension.`);
|
||||
} else {
|
||||
const type = packageManifest[EXTENSION_PKG_KEY].type;
|
||||
|
||||
if (!APP_EXTENSION_TYPES.includes(type)) {
|
||||
console.log(
|
||||
`${chalk.bold.yellow('[Warn]')} Extension type ${chalk.bold(
|
||||
type
|
||||
)} is not supported. Available extension types: ${APP_EXTENSION_TYPES.map((t) => chalk.bold.magenta(t)).join(
|
||||
', '
|
||||
)}.`
|
||||
);
|
||||
}
|
||||
if (!output) {
|
||||
log(`Output file must be a valid path.`, 'error');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const spinner = ora('Building Directus extension...').start();
|
||||
|
||||
const bundle = await rollup({
|
||||
input: options.input,
|
||||
input,
|
||||
external: SHARED_DEPS,
|
||||
plugins: [
|
||||
vue({ preprocessStyles: true }),
|
||||
@@ -54,7 +71,7 @@ export default async function build(options: { input: string; output: string }):
|
||||
|
||||
await bundle.write({
|
||||
format: 'es',
|
||||
file: options.output,
|
||||
file: output,
|
||||
});
|
||||
|
||||
await bundle.close();
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import fse from 'fs-extra';
|
||||
@@ -7,6 +5,7 @@ import execa from 'execa';
|
||||
import ora from 'ora';
|
||||
import { EXTENSION_TYPES, EXTENSION_PKG_KEY } from '@directus/shared/constants';
|
||||
import { ExtensionType } from '@directus/shared/types';
|
||||
import log from '../utils/logger';
|
||||
|
||||
const pkg = require('../../../../package.json');
|
||||
|
||||
@@ -16,10 +15,11 @@ export default async function create(type: ExtensionType, name: string): Promise
|
||||
const targetPath = path.resolve(name);
|
||||
|
||||
if (!EXTENSION_TYPES.includes(type)) {
|
||||
console.log(
|
||||
`${chalk.bold.red('[Error]')} Extension type ${chalk.bold(
|
||||
type
|
||||
)} does not exist. Available extension types: ${EXTENSION_TYPES.map((t) => chalk.bold.magenta(t)).join(', ')}.`
|
||||
log(
|
||||
`Extension type ${chalk.bold(type)} does not exist. Available extension types: ${EXTENSION_TYPES.map((t) =>
|
||||
chalk.bold.magenta(t)
|
||||
).join(', ')}.`,
|
||||
'error'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -28,16 +28,14 @@ export default async function create(type: ExtensionType, name: string): Promise
|
||||
const info = await fse.stat(targetPath);
|
||||
|
||||
if (!info.isDirectory()) {
|
||||
console.log(
|
||||
`${chalk.bold.red('[Error]')} Destination ${chalk.bold(name)} already exists and is not a directory.`
|
||||
);
|
||||
log(`Destination ${chalk.bold(name)} already exists and is not a directory.`, 'error');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const files = await fse.readdir(targetPath);
|
||||
|
||||
if (files.length > 0) {
|
||||
console.log(`${chalk.bold.red('[Error]')} Destination ${chalk.bold(name)} already exists and is not empty.`);
|
||||
log(`Destination ${chalk.bold(name)} already exists and is not empty.`, 'error');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -54,7 +52,7 @@ export default async function create(type: ExtensionType, name: string): Promise
|
||||
version: '1.0.0',
|
||||
keywords: ['directus', 'directus-extension', `directus-custom-${type}`],
|
||||
[EXTENSION_PKG_KEY]: {
|
||||
type: type,
|
||||
type,
|
||||
path: 'dist/index.js',
|
||||
source: 'src/index.js',
|
||||
host: `^${pkg.version}`,
|
||||
@@ -74,7 +72,7 @@ export default async function create(type: ExtensionType, name: string): Promise
|
||||
|
||||
spinner.succeed('Done');
|
||||
|
||||
console.log(`
|
||||
log(`
|
||||
Your ${type} extension has been created at ${chalk.green(targetPath)}
|
||||
|
||||
Build your extension by running:
|
||||
|
||||
@@ -14,8 +14,10 @@ program.command('create').arguments('<type> <name>').description('Scaffold a new
|
||||
program
|
||||
.command('build')
|
||||
.description('Bundle a Directus extension to a single entrypoint')
|
||||
.option('-i, --input <file>', 'change the default entrypoint', 'src/index.js')
|
||||
.option('-o, --output <file>', 'change the default output file', 'dist/index.js')
|
||||
.option('-t, --type <type>', 'overwrite the extension type read from package manifest')
|
||||
.option('-i, --input <file>', 'overwrite the entrypoint read from package manifest')
|
||||
.option('-o, --output <file>', 'overwrite the output file read from package manifest')
|
||||
.option('-f, --force', 'ignore the package manifest')
|
||||
.action(build);
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
15
packages/extension-sdk/src/cli/utils/logger.ts
Normal file
15
packages/extension-sdk/src/cli/utils/logger.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import chalk from 'chalk';
|
||||
|
||||
export default function log(message: string, type?: 'info' | 'warn' | 'error'): void {
|
||||
if (type === 'info') {
|
||||
console.log(`${chalk.bold.gray('[Info]')} ${message}`);
|
||||
} else if (type === 'warn') {
|
||||
console.warn(`${chalk.bold.yellow('[Warn]')} ${message}`);
|
||||
} else if (type === 'error') {
|
||||
console.error(`${chalk.bold.red('[Error]')} ${message}`);
|
||||
} else {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export default function validateExtensionPackage(extension: Record<string, any>): boolean {
|
||||
if (
|
||||
extension.type === undefined ||
|
||||
extension.path === undefined ||
|
||||
extension.source === undefined ||
|
||||
extension.host === undefined ||
|
||||
extension.hidden === undefined
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user