Skip to content

Commit

Permalink
refactor(vpipe): refactor VPipe so pipe name is in decorator instead (#…
Browse files Browse the repository at this point in the history
…72)

BREAKING CHANGE: Pipe name moved to decorator
  • Loading branch information
YoeriNijs committed Aug 1, 2023
1 parent a630f03 commit 94f7aac
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 31 deletions.
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -577,16 +577,14 @@ export class PipeComponent {

### Create custom pipes

Vienna supports custom pipes. In order to create a custom pipe, implement the `VPipe` interface accordingly.
Vienna supports custom pipes. In order to create a custom pipe, add the `VPipe` decorator accordingly. Also, implement
the `VPipeTransform` interface.

For example:

```
@VPipe({ name: 'greeting' })
export class GreetingPipe implements VPipe {
name(): string {
return "greeting";
}
transform(value: string): string {
return `${value}, world!`;
}
Expand Down
11 changes: 5 additions & 6 deletions demo/pipes/greeting.pipe.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {VPipe} from "../../src/core/application/v-pipe";
import {VPipe, VPipeTransform} from "../../src";

/**
* This demo app is for <b>development purposes only</b>, needed to test some edge cases.
* If you want to see a 'real world' example of Vienna, please check https://github.com/YoeriNijs/vienna-demo-app.
*/
export class GreetingPipe implements VPipe {
name(): string {
return "greeting";
}

@VPipe({
name: 'greeting'
})
export class GreetingPipe implements VPipeTransform {
transform(value: string): string {
return `${value}, world!`;
}
Expand Down
10 changes: 5 additions & 5 deletions demo/pipes/translate.pipe.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {VPipe} from "../../src/core/application/v-pipe";
import {VPipe, VPipeTransform} from "../../src";

/**
* This demo app is for <b>development purposes only</b>, needed to test some edge cases.
* If you want to see a 'real world' example of Vienna, please check https://github.com/YoeriNijs/vienna-demo-app.
*/
export class TranslatePipe implements VPipe {
name(): string {
return "translate";
}

@VPipe({
name: 'translate'
})
export class TranslatePipe implements VPipeTransform {
transform(value: string): string {
if (value.toLowerCase() === 'hello, world!') {
return 'Hallo, wereld!';
Expand Down
4 changes: 2 additions & 2 deletions src/core/application/v-application-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {VRouteNotFoundStrategy} from '../router/v-route-not-found-strategy';
import {VRouteNotFoundRedirect} from "../router/v-route-not-found-redirect";
import {VGlobalStyles} from "./v-global-styles";
import {VApplicationPlugins} from "./v-application-plugins";
import {VPipe} from "./v-pipe";
import {VPipeTransform} from "../pipe/v-pipe-transform";
import {VI18nConfig} from "./v-i18n-config";

export interface VApplicationConfig {
Expand All @@ -17,6 +17,6 @@ export interface VApplicationConfig {
darkModeEnabled?: () => boolean;
darkModeClassOverride?: string;
plugins?: VApplicationPlugins;
pipes?: Type<VPipe>[];
pipes?: Type<VPipeTransform>[];
i18n?: VI18nConfig;
}
11 changes: 7 additions & 4 deletions src/core/application/v-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import {VInternalLogSender} from "../logger/v-internal-log-sender";
import {VWeb, VWebDocTags} from "../misc/web";
import {getCurrentDocTags} from "../util/v-internal-document-util";
import {VInternalCustomPipes} from "../template-engine/pipes/v-internal-custom-pipes";
import {VPipe} from "./v-pipe";
import {VDuplicatePipeException} from "./v-duplicate-pipe-exception";

import * as pincet from 'pincet';
import {VI18n} from "../i18n/v-i18n";
import {VI18nConfig} from "./v-i18n-config";
import {VInternalPipeTransform} from "../pipe/v-internal-pipe-transform";

export function VApplication(config: VApplicationConfig) {
function override<T extends new(...arg: any[]) => any>(target: T) {
Expand Down Expand Up @@ -122,13 +122,16 @@ export function VApplication(config: VApplicationConfig) {

private initializePipes(): void {
if (config.pipes) {
const pipes = config.pipes.map<VPipe>(pipeType => VInjector.resolve(pipeType));
const pipeNames = pipes.map(p => p.name());
const pipes = config.pipes.map<VInternalPipeTransform>(pipeType =>
VInjector.resolve(pipeType) as VInternalPipeTransform);
const pipeNames = pipes.map(p => p.vPipeOptions.name);
const uniquePipeNames = pincet.unique<string>(pipeNames);
if (uniquePipeNames.length === pipes.length) {
this._pipes.register(pipes);
} else {
const pipeNames = pipes.map(p => p.name()).toString();
const pipeNames = pipes
.map(p => p.vPipeOptions.name)
.toString();
throw new VDuplicatePipeException(`Duplicate pipe names found: ${pipeNames}. Vienna only accepts unique pipe names!`);
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/core/application/v-pipe.ts

This file was deleted.

4 changes: 4 additions & 0 deletions src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export * from './i18n/v-i18n';
export * from './misc/audit/v-audit';
export * from './misc/web';

export * from './pipe/v-pipe';
export * from './pipe/v-pipe-options';
export * from './pipe/v-pipe-transform';

export * from './binding/v-emit';
export * from './binding/v-emitter';
export * from './binding/v-prop';
Expand Down
6 changes: 6 additions & 0 deletions src/core/pipe/v-internal-pipe-transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {VPipeTransform} from "./v-pipe-transform";
import {VPipeOptions} from "./v-pipe-options";

export interface VInternalPipeTransform extends VPipeTransform {
vPipeOptions: VPipeOptions;
}
3 changes: 3 additions & 0 deletions src/core/pipe/v-pipe-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface VPipeOptions {
name: string;
}
3 changes: 3 additions & 0 deletions src/core/pipe/v-pipe-transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface VPipeTransform {
transform(value: string): string;
}
18 changes: 18 additions & 0 deletions src/core/pipe/v-pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {VPipeOptions} from "./v-pipe-options";

export function VPipe(options: VPipeOptions) {
function override<T extends new(...arg: any[]) => any>(target: T) {
return class extends target {
constructor(...args: any[]) {
super(...args);
Object.defineProperty(this, 'vPipeOptions', {
value: options,
configurable: false,
writable: false
});
}
};
}

return override;
}
10 changes: 6 additions & 4 deletions src/core/template-engine/pipes/v-internal-custom-pipes.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {VInjectable} from "../../injector/v-injectable-decorator";
import {VPipe} from "../../application/v-pipe";
import {VPipeTransform} from "../../pipe/v-pipe-transform";
import {VInternalTemplatePipe} from "./v-internal-template-pipe";
import {VPipeOptions} from "../../pipe/v-pipe-options";

@VInjectable({singleton: true})
export class VInternalCustomPipes {
private _pipes: VPipe[] = [];
private _pipes: VPipeTransform[] = [];

register(pipes: VPipe[]) {
register(pipes: VPipeTransform[]) {
this._pipes.push(...pipes);
}

Expand All @@ -17,7 +18,8 @@ export class VInternalCustomPipes {
return p.transform(value);
},
name(): string {
return p.name();
const options: VPipeOptions = (p as any).vPipeOptions;
return options.name;
},
accept(segment: string, pipeName: string, _: string): boolean {
return segment === pipeName;
Expand Down

0 comments on commit 94f7aac

Please sign in to comment.