From 1989760ccce4ed6d117127dc5ccf7615614a76e7 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Sun, 11 Jul 2021 10:01:18 +0200 Subject: [PATCH] Allow extension-sdk to bundle API extensions as well (#6735) This also converts the API extension templates to ESM syntax. --- .../extension-sdk/src/cli/commands/build.ts | 73 +++++++++++++------ .../templates/endpoint/src/index.js | 2 +- .../extension-sdk/templates/hook/src/index.js | 14 ++-- packages/shared/src/constants/extensions.ts | 3 +- 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/packages/extension-sdk/src/cli/commands/build.ts b/packages/extension-sdk/src/cli/commands/build.ts index 3d33b24fae..9508f50cf2 100644 --- a/packages/extension-sdk/src/cli/commands/build.ts +++ b/packages/extension-sdk/src/cli/commands/build.ts @@ -2,14 +2,14 @@ import path from 'path'; import chalk from 'chalk'; import fse from 'fs-extra'; import ora from 'ora'; -import { rollup } from 'rollup'; +import { OutputOptions as RollupOutputOptions, rollup, RollupOptions } from 'rollup'; import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; 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 { isAppExtension } from '@directus/shared/utils'; +import { EXTENSION_PKG_KEY, EXTENSION_TYPES, APP_SHARED_DEPS, API_SHARED_DEPS } from '@directus/shared/constants'; +import { isAppExtension, isExtension } from '@directus/shared/utils'; import { ExtensionManifest } from '@directus/shared/types'; import log from '../utils/logger'; import validateExtensionManifest from '../utils/validate-extension-manifest'; @@ -36,14 +36,14 @@ export default async function build(options: BuildOptions): Promise { const input = options.input || extensionManifest[EXTENSION_PKG_KEY]?.source; const output = options.output || extensionManifest[EXTENSION_PKG_KEY]?.path; - if (!type || !isAppExtension(type)) { + if (!type || !isExtension(type)) { log( - `Extension type ${chalk.bold(type)} is not supported. Available extension types: ${APP_EXTENSION_TYPES.map((t) => + `Extension type ${chalk.bold(type)} does not exist. Available extension types: ${EXTENSION_TYPES.map((t) => chalk.bold.magenta(t) ).join(', ')}.`, - !options.force ? 'error' : 'warn' + 'error' ); - if (!options.force) process.exit(1); + process.exit(1); } if (!input || !(await fse.pathExists(input)) || !(await fse.stat(input)).isFile()) { @@ -56,26 +56,55 @@ export default async function build(options: BuildOptions): Promise { process.exit(1); } + const isApp = isAppExtension(type); + const spinner = ora('Building Directus extension...').start(); - const bundle = await rollup({ - input, - external: SHARED_DEPS, - plugins: [ - vue({ preprocessStyles: true }), - styles(), - nodeResolve(), - commonjs({ esmExternals: true, sourceMap: false }), - terser(), - ], - }); + const rollupOptions = getRollupOptions(isApp, input); + const rollupOutputOptions = getRollupOutputOptions(isApp, output); - await bundle.write({ - format: 'es', - file: output, - }); + const bundle = await rollup(rollupOptions); + + await bundle.write(rollupOutputOptions); await bundle.close(); spinner.succeed('Done'); } + +function getRollupOptions(isApp: boolean, input: string): RollupOptions { + if (isApp) { + return { + input, + external: APP_SHARED_DEPS, + plugins: [ + vue({ preprocessStyles: true }), + styles(), + nodeResolve(), + commonjs({ esmExternals: true, sourceMap: false }), + terser(), + ], + }; + } else { + return { + input, + external: API_SHARED_DEPS, + plugins: [nodeResolve(), commonjs({ sourceMap: false }), terser()], + }; + } +} + +function getRollupOutputOptions(isApp: boolean, output: string): RollupOutputOptions { + if (isApp) { + return { + file: output, + format: 'es', + }; + } else { + return { + file: output, + format: 'cjs', + exports: 'default', + }; + } +} diff --git a/packages/extension-sdk/templates/endpoint/src/index.js b/packages/extension-sdk/templates/endpoint/src/index.js index 8cc23f3271..92f2edbb89 100644 --- a/packages/extension-sdk/templates/endpoint/src/index.js +++ b/packages/extension-sdk/templates/endpoint/src/index.js @@ -1,3 +1,3 @@ -module.exports = function registerEndpoint(router) { +export default (router) => { router.get('/', (req, res) => res.send('Hello, World!')); }; diff --git a/packages/extension-sdk/templates/hook/src/index.js b/packages/extension-sdk/templates/hook/src/index.js index a6e83fc558..ae6c61418c 100644 --- a/packages/extension-sdk/templates/hook/src/index.js +++ b/packages/extension-sdk/templates/hook/src/index.js @@ -1,9 +1,5 @@ -const axios = require('axios'); - -module.exports = function registerHook() { - return { - 'items.create': function () { - axios.post('http://example.com/webhook'); - }, - }; -}; +export default () => ({ + 'items.create': () => { + console.log('Item created!'); + }, +}); diff --git a/packages/shared/src/constants/extensions.ts b/packages/shared/src/constants/extensions.ts index 62209573f1..cdeada3ddb 100644 --- a/packages/shared/src/constants/extensions.ts +++ b/packages/shared/src/constants/extensions.ts @@ -1,6 +1,7 @@ import { ApiExtensionType, AppExtensionType, ExtensionType } from '../types'; -export const SHARED_DEPS = ['@directus/extension-sdk', 'vue']; +export const APP_SHARED_DEPS = ['@directus/extension-sdk', 'vue']; +export const API_SHARED_DEPS = ['axios']; export const APP_EXTENSION_TYPES: AppExtensionType[] = ['interface', 'display', 'layout', 'module']; export const API_EXTENSION_TYPES: ApiExtensionType[] = ['endpoint', 'hook'];