open-index/open-npm huggingface dataset:
npm package: @kovalenko/is-cron
Description: Class validator decorator for crontab config
Author: kovalenko
Latest version: 1.0.10

# IsCron

Typescript property decorator for the crontab config validation

## Installation

```
npm install @kovalenko/is-cron
```

## Usage
```typescript
function IsCron(): PropertyDecorator;
function IsCron(options: InputOptions): PropertyDecorator;
function IsCron(options: ValidationOptions): PropertyDecorator;
function IsCron(cronOptions: InputOptions, options: ValidationOptions): PropertyDecorator;
```

### Basic
```typescript
import {IsCron} from '@kovalenko/is-cron';

export class Foo {

  @IsCron()
  bar: string;
}

```

### With `InputOptions`
```typescript
import {IsCron} from '@kovalenko/is-cron';
import {InputOptions} from 'cron-validate/lib/types';

const cronOptions: InputOptions = {
  override: {
    useSeconds: true,
  },
};

export class Foo {

  @IsCron(cronOptions)
  baz: string[];
}

```

### With `ValidationOptions`
```typescript
import {IsCron} from '@kovalenko/is-cron';

export class Foo {

  @IsCron({each: true})
  baz: string[];
}

```

### With `InputOptions` and `ValidationOptions`

```typescript
import {IsCron} from '@kovalenko/is-cron';
import {InputOptions} from 'cron-validate/lib/types';

const cronOptions: InputOptions = {
  override: {
    useSeconds: true,
  },
};

export class Foo {

  @IsCron(cronOptions, {each: true})
  baz: string[];
}

```
npm package: @kovalenko/main-menu
Description: Provides a service building the menu tree based on Angular router config. Also it sets the page title on navigation end.
Author: Kovalenko
Latest version: 1.0.0

# MainMenu

Provides a service building the menu tree based on Angular router config. Also it sets the page title on navigation end.

## Installation

```
npm install @kovalenko/main-menu
```

First, import the MainMenuModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {MainMenuModule} from '@kovalenko/main-menu';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppComponent} from './app';

@NgModule({
  imports: [
    BrowserModule,
    MainMenuModule
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {
}

platformBrowserDynamic().bootstrapModule(AppModule);
```

For custom title service, provide it to the module using `config(provider: Provider)` static method:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {MainMenuModule, MainMenuTitleService} from '@kovalenko/main-menu';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppComponent} from './app';

class MyTitleClass implements MainMenuTitleService {
  setTitle(title: string): void {
    // ...
  }
}

@NgModule({
  imports: [
    BrowserModule,
    MainMenuModule.config({
      provide: MainMenuTitleService,
      useClass: MyTitleClass
    })
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {
}

platformBrowserDynamic().bootstrapModule(AppModule);
```

To add routes to main menu, add `title: string` to route data. To set only page title, add `pageTitle: string` to route data. Add both to have different menu item and page titles.
If you add `access: string[]` field to route data, it will be added in main menu items `access` field; otherwise it will be `false`.

```typescript
import { Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'route1',
    component: Route1Component,
    data: {
      title: 'Route 1',
    },
  },
  { // not included to main menu, just sets the page title
    path: 'route2',
    component: Route2Component,
    data: {
      pageTitle: 'Route 2',
    },
  },
  {
    path: 'route3',
    component: Route3Component,
    data: {
      title: 'Route 3 menu title',
      pageTitle: 'Route 3 page title',
      access: ['route3.read']
    },
  },
];
```

Then inject MainMenuService into your component:

```typescript
import {Component} from '@angular/core';
import {MainMenuService} from '@kovalenko/main-menu';

@Component({
  selector: 'app',
  template: `
    <ng-container *ngFor="let item of items">
      <a *ngIf="!item.access || (item.access | yourAccessControlPipe)" [routerLink]="item.routerLink">{{ item.name }}</a>
    </ng-container>
  `,
})
export class AppComponent {
  readonly items = this.mainMenuService.items;
  constructor(private mainMenuService: MainMenuService<string[]>) { }
}
```

## License

MIT
npm package: @kovalenko/mat-dialog-drag-bounds
Description: This module provides a directive that prevents material dialog to be dragged beyond the viewport bounds.
Author: Kovalenko
Latest version: 1.1.1

# Material Dialog Drag Bounds

This module provides a directive that prevents material dialog to be dragged beyond the viewport bounds.

## Installation

```
npm install @kovalenko/mat-dialog-drag-bounds
```

## Usage

First, import the MatDialogDragBoundsModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {MatDialogDragBoundsModule} from '@kovalenko/mat-dialog-drag-bounds';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {DialogComponent} from './app';

@NgModule({
  imports: [BrowserModule, MatDialogDragBoundsModule],
  declarations: [DialogComponent],
  bootstrap: [DialogComponent],
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(DialogComponent);
```

Then put all the directives inside the mat-dialog-header tag:
```typescript
import {Component} from '@angular/core';

@Component({
  template: `
  <div mat-dialog-title cdkDrag cdkDragRootElement=".cdk-overlay-pane" cdkDragHandle cdkDragBoundary=".cdk-global-overlay-wrapper" ngcMatDialogDragBounds>
    Dialog title
  </div>
  <mat-dialog-content>
    Dialog content
  </mat-dialog-content>
`
})
export class DialogComponent { }
```

## License

[MIT](LICENSE)
npm package: @kovalenko/material-color-picker
Description: Material color picker
Author: Kovalenko
Latest version: 1.0.1

# MaterialColorPicker

Material color picker

## Installation

```
npm install @kovalenko/material-color-picker
```

### ColorPicker

Selector: `ngc-color-picker`

Color picker. MatFormFieldControl

Title | Description
--- | ---
`@Input() ngModel: string` | Color
`@Output() ngModelChange: EventEmitter<string>` | ngModel change


## Usage

First, import the ColorPickerModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {ColorPickerModule} from '@kovalenko/material-color-picker';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppComponent} from './app';

@NgModule({
  imports: [
    BrowserModule,
    ColorPickerModule
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {
}

platformBrowserDynamic().bootstrapModule(AppModule);
```

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: `
    <form>
      <mat-form-field>
        <ngc-color-picker placeholder="Color" [(ngModel)]="color" name="color"></ngc-datetime-picker>
      </mat-form-field>
    </form>
  `,
})
export class AppComponent {
  date = '#ff0000';

}
```

## License

MIT
npm package: @kovalenko/material-dark-mode
Description: ## Installation
Author: Kovalenko
Latest version: 1.1.0

# Material table

## Installation

```
npm i @kovalenko/material-dark-mode
```

## Usage

```typescript

@Component({
  selector: 'selector',
  templateUrl: './selector.component.html',
  imports: [
    MatMenuTrigger,
    MatIcon,
    MatMenu,
    MatMenuItem,
    NgTemplateOutlet,
    SelectColorSchemeComponent,
  ],
})
export class SelectorComponent {}
```

`selector.component.html`
```angular181html
<mat-menu #menu="matMenu" yPosition="below">
  <button
    mat-menu-item
    [matMenuTriggerFor]="color.menu"
  >
    <ng-container *ngTemplateOutlet="color.button"/>
  </button>
  <ngc-select-color-scheme #color/>
</mat-menu>
```
npm package: @kovalenko/material-datetime-picker
Description: Material datetime picker
Author: Kovalenko
Latest version: 4.0.1

# MaterialDatetimePicker

Material datetime picker

## Installation

```
npm install @kovalenko/material-datetime-picker
```

### DatetimePicker

Selector: `ngc-datetime-picker`

Пикер даты и времени. MatFormFieldControl

Title | Description
--- | ---
`@Input() ngModel: Moment` | Date
`@Input() min: Moment` | Min date
`@Input() max: Moment` | Max date
`@Input() hasTimePicker: boolean` | Time input
`@Input() defaultTime: number` | Default time offset in seconds
`@Output() ngModelChange: EventEmitter<Moment>` | ngModel change
`@Output() dateChange: EventEmitter<Moment>` | User date change


## Usage

First, import the MaterialDatetimePickerModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {MaterialDatetimePickerModule} from '@kovalenko/material-datetime-picker';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppComponent} from './app';

@NgModule({
  imports: [
    BrowserModule,
    MaterialDatetimePickerModule
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {
}

platformBrowserDynamic().bootstrapModule(AppModule);
```

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: `
    <form>
      <mat-form-field>
        <ngc-datetime-picker placeholder="Date" [(ngModel)]="date" [hasTimePicker]="true" name="date"></ngc-datetime-picker>
      </mat-form-field>
    </form>
  `,
})
export class AppComponent {
  date = moment();

}
```
npm package: @kovalenko/max-length-reached
Description: Emits an event if input's max length reached
Author: Kovalenko
Latest version: 1.0.0

# MaxLengthReached

Emits an event if input's max length reached

## Usage

First, import the MaxLengthReachedModule to your module:

```typescript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ScrollHereModule } from '@kovalenko/max-length-reached';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app';

@NgModule({
  imports: [BrowserModule, MaxLengthReachedModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);
```

In this example, the second input will be focused when the first input will reach max length  

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: `
    <input type="text" maxlangth="5" (ngcMaxLengthReached)="second.nativeElement.focus()">
    <input type="text" #second>
  `,
})
export class AppComponent {
}
```

## License

MIT
npm package: @kovalenko/nestjs-pg-notify
Description: pg_notify listener for NestJS
Author: kovalenko@gmail.com
Latest version: 1.0.0

# NestJS PostgreSQL notification listener

## Installation

```
npm i @kovalenko/nestjs-pg-notify
```

## Usage

Import `PgNotifyModule`

```typescript
import {Module} from '@nestjs/common';
import {PgNotifyModule} from '@kovalenko/nestjs-pg-notify';

import {UserNotificationHandler} from '@/user/events/handlers/user-notification.handler';

@Module({
  imports: [
    PgNotifyModule.forRoot(
      {
        user: 'username',
        password: 'password',
        host: 'host',
        port: 5432,
        database: 'database',
      },
      {
        retryInterval: 1000,
        retryTimeout: Infinity,
      },
    ),
  ],
  providers: [
    UserNotificationHandler,
  ],
})
export class AppModule {}
```

Listen in `UserNotificationHandler`

```typescript
import {IsUUID} from 'class-validator';

export class UserNotificationDto {
  @IsUUID()
  id: string;
}
```

```typescript
import {QueryBus} from '@nestjs/cqrs';
import {IPgNotifyHandler, PgNotification, PgPayload} from '@kovalenko/nestjs-pg-notify';

import {UserNotificationDto} from '@/user/entities/user-notification.dto';

@PgNotification('user_is_updated')
export class UserNotificationHandler implements IPgNotifyHandler<UserNotificationDto> {
  constructor(
    private readonly queryBus: QueryBus,
  ) {}

  async handle(
    @PgPayload(new ValidationPipe({whitelist: true, transform: true})) data: UserNotificationDto,
  ): Promise<any> {
    console.log(data);
  }
}
```

Class decorated with `PgNotification` is injectable.


In postgreSQL

```sql
select pg_notify('user_is_updated', '{"id": "69b17e87-40c8-832b-b8e5-a94d2a3c1f87"}')
```

[MIT](LICENSE)
npm package: @kovalenko/nestjs-tools
Description: Decorators to share between projects
Author: kovalenko@gmail.com
Latest version: 1.3.1

## NestJS tools

## Декораторы

### @BodyArrayWithValidation(items: Type<any>, opts?: ValidationPipeOptions): ParameterDecorator
парсит и валидирует тело запроса, которе массив

### @ValidateWithCallback<T>(values: (object: T) => boolean, validationOptions?: ValidationOptions)
валидация поля объекта с использованием колбека. В колбек поступает объект целиком

### @Serialize(options: ClassSerializerContextOptions = {}): ClassDecorator & MethodDecorator
для сериализации ответов API — скрывать поля и т.п.

### @ApiUnauthorizedResponse(description = 'Пользователь не авторизован')
описывает информацию об ответе 401 для swagger

### @ApiNotFoundResponse(description = 'Запрашиваемый ресурс не найден')
описывает информацию об ответе 404 для swagger

### @BodyWithValidation(opts?: ValidationPipeOptions)
парсит и валидирует тело запроса

### @QueryWithValidation(opts?: ValidationPipeOptions)
парсит и валидирует гет-параметры

### TransformBoolean()
преобразует строковый boolean в обычный

## Функции

### sha256(input: string): string
создает sha256-хеш

### mergeDeep(...objects): any
производит глубокое слияние нескольких объектов

### escapeLikeString(src: string): string
экранирует % b _ для поиска в sql

### paginate

```typescript
paginate<T>(
  builder: SelectQueryBuilder<T>,
  pagination: PaginationOptions,
  callbackAfterCount?: () => void | Promise<void>,
): Promise<Pagination<T>>
```

Используется как обертка функции `paginate` модуля `nestjs-typeorm-paginate`.
* `T` — тип сущности TypeORM
* `builder` — запрос
* `pagination` — опции пагинации из модуля `nestjs-typeorm-paginate`
* `callbackAfterCount` — промежуточное действие после подсчета количества. Например, можно установить addOrderBy, не нужное в счете.

## Классы

### ApiPaginationResponse<T>
Базовый класс, описывающий ответ списка сущностей с пагинацией.

T — тип сущности

### ApiErrorResponse
описывает ответ сервера 4xx, 5xx

### ApiPaginationLinks
используется в `ApiPaginationResponse` для вывода ссылок

### ApiPaginationMeta
используется в `ApiPaginationResponse` для описания количества сущностей

### ApiPaginationQuery
описание и валидация query-строки запроса на выдачу сущностей с пагинацией

### PaginationOptions
описание и валидация query-строки запроса на выдачу сущностей с пагинацией

### TrimPipe
пайп, используемый для обрезки в `@BodyWithValidation()` и `@QueryWithValidation`.

### ValidateArrayOfEnumsPipe(enum)
пайп, парсит и валидирует массив енумов


Список необрезных полей можно указать в статическом поле `static readonly safeFields: string[]`.
По умолчанию туда включены поля `password`, `passwordConfirmation`.

[MIT](LICENSE)
npm package: @kovalenko/ng-fingerprint
Description: Angular service wrapper for fingerprintjs2
Author: Kovalenko
Latest version: 1.1.1

# NgFingerprint

Angular service wrapper for fingerprintjs2

## Installation

```
npm install @kovalenko/ng-fingerprint
```

## Usage

First, import the NgFingerprintModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {NgFingerprintModule} from '@kovalenko/ng-fingerprint';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppComponent} from './app';

@NgModule({
  imports: [
    BrowserModule,
    NgFingerprintModule.config('localstorageItemName')
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {
}

platformBrowserDynamic().bootstrapModule(AppModule);
```

Then inject NgFingerprintService into your component:

```typescript
import {Component} from '@angular/core';
import {NgFingerprintService} from '@kovalenko/ng-fingerprint';

@Component({
  selector: 'app',
  template: ``,
})
export class AppComponent {
  constructor(private ngFingerprintService: NgFingerprintService) {
    ngFingerprintService.fingerprint.subscribe(fp => {
      // ...
    });
  }
}
```
## License

MIT
npm package: @kovalenko/print-element
Description: Prints selected element only
Author: Kovalenko
Latest version: 1.0.0

# PrintElement

Prints selected element only

## Installation

```
npm install @kovalenko/print-element
```

First, import the PrintElementModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {PrintElementModule} from '@kovalenko/print-element';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppComponent} from './app';

@NgModule({
  imports: [
    BrowserModule,
    PrintElementModule
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {
}

platformBrowserDynamic().bootstrapModule(AppModule);
```

Then use the directive to print an element:

```typescript
import {Component} from '@angular/core';
import {MainMenuService} from '@kovalenko/main-menu';

@Component({
  selector: 'app',
  template: `
    <button [ngcPrintElement]="printable"></button>
    <div #printable>
      Printable element
    </div>
  `,
})
export class AppComponent { }
```

### Directive

Selector: `[ngcPrintElement]`

#### Properties

Name | Description
--- | ---
`@Input() ngcPrintElement: HTMLElement` | printable element

## License

MIT
npm package: @kovalenko/scroll-here
Description: Scrolls specified container to the element with this directive when it's condition becomes truthy.
Author: Kovalenko
Latest version: 1.0.0

# ScrollHere

Scrolls specified container to the element with this directive when it's condition becomes truthy.

## Installation

```
npm install @kovalenko/scroll-here
```

## Supported API

### Properties

| @Input() | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| ngcScrollHere | boolean | required | | Sets condition when to start scrolling
| ngcScrollContainer | string / HTMLElement	| optional | 'html' | Place this attribute BEFORE [ngcScrollHere] in template. Should get a html element or css selector for a scrollable element; window will be used if this attribute is empty
| ngcScrollDuration | number | optional | 200 | Sets the scroll duration


### Events

| @Output() | Type | Event Type | Required | Description |
| --- | --- | --- | --- | --- |
| ngcScrollTriggered | EventEmitter | void | optional | this will callback if start scrolling condition has been met
| ngcScrollFinished | EventEmitter | void | optional | this will callback if scrolling has been finished

## Usage

First, import the ScrollHereModule to your module:

```typescript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ScrollHereModule } from '@kovalenko/scroll-here';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app';

@NgModule({
  imports: [BrowserModule, ScrollHereModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);
```

In this example, window will be scrolled to inner div and when **ngcScrollFinished** callback will be invoked the window will be scrolled to outer div 

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: `
    <div style="padding-top: 3000px" [ngcScrollHere]="toTop" [ngcScrollDuration]="4000">
      <div [ngcScrollHere]="!triggered && s" [ngcScrollDuration]="2000" (ngcScrollTriggered)="triggered = true" (ngcScrollFinished)="toTop = true">Bottom</div>
    </div>
  `,
})
export class AppComponent {
  s = true;
  triggered = false;
  toTop = false;
}
```

## License

MIT
npm package: @kovalenko/snack-bar
Description: This module provides a service to open Material Snackbar with default dismiss action.
Author: Kovalenko
Latest version: 1.0.3

# Material Snackbar with default action

This module provides a service to open Material Snackbar with default dismiss action.

## Installation

```
npm install @kovalenko/snack-bar
```

## Usage

First, import the SnackBarModule to your module:

```typescript
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {SnackBarModule} from '@kovalenko/snack-bar';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {DialogComponent} from './app';

@NgModule({
  imports: [BrowserModule, SnackBarModule],
  declarations: [DialogComponent],
  bootstrap: [DialogComponent],
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(DialogComponent);
```

Then inject SnackBarService:
```typescript
import {Component} from '@angular/core';
import {SnackBarService, snack} from 'snack-bar';

@Component({
  template: ``
})
export class DialogComponent {

  constructor(
    private readonly snackBarService: SnackBarService,
  ) { }

  ngOnInit(): void {
    // Set default action title globally
    this.snackBarService.defaultAction = 'Close';
    
    // Launch snackbar
    this.snackBarService.open('Privet', snack.error);
  }
}
```

### API

#### SnackBarService

##### Properties

defaultAction?: string;

##### Methods

<table>
<tr>
<th colspan="2">open</th>
</tr>
<tr>
<td colspan="2">Opens a snackbar with a message and default action</td>
</tr>
<tr>
<th colspan="2">Parameters</th>
</tr>
<tr>
<td>message<br>string</td><td>The message to show in the snackbar</td>
</tr>
<tr>
<td>config?<br>MatSnackBarConfig&lt;any&gt;</td><td>Additional configuration options for the snackbar</td>
</tr>
<tr>
<td>action?<br>string</td><td>The label for the snackbar action</td>
</tr>
<tr>
<th colspan="2">Returns</th>
</tr>
<tr>
<td colspan="2">MatSnackBarRef&lt;any&gt;</td>
</tr>
</table>


## License

[MIT](LICENSE)
npm package: @kovalenko/swipe-sidenav
Description: Adds swipe functionality to material sidenav or drawer
Author: Kovalenko
Latest version: 1.0.0

# SwipeSidenav

Adds swipe functionality to material sidenav or drawer

## Installation

```
npm install @kovalenko/swipe-sidenav
```

## Usage

Extend your component from `SwipeableSidenav`. In template, add `#drawer` export to sidenav or drawer and `[@.disabled]="disableAnimation"` to the container.

```typescript
import {Component} from '@angular/core';
import {SwipeableSidenav} from '@kovalenko/swipe-sidenav';

@Component({
  selector: 'app',
  template: `
    <mat-drawer-container [@.disabled]="disableAnimation">
      <mat-drawer #drawer>mat-drawer-content</mat-drawer>
    </mat-drawer-container>
  `,
})
export class AppComponent extends SwipeableSidenav {
  constructor() {
    super();
  }

}
```

## License

MIT