Skip to content

Commit

Permalink
refactor(watch): factorize the watch code into some commands
Browse files Browse the repository at this point in the history
Allows to generate types from commands, use `npm run watch` for the watch mode instead and adds some
docs.
  • Loading branch information
nfroidure committed Jul 20, 2020
1 parent c2a0acd commit 1622817
Show file tree
Hide file tree
Showing 14 changed files with 374 additions and 25 deletions.

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/whook-create/src/services/createWhook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ Mr Bean
},
"private": true,
"scripts": Object {
"apitypes": "npm run --silent whook -- generateOpenAPISchema --authenticated=false | npm run --silent whook -- generateOpenAPITypes > src/openAPISchema.d.ts",
"build": "npm run compile && NODE_ENV=\${NODE_ENV:-development} node bin/build",
"compile": "rimraf -f 'dist' && npm run compile:cjs && npm run compile:mjs",
"compile:cjs": "babel --env-name=cjs --out-dir=dist --extensions '.ts,.js' --source-maps=true src",
Expand All @@ -317,6 +318,7 @@ Mr Bean
"start": "NODE_ENV=\${NODE_ENV:-development} node bin/start",
"test": "npm run jest",
"types": "rimraf -f 'dist/**/*.d.ts' && tsc --project . --declaration --emitDeclarationOnly --outDir dist",
"watch": "NODE_ENV=\${NODE_ENV:-development} DEV_MODE=1 DESTROY_SOCKETS=1 babel-node --extensions '.ts,.js' bin/watch",
"whook": "NODE_ENV=\${NODE_ENV:-development} whook",
"whook-dev": "PROJECT_SRC=\\"$PWD/src\\" NODE_ENV=\${NODE_ENV:-development} babel-node --extensions '.ts,.js' -- node_modules/@whook/cli/bin/whook.js",
},
Expand Down Expand Up @@ -566,6 +568,7 @@ Mr Bean
},
"private": true,
"scripts": Object {
"apitypes": "npm run --silent whook -- generateOpenAPISchema --authenticated=false | npm run --silent whook -- generateOpenAPITypes > src/openAPISchema.d.ts",
"build": "npm run compile && NODE_ENV=\${NODE_ENV:-development} node bin/build",
"compile": "rimraf -f 'dist' && npm run compile:cjs && npm run compile:mjs",
"compile:cjs": "babel --env-name=cjs --out-dir=dist --extensions '.ts,.js' --source-maps=true src",
Expand All @@ -579,6 +582,7 @@ Mr Bean
"start": "NODE_ENV=\${NODE_ENV:-development} node bin/start",
"test": "npm run jest",
"types": "rimraf -f 'dist/**/*.d.ts' && tsc --project . --declaration --emitDeclarationOnly --outDir dist",
"watch": "NODE_ENV=\${NODE_ENV:-development} DEV_MODE=1 DESTROY_SOCKETS=1 babel-node --extensions '.ts,.js' bin/watch",
"whook": "NODE_ENV=\${NODE_ENV:-development} whook",
"whook-dev": "PROJECT_SRC=\\"$PWD/src\\" NODE_ENV=\${NODE_ENV:-development} babel-node --extensions '.ts,.js' -- node_modules/@whook/cli/bin/whook.js",
},
Expand Down Expand Up @@ -813,6 +817,7 @@ Mr Bean
},
"private": true,
"scripts": Object {
"apitypes": "npm run --silent whook -- generateOpenAPISchema --authenticated=false | npm run --silent whook -- generateOpenAPITypes > src/openAPISchema.d.ts",
"build": "npm run compile && NODE_ENV=\${NODE_ENV:-development} node bin/build",
"compile": "rimraf -f 'dist' && npm run compile:cjs && npm run compile:mjs",
"compile:cjs": "babel --env-name=cjs --out-dir=dist --extensions '.ts,.js' --source-maps=true src",
Expand All @@ -826,6 +831,7 @@ Mr Bean
"start": "NODE_ENV=\${NODE_ENV:-development} node bin/start",
"test": "npm run jest",
"types": "rimraf -f 'dist/**/*.d.ts' && tsc --project . --declaration --emitDeclarationOnly --outDir dist",
"watch": "NODE_ENV=\${NODE_ENV:-development} DEV_MODE=1 DESTROY_SOCKETS=1 babel-node --extensions '.ts,.js' bin/watch",
"whook": "NODE_ENV=\${NODE_ENV:-development} whook",
"whook-dev": "PROJECT_SRC=\\"$PWD/src\\" NODE_ENV=\${NODE_ENV:-development} babel-node --extensions '.ts,.js' -- node_modules/@whook/cli/bin/whook.js",
},
Expand Down
11 changes: 10 additions & 1 deletion packages/whook-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ NODE_ENV=production npm start

## Dev

Start the server in development mode:
Start the server in development:
```sh
# Simple dev mode
npm run dev

# Watch mode
npm run watch
```

Create a new endpoint / service / provider or command:
Expand All @@ -41,6 +45,11 @@ List available commands:
npx whook ls
```

Generate API types:
```sh
npm run apitypes
```

## Debug
Execute a handler in isolation:
```sh
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 { watchDevServer } from '../src/dev';
const { runServer } = require('../src/index');

watchDevServer();
runServer();
3 changes: 3 additions & 0 deletions packages/whook-example/bin/watch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { watchDevServer } from '../src/watch';

watchDevServer();
2 changes: 2 additions & 0 deletions packages/whook-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
}
},
"scripts": {
"apitypes": "npm run --silent whook -- generateOpenAPISchema --authenticated=false | npm run --silent whook -- generateOpenAPITypes > src/openAPISchema.d.ts",
"build": "npm run compile && NODE_ENV=${NODE_ENV:-development} node bin/build",
"cli": "env NODE_ENV=${NODE_ENV:-cli}",
"compile": "rimraf -f 'dist' && npm run compile:cjs && npm run compile:mjs",
Expand All @@ -57,6 +58,7 @@
"start": "NODE_ENV=${NODE_ENV:-development} node bin/start",
"test": "npm run jest",
"types": "rimraf -f 'dist/**/*.d.ts' && tsc --project . --declaration --emitDeclarationOnly --outDir dist",
"watch": "NODE_ENV=${NODE_ENV:-development} DEV_MODE=1 DESTROY_SOCKETS=1 babel-node --extensions '.ts,.js' bin/watch",
"whook": "NODE_ENV=${NODE_ENV:-development} whook",
"whook-dev": "PROJECT_SRC=\"$PWD/src\" NODE_ENV=${NODE_ENV:-development} babel-node --extensions '.ts,.js' -- node_modules/@whook/cli/bin/whook.js"
},
Expand Down
4 changes: 3 additions & 1 deletion packages/whook-example/src/__snapshots__/cli.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ Object {
",
"stdout": "
# Provided by \\"@whook/example\\": 1 commands
# Provided by \\"@whook/example\\": 3 commands
- generateOpenAPISchema: Write openAPI schema to stdout
- generateOpenAPITypes: Write openAPI types to stdout
- printEnv: A command printing every env values
Expand Down
94 changes: 94 additions & 0 deletions packages/whook-example/src/commands/generateOpenAPISchema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import initGenerateOpenAPISchema from './generateOpenAPISchema';
import { PassThrough } from 'stream';
import type { WhookCommandArgs } from '@whook/cli';

describe('generateOpenAPISchema', () => {
const getOpenAPI = jest.fn();
const log = jest.fn();

beforeEach(() => {
getOpenAPI.mockReset();
log.mockReset();
});

it('should work', async () => {
getOpenAPI.mockResolvedValueOnce({
status: 200,
body: {
openapi: '3.0.2',
info: {
version: '0.0.0',
title: 'api',
description: 'The API',
},
},
});

const outstream = new PassThrough();
const outputPromise = new Promise((resolve, reject) => {
let buffer = Buffer.from('');
outstream.on('data', (aBuffer) => {
buffer = Buffer.concat([buffer, aBuffer]);
});
outstream.once('error', () => reject);
outstream.once('end', () => resolve(buffer.toString()));
});
const generateOpenAPISchema = await initGenerateOpenAPISchema({
log,
getOpenAPI,
outstream,
args: (Object.assign(
{
pretty: true,
},
{
_: ['generateOpenAPISchema'],
},
) as unknown) as WhookCommandArgs,
});
const result = await generateOpenAPISchema();

expect({
result,
output: await outputPromise,
getOpenAPICalls: getOpenAPI.mock.calls,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
}).toMatchInlineSnapshot(
{},
`
Object {
"getOpenAPICalls": Array [
Array [
Object {
"authenticated": true,
"mutedMethods": Array [
"options",
],
"mutedParameters": Array [],
},
],
],
"logCalls": Array [
Array [
"warning",
"📥 - Retrieving schema...",
],
Array [
"warning",
"📇 - Writing Open API schema...",
],
],
"output": "{
\\"openapi\\": \\"3.0.2\\",
\\"info\\": {
\\"version\\": \\"0.0.0\\",
\\"title\\": \\"api\\",
\\"description\\": \\"The API\\"
}
}",
"result": undefined,
}
`,
);
});
});
66 changes: 66 additions & 0 deletions packages/whook-example/src/commands/generateOpenAPISchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { initGetOpenAPI } from '@whook/swagger-ui';
import { readArgs } from '@whook/cli';
import { autoService, extra } from 'knifecycle';
import type { LogService } from 'common-services';
import type { PromiseValue } from 'type-fest';
import type { WhookCommandDefinition, WhookCommandArgs } from '@whook/cli';

export const definition: WhookCommandDefinition = {
description: 'Write openAPI schema to stdout',
example: `whook generateOpenAPISchema`,
arguments: {
type: 'object',
additionalProperties: false,
required: [],
properties: {
pretty: {
description: 'Option to prettify output',
type: 'boolean',
default: true,
},
authenticated: {
description: 'Option to get the private routes too',
type: 'boolean',
default: true,
},
},
},
};

export default extra(definition, autoService(initGenerateOpenAPISchema));

async function initGenerateOpenAPISchema({
getOpenAPI,
outstream = process.stdout,
args,
log,
}: {
getOpenAPI: PromiseValue<ReturnType<typeof initGetOpenAPI>>;
outstream: NodeJS.WritableStream;
args: WhookCommandArgs;
log: LogService;
}): Promise<() => Promise<void>> {
return async function generateOpenAPISchema() {
const { pretty, authenticated } = readArgs(definition.arguments, args) as {
pretty: boolean;
authenticated: boolean;
};

log('warning', '📥 - Retrieving schema...');
const response = await getOpenAPI({
authenticated,
mutedMethods: ['options'],
mutedParameters: [],
});
log('warning', '📇 - Writing Open API schema...');

await new Promise((resolve, reject) => {
outstream.once('finish', resolve);
outstream.once('error', reject);
outstream.write(
JSON.stringify(response.body, null, pretty ? 2 : undefined),
);
outstream.end();
});
};
}
86 changes: 86 additions & 0 deletions packages/whook-example/src/commands/generateOpenAPITypes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import initGenerateOpenAPITypes from './generateOpenAPITypes';
import { PassThrough } from 'stream';
import { initGetPingDefinition } from '@whook/whook';
import type { WhookCommandArgs } from '@whook/cli';
import type { OpenAPIV3 } from 'openapi-types';

describe('generateOpenAPITypes', () => {
const getOpenAPI = jest.fn();
const log = jest.fn();
const API: OpenAPIV3.Document = {
openapi: '3.0.2',
info: {
version: '1.0.0',
title: 'Sample OpenAPI',
description: 'A sample OpenAPI file for testing purpose.',
},
paths: {
[initGetPingDefinition.path]: {
[initGetPingDefinition.method]: initGetPingDefinition.operation,
},
},
};

beforeEach(() => {
getOpenAPI.mockReset();
log.mockReset();
});

it('should work', async () => {
const instream = new PassThrough();
const outstream = new PassThrough();
const outputPromise = new Promise((resolve, reject) => {
let buffer = Buffer.from('');
outstream.on('data', (aBuffer) => {
buffer = Buffer.concat([buffer, aBuffer]);
});
outstream.once('error', () => reject);
outstream.once('end', () => resolve(buffer.toString()));
});
const generateOpenAPITypes = await initGenerateOpenAPITypes({
instream,
outstream,
log,
});

const resultPromise = generateOpenAPITypes();

instream.write(JSON.stringify(API));
instream.end();

expect({
result: await resultPromise,
output: await outputPromise,
getOpenAPICalls: getOpenAPI.mock.calls,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
}).toMatchInlineSnapshot(
{},
`
Object {
"getOpenAPICalls": Array [],
"logCalls": Array [
Array [
"warning",
"📥 - Retrieving API schema...",
],
Array [
"warning",
"📇 - Writing types...",
],
],
"output": "declare namespace Paths {
namespace GetPing {
namespace Responses {
export interface $200 {
pong?: \\"pong\\";
}
}
}
}
",
"result": undefined,
}
`,
);
});
});
Loading

0 comments on commit 1622817

Please sign in to comment.