Skip to content

Commit

Permalink
Merge pull request #7 from angular-architects/enabler/linting
Browse files Browse the repository at this point in the history
Optimized naming and Code linting
  • Loading branch information
fancyDevelopment authored Sep 28, 2024
2 parents 2832f65 + f3e2d48 commit be10ae0
Show file tree
Hide file tree
Showing 52 changed files with 2,553 additions and 427 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ngrx-hateoas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ jobs:
- name: Build library
run: |
npm run build
# Lint library
- name: Lint library
run: |
npm run lint
10 changes: 10 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
"zone.js/testing"
]
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"libs/ngrx-hateoas/**/*.ts",
"libs/ngrx-hateoas/**/*.html"
],
"eslintConfig": "libs/ngrx-hateoas/eslint.config.js"
}
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions apps/playground/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
</div>
</div>
<div class="navbar-nav px-3">
@if(!appState.userInfo.isAvailable()) {
@if(!appState.userInfoState.isAvailable()) {
<div class="nav-item">
<button class="btn btn-secondary" (click)="logIn()">Login</button>
</div>
} @else {
<div class="nav-item">
<button class="btn btn-info text-nowrap" (click)="logOut()">
Logout <span class="badge text-bg-light">{{ appState.userInfo.resource.name() }}</span>
Logout <span class="badge text-bg-light">{{ appState.userInfo.name() }}</span>
</button>
</div>
}
Expand Down
6 changes: 1 addition & 5 deletions apps/playground/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import { AppState } from './app.state';
export class AppComponent {

appState = inject(AppState);
rootApiLoaded = this.appState.rootApi.isLoaded;

constructor() {

}
rootApiLoaded = this.appState.rootApiState.isLoaded;

logIn() {
window.location.href = './login?redirectUri=' + encodeURIComponent(window.origin);
Expand Down
2 changes: 1 addition & 1 deletion apps/playground/src/app/app.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const AppState = signalStore(
withLinkedHypermediaResource('userInfo', { name: '', preferred_username: '' }),
withHooks({
onInit(store) {
store.connectUserInfo(store.rootApi.resource, 'userinfo')
store.connectUserInfo(store.rootApi, 'userinfo')
}
})
);
2 changes: 1 addition & 1 deletion apps/playground/src/app/core/core.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export const CORE_ROUTES: Routes = [{
}, {
path: 'home',
component: HomeComponent,
canActivate: [ () => whenTrue(inject(CoreState).homeVm.initiallyLoaded) ]
canActivate: [ () => whenTrue(inject(CoreState).homeVmState.initiallyLoaded) ]
}];
2 changes: 1 addition & 1 deletion apps/playground/src/app/core/core.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const CoreState = signalStore(
withLinkedHypermediaResource('homeVm', initialHomeVm),
withHooks({
onInit(store) {
store.connectHomeVm(inject(AppState).rootApi.resource, 'homeVm')
store.connectHomeVm(inject(AppState).rootApi, 'homeVm')
}
})
);
2 changes: 1 addition & 1 deletion apps/playground/src/app/core/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import { CoreState } from '../core.state';
templateUrl: './home.component.html'
})
export class HomeComponent {
viewModel = inject(CoreState).homeVm.resource;
viewModel = inject(CoreState).homeVm;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class FlightCreateComponent {

viewModel = this.flightState.getFlightCreateVmAsPatchable();

saveEnabled = this.flightState.createFlight.isAvailable;
saveEnabled = this.flightState.createFlightState.isAvailable;

aircrafts = this.viewModel.aircrafts;

Expand All @@ -27,7 +27,7 @@ export class FlightCreateComponent {
flightOperator = this.viewModel.template.operator;

async onSaveFlight() {
await this.flightState.executeCreateFlight();
await this.flightState.createFlight();
this.location.back();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@

<div class="row">
<div class="col">
<app-action-card [disabled]="!flightState.updateFlightConnection.isAvailable()"
[showSuccess]="flightState.updateFlightConnection.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightConnection.hasExecutedWithError()"
(execute)="flightState.executeUpdateFlightConnection()">
<app-action-card [disabled]="!flightState.updateFlightConnectionState.isAvailable()"
[showSuccess]="flightState.updateFlightConnectionState.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightConnectionState.hasExecutedWithError()"
(execute)="flightState.updateFlightConnection()">
<app-flight-connection-form [model]="flightConnection()" (modelChange)="flightConnection.set($event)" />
</app-action-card>
<app-action-card [disabled]="!flightState.updateFlightTimes.isAvailable()"
[showSuccess]="flightState.updateFlightTimes.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightTimes.hasExecutedWithError()"
(execute)="flightState.executeUpdateFlightTimes()">
<app-action-card [disabled]="!flightState.updateFlightTimesState.isAvailable()"
[showSuccess]="flightState.updateFlightTimesState.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightTimesState.hasExecutedWithError()"
(execute)="flightState.updateFlightTimes()">
<app-flight-times-form [model]="flightTimes()" (modelChange)="flightTimes.set($event)" />
</app-action-card>
<app-action-card [disabled]="!flightState.updateFlightOperator.isAvailable()"
[showSuccess]="flightState.updateFlightOperator.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightOperator.hasExecutedWithError()"
(execute)="flightState.executeUpdateFlightOperator()">
<app-action-card [disabled]="!flightState.updateFlightOperatorState.isAvailable()"
[showSuccess]="flightState.updateFlightOperatorState.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightOperatorState.hasExecutedWithError()"
(execute)="flightState.updateFlightOperator()">
<app-flight-operator-form [aircrafts]="viewModel.aircrafts()" [model]="flightOperator()" (modelChange)="flightOperator.set($event)" />
</app-action-card>
@if(flightPrice(); as flightPriceValue) {
<app-action-card [disabled]="!flightState.updateFlightPrice.isAvailable()"
[showSuccess]="flightState.updateFlightPrice.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightPrice.hasExecutedWithError()"
(execute)="flightState.executeUpdateFlightPrice()">
<app-action-card [disabled]="!flightState.updateFlightPriceState.isAvailable()"
[showSuccess]="flightState.updateFlightPriceState.hasExecutedSuccessfully()"
[showError]="flightState.updateFlightPriceState.hasExecutedWithError()"
(execute)="flightState.updateFlightPrice()">
<app-flight-price-form [model]="flightPriceValue" (modelChange)="flightPrice.set($event)" />
</app-action-card>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<div class="col">
<app-flight-summary-card [flight]="flight">
@if(flight | hasLink:'flightEditVm') {
<a class="btn btn-primary" [routerLink]="['/flight/edit', (flight | getLink:'flightEditVm').href]">Edit</a>
<a class="btn btn-primary" [routerLink]="['/flight/edit', (flight | getLink:'flightEditVm')?.href]">Edit</a>
}
</app-flight-summary-card>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class FlightSearchComponent {
hateoasService = inject(HateoasService);
router = inject(Router);
flightState = inject(FlightState);
showCreate = this.flightState.createFlight.isAvailable;
showCreate = this.flightState.createFlightState.isAvailable;
viewModel = this.flightState.getFlightSearchVmAsPatchable();
from = this.viewModel['from'];
to = this.viewModel['to'];
Expand Down
4 changes: 2 additions & 2 deletions apps/playground/src/app/flight/flight.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const FLIHGT_ROUTES: Routes = [{
}, {
path: "search",
component: FlightSearchComponent,
canActivate: [() => inject(FlightState).loadFlightSearchVmFromLink(inject(AppState).rootApi.resource(), 'flightSearchVm')]
canActivate: [() => inject(FlightState).loadFlightSearchVmFromLink(inject(AppState).rootApi(), 'flightSearchVm')]
}, {
path: "search/:url",
component: FlightSearchComponent,
Expand All @@ -26,5 +26,5 @@ export const FLIHGT_ROUTES: Routes = [{
}, {
path: "create",
component: FlightCreateComponent,
canActivate: [() => whenTrue(inject(FlightState).flightCreateVm.initiallyLoaded)]
canActivate: [() => whenTrue(inject(FlightState).flightCreateVmState.initiallyLoaded)]
}];
12 changes: 6 additions & 6 deletions apps/playground/src/app/flight/flight.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ export const FlightState = signalStore(
withHypermediaAction('createFlight'),
withHooks({
onInit(store) {
store.connectUpdateFlightConnection(store.flightEditVm.resource.flight.connection, 'update');
store.connectUpdateFlightTimes(store.flightEditVm.resource.flight.times, 'update');
store.connectUpdateFlightOperator(store.flightEditVm.resource.flight.operator, 'update');
store.connectUpdateFlightPrice(store.flightEditVm.resource.flight.price, 'update');
store.connectFlightCreateVm(store.flightSearchVm.resource, 'flightCreateVm');
store.connectCreateFlight(store.flightCreateVm.resource.template, 'create');
store.connectUpdateFlightConnection(store.flightEditVm.flight.connection, 'update');
store.connectUpdateFlightTimes(store.flightEditVm.flight.times, 'update');
store.connectUpdateFlightOperator(store.flightEditVm.flight.operator, 'update');
store.connectUpdateFlightPrice(store.flightEditVm.flight.price, 'update');
store.connectFlightCreateVm(store.flightSearchVm, 'flightCreateVm');
store.connectCreateFlight(store.flightCreateVm.template, 'create');
}
})
);
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h5 class="card-title">{{flight.connection.from}} - {{flight.connection.to}}</h5
</div>
<div class="card-footer d-flex justify-content-between align-items-center">
@if(flight | hasLink:'flightEditVm') {
<a class="btn btn-primary" [routerLink]="['/flight/edit', (flight | getLink:'flightEditVm').href]">Edit</a>
<a class="btn btn-primary" [routerLink]="['/flight/edit', (flight | getLink:'flightEditVm')?.href]">Edit</a>
}
</div>
</div>
Expand Down
43 changes: 43 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// @ts-check
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const angular = require("angular-eslint");

module.exports = tseslint.config(
{
files: ["**/*.ts"],
extends: [
eslint.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.stylistic,
...angular.configs.tsRecommended,
],
processor: angular.processInlineTemplates,
rules: {
"@angular-eslint/directive-selector": [
"error",
{
type: "attribute",
prefix: "lib",
style: "camelCase",
},
],
"@angular-eslint/component-selector": [
"error",
{
type: "element",
prefix: "lib",
style: "kebab-case",
},
],
},
},
{
files: ["**/*.html"],
extends: [
...angular.configs.templateRecommended,
...angular.configs.templateAccessibility,
],
rules: {},
}
);
38 changes: 38 additions & 0 deletions libs/ngrx-hateoas/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @ts-check
const tseslint = require("typescript-eslint");
const rootConfig = require("../../eslint.config.js");

module.exports = tseslint.config(
...rootConfig,
{
files: ["**/*.ts"],
rules: {
"@angular-eslint/directive-selector": [
"error",
{
type: "attribute",
prefix: "hat",
style: "camelCase",
},
],
"@angular-eslint/component-selector": [
"error",
{
type: "element",
prefix: "hat",
style: "kebab-case",
},
],
"@typescript-eslint/consistent-type-definitions": [
"off"
],
"@typescript-eslint/no-unsafe-function-type": [
"off"
]
},
},
{
files: ["**/*.html"],
rules: {},
}
);
2 changes: 1 addition & 1 deletion libs/ngrx-hateoas/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@angular-architects/ngrx-hateoas",
"version": "18.0.0-rc.1",
"version": "18.0.0-rc.3",
"peerDependencies": {
"@angular/common": "^18.0.0",
"@angular/core": "^18.0.0",
Expand Down
5 changes: 2 additions & 3 deletions libs/ngrx-hateoas/src/lib/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ export interface ResourceSocket {
href: string
}

export type Resource = {
}
export type Resource = Record<string, unknown>;

export type DynamicResourceValue = DynamicResource | Resource | number | string | boolean | DynamicResource[] | Resource[] | number[] | boolean[] | null;

export type DynamicResource = Resource & {
[key: string]: DynamicResourceValue;
[key: string]: DynamicResource | number | string | boolean | DynamicResource[] | number[] | boolean[] | null;
}

export const initialDynamicResource: DynamicResource = {};
12 changes: 6 additions & 6 deletions libs/ngrx-hateoas/src/lib/pipes/get-action.pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestBed } from '@angular/core/testing';
import { GetActionPipe } from './get-action.pipe';
import { HateoasConfig, HateoasService } from '../services/hateoas.service';
import { HateoasService } from '../services/hateoas.service';

const testModel = {
_actions: {
Expand All @@ -13,18 +13,18 @@ describe('GetActionPipe', () => {
let getActionPipe: GetActionPipe;

beforeEach(() => {
TestBed.configureTestingModule({ providers: [ GetActionPipe, HateoasService, HateoasConfig ]});
TestBed.configureTestingModule({ providers: [ GetActionPipe, HateoasService ]});
getActionPipe = TestBed.inject(GetActionPipe);
});

it('gets an action from hypermedia json', () => {
const transformResult = getActionPipe.transform(testModel, 'create');
expect(transformResult.href).toBe('/api/test');
expect(transformResult.method).toBe('POST');
expect(transformResult?.href).toBe('/api/test');
expect(transformResult?.method).toBe('POST');
});

it('throws an exception for a non existing action', () => {
expect(() => getActionPipe.transform(testModel, 'create1')).toThrowError('The requested action does not exist on the specified resource. Use the "hasAction" pipe to check the existance of the link first');
it('returns undefined for a non existing action', () => {
expect(getActionPipe.transform(testModel, 'create1')).toBeUndefined();
});

});
10 changes: 2 additions & 8 deletions libs/ngrx-hateoas/src/lib/pipes/get-action.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,8 @@ export class GetActionPipe implements PipeTransform {

private hateoasService = inject(HateoasService);

transform(resource: unknown, actionName: string): ResourceAction {
const action = this.hateoasService.getAction(resource, actionName);

if (action === undefined) {
throw new Error('The requested action does not exist on the specified resource. Use the "hasAction" pipe to check the existance of the link first');
}

return action;
transform(resource: unknown, actionName: string): ResourceAction | undefined {
return this.hateoasService.getAction(resource, actionName);
}

}
10 changes: 5 additions & 5 deletions libs/ngrx-hateoas/src/lib/pipes/get-link.pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TestBed } from '@angular/core/testing';
import { HateoasConfig, HateoasService } from '../services/hateoas.service';
import { HateoasService } from '../services/hateoas.service';
import { GetLinkPipe } from './get-link.pipe';

const testModel = {
Expand All @@ -13,17 +13,17 @@ describe('GetLinkPipe', () => {
let getLinkPipe: GetLinkPipe;

beforeEach(() => {
TestBed.configureTestingModule({ providers: [ GetLinkPipe, HateoasService, HateoasConfig ]});
TestBed.configureTestingModule({ providers: [ GetLinkPipe, HateoasService ]});
getLinkPipe = TestBed.inject(GetLinkPipe);
});

it('gets a link from hypermedia json', () => {
const transformResult = getLinkPipe.transform(testModel, 'foo');
expect(transformResult.href).toBe('/api/foo');
expect(transformResult?.href).toBe('/api/foo');
});

it('throws an exception for a non existing link', () => {
expect(() => getLinkPipe.transform(testModel, 'foo1')).toThrowError('The requested link does not exist on the specified resource. Use the "hasLink" pipe to check the existance of the link first');
it('returns undefined for a non existing link', () => {
expect(getLinkPipe.transform(testModel, 'foo1')).toBeUndefined();
});

});
Loading

0 comments on commit be10ae0

Please sign in to comment.