diff --git a/.eslintrc.js b/.eslintrc.js index 259de13..4101a9d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,7 +8,7 @@ module.exports = { plugins: ['@typescript-eslint/eslint-plugin'], extends: [ 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', + 'prettier', ], root: true, env: { diff --git a/libs/modules/src/appConfig/app-config.constants.ts b/libs/modules/src/appConfig/app-config.constants.ts new file mode 100644 index 0000000..5c4719d --- /dev/null +++ b/libs/modules/src/appConfig/app-config.constants.ts @@ -0,0 +1 @@ +export const APP_CONFIG_OPTIONS = 'APP_CONFIG_OPTIONS'; diff --git a/libs/modules/src/appConfig/app-config.interface.ts b/libs/modules/src/appConfig/app-config.interface.ts new file mode 100644 index 0000000..469fb91 --- /dev/null +++ b/libs/modules/src/appConfig/app-config.interface.ts @@ -0,0 +1,3 @@ +export interface AppConfigOptions { + url: string; +} diff --git a/libs/modules/src/appConfig/app-config.module.ts b/libs/modules/src/appConfig/app-config.module.ts new file mode 100644 index 0000000..00b83bb --- /dev/null +++ b/libs/modules/src/appConfig/app-config.module.ts @@ -0,0 +1,21 @@ +import { Module, DynamicModule } from '@nestjs/common'; +import { AppConfigService } from './app-config.service'; +import { AppConfigOptions } from './app-config.interface'; +import { APP_CONFIG_OPTIONS } from './app-config.constants'; + +@Module({}) +export class AppConfigModule { + static register(options: AppConfigOptions): DynamicModule { + return { + module: AppConfigModule, + providers: [ + { + provide: APP_CONFIG_OPTIONS, + useValue: options + }, + AppConfigService + ], + exports: [AppConfigService] + }; + } +} diff --git a/libs/modules/src/appConfig/app-config.service.ts b/libs/modules/src/appConfig/app-config.service.ts new file mode 100644 index 0000000..3e368d9 --- /dev/null +++ b/libs/modules/src/appConfig/app-config.service.ts @@ -0,0 +1,31 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { AppConfigOptions } from './app-config.interface'; +import { APP_CONFIG_OPTIONS } from './app-config.constants'; +import axios, { AxiosResponse } from 'axios'; +import { FeatureFlagValue } from '@azure/app-configuration'; + +@Injectable() +export class AppConfigService { + constructor( + @Inject(APP_CONFIG_OPTIONS) + private appConfigOptions: AppConfigOptions + ) { } + + async getFeatureFlags(token: string, key: string, label: string): Promise { + try { + const response: AxiosResponse = await axios.get( + `${this.appConfigOptions.url}/kv?key=.appconfig.featureflag/${key}&label=${label}`, + { + headers: { + Authorization: `Bearer ${token}` + } + } + ); + const featureFlags: FeatureFlagValue[] = response.data.items.map((item) => item.value) + + return featureFlags; + } catch (error) { + return error; + } + } +} diff --git a/libs/modules/src/auth/auth.constants.ts b/libs/modules/src/auth/auth.constants.ts new file mode 100644 index 0000000..187e7f0 --- /dev/null +++ b/libs/modules/src/auth/auth.constants.ts @@ -0,0 +1 @@ +export const AUTH_OPTIONS = 'AUTH_OPTIONS'; diff --git a/libs/modules/src/auth/auth.interface.ts b/libs/modules/src/auth/auth.interface.ts new file mode 100644 index 0000000..22a20b8 --- /dev/null +++ b/libs/modules/src/auth/auth.interface.ts @@ -0,0 +1,3 @@ +export interface AuthOptions { + tenantId: string; +} diff --git a/libs/modules/src/auth/auth.module.ts b/libs/modules/src/auth/auth.module.ts new file mode 100644 index 0000000..70c16c3 --- /dev/null +++ b/libs/modules/src/auth/auth.module.ts @@ -0,0 +1,21 @@ +import { Module, DynamicModule } from '@nestjs/common'; +import { AuthService } from './auth.service'; +import { AuthOptions } from './auth.interface'; +import { AUTH_OPTIONS } from './auth.constants'; + +@Module({}) +export class AuthModule { + static register(options: AuthOptions): DynamicModule { + return { + module: AuthModule, + providers: [ + { + provide: AUTH_OPTIONS, + useValue: options + }, + AuthService + ], + exports: [AuthService] + }; + } +} diff --git a/libs/modules/src/auth/auth.service.ts b/libs/modules/src/auth/auth.service.ts new file mode 100644 index 0000000..20120b1 --- /dev/null +++ b/libs/modules/src/auth/auth.service.ts @@ -0,0 +1,41 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { AuthOptions } from './auth.interface'; +import { AUTH_OPTIONS } from './auth.constants'; +import axios, { AxiosResponse } from 'axios'; + +@Injectable() +export class AuthService { + constructor( + @Inject(AUTH_OPTIONS) + private authOptions: AuthOptions + ) { } + + async getToken( + grantType: string, + clientId: string, + clientSecret: string, + resource: string + ): Promise { + try { + + const { data }: AxiosResponse = await axios.post( + `https://login.microsoftonline.com/${this.authOptions.tenantId}/oauth2/token`, + { + grant_type: grantType, + client_id: clientId, + client_secret: clientSecret, + resource: resource + }, + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + } + ); + + return data.access_token; + } catch (error) { + return error; + } + } +} diff --git a/libs/modules/src/azAppConfig/az-app-config.constants.ts b/libs/modules/src/azAppConfig/az-app-config.constants.ts deleted file mode 100644 index b4c7a8d..0000000 --- a/libs/modules/src/azAppConfig/az-app-config.constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const AZ_APP_CONFIG_OPTIONS = 'AZ_APP_CONFIG_OPTIONS'; diff --git a/libs/modules/src/azAppConfig/az-app-config.interface.ts b/libs/modules/src/azAppConfig/az-app-config.interface.ts deleted file mode 100644 index 3282d0e..0000000 --- a/libs/modules/src/azAppConfig/az-app-config.interface.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface AzAppConfigOptions { - connectionString: string; -} diff --git a/libs/modules/src/azAppConfig/az-app-config.module.ts b/libs/modules/src/azAppConfig/az-app-config.module.ts deleted file mode 100644 index 4eee4a2..0000000 --- a/libs/modules/src/azAppConfig/az-app-config.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Module, DynamicModule } from '@nestjs/common'; -import { AzAppConfigService } from './az-app-config.service'; -import { AzAppConfigOptions } from './az-app-config.interface'; -import { AZ_APP_CONFIG_OPTIONS } from './az-app-config.constants'; - -@Module({}) -export class AzAppConfigModule { - static register(options: AzAppConfigOptions): DynamicModule { - return { - module: AzAppConfigModule, - providers: [ - { - provide: AZ_APP_CONFIG_OPTIONS, - useValue: options, - }, - AzAppConfigService, - ], - exports: [AzAppConfigService], - }; - } -} diff --git a/libs/modules/src/azAppConfig/az-app-config.service.ts b/libs/modules/src/azAppConfig/az-app-config.service.ts deleted file mode 100644 index 64eeadc..0000000 --- a/libs/modules/src/azAppConfig/az-app-config.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { AzAppConfigOptions } from './az-app-config.interface'; -import { FeatureFlag } from './feature-flag.interface'; -import { AppConfigurationClient } from '@azure/app-configuration'; -import { AZ_APP_CONFIG_OPTIONS } from './az-app-config.constants'; - -@Injectable() -export class AzAppConfigService { - constructor( - @Inject(AZ_APP_CONFIG_OPTIONS) - private azAppConfigOptions: AzAppConfigOptions, - ) { } - - async getFeatureFlag(key: string, label: string): Promise { - try { - const client = new AppConfigurationClient( - this.azAppConfigOptions.connectionString, - ); - const configurationSetting = await client.getConfigurationSetting({ - key: key, - label: label, - }); - const featureFlag: FeatureFlag = { - name: configurationSetting.key, - environment: configurationSetting.label, - active: configurationSetting.value, - }; - - return featureFlag; - } catch (error) { - return error; - } - } -} diff --git a/libs/modules/src/azAppConfig/feature-flag.interface.ts b/libs/modules/src/azAppConfig/feature-flag.interface.ts deleted file mode 100644 index bdda6d8..0000000 --- a/libs/modules/src/azAppConfig/feature-flag.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface FeatureFlag { - name: string; - environment: string; - active: string; -} diff --git a/libs/modules/src/index.ts b/libs/modules/src/index.ts index f7a1042..9fc64f1 100644 --- a/libs/modules/src/index.ts +++ b/libs/modules/src/index.ts @@ -1,2 +1,4 @@ -export * from './azAppConfig/az-app-config.module'; -export * from './azAppConfig/az-app-config.service'; +export * from './appConfig/app-config.module'; +export * from './appConfig/app-config.service'; +export * from './auth/auth.module'; +export * from './auth/auth.service' diff --git a/package-lock.json b/package-lock.json index 2535ee5..808f46a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "@noahspan/noahspan-modules", - "version": "0.0.1", + "version": "0.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@noahspan/noahspan-modules", - "version": "0.0.1", + "version": "0.0.3", "license": "UNLICENSED", "dependencies": { "@azure/app-configuration": "^1.6.0", "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", + "axios": "^1.7.2", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, @@ -28,7 +29,6 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", "source-map-support": "^0.5.21", @@ -2137,18 +2137,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -3049,8 +3037,17 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } }, "node_modules/babel-jest": { "version": "29.7.0", @@ -3653,7 +3650,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -3925,7 +3921,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -4191,36 +4186,6 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -4527,12 +4492,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -4757,6 +4716,25 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -4827,7 +4805,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7124,18 +7101,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -7192,6 +7157,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8115,22 +8085,6 @@ "node": ">=0.10" } }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", diff --git a/package.json b/package.json index ebf39f0..cb2c963 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,8 @@ { "name": "@noahspan/noahspan-modules", - "version": "0.0.1", + "version": "0.1.1", "description": "", "author": "", - "private": true, "license": "UNLICENSED", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -12,7 +11,7 @@ ], "scripts": { "build": "rm -rf ./dist && tsc", - "format": "prettier --write \"test/**/*.ts\" \"libs/**/*.ts\"", + "format": "prettier --write \"libs/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", @@ -29,6 +28,7 @@ "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", + "axios": "^1.7.2", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, @@ -44,7 +44,6 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", "source-map-support": "^0.5.21",