From d6583a6945565ebe4e446d961051a720e1e7e8a1 Mon Sep 17 00:00:00 2001 From: Quentin Deroubaix <139884126+quentinderoubaix@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:32:25 +0100 Subject: [PATCH] ci(angular): fail build when an angular directive or component is not exported (#561) --- angular/lib/package.json | 6 ++- angular/lib/scripts/verify-module.mjs | 50 ++++++++++++++++++++++ angular/lib/src/agnos-ui-angular.module.ts | 3 +- package.json | 1 + 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 angular/lib/scripts/verify-module.mjs diff --git a/angular/lib/package.json b/angular/lib/package.json index 5f13b4110d..c23e969cde 100644 --- a/angular/lib/package.json +++ b/angular/lib/package.json @@ -12,7 +12,8 @@ }, "scripts": { "ng": "ng", - "build": "wireit" + "build": "wireit", + "check": "wireit" }, "wireit": { "build:src": { @@ -52,6 +53,9 @@ "dependencies": [ "build:pkg" ] + }, + "check": { + "command": "node scripts/verify-module.mjs" } }, "peerDependencies": { diff --git a/angular/lib/scripts/verify-module.mjs b/angular/lib/scripts/verify-module.mjs new file mode 100644 index 0000000000..d42e3db6ec --- /dev/null +++ b/angular/lib/scripts/verify-module.mjs @@ -0,0 +1,50 @@ +import {glob} from 'glob'; +import path from 'path'; +import {fileURLToPath} from 'url'; +import {readFile} from 'fs/promises'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const pathRegExp = /\\/g; +function normalizePath(str) { + return str.replace(pathRegExp, '/'); +} + +const COMPONENTS_FOLDER = path.join(__dirname, '../src/components'); + +const files = ( + await glob('**/*.component.ts', { + cwd: COMPONENTS_FOLDER, + nodir: true, + }) +).map((file) => normalizePath(path.join(COMPONENTS_FOLDER, file))); + +const stuffToExportRegex = /(@Directive|@Component)\({[\S\s]+?}\)\s*export class ([a-zA-Z]*)/g; + +const classesToExport = []; +for (const file of files) { + const content = await readFile(file, {encoding: 'utf-8'}); + const matches = [...content.matchAll(stuffToExportRegex)]; + for (const match of matches) { + classesToExport.push(match[2]); + } +} + +const angularModuleContent = await readFile(normalizePath(path.join(__dirname, '../src/agnos-ui-angular.module.ts')), {encoding: 'utf-8'}); +const componentsFromAngularModule = new Set( + angularModuleContent + .match(/const components = \[([^\]]+)\];/)[1] + .split(',') + .map((component) => component.trim()) + .filter((component) => !!component), +); + +const defaultSlotRegex = /^[a-zA-Z]*Default[a-zA-Z]*Slots?Component$/; +const missingComponents = classesToExport.filter( + (classToExport) => !componentsFromAngularModule.has(classToExport) && !classToExport.match(defaultSlotRegex), +); + +if (missingComponents.length) { + console.error(`ERROR ! The following Angular components / directives are not exported in the main angular module: ${missingComponents.join(', ')}`); + process.exit(1); +} diff --git a/angular/lib/src/agnos-ui-angular.module.ts b/angular/lib/src/agnos-ui-angular.module.ts index a3b4aabf2f..5bf2de4072 100644 --- a/angular/lib/src/agnos-ui-angular.module.ts +++ b/angular/lib/src/agnos-ui-angular.module.ts @@ -31,7 +31,7 @@ import { } from './components/accordion/accordion.component'; import {SliderComponent, SliderHandleDirective, SliderLabelDirective, SliderStructureDirective} from './components/slider/slider.component'; import {ProgressbarComponent, ProgressbarStructureDirective} from './components/progressbar/progressbar.component'; -import {ToastBodyDirective, ToastComponent, ToastStructureDirective} from './components/toast/toast.component'; +import {ToastBodyDirective, ToastComponent, ToastHeaderDirective, ToastStructureDirective} from './components/toast/toast.component'; /* istanbul ignore next */ const components = [ SlotDirective, @@ -73,6 +73,7 @@ const components = [ ToastComponent, ToastStructureDirective, ToastBodyDirective, + ToastHeaderDirective, ]; @NgModule({ diff --git a/package.json b/package.json index 08e0a9bb02..611d343ca3 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,7 @@ "./svelte/headless:check", "./svelte/lib:check", "./svelte/demo:check", + "./angular/lib:check", "./demo:check" ] },