From 19eeee6bdf1aa9a5ad998b387b61fa98713dc089 Mon Sep 17 00:00:00 2001 From: cipchk Date: Fri, 10 Nov 2023 13:11:56 +0800 Subject: [PATCH] feat(acl): remove `forRoot` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: 提升 `ACLService`,`ACLGuardService` 为 `root` 就无须再依赖 `forRoot`,事实上 `root` 当未使用时是不影响摇树 --- packages/acl/docs/getting-started.en-US.md | 4 +- packages/acl/docs/getting-started.zh-CN.md | 4 +- packages/acl/src/acl-guard.spec.ts | 2 +- packages/acl/src/acl-guard.ts | 2 +- packages/acl/src/acl-if.directive.spec.ts | 2 +- packages/acl/src/acl-if.directive.ts | 3 +- packages/acl/src/acl.directive.spec.ts | 2 +- packages/acl/src/acl.directive.ts | 3 +- packages/acl/src/acl.module.ts | 16 ++---- packages/acl/src/acl.service.ts | 4 +- packages/form/spec/form.spec.ts | 2 +- .../ng-update/upgrade-rules/v17/index.spec.ts | 3 +- .../ng-update/upgrade-rules/v17/index.ts | 4 +- .../v17/removeAlainThemeModuleForRoot.ts | 40 -------------- .../upgrade-rules/v17/removeForRoot.ts | 53 +++++++++++++++++++ src/app/core/code/files/app.module.ts | 2 +- .../core/code/files/global-config.module.ts | 3 +- src/app/global-config.module.ts | 3 +- 18 files changed, 77 insertions(+), 75 deletions(-) delete mode 100644 schematics/ng-update/upgrade-rules/v17/removeAlainThemeModuleForRoot.ts create mode 100644 schematics/ng-update/upgrade-rules/v17/removeForRoot.ts diff --git a/packages/acl/docs/getting-started.en-US.md b/packages/acl/docs/getting-started.en-US.md index 32455427fc..23786f285a 100644 --- a/packages/acl/docs/getting-started.en-US.md +++ b/packages/acl/docs/getting-started.en-US.md @@ -18,14 +18,14 @@ Install `@delon/acl`: npm i -S @delon/acl ``` -Import `DelonACLModule` module: +If you use Standalone, there is no need to import the `DelonACLModule` module, otherwise: ```typescript import { DelonACLModule } from '@delon/acl'; @NgModule({ imports: [ - DelonACLModule.forRoot() + DelonACLModule ] }) export class AppModule { } diff --git a/packages/acl/docs/getting-started.zh-CN.md b/packages/acl/docs/getting-started.zh-CN.md index cd9fc0ea29..f5d832e641 100644 --- a/packages/acl/docs/getting-started.zh-CN.md +++ b/packages/acl/docs/getting-started.zh-CN.md @@ -18,14 +18,14 @@ ACL 全称叫访问控制列表(Access Control List),是一种非常简单 npm i -S @delon/acl ``` -导入 `DelonACLModule` 模块: +若使用 Standalone 无需要额外导入 `DelonACLModule` 模块,否则: ```typescript import { DelonACLModule } from '@delon/acl'; @NgModule({ imports: [ - DelonACLModule.forRoot() + DelonACLModule ] }) export class AppModule { } diff --git a/packages/acl/src/acl-guard.spec.ts b/packages/acl/src/acl-guard.spec.ts index ede2957ee6..53b27a71c8 100644 --- a/packages/acl/src/acl-guard.spec.ts +++ b/packages/acl/src/acl-guard.spec.ts @@ -40,7 +40,7 @@ describe('acl: guard', () => { data: { guard: { role: ['admin'] } } as ACLGuardData } ]), - DelonACLModule.forRoot() + DelonACLModule ] }); srv = TestBed.inject(ACLGuardService); diff --git a/packages/acl/src/acl-guard.ts b/packages/acl/src/acl-guard.ts index 1b1339cd34..d178f942fd 100644 --- a/packages/acl/src/acl-guard.ts +++ b/packages/acl/src/acl-guard.ts @@ -5,7 +5,7 @@ import { Observable, of, map, tap } from 'rxjs'; import { ACLService } from './acl.service'; import type { ACLCanType, ACLGuardData } from './acl.type'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class ACLGuardService { constructor( private srv: ACLService, diff --git a/packages/acl/src/acl-if.directive.spec.ts b/packages/acl/src/acl-if.directive.spec.ts index e86d4f6cea..6d60e36c2f 100644 --- a/packages/acl/src/acl-if.directive.spec.ts +++ b/packages/acl/src/acl-if.directive.spec.ts @@ -16,7 +16,7 @@ describe('acl-if: directive', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [TestComponent], - imports: [DelonACLModule.forRoot()], + imports: [DelonACLModule], providers: [{ provide: ComponentFixtureAutoDetect, useValue: true }] }); fixture = TestBed.createComponent(TestComponent); diff --git a/packages/acl/src/acl-if.directive.ts b/packages/acl/src/acl-if.directive.ts index 50bad02185..6b3e2753d9 100644 --- a/packages/acl/src/acl-if.directive.ts +++ b/packages/acl/src/acl-if.directive.ts @@ -6,7 +6,8 @@ import { ACLCanType } from './acl.type'; @Directive({ selector: '[aclIf]', - exportAs: 'aclIf' + exportAs: 'aclIf', + standalone: true }) export class ACLIfDirective implements OnDestroy { static ngAcceptInputType_except: boolean | string | undefined | null; diff --git a/packages/acl/src/acl.directive.spec.ts b/packages/acl/src/acl.directive.spec.ts index e667e09cc6..6dc403fcc6 100644 --- a/packages/acl/src/acl.directive.spec.ts +++ b/packages/acl/src/acl.directive.spec.ts @@ -14,7 +14,7 @@ describe('acl: directive', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [TestComponent], - imports: [DelonACLModule.forRoot()], + imports: [DelonACLModule], providers: [{ provide: ComponentFixtureAutoDetect, useValue: true }] }); fixture = TestBed.createComponent(TestComponent); diff --git a/packages/acl/src/acl.directive.ts b/packages/acl/src/acl.directive.ts index 9a5a5bdcde..12d11d55b9 100644 --- a/packages/acl/src/acl.directive.ts +++ b/packages/acl/src/acl.directive.ts @@ -6,7 +6,8 @@ import { ACLCanType } from './acl.type'; @Directive({ selector: '[acl]', - exportAs: 'acl' + exportAs: 'acl', + standalone: true }) export class ACLDirective implements OnDestroy { private _value!: ACLCanType; diff --git a/packages/acl/src/acl.module.ts b/packages/acl/src/acl.module.ts index 64e366cc90..386fc5374d 100644 --- a/packages/acl/src/acl.module.ts +++ b/packages/acl/src/acl.module.ts @@ -1,23 +1,13 @@ import { CommonModule } from '@angular/common'; -import { ModuleWithProviders, NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; -import { ACLGuardService } from './acl-guard'; import { ACLIfDirective } from './acl-if.directive'; import { ACLDirective } from './acl.directive'; -import { ACLService } from './acl.service'; const COMPONENTS = [ACLDirective, ACLIfDirective]; @NgModule({ - imports: [CommonModule], - declarations: COMPONENTS, + imports: [CommonModule, ...COMPONENTS], exports: COMPONENTS }) -export class DelonACLModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: DelonACLModule, - providers: [ACLService, ACLGuardService] - }; - } -} +export class DelonACLModule {} diff --git a/packages/acl/src/acl.service.ts b/packages/acl/src/acl.service.ts index 463f489018..7c172f3a0c 100644 --- a/packages/acl/src/acl.service.ts +++ b/packages/acl/src/acl.service.ts @@ -8,10 +8,8 @@ import { ACLCanType, ACLType } from './acl.type'; /** * ACL 控制服务,[在线文档](https://ng-alain.com/acl) - * - * 务必在根目录注册 `DelonACLModule.forRoot()` 才能使用服务 */ -@Injectable() +@Injectable({ providedIn: 'root' }) export class ACLService { private options: AlainACLConfig; private roles: string[] = []; diff --git a/packages/form/spec/form.spec.ts b/packages/form/spec/form.spec.ts index da39ceede7..75b0352cb2 100644 --- a/packages/form/spec/form.spec.ts +++ b/packages/form/spec/form.spec.ts @@ -29,7 +29,7 @@ describe('form: component', () => { options = { acl: false, i18n: false, ...options }; const imports = [NoopAnimationsModule, DelonFormModule.forRoot(), AlainThemeModule]; if (options.acl) { - imports.push(DelonACLModule.forRoot()); + imports.push(DelonACLModule); } TestBed.configureTestingModule({ imports, diff --git a/schematics/ng-update/upgrade-rules/v17/index.spec.ts b/schematics/ng-update/upgrade-rules/v17/index.spec.ts index 2cbb993b8e..b59c1f3973 100644 --- a/schematics/ng-update/upgrade-rules/v17/index.spec.ts +++ b/schematics/ng-update/upgrade-rules/v17/index.spec.ts @@ -50,7 +50,7 @@ describe('Schematic: ng-update: v17Rule', () => { expect(content).toContain(`, UploadWidgetModule`); }); - it('#removeAlainThemeModuleForRoot', async () => { + it('#removeForRoot', async () => { const globalConfigPath = '/projects/foo/src/app/global-config.module.ts'; tree.create( globalConfigPath, @@ -62,5 +62,6 @@ describe('Schematic: ng-update: v17Rule', () => { await runMigration(); const content = tree.readContent(globalConfigPath); expect(content).not.toContain(`AlainThemeModule.forRoot()`); + expect(content).not.toContain(`DelonACLModule.forRoot()`); }); }); diff --git a/schematics/ng-update/upgrade-rules/v17/index.ts b/schematics/ng-update/upgrade-rules/v17/index.ts index ae90cf5d07..a01ca4636e 100644 --- a/schematics/ng-update/upgrade-rules/v17/index.ts +++ b/schematics/ng-update/upgrade-rules/v17/index.ts @@ -2,7 +2,7 @@ import { chain, Rule, SchematicContext, Tree } from '@angular-devkit/schematics' import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks'; import { autoRegisterFormWidgets } from './autoRegisterFormWidgets'; -import { removeAlainThemeModuleForRoot } from './removeAlainThemeModuleForRoot'; +import { removeForRoot } from './removeForRoot'; import { logFinished, logInfo, logWarn } from '../../../utils'; import { UpgradeMainVersions } from '../../../utils/versions'; @@ -30,6 +30,6 @@ export function v17Rule(): Rule { return async (tree: Tree, context: SchematicContext) => { UpgradeMainVersions(tree); logInfo(context, `Upgrade dependency version number`); - return chain([removeAlainThemeModuleForRoot(), autoRegisterFormWidgets(), qr(), finished()]); + return chain([removeForRoot(), autoRegisterFormWidgets(), qr(), finished()]); }; } diff --git a/schematics/ng-update/upgrade-rules/v17/removeAlainThemeModuleForRoot.ts b/schematics/ng-update/upgrade-rules/v17/removeAlainThemeModuleForRoot.ts deleted file mode 100644 index 4acc85ea8f..0000000000 --- a/schematics/ng-update/upgrade-rules/v17/removeAlainThemeModuleForRoot.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; - -import { DEFAULT_WORKSPACE_PATH, logInfo, readJSON } from '../../../utils'; - -export function removeAlainThemeModuleForRoot(): Rule { - return (tree: Tree, context: SchematicContext) => { - const angularJson = readJSON(tree, DEFAULT_WORKSPACE_PATH); - const projectNames = Object.keys(angularJson.projects); - for (const name of projectNames) { - removeForRoot(tree, name, angularJson.projects[name].sourceRoot, context); - removeForChild(tree, name, angularJson.projects[name].sourceRoot, context); - } - }; -} - -function removeForRoot(tree: Tree, name: string, sourceRoot: string, context: SchematicContext): void { - const modulePath = `${sourceRoot}/app/global-config.module.ts`; - if (!tree.exists(modulePath)) return; - - const forRoot = 'AlainThemeModule.forRoot()'; - const content = tree.readText(modulePath).replace(`${forRoot},`, ''); - tree.overwrite(modulePath, content); - - logInfo(context, `Remove ${forRoot} in ${name} project`); -} - -function removeForChild(tree: Tree, name: string, _: string, context: SchematicContext): void { - const forChild = 'AlainThemeModule.forChild()'; - - tree.visit((path, entry) => { - if (!entry || !path.endsWith('.ts')) return; - - const content = tree.readText(path); - if (!content.includes(forChild)) return; - - tree.overwrite(path, content.replace(forChild, 'AlainThemeModule')); - }); - - logInfo(context, `Remove ${forChild} in ${name} project`); -} diff --git a/schematics/ng-update/upgrade-rules/v17/removeForRoot.ts b/schematics/ng-update/upgrade-rules/v17/removeForRoot.ts new file mode 100644 index 0000000000..7b65f32a92 --- /dev/null +++ b/schematics/ng-update/upgrade-rules/v17/removeForRoot.ts @@ -0,0 +1,53 @@ +import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; + +import { DEFAULT_WORKSPACE_PATH, logInfo, readJSON } from '../../../utils'; + +export function removeForRoot(): Rule { + return (tree: Tree, context: SchematicContext) => { + const angularJson = readJSON(tree, DEFAULT_WORKSPACE_PATH); + const projectNames = Object.keys(angularJson.projects); + for (const name of projectNames) { + const sourceRoot = angularJson.projects[name].sourceRoot; + removeAlainThemeForRoot(tree, name, sourceRoot, context); + removeAlainThemeForChild(tree, name, sourceRoot, context); + removeDelonACLModuleForRoot(tree, name, sourceRoot, context); + } + }; +} + +function removeAlainThemeForRoot(tree: Tree, name: string, sourceRoot: string, context: SchematicContext): void { + const modulePath = `${sourceRoot}/app/global-config.module.ts`; + if (!tree.exists(modulePath)) return; + + const forRoot = 'AlainThemeModule.forRoot()'; + const content = tree.readText(modulePath); + tree.overwrite(modulePath, content.replace(/AlainThemeModule\.forRoot\(\),?/g, '')); + + logInfo(context, `Remove ${forRoot} in ${name} project`); +} + +function removeAlainThemeForChild(tree: Tree, name: string, _: string, context: SchematicContext): void { + const forChild = 'AlainThemeModule.forChild()'; + + tree.visit((path, entry) => { + if (!entry || !path.endsWith('.ts')) return; + + const content = tree.readText(path); + if (!content.includes(forChild)) return; + + tree.overwrite(path, content.replace(forChild, 'AlainThemeModule')); + }); + + logInfo(context, `Remove ${forChild} in ${name} project`); +} + +function removeDelonACLModuleForRoot(tree: Tree, name: string, sourceRoot: string, context: SchematicContext): void { + const modulePath = `${sourceRoot}/app/global-config.module.ts`; + if (!tree.exists(modulePath)) return; + + const forRoot = 'DelonACLModule.forRoot()'; + const content = tree.readText(modulePath); + tree.overwrite(modulePath, content.replace(/DelonACLModule\.forRoot\(\),?/g, '')); + + logInfo(context, `Remove ${forRoot} in ${name} project`); +} diff --git a/src/app/core/code/files/app.module.ts b/src/app/core/code/files/app.module.ts index b97ba21997..e6954db8ff 100644 --- a/src/app/core/code/files/app.module.ts +++ b/src/app/core/code/files/app.module.ts @@ -48,7 +48,7 @@ imports: [ AlainThemeModule, DemoDelonABCModule, DemoDelonChartModule, - DelonACLModule.forRoot(), + DelonACLModule, DelonCacheModule, DelonAuthModule, DelonFormModule.forRoot(), diff --git a/src/app/core/code/files/global-config.module.ts b/src/app/core/code/files/global-config.module.ts index 55ec11864b..76f0c8b0c0 100644 --- a/src/app/core/code/files/global-config.module.ts +++ b/src/app/core/code/files/global-config.module.ts @@ -5,12 +5,11 @@ import { AlainConfig, ALAIN_CONFIG, AlainConfigService } from '@delon/util/confi // Please refer to: https://ng-alain.com/docs/global-config // #region NG-ALAIN Config -import { DelonACLModule } from '@delon/acl'; import * as MOCKDATA from '../../_mock'; const alainConfig: AlainConfig = { }; -const alainModules = [DelonACLModule.forRoot(), DelonMockModule.forRoot({ data: MOCKDATA })]; +const alainModules = [DelonMockModule.forRoot({ data: MOCKDATA })]; const alainProvides = [{ provide: ALAIN_CONFIG, useValue: alainConfig }]; // #region reuse-tab diff --git a/src/app/global-config.module.ts b/src/app/global-config.module.ts index a9499abdeb..1611b40eea 100644 --- a/src/app/global-config.module.ts +++ b/src/app/global-config.module.ts @@ -1,7 +1,6 @@ /* eslint-disable import/order */ import { ModuleWithProviders, NgModule } from '@angular/core'; -import { DelonACLModule } from '@delon/acl'; import { DelonMockModule } from '@delon/mock'; import { AlainConfig, ALAIN_CONFIG } from '@delon/util/config'; @@ -72,7 +71,7 @@ const zorroProvides = [provideNzConfig(ngZorroConfig)]; // #endregion @NgModule({ - imports: [DelonACLModule.forRoot(), DelonMockModule.forRoot({ data: MOCKDATA })] + imports: [DelonMockModule.forRoot({ data: MOCKDATA })] }) export class GlobalConfigModule { static forRoot(): ModuleWithProviders {