First working version of all examples including swagger.
This commit is contained in:
parent
430a7ed162
commit
8d23b67592
12 changed files with 2101 additions and 0 deletions
55
example2b_swagger.yml
Normal file
55
example2b_swagger.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
openapi: 3.0.3
|
||||
info:
|
||||
title: Swagger UserApi - OpenAPI 3.0
|
||||
description: |-
|
||||
This is a sample User API
|
||||
termsOfService: http://swagger.io/terms/
|
||||
contact:
|
||||
email: apiteam@swagger.io
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
version: 1.0.11
|
||||
externalDocs:
|
||||
description: Find out more about Swagger
|
||||
url: http://swagger.io
|
||||
tags:
|
||||
- name: user
|
||||
description: Information about user
|
||||
paths:
|
||||
/api/users:
|
||||
post:
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: number
|
||||
name:
|
||||
type: string
|
||||
email:
|
||||
format: email
|
||||
type: string
|
||||
age:
|
||||
minimum: 0
|
||||
type: number
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- email
|
||||
- age
|
||||
responses:
|
||||
'200':
|
||||
description: User created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: true
|
||||
'400':
|
||||
description: Invalid input
|
||||
1394
package-lock.json
generated
Normal file
1394
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
27
package.json
Normal file
27
package.json
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "nodejs-warsaw-xxi",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.techserio.com:mattiashz/nodejs-warsaw-xxi.git"
|
||||
},
|
||||
"author": "hz",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@fastify/swagger": "^9.4.2",
|
||||
"@fastify/swagger-ui": "^5.2.2",
|
||||
"@fastify/type-provider-typebox": "^5.1.0",
|
||||
"@sinclair/typebox": "^0.34.28",
|
||||
"fastify": "^5.2.1",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^22.13.8"
|
||||
}
|
||||
}
|
||||
57
src/example1.ts
Normal file
57
src/example1.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import fastify from 'fastify';
|
||||
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
app.post<{ Body: User; }> ('/api/users', async (request, reply) => {
|
||||
const user = request.body;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
const start = async () => {
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Try making a POST request with this "deranged" JSON:
|
||||
|
||||
{
|
||||
"id": "42",
|
||||
"name": 12345,
|
||||
"email": {"address": "bad@example.com"},
|
||||
"age": "twenty-one"
|
||||
}
|
||||
|
||||
What happens:
|
||||
1. TypeScript is happy at compile time (we said body is User)
|
||||
2. Fastify accepts this JSON as valid (no runtime validation)
|
||||
3. Code fails when trying operations like toUpperCase() on a number
|
||||
or comparing "twenty-one" >= 21
|
||||
*/
|
||||
46
src/example2.ts
Normal file
46
src/example2.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import fastify from 'fastify';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox';
|
||||
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
const TBUser = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String(),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
});
|
||||
|
||||
app.post('/api/users', {
|
||||
schema: {
|
||||
body: TBUser
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const user = request.body as User;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
const start = async () => {
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
21
src/example2b.ts
Normal file
21
src/example2b.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { Type } from '@sinclair/typebox';
|
||||
import * as yaml from 'js-yaml';
|
||||
|
||||
|
||||
// Define the TypeBox schema
|
||||
const TBUser = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String({ format: 'email' }),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
});
|
||||
|
||||
|
||||
//console.log('JSON Schema:');
|
||||
//console.log(JSON.stringify(TBUser, null, 2));
|
||||
|
||||
// Convert to YAML
|
||||
const openApiYaml = yaml.dump(TBUser);
|
||||
|
||||
console.log('JSON Schema (YAML):');
|
||||
console.log(openApiYaml);
|
||||
46
src/example3.ts
Normal file
46
src/example3.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import fastify from 'fastify';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox';
|
||||
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
||||
|
||||
// Define TypeBox schema as the single source of truth
|
||||
const UserSchema = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String(),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
});
|
||||
|
||||
// Derive TypeScript type from the TypeBox schema
|
||||
type User = Static<typeof UserSchema>;
|
||||
|
||||
app.post<{
|
||||
Body: User; // Using the derived TypeScript type
|
||||
}>('/api/users', {
|
||||
schema: {
|
||||
body: UserSchema // Using the TypeBox schema for validation
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
// No type assertion needed - Fastify + TypeBox understands the connection
|
||||
const user = request.body;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
const start = async () => {
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
89
src/example4.ts
Normal file
89
src/example4.ts
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import fastify from 'fastify';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox';
|
||||
|
||||
// Create Fastify instance
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
// Set up TypeBox validator
|
||||
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
||||
|
||||
// Define TypeBox schema as the single source of truth
|
||||
const UserSchema = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String(),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
});
|
||||
|
||||
// Derive TypeScript type from the TypeBox schema
|
||||
type User = Static<typeof UserSchema>;
|
||||
|
||||
// Response schema for better documentation
|
||||
const ResponseSchema = Type.Object({
|
||||
user: UserSchema,
|
||||
canDrink: Type.Boolean(),
|
||||
greeting: Type.String()
|
||||
});
|
||||
|
||||
// Main function to set up the server
|
||||
async function startServer() {
|
||||
// Register Swagger plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger'), {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'User API',
|
||||
description: 'API for user operations with TypeBox validation',
|
||||
version: '1.0.0'
|
||||
},
|
||||
tags: [
|
||||
{ name: 'users', description: 'User related endpoints' }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
// Register Swagger UI plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger-ui'), {
|
||||
routePrefix: '/swagger',
|
||||
uiConfig: {
|
||||
docExpansion: 'list',
|
||||
deepLinking: false
|
||||
},
|
||||
staticCSP: true
|
||||
});
|
||||
|
||||
// Register our route
|
||||
app.post('/api/users', {
|
||||
schema: {
|
||||
description: 'Create a new user',
|
||||
tags: ['users'],
|
||||
body: UserSchema,
|
||||
response: {
|
||||
200: ResponseSchema
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const user = request.body as User;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
// Wait until all plugins are ready
|
||||
await app.ready();
|
||||
|
||||
// Start the server
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
console.log('Swagger UI available at: http://localhost:3000/swagger');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the server
|
||||
startServer();
|
||||
117
src/example4b.ts
Normal file
117
src/example4b.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import fastify from 'fastify';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox';
|
||||
|
||||
// Create Fastify instance
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
// Set up TypeBox validator
|
||||
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
||||
|
||||
// Define TypeBox schema as the single source of truth
|
||||
const UserSchema = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String(),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
});
|
||||
|
||||
// Derive TypeScript type from the TypeBox schema
|
||||
type User = Static<typeof UserSchema>;
|
||||
|
||||
// Response schema for better documentation
|
||||
const ResponseSchema = Type.Object({
|
||||
user: UserSchema,
|
||||
canDrink: Type.Boolean(),
|
||||
greeting: Type.String()
|
||||
});
|
||||
|
||||
// Main function to set up the server
|
||||
async function startServer() {
|
||||
// Register Swagger plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger'), {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'User API',
|
||||
description: 'API for user operations with TypeBox validation',
|
||||
version: '1.0.0'
|
||||
},
|
||||
tags: [
|
||||
{ name: 'users', description: 'User related endpoints' }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
// Register Swagger UI plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger-ui'), {
|
||||
routePrefix: '/swagger',
|
||||
uiConfig: {
|
||||
docExpansion: 'list',
|
||||
deepLinking: false
|
||||
},
|
||||
staticCSP: true
|
||||
});
|
||||
|
||||
// Register our route
|
||||
app.post('/api/users', {
|
||||
schema: {
|
||||
description: 'Create a new user',
|
||||
tags: ['users'],
|
||||
body: UserSchema,
|
||||
response: {
|
||||
200: ResponseSchema
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const user = request.body as User;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
app.get('/api/users', {
|
||||
schema: {
|
||||
description: 'Get all users',
|
||||
tags: ['users'],
|
||||
response: {
|
||||
200: Type.Array(UserSchema)
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
// Sample data that follows our User type
|
||||
const users: User[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "John Doe",
|
||||
email: "john@example.com",
|
||||
age: 30
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Jane Smith",
|
||||
email: "jane@example.com",
|
||||
age: 25
|
||||
}
|
||||
];
|
||||
|
||||
return users;
|
||||
});
|
||||
|
||||
// Wait until all plugins are ready
|
||||
await app.ready();
|
||||
|
||||
// Start the server
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
console.log('Swagger UI available at: http://localhost:3000/swagger');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the server
|
||||
startServer();
|
||||
100
src/example4c.ts
Normal file
100
src/example4c.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import fastify from 'fastify';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox';
|
||||
|
||||
// Create Fastify instance
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
// Set up TypeBox validator
|
||||
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
||||
|
||||
// Define TypeBox schema as the single source of truth
|
||||
const UserSchema = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String(),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
}, { $id: 'User' });
|
||||
|
||||
// Derive TypeScript type from the TypeBox schema
|
||||
type User = Static<typeof UserSchema>;
|
||||
|
||||
// Response schema for better documentation
|
||||
const ResponseSchema = Type.Object({
|
||||
user: Type.Ref(UserSchema),
|
||||
canDrink: Type.Boolean(),
|
||||
greeting: Type.String()
|
||||
}, { $id: 'UserResponse' });
|
||||
|
||||
// Main function to set up the server
|
||||
async function startServer() {
|
||||
// Register schemas with Fastify
|
||||
app.addSchema(UserSchema);
|
||||
app.addSchema(ResponseSchema);
|
||||
|
||||
// Register Swagger plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger'), {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'User API',
|
||||
description: 'API for user operations with TypeBox validation',
|
||||
version: '1.0.0'
|
||||
},
|
||||
consumes: ['application/json'],
|
||||
produces: ['application/json'],
|
||||
tags: [
|
||||
{ name: 'users', description: 'User related endpoints' }
|
||||
],
|
||||
// Extract schemas to definitions section
|
||||
definitions: {
|
||||
User: UserSchema as any,
|
||||
UserResponse: ResponseSchema as any
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register Swagger UI plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger-ui'), {
|
||||
routePrefix: '/swagger',
|
||||
uiConfig: {
|
||||
docExpansion: 'list',
|
||||
deepLinking: false
|
||||
},
|
||||
staticCSP: true
|
||||
});
|
||||
|
||||
// Register our route
|
||||
app.post('/api/users', {
|
||||
schema: {
|
||||
description: 'Create a new user',
|
||||
tags: ['users'],
|
||||
body: { $ref: 'User#' },
|
||||
response: {
|
||||
200: { $ref: 'UserResponse#' }
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const user = request.body as User;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
// Wait until all plugins are ready
|
||||
await app.ready();
|
||||
|
||||
// Start the server
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
console.log('Swagger UI available at: http://localhost:3000/swagger');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the server
|
||||
startServer();
|
||||
131
src/example4d.ts
Normal file
131
src/example4d.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import fastify from 'fastify';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox';
|
||||
|
||||
// Create Fastify instance
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
// Set up TypeBox validator
|
||||
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
||||
|
||||
// Define TypeBox schema as the single source of truth
|
||||
const UserSchema = Type.Object({
|
||||
id: Type.Number(),
|
||||
name: Type.String(),
|
||||
email: Type.String(),
|
||||
age: Type.Number({ minimum: 0 })
|
||||
}, { $id: 'User' });
|
||||
|
||||
// Derive TypeScript type from the TypeBox schema
|
||||
type User = Static<typeof UserSchema>;
|
||||
|
||||
// Response schema for better documentation
|
||||
const ResponseSchema = Type.Object({
|
||||
user: UserSchema,
|
||||
canDrink: Type.Boolean(),
|
||||
greeting: Type.String()
|
||||
}, { $id: 'UserResponse' });
|
||||
|
||||
// Main function to set up the server
|
||||
async function startServer() {
|
||||
// Register schemas with Fastify
|
||||
app.addSchema(UserSchema);
|
||||
app.addSchema(ResponseSchema);
|
||||
|
||||
// Register Swagger plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger'), {
|
||||
openapi: {
|
||||
info: {
|
||||
title: 'User API',
|
||||
description: 'API for user operations with TypeBox validation',
|
||||
version: '1.0.0'
|
||||
},
|
||||
tags: [
|
||||
{ name: 'users', description: 'User related endpoints' }
|
||||
]
|
||||
},
|
||||
refResolver: {
|
||||
buildLocalReference: (json, baseUri, fragment, i) => {
|
||||
// Use $id property from schema
|
||||
if (json.$id) {
|
||||
return `#/components/schemas/${json.$id}`;
|
||||
}
|
||||
// Fall back to default behavior
|
||||
return `#/components/schemas/${fragment[1]}${i}`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register Swagger UI plugin using dynamic import
|
||||
await app.register(import('@fastify/swagger-ui'), {
|
||||
routePrefix: '/swagger',
|
||||
uiConfig: {
|
||||
docExpansion: 'list',
|
||||
deepLinking: false
|
||||
},
|
||||
staticCSP: true
|
||||
});
|
||||
|
||||
// Register our route
|
||||
app.post('/api/users', {
|
||||
schema: {
|
||||
description: 'Create a new user',
|
||||
tags: ['users'],
|
||||
body: UserSchema,
|
||||
response: {
|
||||
200: ResponseSchema
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const user = request.body as User;
|
||||
|
||||
const canDrink = user.age >= 21;
|
||||
const greeting = `Hello ${user.name.toUpperCase()}, your email ${user.email.toLowerCase()} has been recorded`;
|
||||
|
||||
return { user, canDrink, greeting };
|
||||
});
|
||||
|
||||
app.get('/api/users', {
|
||||
schema: {
|
||||
description: 'Get all users',
|
||||
tags: ['users'],
|
||||
response: {
|
||||
200: Type.Array(UserSchema)
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
// Sample data that follows our User type
|
||||
const users: User[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "John Doe",
|
||||
email: "john@example.com",
|
||||
age: 30
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Jane Smith",
|
||||
email: "jane@example.com",
|
||||
age: 25
|
||||
}
|
||||
];
|
||||
|
||||
return users;
|
||||
});
|
||||
|
||||
// Wait until all plugins are ready
|
||||
await app.ready();
|
||||
|
||||
// Start the server
|
||||
try {
|
||||
await app.listen({ port: 3000 });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
console.log('Swagger UI available at: http://localhost:3000/swagger');
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the server
|
||||
startServer();
|
||||
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"ES2020.Promise",
|
||||
"DOM"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "build",
|
||||
"rootDir": "src",
|
||||
"sourceMap": true,
|
||||
"target": "es2017"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue