Browse Source

refactor(ui-devkit): Refactor uiExtension wrapper allow multiple files

Michael Bromley 2 years ago
parent
commit
8385ce86d7

+ 30 - 15
packages/ui-devkit/src/compiler/scaffold.ts

@@ -12,6 +12,7 @@ import {
 } from './constants';
 import { getAllTranslationFiles, mergeExtensionTranslations } from './translations';
 import {
+    AdminUiExtension,
     AdminUiExtensionLazyModule,
     AdminUiExtensionSharedModule,
     AdminUiExtensionWithId,
@@ -38,14 +39,16 @@ import {
 export async function setupScaffold(outputPath: string, extensions: Extension[]) {
     deleteExistingExtensionModules(outputPath);
 
-    const adminUiExtensions = extensions.filter(isAdminUiExtension);
-    const sharedUiProvidersExtensions = extensions.filter(isSharedUiProvidersExtension);
+    const adminUiExtensions = extensions.filter(
+        (e): e is AdminUiExtension | SharedUiProvidersExtension =>
+            isAdminUiExtension(e) || isSharedUiProvidersExtension(e),
+    );
     const normalizedExtensions = normalizeExtensions(adminUiExtensions);
 
     const modulePathMapping = generateModulePathMapping(normalizedExtensions);
     copyAdminUiSource(outputPath, modulePathMapping);
 
-    await copyExtensionModules(outputPath, [...normalizedExtensions, ...sharedUiProvidersExtensions]);
+    await copyExtensionModules(outputPath, normalizedExtensions);
 
     const staticAssetExtensions = extensions.filter(isStaticAssetExtension);
     await copyStaticAssets(outputPath, staticAssetExtensions);
@@ -91,11 +94,8 @@ function generateModulePathMapping(extensions: AdminUiExtensionWithId[]) {
  * Copies all files from the extensionPaths of the configured extensions into the
  * admin-ui source tree.
  */
-async function copyExtensionModules(
-    outputPath: string,
-    extensions: Array<AdminUiExtensionWithId | SharedUiProvidersExtension>,
-) {
-    const adminUiExtensions = extensions.filter(isAdminUiExtension) as AdminUiExtensionWithId[];
+async function copyExtensionModules(outputPath: string, extensions: AdminUiExtensionWithId[]) {
+    const adminUiExtensions = extensions.filter(isAdminUiExtension);
     const sharedUiProvidersExtensions = extensions.filter(isSharedUiProvidersExtension);
     const extensionRoutesSource = generateLazyExtensionRoutes(adminUiExtensions);
     fs.writeFileSync(path.join(outputPath, EXTENSION_ROUTES_FILE), extensionRoutesSource, 'utf8');
@@ -103,22 +103,31 @@ async function copyExtensionModules(
     fs.writeFileSync(path.join(outputPath, SHARED_EXTENSIONS_FILE), sharedExtensionModulesSource, 'utf8');
 
     for (const extension of adminUiExtensions) {
+        if (!extension.extensionPath) {
+            continue;
+        }
         const dest = path.join(outputPath, MODULES_OUTPUT_DIR, extension.id);
         if (!extension.exclude) {
             fs.copySync(extension.extensionPath, dest);
             continue;
         }
 
-        const exclude = extension.exclude
-            .map(e => globSync(path.join(extension.extensionPath, e)))
-            .flatMap(e => e);
+        const exclude =
+            extension.exclude?.map(e => globSync(path.join(extension.extensionPath, e))).flatMap(e => e) ??
+            [];
         fs.copySync(extension.extensionPath, dest, {
             filter: name => name === extension.extensionPath || exclude.every(e => e !== name),
         });
     }
     for (const extension of sharedUiProvidersExtensions) {
-        const dest = path.join(outputPath, MODULES_OUTPUT_DIR, `${extension.id}.ts`);
-        fs.copySync(extension.sharedProviders, dest);
+        if (extension.sharedProviders) {
+            let i = 0;
+            for (const filePath of extension.sharedProviders) {
+                const dest = path.join(outputPath, MODULES_OUTPUT_DIR, `${extension.id}_${i}.ts`);
+                fs.copySync(filePath, dest);
+                i++;
+            }
+        }
     }
 }
 
@@ -215,7 +224,11 @@ ${adminUiExtensions
     )
     .join('')}
 ${sharedProviderExtensions
-    .map((m, i) => `import SharedProviders${i} from './extensions/${m.id}';\n`)
+    .map((m, i) =>
+        m.sharedProviders
+            .map((f, j) => `import SharedProviders_${i}_${j} from './extensions/${m.id}_${i}';\n`)
+            .join(''),
+    )
     .join('')}
 
 @NgModule({
@@ -227,7 +240,9 @@ ${sharedProviderExtensions
                 .join(', '),
         )
         .join(', ')}],
-    providers: [${sharedProviderExtensions.map((m, i) => `...SharedProviders${i}`).join(', ')}],
+    providers: [${sharedProviderExtensions
+        .map((m, i) => m.sharedProviders.map((f, j) => `...SharedProviders_${i}_${j}`))
+        .join(', ')}],
 })
 export class SharedExtensionsModule {}
 `;

+ 11 - 10
packages/ui-devkit/src/compiler/types.ts

@@ -93,7 +93,7 @@ export interface SassVariableOverridesExtension {
  */
 export interface SharedUiProvidersExtension {
     id: string;
-    sharedProviders: string;
+    sharedProviders: string[];
 }
 
 /**
@@ -112,7 +112,8 @@ export interface SharedUiProvidersExtension {
 export interface AdminUiExtension
     extends Partial<TranslationExtension>,
         Partial<StaticAssetExtension>,
-        Partial<GlobalStylesExtension> {
+        Partial<GlobalStylesExtension>,
+        Partial<SharedUiProvidersExtension> {
     /**
      * @description
      * An optional ID for the extension module. Only used internally for generating
@@ -148,8 +149,7 @@ export interface AdminUiExtension
      * well as linting.
      *
      * @example
-     * ```ts
-     * // packages/common-ui-module/src/ui/ui-shared.module.ts
+     * ```ts title="packages/common-ui-module/src/ui/ui-shared.module.ts"
      * import { NgModule } from '\@angular/core';
      * import { SharedModule } from '\@vendure/admin-ui/core';
      * import { CommonUiComponent } from './components/common-ui/common-ui.component';
@@ -164,13 +164,13 @@ export interface AdminUiExtension
      * export class CommonSharedUiModule {}
      * ```
      *
-     * ```ts
-     * // packages/common-ui-module/src/index.ts
+     * ```ts title="packages/common-ui-module/src/index.ts"
      * import path from 'path';
      *
      * import { AdminUiExtension } from '\@vendure/ui-devkit/compiler';
      *
      * export const uiExtensions: AdminUiExtension = {
+     *   // highlight-next-line
      *   pathAlias: '\@common-ui-module',     // this is the important part
      *   extensionPath: path.join(__dirname, 'ui'),
      *   ngModules: [
@@ -183,25 +183,26 @@ export interface AdminUiExtension
      * };
      * ```
      *
-     * ```json
-     * // tsconfig.json
+     * ```json title="tsconfig.json"
      * {
      *   "compilerOptions": {
      *     "baseUrl": ".",
      *     "paths": {
+     *       // highlight-next-line
      *       "\@common-ui-module/*": ["packages/common-ui-module/src/ui/*"]
      *     }
      *   }
      * }
      * ```
      *
-     * ```ts
-     * // packages/sample-plugin/src/ui/ui-extension.module.ts
+     * ```ts title="packages/sample-plugin/src/ui/ui-extension.module.ts"
      * import { NgModule } from '\@angular/core';
      * import { SharedModule } from '\@vendure/admin-ui/core';
+     * // highlight-start
      * // the import below works both in the context of the custom Admin UI app as well as the main project
      * // '\@common-ui-module' is the value of "pathAlias" and 'ui-shared.module' is the file we want to reference inside "extensionPath"
      * import { CommonSharedUiModule, CommonUiComponent } from '\@common-ui-module/ui-shared.module';
+     * // highlight-end
      *
      * \@NgModule({
      *   imports: [

+ 12 - 2
packages/ui-devkit/src/compiler/utils.ts

@@ -80,7 +80,9 @@ export async function copyStaticAsset(outputPath: string, staticAssetDef: Static
  * If not defined by the user, a deterministic ID is generated
  * from a hash of the extension config.
  */
-export function normalizeExtensions(extensions?: AdminUiExtension[]): AdminUiExtensionWithId[] {
+export function normalizeExtensions(
+    extensions?: Array<AdminUiExtension | SharedUiProvidersExtension>,
+): AdminUiExtensionWithId[] {
     return (extensions || []).map(e => {
         let id = e.id;
         if (!id) {
@@ -89,7 +91,15 @@ export function normalizeExtensions(extensions?: AdminUiExtension[]): AdminUiExt
             id = hash.digest('hex');
         }
 
-        return { staticAssets: [], translations: {}, globalStyles: [], ...e, id };
+        return {
+            staticAssets: [],
+            translations: {},
+            globalStyles: [],
+            extensionPath: '',
+            ngModules: [],
+            ...e,
+            id,
+        };
     });
 }
 

+ 4 - 3
packages/ui-devkit/src/compiler/wrappers.ts

@@ -3,10 +3,11 @@ import path from 'path';
 
 import { SharedUiProvidersExtension } from './types';
 
-export function uiExtensions(filePath: string): SharedUiProvidersExtension {
+export function uiExtensions(options: { id?: string; files: string | string[] }): SharedUiProvidersExtension {
+    const files = Array.isArray(options.files) ? options.files : [options.files];
     return {
-        id: getIdFromFilePath(filePath),
-        sharedProviders: filePath,
+        id: options.id || getIdFromFilePath(files[0]),
+        sharedProviders: files,
     };
 }