Skip to content

Commit

Permalink
feat(dev): watch mode and API types
Browse files Browse the repository at this point in the history
Adds a watch mode that restart and empty the require cache when needed. Also adds the API types
automatically generated and updated on changes.

concerns #75 #51
  • Loading branch information
nfroidure committed Jul 19, 2020
1 parent 1d7a9b3 commit c2a0acd
Show file tree
Hide file tree
Showing 25 changed files with 631 additions and 380 deletions.
639 changes: 335 additions & 304 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"lerna": "lerna",
"lint": "lerna run lint",
"metapak": "metapak",
"postinstall": "lerna bootstrap --hoist && npm run compile && lerna link",
"postinstall": "lerna bootstrap --hoist && npm run compile && lerna link && npm run lerna -- run types",
"postmetapak": "lerna run metapak",
"precz": "npm t && npm run lint && npm run compile && npm run lerna -- run types && npm run metapak -- -s",
"prettier": "prettier --write 'src/**/*.js'",
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-authorization/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"homepage": "https://github.com/nfroidure/whook",
"dependencies": {
"@whook/whook": "^4.0.4",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"http-auth-utils": "^2.5.0",
"knifecycle": "^9.1.1"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-aws-lambda/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"ajv": "^6.12.2",
"bytes": "^3.1.0",
"camelcase": "^6.0.0",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"cpr": "3.0.1",
"knifecycle": "^9.1.1",
"memfs": "3.2.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"@whook/whook": "^4.0.4",
"ajv": "^6.12.2",
"camelcase": "^6.0.0",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"fs-extra": "^9.0.0",
"inquirer": "^7.1.0",
"knifecycle": "^9.1.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-create/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"@whook/cli": "^4.0.4",
"@whook/example": "^4.0.4",
"axios": "^0.19.2",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"debug": "^4.1.1",
"fs-extra": "^9.0.0",
"inquirer": "^7.1.0",
Expand Down

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions packages/whook-create/src/services/createWhook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ Mr Bean
"@whook/http-transaction": "<current_version>",
"@whook/swagger-ui": "<current_version>",
"@whook/whook": "<current_version>",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"http-auth-utils": "^2.5.0",
"jwt-service": "^5.0.0",
"knifecycle": "^9.1.1",
Expand All @@ -215,6 +215,8 @@ Mr Bean
"axios": "^0.19.2",
"babel-eslint": "^10.1.0",
"babel-plugin-knifecycle": "^1.2.0",
"chokidar": "^3.4.1",
"dtsgenerator": "^3.1.1",
"eslint": "^7.0.0",
"eslint-plugin-prettier": "^3.1.3",
"jest": "^26.0.1",
Expand Down Expand Up @@ -449,7 +451,7 @@ Mr Bean
"@whook/http-transaction": "<current_version>",
"@whook/swagger-ui": "<current_version>",
"@whook/whook": "<current_version>",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"http-auth-utils": "^2.5.0",
"jwt-service": "^5.0.0",
"knifecycle": "^9.1.1",
Expand All @@ -475,6 +477,8 @@ Mr Bean
"axios": "^0.19.2",
"babel-eslint": "^10.1.0",
"babel-plugin-knifecycle": "^1.2.0",
"chokidar": "^3.4.1",
"dtsgenerator": "^3.1.1",
"eslint": "^7.0.0",
"eslint-plugin-prettier": "^3.1.3",
"jest": "^26.0.1",
Expand Down Expand Up @@ -694,7 +698,7 @@ Mr Bean
"@whook/http-transaction": "<current_version>",
"@whook/swagger-ui": "<current_version>",
"@whook/whook": "<current_version>",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"http-auth-utils": "^2.5.0",
"jwt-service": "^5.0.0",
"knifecycle": "^9.1.1",
Expand All @@ -720,6 +724,8 @@ Mr Bean
"axios": "^0.19.2",
"babel-eslint": "^10.1.0",
"babel-plugin-knifecycle": "^1.2.0",
"chokidar": "^3.4.1",
"dtsgenerator": "^3.1.1",
"eslint": "^7.0.0",
"eslint-plugin-prettier": "^3.1.3",
"jest": "^26.0.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/whook-example/bin/dev.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { runServer } from '../src/index';
import { watchDevServer } from '../src/dev';

runServer();
watchDevServer();
4 changes: 3 additions & 1 deletion packages/whook-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"@whook/http-transaction": "^4.0.4",
"@whook/swagger-ui": "^4.0.4",
"@whook/whook": "^4.0.4",
"common-services": "^7.1.4",
"common-services": "^7.1.5",
"http-auth-utils": "^2.5.0",
"jwt-service": "^5.0.0",
"knifecycle": "^9.1.1",
Expand All @@ -107,6 +107,8 @@
"axios": "^0.19.2",
"babel-eslint": "^10.1.0",
"babel-plugin-knifecycle": "^1.2.0",
"chokidar": "^3.4.1",
"dtsgenerator": "^3.1.1",
"eslint": "^7.0.0",
"eslint-plugin-prettier": "^3.1.3",
"jest": "^26.0.1",
Expand Down
89 changes: 89 additions & 0 deletions packages/whook-example/src/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import chokidar from 'chokidar';
import dtsgenerator, { parseSchema } from 'dtsgenerator';
import path from 'path';
import crypto from 'crypto';
import { writeFileSync } from 'fs';
import type { Schema } from 'dtsgenerator';
import type { Knifecycle } from 'knifecycle';
import type { DelayService } from 'common-services';

let $instance: Knifecycle;
let delay: DelayService;
let delayPromise: Promise<void>;
let hash: string;

export async function watchDevServer() {
await restartDevServer();
chokidar
.watch(['**/*.ts', 'package*.json', ''], {
ignored: ['node_modules', 'coverage', '*.d.ts'],
ignoreInitial: true,
})
.on('all', (_event, filePath) => {
const absolutePath = path.join(process.cwd(), filePath);

if (filePath.match(/package.*\.json/)) {
for (let key in require.cache) {
delete require.cache[key];
}
} else {
delete require.cache[absolutePath];
}

if (delay) {
if (!delayPromise) {
delayPromise = delay.create(2000);
restartDevServer();
}
}
});
}

export async function restartDevServer() {
if ($instance) {
console.log(
'info',
'➡️ Changes detected : Will restart the server soon...',
);
await delayPromise;
await $instance.destroy();
delayPromise = undefined;
}

const { runServer, prepareEnvironment, prepareServer } = await import('.');

const {
PROJECT_SRC,
$instance: _instance,
delay: _delay,
getOpenAPI,
} = await runServer(prepareEnvironment, prepareServer, [
'PROJECT_SRC',
'$instance',
'delay',
'getOpenAPI',
]);

$instance = _instance;
delay = _delay;

const response = await getOpenAPI({
authenticated: true,
mutedMethods: ['options'],
mutedParameters: [],
});
const openAPIData = JSON.stringify(response.body);
const newHash = crypto.createHash('md5').update(openAPIData).digest('hex');

if (hash !== newHash) {
hash = newHash;
console.log('info', '🦄 - API Changed : Generating API types...');

const schema = await parseSchema(response.body);
const typesDefs = await dtsgenerator({
contents: [schema],
});

writeFileSync(path.join(PROJECT_SRC, 'openAPISchema.d.ts'), typesDefs);
}
}
2 changes: 1 addition & 1 deletion packages/whook-example/src/handlers/getDelay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async function getDelay(
}: {
delay: DelayService;
},
{ duration }: { duration: number },
{ duration }: { duration: Components.Parameters.Duration.Duration },
): Promise<WhookResponse<200, {}, undefined>> {
await delay.create(duration);
return {
Expand Down
15 changes: 9 additions & 6 deletions packages/whook-example/src/handlers/getDiagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ export const definition: WhookAPIHandlerDefinition = {
'application/json': {
schema: {
type: 'object',
additionalProperties: true,
required: ['transactions'],
properties: {
transactions: {
type: 'object',
additionalProperties: true,
},
},
},
},
},
Expand All @@ -32,14 +38,11 @@ export const definition: WhookAPIHandlerDefinition = {

export default autoHandler(getDiagnostic);

type Transaction = {};
type Transactions = { [id: string]: Transaction };

async function getDiagnostic({
TRANSACTIONS,
}: {
TRANSACTIONS: Transactions;
}): Promise<WhookResponse<200, {}, { transactions: Transactions }>> {
TRANSACTIONS: Paths.GetDiagnostic.Responses.$200['transactions'];
}): Promise<WhookResponse<200, {}, Paths.GetDiagnostic.Responses.$200>> {
return {
status: 200,
body: {
Expand Down
35 changes: 25 additions & 10 deletions packages/whook-example/src/handlers/getParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ export const definition: WhookAPIHandlerDefinition = {
responses: {
204: {
description: 'Delay expired',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
aHeader: {
type: 'boolean',
},
pathParam1: {
type: 'number',
},
pathParam2: {
type: 'array',
items: {
type: 'string',
},
},
},
},
},
},
},
},
},
Expand All @@ -72,17 +93,11 @@ async function getParameters(
pathParam1,
pathParam2,
}: {
aHeader: boolean;
pathParam1: number;
pathParam2: string[];
aHeader: Paths.GetParameters.Parameters.AHeader;
pathParam1: Components.Parameters.PathParam1.PathParam1;
pathParam2: Components.Parameters.PathParam2.PathParam2;
},
): Promise<
WhookResponse<
200,
{},
{ aHeader: boolean; pathParam1: number; pathParam2: string[] }
>
> {
): Promise<WhookResponse<200, {}, Paths.GetParameters.Responses.$204>> {
return {
status: 200,
body: {
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-example/src/handlers/getTime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('getTime', () => {
Object {
"response": Object {
"body": Object {
"time": 1390694400000,
"currentDate": "2014-01-26T00:00:00.000Z",
},
"status": 200,
},
Expand Down
4 changes: 2 additions & 2 deletions packages/whook-example/src/handlers/getTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ async function getTime({
time,
}: {
time: TimeService;
}): Promise<WhookResponse<200, {}, { time: number }>> {
}): Promise<WhookResponse<200, {}, Components.Schemas.TimeSchema>> {
return {
status: 200,
body: {
time: time(),
currentDate: new Date(time()).toISOString(),
},
};
}
33 changes: 19 additions & 14 deletions packages/whook-example/src/handlers/putEcho.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { autoHandler } from 'knifecycle';
import YHTTPError from 'yhttperror';
import type { WhookAPIHandlerDefinition, WhookResponse } from '@whook/whook';
import type { OpenAPIV3 } from 'openapi-types';
import type { LogService } from 'common-services';
import type { WhookAPISchemaDefinition } from '@whook/whook';

const echoSchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: ['echo'],
additionalProperties: false,
properties: {
echo: {
type: 'string',
export const echoSchema: WhookAPISchemaDefinition = {
name: 'Echo',
schema: {
type: 'object',
required: ['echo'],
additionalProperties: false,
properties: {
echo: {
type: 'string',
},
},
},
};
Expand All @@ -27,7 +30,9 @@ export const definition: WhookAPIHandlerDefinition = {
required: true,
content: {
'application/json': {
schema: echoSchema,
schema: {
$ref: `#/components/schemas/${echoSchema.name}`,
},
example: {
echo: 'Repeat this!',
},
Expand All @@ -39,7 +44,9 @@ export const definition: WhookAPIHandlerDefinition = {
description: 'The actual echo',
content: {
'application/json': {
schema: echoSchema,
schema: {
$ref: `#/components/schemas/${echoSchema.name}`,
},
},
},
},
Expand All @@ -49,12 +56,10 @@ export const definition: WhookAPIHandlerDefinition = {

export default autoHandler(putEcho);

type Echo = { echo: string };

async function putEcho(
{ log }: { log: LogService },
{ body }: { body: Echo },
): Promise<WhookResponse<200, {}, Echo>> {
{ body }: { body: Components.Schemas.Echo },
): Promise<WhookResponse<200, {}, Components.Schemas.Echo>> {
if (body.echo.includes('Voldemort')) {
throw new YHTTPError(400, 'E_MUST_NOT_BE_NAMED', body.echo);
}
Expand Down
Loading

0 comments on commit c2a0acd

Please sign in to comment.