Browse Source

refactor: improve code readability

pull/4956/head
mehmet-erim 6 years ago
parent
commit
18d6a9ec8e
  1. 7
      npm/ng-packs/packages/core/src/lib/core.module.ts
  2. 22
      npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts
  3. 18
      npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts
  4. 156
      npm/ng-packs/packages/core/src/lib/utils/formatted-string-value-extractor.ts
  5. 10
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  6. 23
      npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts

7
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -21,6 +21,7 @@ import { PermissionDirective } from './directives/permission.directive';
import { ReplaceableTemplateDirective } from './directives/replaceable-template.directive';
import { StopPropagationDirective } from './directives/stop-propagation.directive';
import { VisibilityDirective } from './directives/visibility.directive';
import { OAuthConfigurationHandler } from './handlers/oauth-configuration.handler';
import { RoutesHandler } from './handlers/routes.handler';
import { ApiInterceptor } from './interceptors/api.interceptor';
import { LocalizationModule } from './localization.module';
@ -37,7 +38,7 @@ import { SessionState } from './states/session.state';
import { coreOptionsFactory, CORE_OPTIONS } from './tokens/options.token';
import { noop } from './utils/common-utils';
import './utils/date-extensions';
import { configureOAuth, getInitialData, localeInitializer } from './utils/initial-utils';
import { getInitialData, localeInitializer } from './utils/initial-utils';
export function storageFactory(): OAuthStorage {
return localStorage;
@ -187,8 +188,8 @@ export class CoreModule {
{
provide: APP_INITIALIZER,
multi: true,
deps: [Injector, NGXS_CONFIG_PLUGIN_OPTIONS],
useFactory: configureOAuth,
deps: [OAuthConfigurationHandler],
useFactory: noop,
},
{
provide: APP_INITIALIZER,

22
npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts

@ -1,10 +1,11 @@
import { Component, Injector } from '@angular/core';
import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { of } from 'rxjs';
import { GetAppConfiguration } from '../actions';
import { getInitialData, localeInitializer, configureOAuth, checkAccessToken } from '../utils';
import { OAuthService } from 'angular-oauth2-oidc';
import { CORE_OPTIONS } from '../tokens/options.token';
import { checkAccessToken, getInitialData, localeInitializer } from '../utils';
import * as multiTenancyUtils from '../utils/multi-tenancy-utils';
@Component({
@ -18,24 +19,13 @@ describe('InitialUtils', () => {
const createComponent = createComponentFactory({
component: DummyComponent,
mocks: [Store, OAuthService],
providers: [
{ provide: CORE_OPTIONS, useValue: { environment: { oAuthConfig: { issuer: 'test' } } } },
],
});
beforeEach(() => (spectator = createComponent()));
describe('#configureOAuth', () => {
test('should be called the the configure method of OAuthService', async () => {
const injector = spectator.inject(Injector);
const injectorSpy = jest.spyOn(injector, 'get');
const oAuth = spectator.inject(OAuthService);
const configureSpy = jest.spyOn(oAuth, 'configure');
injectorSpy.mockReturnValueOnce(oAuth);
await configureOAuth(injector, { environment: { oAuthConfig: { issuer: 'test' } } })();
expect(configureSpy).toHaveBeenCalledWith({ issuer: 'test' });
});
});
describe('#getInitialData', () => {
test('should dispatch GetAppConfiguration and return', async () => {
const injector = spectator.inject(Injector);

18
npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts

@ -1,12 +1,11 @@
import { Component, Injector } from '@angular/core';
import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { Store } from '@ngxs/store';
import { MultiTenancyService } from '../services/multi-tenancy.service';
import { parseTenantFromUrl, getCurrentTenancyNameOrNull } from '../utils';
import * as multiTenancyUtils from '../utils/multi-tenancy-utils';
import { of, Subject, BehaviorSubject } from 'rxjs';
import { FindTenantResultDto } from '../models/find-tenant-result-dto';
import clone from 'just-clone';
import { BehaviorSubject } from 'rxjs';
import { FindTenantResultDto } from '../models/find-tenant-result-dto';
import { MultiTenancyService } from '../services/multi-tenancy.service';
import { getCurrentTenancyName, parseTenantFromUrl } from '../utils';
const environment = {
production: false,
@ -59,16 +58,17 @@ describe('MultiTenancyUtils', () => {
beforeEach(() => (spectator = createComponent()));
describe('#getCurrentTenancyNameOrNull', () => {
describe('#getCurrentTenancyName', () => {
test('should get tenancy name from href', async () => {
setHref('https://abp.volosoft.com/');
expect(getCurrentTenancyNameOrNull('https://{0}.volosoft.com')).toBe('abp');
expect(getCurrentTenancyName('https://{0}.volosoft.com')).toBe('abp');
setHref('https://volosoft.com/');
expect(getCurrentTenancyNameOrNull('https://{0}.com')).toBe('volosoft');
expect(getCurrentTenancyName('https://{0}.com')).toBe('volosoft');
setHref('https://volosoft.com/abp/');
expect(getCurrentTenancyNameOrNull('https://volosoft.com/{0}')).toBe('abp');
expect(getCurrentTenancyName('https://volosoft.com/{0}')).toBe('abp');
expect(getCurrentTenancyName('https://volosoft.com')).toBe(undefined);
});
});

156
npm/ng-packs/packages/core/src/lib/utils/formatted-string-value-extractor.ts

@ -1,156 +0,0 @@
class ExtractionResult {
public isMatch: boolean;
public matches: any[];
constructor(isMatch: boolean) {
this.isMatch = isMatch;
this.matches = [];
}
}
enum FormatStringTokenType {
ConstantText,
DynamicValue,
}
class FormatStringToken {
public text: string;
public type: FormatStringTokenType;
constructor(text: string, type: FormatStringTokenType) {
this.text = text;
this.type = type;
}
}
class FormatStringTokenizer {
tokenize(format: string, includeBracketsForDynamicValues: boolean = false): FormatStringToken[] {
const tokens: FormatStringToken[] = [];
let currentText = '';
let inDynamicValue = false;
for (let i = 0; i < format.length; i++) {
const c = format[i];
switch (c) {
case '{':
if (inDynamicValue) {
throw new Error(
'Incorrect syntax at char ' +
i +
'! format string can not contain nested dynamic value expression!',
);
}
inDynamicValue = true;
if (currentText.length > 0) {
tokens.push(new FormatStringToken(currentText, FormatStringTokenType.ConstantText));
currentText = '';
}
break;
case '}':
if (!inDynamicValue) {
throw new Error(
'Incorrect syntax at char ' +
i +
'! These is no opening brackets for the closing bracket }.',
);
}
inDynamicValue = false;
if (currentText.length <= 0) {
throw new Error(
'Incorrect syntax at char ' + i + '! Brackets does not containt any chars.',
);
}
let dynamicValue = currentText;
if (includeBracketsForDynamicValues) {
dynamicValue = '{' + dynamicValue + '}';
}
tokens.push(new FormatStringToken(dynamicValue, FormatStringTokenType.DynamicValue));
currentText = '';
break;
default:
currentText += c;
break;
}
}
if (inDynamicValue) {
throw new Error('There is no closing } char for an opened { char.');
}
if (currentText.length > 0) {
tokens.push(new FormatStringToken(currentText, FormatStringTokenType.ConstantText));
}
return tokens;
}
}
export class FormattedStringValueExtractor {
extract(str: string, format: string): ExtractionResult {
if (str === format) {
return new ExtractionResult(true);
}
const formatTokens = new FormatStringTokenizer().tokenize(format);
if (!formatTokens) {
return new ExtractionResult(str === '');
}
const result = new ExtractionResult(true);
for (let i = 0; i < formatTokens.length; i++) {
const currentToken = formatTokens[i];
const previousToken = i > 0 ? formatTokens[i - 1] : null;
if (currentToken.type === FormatStringTokenType.ConstantText) {
if (i === 0) {
if (str.indexOf(currentToken.text) !== 0) {
result.isMatch = false;
return result;
}
str = str.substr(currentToken.text.length, str.length - currentToken.text.length);
} else {
const matchIndex = str.indexOf(currentToken.text);
if (matchIndex < 0) {
result.isMatch = false;
return result;
}
result.matches.push({ name: previousToken.text, value: str.substr(0, matchIndex) });
str = str.substring(0, matchIndex + currentToken.text.length);
}
}
}
const lastToken = formatTokens[formatTokens.length - 1];
if (lastToken.type === FormatStringTokenType.DynamicValue) {
result.matches.push({ name: lastToken.text, value: str });
}
return result;
}
isMatch(str: string, format: string): string[] {
const result = new FormattedStringValueExtractor().extract(str, format);
if (!result.isMatch) {
return [];
}
const values = [];
for (let i = 0; i < result.matches.length; i++) {
values.push(result.matches[i].value);
}
return values;
}
}

10
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -9,16 +9,6 @@ import { ConfigState } from '../states/config.state';
import { CORE_OPTIONS } from '../tokens/options.token';
import { parseTenantFromUrl } from './multi-tenancy-utils';
export function configureOAuth(injector: Injector, options: ABP.Root) {
const fn = () => {
const oAuth = injector.get(OAuthService);
oAuth.configure(options.environment.oAuthConfig);
return Promise.resolve();
};
return fn;
}
export function getInitialData(injector: Injector) {
const fn = async () => {
const store: Store = injector.get(Store);

23
npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts

@ -5,24 +5,17 @@ import { SetEnvironment } from '../actions';
import { Config } from '../models/config';
import { MultiTenancyService } from '../services/multi-tenancy.service';
import { ConfigState } from '../states/config.state';
import { FormattedStringValueExtractor } from './formatted-string-value-extractor';
import clone from 'just-clone';
const tenancyPlaceholder = '{0}';
export function getCurrentTenancyNameOrNull(appBaseUrl: string): string {
if (appBaseUrl.indexOf(tenancyPlaceholder) < 0) return null;
export function getCurrentTenancyName(appBaseUrl: string): string {
if (appBaseUrl.charAt(appBaseUrl.length - 1) !== '/') appBaseUrl += '/';
const currentRootAddress = window.location.href;
const formattedStringValueExtractor = new FormattedStringValueExtractor();
const values = formattedStringValueExtractor.isMatch(currentRootAddress, appBaseUrl);
if (!values.length) {
return null;
}
return values[0];
const regex = appBaseUrl.replace(/\./g, '.').replace(tenancyPlaceholder, '(.+)');
return (currentRootAddress.match(regex) || []).slice(1)[0];
}
export async function parseTenantFromUrl(injector: Injector) {
@ -31,7 +24,7 @@ export async function parseTenantFromUrl(injector: Injector) {
const environment = store.selectSnapshot(ConfigState.getOne('environment')) as Config.Environment;
const { baseUrl = '' } = environment.application;
const tenancyName = getCurrentTenancyNameOrNull(baseUrl);
const tenancyName = getCurrentTenancyName(baseUrl);
if (tenancyName) {
multiTenancyService.isTenantBoxVisible = false;
@ -51,8 +44,10 @@ export async function parseTenantFromUrl(injector: Injector) {
return Promise.resolve();
}
export function setEnvironment(store: Store, tenancyName: string) {
const environment = store.selectSnapshot(ConfigState.getOne('environment')) as Config.Environment;
function setEnvironment(store: Store, tenancyName: string) {
const environment = clone(
store.selectSnapshot(ConfigState.getOne('environment')),
) as Config.Environment;
if (environment.application.baseUrl) {
environment.application.baseUrl = environment.application.baseUrl.replace(

Loading…
Cancel
Save