From e99d97811dbad4f18d9cbc467a0ec1d430598d53 Mon Sep 17 00:00:00 2001 From: Szymon Date: Wed, 2 Sep 2020 20:57:08 +0200 Subject: [PATCH] feat: added async and sync, docs - Changed name from createAdminModule to createAdminAsync - Fixed type for authentication in AdminModuleOptions - Improvements for jsdoc - Adjusted example for the change - Removed packages for express, as developer should add them on his own --- example-app/src/app.module.ts | 5 +- package.json | 5 +- src/admin.module.ts | 15 ++- src/index.ts | 97 +++++++++++++++---- .../admin-module-options.interface.ts | 4 +- yarn.lock | 87 ++--------------- 6 files changed, 102 insertions(+), 111 deletions(-) diff --git a/example-app/src/app.module.ts b/example-app/src/app.module.ts index 894981a..fe57367 100644 --- a/example-app/src/app.module.ts +++ b/example-app/src/app.module.ts @@ -1,8 +1,9 @@ import { Module } from '@nestjs/common'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { AdminModule } from '@admin-bro/nestjs'; import { Model } from 'mongoose'; +import { AdminModule } from '../../src'; // lib + import { AppController } from './app.controller'; import { AppService } from './app.service'; import { Admin } from './mongoose/admin-model'; @@ -11,7 +12,7 @@ import { MongooseSchemasModule } from './mongoose/mongoose.module'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost:27017/nest'), - AdminModule.createAdminModule({ + AdminModule.createAdminAsync({ imports: [ MongooseSchemasModule, ], diff --git a/package.json b/package.json index e234a6e..81c4232 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ } }, "peerDependencies": { - "admin-bro": ">=3.0.0-beta.7" + "admin-bro": ">=3.0.0" }, "devDependencies": { "@commitlint/cli": "^8.3.5", @@ -41,12 +41,9 @@ "typescript": "^3.9.7" }, "dependencies": { - "@admin-bro/express": "^3.0.0-beta.3", "@nestjs/common": "^7.4.2", "@nestjs/core": "^7.4.2", "@types/express-session": "^1.17.0", - "express-formidable": "^1.2.0", - "express-session": "^1.17.1", "reflect-metadata": "^0.1.13", "rxjs": "^6.5.3" } diff --git a/src/admin.module.ts b/src/admin.module.ts index 6516463..40fb658 100644 --- a/src/admin.module.ts +++ b/src/admin.module.ts @@ -18,8 +18,20 @@ export class AdminModule implements OnModuleInit { @Inject(CONFIG_TOKEN) private readonly adminModuleOptions: AdminModuleOptions, ) {} + + public static createAdmin(options: AdminModuleOptions): DynamicModule { + return { + module: AdminModule, + providers: [ + { + provide: CONFIG_TOKEN, + useValue: options, + }, + ], + } + } - public static createAdminModule(options: AdminModuleFactory): DynamicModule { + public static createAdminAsync(options: AdminModuleFactory): DynamicModule { return { imports: options.imports, module: AdminModule, @@ -41,6 +53,5 @@ export class AdminModule implements OnModuleInit { ...this.adminModuleOptions, adminBroOptions: admin.options, }); - admin.watch() } } diff --git a/src/index.ts b/src/index.ts index 1d17f08..f397fe2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,10 +10,26 @@ * 1. First of all, install the AdminBro along with the module: * * ``` - * yarn add admin-bro @admin-bro/nestjs @admin-bro/express + * yarn add admin-bro @admin-bro/nestjs * ``` * - * 2. Once the installation process is complete, we can import the AdminBroModule + * ### Express: + * You have to additionally add admin-bro express plugin along with packages it's using, express and express formidable: + * + * ``` + * yarn add express @admin-bro/express express-formidable + * ``` + * + * If you are passing `authenticate` object you have to also add express-session: + * + * ``` + * yarn add express-session + * ``` + * + * ### Fastify: + * Work in progress - currently not available + * + * 2. Once the installation process is complete, we can import the AdminModule * into the root AppModule. * * ``` @@ -22,14 +38,10 @@ * * @Module({ * imports: [ - * AdminModule.createAdminModule({ - * useFactory: () => ({ - * adminBroOptions: { - * rootPath: '/admin', - * resources: [], - * }, - * }), - * }), + * AdminModule.createAdmin({ + * rootPath: '/admin', + * resources: [], + * }), * ], * }) * export class AppModule {} @@ -68,14 +80,12 @@ * entities: [User], * synchronize: true, * }), - * AdminModule.createAdminModule({ - * useFactory: () => ({ - * adminBroOptions: { + * AdminModule.createAdmin({ + * adminBroOptions: { * rootPath: '/admin', * resources: [User], - * }, - * }), - * }), + * } + * }), * ], * }) * export class AppModule {} @@ -83,7 +93,7 @@ * * ## Authentication * - * Apart from the `adminBroOptions` useFactory can return `auth` settings. + * Apart from the `adminBroOptions` you can define `auth` settings. * * This is an example which always logs users in, since authenticate method * always returns a Promise resolving to {@link CurrentAdmin}. You may @@ -91,8 +101,7 @@ * in the database. * * ``` - * AdminModule.createAdminModule({ - * useFactory: () => ({ + * AdminModule.createAdmin({ * adminBroOptions: { * rootPath: '/admin', * resources: [User], @@ -102,11 +111,57 @@ * cookieName: 'test', * cookiePassword: 'testPass', * }, - * }), + * }), * ``` + * ## Advanced techniques + * Sometimes some thing couldn't be provided synchronously, that's why there is also asynchronous way of providing options. * + * Let's say you use @nestjs/mongoose module, which could define models in modules that fit the best contextually. + * This creates a problem that we don't have model instance available yet when we are creating AdminModule synchronously. + * + * We can take advantage of nestjs dependency injection using `AdminModule.createAdminAsync()`. + * This method alows us to import modules that have necessary dependencies and then inject them to admin bro config. + * + * For example: + * - we have MongooseSchemasModule which defines Admin model and exports it: + * ``` + * @Module({ + * imports: [ + * MongooseModule.forFeature([{ name: 'Admin', schema: AdminSchema }]), + * ], + * exports: [MongooseModule], + * }) + * export class MongooseSchemasModule {} + * ``` + * - we want to use Admin model in admin-bro panel, to be displayed as the resource + * ``` + * @Module({ + * imports: [ + * MongooseModule.forRoot('mongodb://localhost:27017/test'), + * AdminModule.createAdminAsync({ + * imports: [ + * MongooseSchemasModule, // importing module that exported model we want to inject + * ], + * inject: [ + * getModelToken('Admin'), // using mongoose function to inject dependency + * ], + * useFactory: (adminModel: Model) => ({ // injected dependecy will appear as an argument + * adminBroOptions: { + * rootPath: '/admin', + * resources: [ + * { resource: adminModel }, + * ], + * }, + * }), + * }), + * MongooseSchemasModule, + * ], + * }) + * export class AppModule { } + * ``` + * + * There is a working example [here](https://github.com/SoftwareBrothers/admin-bro-nestjs/tree/master/example-app) */ - import * as NestJSPlugin from './admin.module' export * from './admin.module'; diff --git a/src/interfaces/admin-module-options.interface.ts b/src/interfaces/admin-module-options.interface.ts index ae2f36a..2820f55 100644 --- a/src/interfaces/admin-module-options.interface.ts +++ b/src/interfaces/admin-module-options.interface.ts @@ -1,4 +1,4 @@ -import { AdminBroOptions } from 'admin-bro'; +import { AdminBroOptions, CurrentAdmin } from 'admin-bro'; import { SessionOptions } from 'express-session'; import { ExpressFormidableOptions } from './express-formidable-options.interface'; @@ -6,7 +6,7 @@ import { ExpressFormidableOptions } from './express-formidable-options.interface export interface AdminModuleOptions { adminBroOptions: AdminBroOptions, auth?: { - authenticate: Function, + authenticate: (email: string, password: string) => Promise, cookiePassword: string, cookieName: string, } diff --git a/yarn.lock b/yarn.lock index d3902bf..3af3b8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13,11 +13,6 @@ react-datepicker "^3.1.3" styled-system "^5.1.4" -"@admin-bro/express@^3.0.0-beta.3": - version "3.0.0-beta.3" - resolved "https://registry.yarnpkg.com/@admin-bro/express/-/express-3.0.0-beta.3.tgz#61fe45945712781a50c1092c926b5fe5a7bd3f71" - integrity sha512-ePTC8mFWN1RVSVGn30JxwPZR5v0vH+X/O+bvOURKwHEoIA0x/Ajy7Q/nkfJPVFkO8epi/uEAubpu8LYgAUMRaQ== - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" @@ -2792,16 +2787,6 @@ convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -2991,13 +2976,6 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.9, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@3.1.0, debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -3012,6 +2990,13 @@ debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -3088,11 +3073,6 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" @@ -3647,27 +3627,6 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -express-formidable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/express-formidable/-/express-formidable-1.2.0.tgz#6b05bc05da9e4cd712cac166fcb41ef7172b760c" - integrity sha512-w1vXjF3gb50UKTNkFaW8/4rqY4dUrKfZ1sAZzwAF9YxCAgj/29QZsycf71di0GkskrZOAkubk9pvGYfxyAMYiw== - dependencies: - formidable "^1.0.17" - -express-session@^1.17.1: - version "1.17.1" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357" - integrity sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q== - dependencies: - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~2.0.0" - on-headers "~1.0.2" - parseurl "~1.3.3" - safe-buffer "5.2.0" - uid-safe "~2.1.5" - ext@^1.1.2: version "1.4.0" resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" @@ -3860,11 +3819,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -formidable@^1.0.17: - version "1.2.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" - integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== - from2@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" @@ -6024,11 +5978,6 @@ object.values@^1.1.1: function-bind "^1.1.1" has "^1.0.3" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - once@^1.3.0, once@^1.3.1, once@^1.4.0, once@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -6298,11 +6247,6 @@ parse-json@^5.0.0: json-parse-better-errors "^1.0.1" lines-and-columns "^1.1.6" -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -6606,11 +6550,6 @@ raf@^3.4.0: dependencies: performance-now "^2.1.0" -random-bytes@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" - integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs= - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -7293,11 +7232,6 @@ rxjs@^6.5.3: dependencies: tslib "^1.9.0" -safe-buffer@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -8208,13 +8142,6 @@ uid-number@0.0.6: resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= -uid-safe@~2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" - integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== - dependencies: - random-bytes "~1.0.0" - umask@^1.1.0, umask@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"