Skip to content

Commit 5d32df9

Browse files
committed
feat: add api server
1 parent a3b7cc8 commit 5d32df9

20 files changed

+1382
-59
lines changed

apps/api/.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
dist

apps/api/.gitignore

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Runtime data
7+
pids
8+
*.pid
9+
*.seed
10+
11+
# Directory for instrumented libs generated by jscoverage/JSCover
12+
lib-cov
13+
14+
# Coverage directory used by tools like istanbul
15+
coverage
16+
17+
# nyc test coverage
18+
.nyc_output
19+
20+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21+
.grunt
22+
23+
# node-waf configuration
24+
.lock-wscript
25+
26+
# Compiled binary addons (http://nodejs.org/api/addons.html)
27+
build/Release
28+
29+
# Dependency directories
30+
node_modules
31+
jspm_packages
32+
33+
# Optional npm cache directory
34+
.npm
35+
36+
# Optional REPL history
37+
.node_repl_history
38+
39+
# 0x
40+
profile-*
41+
42+
# mac files
43+
.DS_Store
44+
45+
# vim swap files
46+
*.swp
47+
48+
# webstorm
49+
.idea
50+
51+
# vscode
52+
.vscode
53+
*code-workspace
54+
55+
# clinic
56+
profile*
57+
*clinic*
58+
*flamegraph*
59+
60+
# generated code
61+
examples/typescript-server.js
62+
test/types/index.js
63+
64+
# compiled app
65+
dist

apps/api/.lintstagedrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"*.{ts,tsx,js,jsx}": [
3+
"pnpm lint",
4+
"pnpm pre-commit-prettier",
5+
"pnpm pre-commit-eslint"
6+
]
7+
}

apps/api/.taprc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test-env: [
2+
TS_NODE_FILES=true,
3+
TS_NODE_PROJECT=./test/tsconfig.json
4+
]

apps/api/README.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Getting Started with [Fastify-CLI](https://www.npmjs.com/package/fastify-cli)
2+
3+
This project was bootstrapped with Fastify-CLI.
4+
5+
## Available Scripts
6+
7+
In the project directory, you can run:
8+
9+
### `pnpm dev`
10+
11+
To start the app in dev mode.\
12+
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13+
14+
### `pnpm start`
15+
16+
For production mode
17+
18+
### `pnpm test`
19+
20+
Run the test cases.
21+
22+
## Learn More
23+
24+
To learn Fastify, check out the [Fastify documentation](https://www.fastify.io/docs/latest/).

apps/api/package.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "@codeimage/api",
3+
"version": "0.0.1",
4+
"description": "This project was bootstrapped with Fastify-CLI.",
5+
"main": "app.ts",
6+
"directories": {
7+
"test": "test"
8+
},
9+
"scripts": {
10+
"test": "npm run build:ts && tsc -p test/tsconfig.json && tap --ts \\\"test/**/*.test.ts\\\"",
11+
"start": "npm run build:ts && fastify start -l info dist/app.js",
12+
"build:ts": "tsc",
13+
"watch:ts": "tsc -w",
14+
"dev": "npm run build:ts && concurrently -k -p \"[{name}]\" -n \"TypeScript,App\" -c \"yellow.bold,cyan.bold\" \"npm:watch:ts\" \"npm:dev:start\"",
15+
"dev:start": "fastify start --ignore-watch=.ts$ -w -l info -P dist/app.js"
16+
},
17+
"keywords": [],
18+
"author": "Riccardo Perra",
19+
"license": "ISC",
20+
"dependencies": {
21+
"fastify": "^4.0.0",
22+
"fastify-plugin": "^3.0.0",
23+
"@fastify/autoload": "^5.0.0",
24+
"@fastify/sensible": "^4.1.0",
25+
"fastify-cli": "^4.4.0"
26+
},
27+
"devDependencies": {
28+
"@types/node": "^18.0.0",
29+
"@types/tap": "^15.0.5",
30+
"ts-node": "^10.4.0",
31+
"concurrently": "^7.0.0",
32+
"fastify-tsconfig": "^1.0.1",
33+
"tap": "^16.1.0",
34+
"typescript": "^4.5.4"
35+
}
36+
}

apps/api/src/app.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {join} from 'path';
2+
import AutoLoad, {AutoloadPluginOptions} from '@fastify/autoload';
3+
import {FastifyPluginAsync} from 'fastify';
4+
5+
export type AppOptions = {
6+
// Place your custom options for app below here.
7+
} & Partial<AutoloadPluginOptions>;
8+
9+
const app: FastifyPluginAsync<AppOptions> = async (
10+
fastify,
11+
opts,
12+
): Promise<void> => {
13+
// Place here your custom code!
14+
15+
// Do not touch the following lines
16+
17+
// This loads all plugins defined in plugins
18+
// those should be support plugins that are reused
19+
// through your application
20+
void fastify.register(AutoLoad, {
21+
dir: join(__dirname, 'plugins'),
22+
options: opts,
23+
});
24+
25+
// This loads all plugins defined in routes
26+
// define your routes in one of these
27+
void fastify.register(AutoLoad, {
28+
dir: join(__dirname, 'routes'),
29+
options: opts,
30+
});
31+
};
32+
33+
export default app;
34+
export {app};

apps/api/src/plugins/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Plugins Folder
2+
3+
Plugins define behavior that is common to all the routes in your
4+
application. Authentication, caching, templates, and all the other cross
5+
cutting concerns should be handled by plugins placed in this folder.
6+
7+
Files in this folder are typically defined through the
8+
[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module,
9+
making them non-encapsulated. They can define decorators and set hooks
10+
that will then be used in the rest of your application.
11+
12+
Check out:
13+
14+
- [The hitchhiker's guide to plugins](https://www.fastify.io/docs/latest/Guides/Plugins-Guide/)
15+
- [Fastify decorators](https://www.fastify.io/docs/latest/Reference/Decorators/).
16+
- [Fastify lifecycle](https://www.fastify.io/docs/latest/Reference/Lifecycle/).

apps/api/src/plugins/sensible.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import fp from 'fastify-plugin';
2+
import sensible, {SensibleOptions} from '@fastify/sensible';
3+
4+
/**
5+
* This plugins adds some utilities to handle http errors
6+
*
7+
* @see https://github.com/fastify/fastify-sensible
8+
*/
9+
export default fp<SensibleOptions>(async (fastify, opts) => {
10+
fastify.register(sensible, {
11+
errorHandler: false,
12+
});
13+
});

apps/api/src/plugins/support.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import fp from 'fastify-plugin';
2+
3+
export interface SupportPluginOptions {
4+
// Specify Support plugin options here
5+
}
6+
7+
// The use of fastify-plugin is required to be able
8+
// to export the decorators to the outer scope
9+
export default fp<SupportPluginOptions>(async (fastify, opts) => {
10+
fastify.decorate('someSupport', function () {
11+
return 'hugs';
12+
});
13+
});
14+
15+
// When using .decorate you have to specify added properties for Typescript
16+
declare module 'fastify' {
17+
export interface FastifyInstance {
18+
someSupport(): string;
19+
}
20+
}

apps/api/src/routes/README.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Routes Folder
2+
3+
Routes define endpoints within your application. Fastify provides an
4+
easy path to a microservice architecture, in the future you might want
5+
to independently deploy some of those.
6+
7+
In this folder you should define all the routes that define the endpoints
8+
of your web application.
9+
Each service is a [Fastify
10+
plugin](https://www.fastify.io/docs/latest/Reference/Plugins/), it is
11+
encapsulated (it can have its own independent plugins) and it is
12+
typically stored in a file; be careful to group your routes logically,
13+
e.g. all `/users` routes in a `users.js` file. We have added
14+
a `root.js` file for you with a '/' root added.
15+
16+
If a single file become too large, create a folder and add a `index.js` file there:
17+
this file must be a Fastify plugin, and it will be loaded automatically
18+
by the application. You can now add as many files as you want inside that folder.
19+
In this way you can create complex routes within a single monolith,
20+
and eventually extract them.
21+
22+
If you need to share functionality between routes, place that
23+
functionality into the `plugins` folder, and share it via
24+
[decorators](https://www.fastify.io/docs/latest/Reference/Decorators/).

apps/api/src/routes/example/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {FastifyPluginAsync} from 'fastify';
2+
3+
const example: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
4+
fastify.get('/', async function (request, reply) {
5+
return 'this is an example';
6+
});
7+
};
8+
9+
export default example;

apps/api/src/routes/root.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {FastifyPluginAsync} from 'fastify';
2+
3+
const root: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
4+
fastify.get('/', async function (request, reply) {
5+
return {root: true};
6+
});
7+
};
8+
9+
export default root;

apps/api/test/helper.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This file contains code that we reuse between our tests.
2+
import Fastify from 'fastify';
3+
import fp from 'fastify-plugin';
4+
import App from '../src/app';
5+
import * as tap from 'tap';
6+
7+
export type Test = typeof tap['Test']['prototype'];
8+
9+
// Fill in this config with all the configurations
10+
// needed for testing the application
11+
async function config() {
12+
return {};
13+
}
14+
15+
// Automatically build and tear down our instance
16+
async function build(t: Test) {
17+
const app = Fastify();
18+
19+
// fastify-plugin ensures that all decorators
20+
// are exposed for testing purposes, this is
21+
// different from the production setup
22+
void app.register(fp(App), await config());
23+
24+
await app.ready();
25+
26+
// Tear down our app after we are done
27+
t.teardown(() => void app.close());
28+
29+
return app;
30+
}
31+
32+
export {config, build};

apps/api/test/plugins/support.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {test} from 'tap';
2+
import Fastify from 'fastify';
3+
import Support from '../../src/plugins/support';
4+
5+
test('support works standalone', async t => {
6+
const fastify = Fastify();
7+
void fastify.register(Support);
8+
await fastify.ready();
9+
10+
t.equal(fastify.someSupport(), 'hugs');
11+
});

apps/api/test/routes/example.test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import {test} from 'tap';
2+
import {build} from '../helper';
3+
4+
test('example is loaded', async t => {
5+
const app = await build(t);
6+
7+
const res = await app.inject({
8+
url: '/example',
9+
});
10+
11+
t.equal(res.payload, 'this is an example');
12+
});

apps/api/test/routes/root.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {test} from 'tap';
2+
import {build} from '../helper';
3+
4+
test('default root route', async t => {
5+
const app = await build(t);
6+
7+
const res = await app.inject({
8+
url: '/',
9+
});
10+
t.same(JSON.parse(res.payload), {root: true});
11+
});

apps/api/test/tsconfig.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"compilerOptions": {
4+
"baseUrl": "./",
5+
"noEmit": true
6+
},
7+
"include": ["../src/**/*.ts", "**/*.ts"]
8+
}

apps/api/tsconfig.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "fastify-tsconfig",
3+
"compilerOptions": {
4+
"outDir": "dist",
5+
"sourceMap": true
6+
},
7+
"include": ["src/**/*.ts"]
8+
}

0 commit comments

Comments
 (0)