Skip to content

Commit

Permalink
feat(driver): add backend delegate service (#3146)
Browse files Browse the repository at this point in the history
  • Loading branch information
griest024 authored Oct 7, 2024
1 parent 87277c6 commit 8a616ee
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 0 deletions.
8 changes: 8 additions & 0 deletions libs/driver/in-memory/src/backend/backends.token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createServicesInjectionToken } from '@daffodil/core';

import { DaffInMemoryBackendInterface } from './type';

export const {
token: DAFF_IN_MEMORY_BACKENDS,
provider: provideDaffInMemoryBackends,
} = createServicesInjectionToken<DaffInMemoryBackendInterface>('DAFF_IN_MEMORY_BACKENDS');
66 changes: 66 additions & 0 deletions libs/driver/in-memory/src/backend/delegate.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { STATUS } from 'angular-in-memory-web-api';

import {
DaffInMemoryBackendInterface,
DaffInMemoryDataServiceInterface,
} from '@daffodil/driver/in-memory';

import { DaffInMemoryBackendDelegate } from './delegate.service';

describe('@daffodil/driver/in-memory', () => {
let service: DaffInMemoryBackendDelegate;
let backends: Array<jasmine.SpyObj<DaffInMemoryBackendInterface>>;
let methods: Array<keyof DaffInMemoryDataServiceInterface>;

beforeEach(() => {
methods = ['get', 'put', 'post', 'delete'];
backends = [
jasmine.createSpyObj('a', methods, {
collectionName: 'a',
}),
jasmine.createSpyObj('b', methods, {
collectionName: 'b',
}),
jasmine.createSpyObj('c', [], {
collectionName: 'c',
}),
];
service = new DaffInMemoryBackendDelegate(backends);
});

// eslint-disable-next-line guard-for-in
for (const method in methods) {
describe(method, () => {
it('should delegate requests to the correct backend', () => {
const reqInfo: any = {
collectionName: 'a',
};
service[method](reqInfo);
expect(backends[0][method]).toHaveBeenCalledWith(reqInfo);
reqInfo.collectionName = 'b';
service[method](reqInfo);
expect(backends[1][method]).toHaveBeenCalledWith(reqInfo);
});

it('should return a "not found" if the method is missing from the backend', (done) => {
const reqInfo: any = {
collectionName: 'c',
};
service[method](reqInfo).subscribe((res) => {
expect(res.status).toEqual(STATUS.NOT_FOUND);
done();
});
});

it('should return a "not found" if there isn\'t a backend for the collection name', (done) => {
const reqInfo: any = {
collectionName: '404backendnotfound',
};
service[method](reqInfo).subscribe((res) => {
expect(res.status).toEqual(STATUS.NOT_FOUND);
done();
});
});
});
}
});
51 changes: 51 additions & 0 deletions libs/driver/in-memory/src/backend/delegate.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
Inject,
Injectable,
} from '@angular/core';
import {
RequestInfo,
STATUS,
} from 'angular-in-memory-web-api';
import { Observable } from 'rxjs';

import { DAFF_IN_MEMORY_BACKENDS } from './backends.token';
import { DaffInMemoryDataServiceInterface } from './data-service.type';
import { DaffInMemoryBackendInterface } from './type';

/**
* An in-memory backend that automatically delegates requests to backends provided to {@link DAFF_IN_MEMORY_BACKENDS}.
*
* @inheritdoc
*/
@Injectable({
providedIn: 'root',
})
export class DaffInMemoryBackendDelegate implements DaffInMemoryDataServiceInterface {
constructor(
@Inject(DAFF_IN_MEMORY_BACKENDS) private backends: Array<DaffInMemoryBackendInterface>,
) {}

protected delegateRequest(reqInfo: RequestInfo, method: keyof DaffInMemoryDataServiceInterface): Observable<any> {
const backend = this.backends.find((b) => b.collectionName === reqInfo.collectionName);
return backend?.[method](reqInfo) || reqInfo.utils.createResponse$(() => ({
status: STATUS.NOT_FOUND,
statusText: `Backend ${reqInfo.collectionName} not found or does not support the ${method} request method`,
}));
}

get?(reqInfo: RequestInfo): Observable<any> {
return this.delegateRequest(reqInfo, 'get');
}

post?(reqInfo: RequestInfo): Observable<any> {
return this.delegateRequest(reqInfo, 'post');
}

put?(reqInfo: RequestInfo): Observable<any> {
return this.delegateRequest(reqInfo, 'put');
}

delete?(reqInfo: RequestInfo): Observable<any> {
return this.delegateRequest(reqInfo, 'delete');
}
}
3 changes: 3 additions & 0 deletions libs/driver/in-memory/src/backend/public_api.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from './backends.token';
export * from './data-service.type';
export * from './delegate.service';
export * from './type';
12 changes: 12 additions & 0 deletions libs/driver/in-memory/src/backend/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DaffInMemoryDataServiceInterface } from './data-service.type';

/**
* An interface for defining in memory backends that use the angular in memory web api.
*/
export interface DaffInMemoryBackendInterface extends DaffInMemoryDataServiceInterface {
/**
* The collection name of the backend service.
* Used for routing requests to the correct backend.
*/
readonly collectionName: string;
}
3 changes: 3 additions & 0 deletions libs/driver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
"publish": "cd ../../dist/driver && npm publish --access=public"
},
"homepage": "https://github.com/graycoreio/daffodil",
"optionalDependencies": {
"angular-in-memory-web-api": "0.0.0-PLACEHOLDER"
},
"peerDependencies": {
"@angular/common": "0.0.0-PLACEHOLDER",
"@angular/core": "0.0.0-PLACEHOLDER",
Expand Down

0 comments on commit 8a616ee

Please sign in to comment.