npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

angular-swagger2

v1.3.0

Published

Generator of types, API and NGRX layer in TypeScript for Angular 12 apps

Downloads

1

Readme

Angular Swagger2

This repository was derived from swagger-angular-generator. The main difference is that it drops support for form services and extends ngrx generation capabilities, introduces eslint and Angular 12 support.

Purpose

Generate minimalistic TypeScript API layer for Angular with full type reflection of backend model.

What is generated

Services for back-end / API communication

  • connect to your API in no-time

Interfaces

  • request and response interfaces are created

NGRX modules for endpoints (optional)

  • so that the server responses can be reached in the redux store
  • requests can be triggered by dispatching an action
Have a look at the demo-app generated files to get better understanding what is being generated.

Install

npm i angular-swagger2

Options

  • -h - show help
  • -s, --src - source directory
  • -d, --dest - destination directory, default: src/api
  • --no-store - do not generate the ngrx modules
  • -u, --swagger-URL-path - swagger URL path, where the swagger ui documentation can be found; default: /swagger, i.e. the resulting address would be http://example/swagger
  • -o, --omit-version - disables API version information to be generated in comments for each file

Use

Run generator

  1. get the swagger scheme (typically at http(s)://[server]/[app-path]/v2/api/api-docs)
  2. save it to json file in input directory and optionally format it for better diff
  3. run via
    1. directly ./node_modules/.bin/angular-swagger2
    2. as module angular-swagger2 package, npm run generate
      "script": {
        "generate": "angular-swagger2 -s src/api/scheme.json -d src/api/generated"
        ...
      }
    3. or programatically as a method invocation
      import {generate} from 'angular-swagger2';
      // or using CommonJS loader
      const {generate} = require('angular-swagger2');
      
      generate('conf/api/api-docs.json', 'src/api');

The resulting API layer contains the following structure in the destination directory:

  1. controllers directory stores services containing all API methods devided by controllers
  2. defs directory stores all response interfaces and enums
  3. store directory has modules, which contain NGRX actions, reducers and effects
  4. model.ts file reexports all of them together for a simple access

When updating your code for new backend version, we recommend you to follow these steps:

  1. git diff the changes
  2. run tsc for immediate problems
  3. adjust the code, solve problems
  4. commit

Use

In order to consume generated model, follow the steps 1-9 in the following example to use generated API model.

API service usage in component

// 1. import used response interfaces
import {ItemDto, PageDto} from '[relative-path-to-destination-directory]/model';
// 2. import used API service and optionally param interfaces
import {DataService, MethodParams} from '[relative-path-to-destination-directory]/api/DataService';

@Component({
  ...
  // 3. make the service injectable (can be also imported in the module)
  providers: [DataService],
})
export class MyComponent implements OnInit {
  // 4. declare response object variables based on the generated API interfaces
  public items: ItemDto[] = [];
  public page: PageDto;

  // 5. declare request params based on the generated API interface (all params are passed together in one object)
  private params: MethodParams = {
    page: 0,
    size: 10,
    sort: ['name:asc']
  };

  // 6. inject the API service
  constructor(private dataService: DataService) {}

  public ngOnInit() {
    // 7. the returned observable is fully typed
    this.dataService
      .get(this.params)
      // 8. returned data are fully typed
      .subscribe(data => {
        // 9. assignments are type-checked
        this.items = data.content;
        this.page = data.page;
      });
  }
}

NGRX workflow with generated modules, actions, effects, reducerss

Import the generated module
@NgModule({
  imports: [
    ...,
    ExampleModule,
    ...,
  ],
})
export class YourModule {}
  • the generated module looks like this
@NgModule({
  imports: [
    NgrxStoreModule.forFeature(selectorName, ExampleReducer),
    NgrxEffectsModule.forFeature([ExampleEffects]),
  ],
  providers: [
    ExampleService,
  ],
})
export class ExampleModule {}
Component (created by you)

In the component, send the above created form via sendForm() method. Notice the way a generated anction is dispatched.

import {Component, OnDestroy} from '@angular/core';
import {Store} from '@ngrx/store';
import {takeUntil} from 'rxjs/operators';
import {Subject} from 'rxjs/Subject';
import {ExampleStart} from '../../generated/store/example/exampleModule/states/actions';
import {AppState} from '../states/exmaple.models';

@Component({
  selector: 'example-component',
  templateUrl: 'example-component.html',
})
export class ExampleComponent implements OnDestroy {

  constructor(
    private store: Store<AppState>,
  ) {}

  sendForm() {
    this.store.dispatch(new ExampleStart());
  }

  ngOnDestroy() {
    this.ngDestroy.next();
    this.ngDestroy.complete();
  }
}
Effect (generated)
  • the dispatched method is intercepted by an effect which calls the API via the generated API service
  • upon success, a Success action is dispatched (payload is the server response data)
  • upon error, an Error action is dispatched (payload is the error message sent from the server)
@Injectable()
export class ExampleEffects {
  @Effect()
  CreateProductCategory = this.storeActions.ofType<ExampleStart>(ExampleActions.START).pipe(
    switchMap((action: ExampleStart) => this.exampleService.exampleEndpointMethod(action.payload)
      .pipe(
        map(result => new ExampleSuccess(result)),
        catchError((error: HttpErrorResponse) => of(new ExampleError(error.message))),
      ),
    ),
  );

  constructor(
    private storeActions: Actions,
    private adminproductService: AdminProductService,
  ) {}
}
Reducer (generated)
  • the reducer catches the Success / Error actions dispatched by the generated effect and stores the payloads to the store
export interface ExampleState {
  data: __model.ExampleServerResponseInterface;
  loading: boolean;
  error: string;
}

export const initialExampleState: ExampleState = {
  data: null,
  loading: false,
  error: null,
};

export const selectorName = 'Example';
export const getExampleSelector = createFeatureSelector<ExampleState>(selectorName);

export function ExampleReducer(
  state: ExampleState = initialExampleState,
  action: ExampleAction): ExampleState {
  switch (action.type) {
    case ExampleActions.START: return {...state, loading: true, error: null};
    case ExampleActions.SUCCESS: return {...state, data: action.payload, loading: false};
    case ExampleActions.ERROR: return {...state, error: action.payload, loading: false};
    default: return state;
  }
}
Component (again)
  • the data can be retrieved by subscribing to the store
ngOnInit() {
    this.exampleState = this.store.pipe(
      takeUntil(this.ngDestroy),
      select(getExampleSelector));
    // OR
    this.data = this.store.select(s => ExampleState.data)
    this.loading = this.store.select(s => ExampleState.loading)
    this.error = this.store.select(s => ExampleState.error)
}

Assumptions / limitations

  1. swagger file is in version 2 format, it must be json
  2. each endpoint must have a tags attribute defined. In addition, there must be exactly one tag defined. The http methods are grouped to services based on the tags, i.e. if two methods have tag "order", both will be generated inside Order.ts
  3. get and delete methods do not contain body
  4. swagger file should contain values for the keys host and basePath so that each generated service method can contain a link to the swagger UI method reference, e.g. http://example.com/swagger/swagger-ui.html#!/Order/Order
  5. definitions section in swagger file does not contain types with inline definitions, i.e. only named subtypes work

Usage of NGRX modules

Development

  • developed with node v16

Docker image

  1. docker build . -t angular-swagger2
  2. docker run -u $(id -u) -it -v "$PWD":/code angular-swagger2 bash
  3. npm i
  4. npm run install:demo

Testing

How the testing works

  • tests are written in the demo-app
  • the test swagger files can be found in demo-app/client/test-swaggers
  • upon these swagger files, interfaces and services are generated
  • the generated services are manually imported to the app.module.ts
  • unit tests can be found in demo-app/client/src/tests

Running the tests

To run client tests in interactive mode:

  1. cd demo-app/client
  2. npm test

Release

  • git checkout -b tech/release on master or other branch you want to release
  • npm version patch or other version change you want
  • make a PR
  • once merged npm publish

Pull requests are welcome!

Please do the following before making a PR:

  1. Build the app and regenerate testing files via npm run build.
  2. Check test pass via npm test.
  3. Check files lint via npm run lint.