Skip to content

Commit

Permalink
feat(@whook/cors): add custom CORS per handlers support
Browse files Browse the repository at this point in the history
Also reshaped handler definitions types to be more modular and set it up in the example project configs directly
  • Loading branch information
nfroidure committed Oct 1, 2020
1 parent 3b227ff commit b62c068
Show file tree
Hide file tree
Showing 25 changed files with 378 additions and 112 deletions.
33 changes: 33 additions & 0 deletions packages/whook-aws-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,39 @@ export async function prepareBuildEnvironment(
}
```

And add the AWS Lambda config (usually in `src/config/common/config.js`):
```diff
+ import type {
+ WhookCompilerConfig,
+ WhookAPIOperationAWSLambdaConfig,
+ } from '@whook/aws-lambda';

// ...

export type AppConfigs = WhookConfigs &
+ WhookCompilerConfig &
APIConfig;

const CONFIG: AppConfigs = {
// ...
+ COMPILER_OPTIONS: {
+ externalModules: [],
+ ignoredModules: [],
+ extensions: ['.ts', '.mjs', '.js', '.json'],
+ mainFields: ['browser', 'module', 'main'],
+ target: '12.13',
+ },
};

// Export custom handlers definitions
export type APIHandlerDefinition = WhookAPIHandlerDefinition<
+ WhookAPIOperationAWSLambdaConfig &
WhookAPIOperationSwaggerConfig
>;

export default CONFIG;
```

# Build

To build your functions :
Expand Down
15 changes: 8 additions & 7 deletions packages/whook-aws-lambda/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
WhookCompilerConfig,
} from './services/compiler';
import type { Autoloader } from 'knifecycle';
import type { WhookAPIOperationAddition } from '@whook/whook';
import type { WhookAPIOperationAddition, WhookOperation } from '@whook/whook';
import type { OpenAPIV3 } from 'openapi-types';
import type { LogService } from 'common-services';

Expand All @@ -29,9 +29,8 @@ export type WhookAPIOperationAWSLambdaConfig = {
sourceOperationId?: string;
staticFiles?: string[];
compilerOptios?: WhookCompilerOptions;
suffix?: string;
};
type WhookAPIAWSLambdaOperation = OpenAPIV3.OperationObject &
WhookAPIOperationAddition<WhookAPIOperationAWSLambdaConfig>;

const readFileAsync = util.promisify(fs.readFile) as (
path: string,
Expand Down Expand Up @@ -145,9 +144,11 @@ export async function runBuild(

log('info', 'Environment initialized 🚀🌕');

const operations: WhookAPIAWSLambdaOperation[] = (
await flattenOpenAPI(API).then(getOpenAPIOperations)
).filter((operation: WhookAPIAWSLambdaOperation) => {
const operations = (
await getOpenAPIOperations<WhookAPIOperationAWSLambdaConfig>(
await flattenOpenAPI(API),
)
).filter((operation) => {
if (handlerName) {
const sourceOperationId =
operation['x-whook'] && operation['x-whook'].sourceOperationId;
Expand Down Expand Up @@ -200,7 +201,7 @@ async function processOperations(
$autoload: Autoloader;
buildInitializer: Function;
},
operations: WhookAPIAWSLambdaOperation[],
operations: WhookOperation<WhookAPIOperationAWSLambdaConfig>[],
) {
const operationsLeft = operations.slice(BUILD_PARALLELISM);

Expand Down
7 changes: 5 additions & 2 deletions packages/whook-aws-lambda/src/services/_autoload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { WhookBuildConstantsService } from '@whook/whook';
import type { Injector } from 'knifecycle';
import type { LogService } from 'common-services';
import type { OpenAPIV3 } from 'openapi-types';
import type { WhookAPIOperationAWSLambdaConfig } from '..';

/**
* Wrap the _autoload service in order to build AWS
Expand Down Expand Up @@ -53,13 +54,15 @@ export default alsoInject(
}>
> => {
let API: OpenAPIV3.Document;
let OPERATION_APIS: WhookOperation[];
let OPERATION_APIS: WhookOperation<WhookAPIOperationAWSLambdaConfig>[];
const getAPIOperation = (() => {
return async (serviceName) => {
// eslint-disable-next-line
API = API || (await flattenOpenAPI((await $injector(['API'])).API));
// eslint-disable-next-line
OPERATION_APIS = OPERATION_APIS || getOpenAPIOperations(API);
OPERATION_APIS =
OPERATION_APIS ||
getOpenAPIOperations<WhookAPIOperationAWSLambdaConfig>(API);

const OPERATION = OPERATION_APIS.find(
(operation) =>
Expand Down
12 changes: 9 additions & 3 deletions packages/whook-cors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ async function initWrappers(): Promise<WhookWrapper<any, any>[]> {

And add the CORS config (usually in `src/config/common/config.js`):
```diff
+ import {
+ CORSConfig
+ import type {
+ CORSConfig,
+ WhookAPIOperationCORSConfig,
+ } from '@whook/cors';

// ...
Expand All @@ -65,10 +66,15 @@ const CONFIG: AppConfigs = {
+ 'Keep-Alive',
+ 'User-Agent',
+ ].join(','),
+ Vary: 'Origin',
+ },
};

// Export custom handlers definitions
export type APIHandlerDefinition = WhookAPIHandlerDefinition<
+ WhookAPIOperationCORSConfig &
WhookAPIOperationSwaggerConfig
>;

export default CONFIG;
```

Expand Down
25 changes: 0 additions & 25 deletions packages/whook-cors/src/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -190,28 +190,3 @@ Object {
},
}
`;

exports[`wrapHandlerWithCORS should add CORS to errors 1`] = `
Object {
"headers": Object {
"Access-Control-Allow-Headers": "Accept,Accept-Encoding,Accept-Language,Referrer,Content-Type,Content-Encoding,Authorization,Keep-Alive,User-Agent",
"Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
"Access-Control-Allow-Origin": "*",
"Vary": "Origin",
},
}
`;

exports[`wrapHandlerWithCORS should work 1`] = `
Object {
"response": Object {
"headers": Object {
"Access-Control-Allow-Headers": "Accept,Accept-Encoding,Accept-Language,Referrer,Content-Type,Content-Encoding,Authorization,Keep-Alive,User-Agent",
"Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
"Access-Control-Allow-Origin": "*",
"Vary": "Origin",
},
"status": 200,
},
}
`;
126 changes: 120 additions & 6 deletions packages/whook-cors/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
} from '.';
import { handler } from 'knifecycle';
import type { OpenAPIV3 } from 'openapi-types';
import { CORSConfig } from '.';
import { WhookOperation } from '@whook/whook';

describe('wrapHandlerWithCORS', () => {
const CORS = {
const CORS: CORSConfig = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS',
'Access-Control-Allow-Headers': [
Expand All @@ -21,7 +23,17 @@ describe('wrapHandlerWithCORS', () => {
'Keep-Alive',
'User-Agent',
].join(','),
Vary: 'Origin',
};
const OPERATION: WhookOperation = {
path: '/test',
method: 'get',
operationId: 'getOp',
responses: {
'200': {
description: 'Ok',
},
},
'x-whook': {},
};

it('should work', async () => {
Expand All @@ -31,11 +43,104 @@ describe('wrapHandlerWithCORS', () => {
const wrappedHandler = await wrappedOptionsWithCORS({
CORS,
});
const response = await wrappedHandler();
const response = await wrappedHandler({}, OPERATION);

expect({
response,
}).toMatchInlineSnapshot(`
Object {
"response": Object {
"headers": Object {
"access-control-allow-headers": "Accept,Accept-Encoding,Accept-Language,Referrer,Content-Type,Content-Encoding,Authorization,Keep-Alive,User-Agent",
"access-control-allow-methods": "GET,POST,PUT,DELETE,OPTIONS",
"access-control-allow-origin": "*",
"vary": "Origin",
},
"status": 200,
},
}
`);
});

it('should work with replace custom CORS', async () => {
const wrappedOptionsWithCORS = wrapHandlerWithCORS<any, any>(
initOptionsWithCORS,
);
const wrappedHandler = await wrappedOptionsWithCORS({
CORS,
});
const response = await wrappedHandler(
{},
{
...OPERATION,
'x-whook': {
cors: {
type: 'replace',
value: {
...CORS,
'Access-Control-Allow-Credentials': 'true',
},
},
},
},
);

expect({
response,
}).toMatchInlineSnapshot(`
Object {
"response": Object {
"headers": Object {
"access-control-allow-credentials": "true",
"access-control-allow-headers": "Accept,Accept-Encoding,Accept-Language,Referrer,Content-Type,Content-Encoding,Authorization,Keep-Alive,User-Agent",
"access-control-allow-methods": "GET,POST,PUT,DELETE,OPTIONS",
"access-control-allow-origin": "*",
"vary": "Origin",
},
"status": 200,
},
}
`);
});

it('should work with merge custom CORS', async () => {
const wrappedOptionsWithCORS = wrapHandlerWithCORS<any, any>(
initOptionsWithCORS,
);
const wrappedHandler = await wrappedOptionsWithCORS({
CORS,
});
const response = await wrappedHandler(
{},
{
...OPERATION,
'x-whook': {
cors: {
type: 'merge',
value: {
'Access-Control-Allow-Credentials': 'true',
},
},
},
},
);

expect({
response,
}).toMatchSnapshot();
}).toMatchInlineSnapshot(`
Object {
"response": Object {
"headers": Object {
"access-control-allow-credentials": "true",
"access-control-allow-headers": "Accept,Accept-Encoding,Accept-Language,Referrer,Content-Type,Content-Encoding,Authorization,Keep-Alive,User-Agent",
"access-control-allow-methods": "GET,POST,PUT,DELETE,OPTIONS",
"access-control-allow-origin": "*",
"vary": "Origin",
},
"status": 200,
},
}
`);
});

it('should add CORS to errors', async () => {
Expand All @@ -53,12 +158,21 @@ describe('wrapHandlerWithCORS', () => {
});

try {
await wrappedHandler();
await wrappedHandler({}, OPERATION);
throw new Error('E_UNEXPECTED_SUCCESS');
} catch (err) {
expect({
headers: err.headers,
}).toMatchSnapshot();
}).toMatchInlineSnapshot(`
Object {
"headers": Object {
"access-control-allow-headers": "Accept,Accept-Encoding,Accept-Language,Referrer,Content-Type,Content-Encoding,Authorization,Keep-Alive,User-Agent",
"access-control-allow-methods": "GET,POST,PUT,DELETE,OPTIONS",
"access-control-allow-origin": "*",
"vary": "Origin",
},
}
`);
}
});
});
Expand Down
Loading

0 comments on commit b62c068

Please sign in to comment.