From d544214c790f77fa529ad7d74c462f9ae48ced27 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Thu, 24 Jun 2021 00:16:13 +0200 Subject: [PATCH] Fix extension loading on initial startup (#6471) --- api/src/extensions.ts | 31 ++++++++----------- app/vite.config.js | 17 +++++++--- .../src/utils/ensure-extensions-dirs.ts | 11 +++++++ .../src/utils/generate-extensions-entry.ts | 10 ++++++ .../{load-extensions.ts => get-extensions.ts} | 10 +----- packages/shared/src/utils/index.ts | 4 ++- 6 files changed, 51 insertions(+), 32 deletions(-) create mode 100644 packages/shared/src/utils/ensure-extensions-dirs.ts create mode 100644 packages/shared/src/utils/generate-extensions-entry.ts rename packages/shared/src/utils/{load-extensions.ts => get-extensions.ts} (85%) diff --git a/api/src/extensions.ts b/api/src/extensions.ts index c7cdada593..9684c230fe 100644 --- a/api/src/extensions.ts +++ b/api/src/extensions.ts @@ -2,13 +2,13 @@ import express, { Router } from 'express'; import path from 'path'; import { AppExtensionType, Extension, ExtensionType } from '@directus/shared/types'; import { + ensureExtensionsDirs, generateExtensionsEntry, getLocalExtensions, getPackageExtensions, - pluralize, resolvePackage, } from '@directus/shared/utils'; -import { APP_EXTENSION_TYPES, EXTENSION_TYPES, SHARED_DEPS } from '@directus/shared/constants'; +import { APP_EXTENSION_TYPES, SHARED_DEPS } from '@directus/shared/constants'; import getDatabase from './database'; import emitter from './emitter'; import env from './env'; @@ -30,11 +30,17 @@ let extensions: Extension[] = []; let extensionBundles: Partial> = {}; export async function initializeExtensions(): Promise { - await ensureDirsExist(); + await ensureExtensionsDirs(env.EXTENSIONS_PATH); extensions = await getExtensions(); - extensionBundles = await generateExtensionBundles(); - logger.info(`Loaded extensions: ${listExtensions().join(', ')}`); + if (!('DIRECTUS_DEV' in process.env)) { + extensionBundles = await generateExtensionBundles(); + } + + const loadedExtensions = listExtensions(); + if (loadedExtensions.length > 0) { + logger.info(`Loaded extensions: ${loadedExtensions.join(', ')}`); + } } export function listExtensions(type?: ExtensionType): string[] { @@ -80,7 +86,7 @@ async function generateExtensionBundles() { const bundle = await rollup({ input: 'entry', - external: SHARED_DEPS, + external: Object.values(sharedDepsMapping), plugins: [virtual({ entry }), alias({ entries: internalImports })], }); const { output } = await bundle.generate({ format: 'es' }); @@ -93,17 +99,6 @@ async function generateExtensionBundles() { return bundles; } -async function ensureDirsExist() { - for (const extensionType of EXTENSION_TYPES) { - const dirPath = path.resolve(env.EXTENSIONS_PATH, pluralize(extensionType)); - try { - await fse.ensureDir(dirPath); - } catch (err) { - logger.warn(err); - } - } -} - async function getSharedDepsMapping(deps: string[]) { const appDir = await fse.readdir(path.join(resolvePackage('@directus/app'), 'dist')); @@ -114,7 +109,7 @@ async function getSharedDepsMapping(deps: string[]) { if (depName) { depsMapping[dep] = `${env.PUBLIC_URL}/admin/${depName}`; } else { - logger.warn(`Couldn't find extension internal dependency "${dep}"`); + logger.warn(`Couldn't find shared extension dependency "${dep}"`); } } diff --git a/app/vite.config.js b/app/vite.config.js index 9bc7a2f2bb..a673cbbc3e 100644 --- a/app/vite.config.js +++ b/app/vite.config.js @@ -2,7 +2,12 @@ import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import yaml from '@rollup/plugin-yaml'; import path from 'path'; -import { getPackageExtensions, getLocalExtensions, generateExtensionsEntry } from '@directus/shared/utils'; +import { + ensureExtensionsDirs, + getPackageExtensions, + getLocalExtensions, + generateExtensionsEntry, +} from '@directus/shared/utils'; import { SHARED_DEPS, APP_EXTENSION_TYPES } from '@directus/shared/constants'; // https://vitejs.dev/config/ @@ -38,7 +43,7 @@ function directusExtensions() { const virtualIds = APP_EXTENSION_TYPES.map((type) => `${prefix}${type}`); let extensionEntrys = {}; - loadExtensions(); + if (process.env.NODE_ENV !== 'production') loadExtensions(); return [ { @@ -84,8 +89,12 @@ function directusExtensions() { ]; async function loadExtensions() { - const packageExtensions = await getPackageExtensions(path.join('..', 'api')); - const localExtensions = await getLocalExtensions(path.join('..', 'api', 'extensions')); + const apiPath = path.join('..', 'api'); + const extensionsPath = path.join(apiPath, 'extensions'); + + await ensureExtensionsDirs(extensionsPath); + const packageExtensions = await getPackageExtensions(apiPath); + const localExtensions = await getLocalExtensions(extensionsPath); const extensions = [...packageExtensions, ...localExtensions]; diff --git a/packages/shared/src/utils/ensure-extensions-dirs.ts b/packages/shared/src/utils/ensure-extensions-dirs.ts new file mode 100644 index 0000000000..57698612c1 --- /dev/null +++ b/packages/shared/src/utils/ensure-extensions-dirs.ts @@ -0,0 +1,11 @@ +import path from 'path'; +import fse from 'fs-extra'; +import { pluralize } from './pluralize'; +import { EXTENSION_TYPES } from '../constants'; + +export async function ensureExtensionsDirs(extensionsPath: string): Promise { + for (const extensionType of EXTENSION_TYPES) { + const dirPath = path.resolve(extensionsPath, pluralize(extensionType)); + await fse.ensureDir(dirPath); + } +} diff --git a/packages/shared/src/utils/generate-extensions-entry.ts b/packages/shared/src/utils/generate-extensions-entry.ts new file mode 100644 index 0000000000..daa5b0a975 --- /dev/null +++ b/packages/shared/src/utils/generate-extensions-entry.ts @@ -0,0 +1,10 @@ +import path from 'path'; +import { AppExtensionType, Extension } from '../types'; + +export function generateExtensionsEntry(type: AppExtensionType, extensions: Extension[]): string { + const filteredExtensions = extensions.filter((extension) => extension.type === type); + + return `${filteredExtensions + .map((extension, i) => `import e${i} from '${path.resolve(extension.path, extension.entrypoint || '')}';\n`) + .join('')}export default [${filteredExtensions.map((_, i) => `e${i}`).join(',')}];`; +} diff --git a/packages/shared/src/utils/load-extensions.ts b/packages/shared/src/utils/get-extensions.ts similarity index 85% rename from packages/shared/src/utils/load-extensions.ts rename to packages/shared/src/utils/get-extensions.ts index 768018395f..8c8dccce73 100644 --- a/packages/shared/src/utils/load-extensions.ts +++ b/packages/shared/src/utils/get-extensions.ts @@ -1,6 +1,6 @@ import path from 'path'; import fse from 'fs-extra'; -import { AppExtensionType, Extension } from '../types'; +import { Extension } from '../types'; import { resolvePackage } from './resolve-package'; import { listFolders } from './list-folders'; import { EXTENSION_NAME_REGEX, EXTENSION_TYPES } from '../constants'; @@ -85,11 +85,3 @@ export async function getLocalExtensions(root: string): Promise { return extensions; } - -export function generateExtensionsEntry(type: AppExtensionType, extensions: Extension[]): string { - const filteredExtensions = extensions.filter((extension) => extension.type === type); - - return `${filteredExtensions - .map((extension, i) => `import e${i} from '${path.resolve(extension.path, extension.entrypoint || '')}';\n`) - .join('')}export default [${filteredExtensions.map((_, i) => `e${i}`).join(',')}];`; -} diff --git a/packages/shared/src/utils/index.ts b/packages/shared/src/utils/index.ts index 95d4e45f30..7ceefd68bb 100644 --- a/packages/shared/src/utils/index.ts +++ b/packages/shared/src/utils/index.ts @@ -1,4 +1,6 @@ +export * from './ensure-extensions-dirs'; +export * from './generate-extensions-entry'; +export * from './get-extensions'; export * from './list-folders'; -export * from './load-extensions'; export * from './pluralize'; export * from './resolve-package';