Skip to content

Commit d3e0fc6

Browse files
committed
feat(template): add template engine eta for code generation
1 parent 14d4e26 commit d3e0fc6

File tree

284 files changed

+6734
-6020
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

284 files changed

+6734
-6020
lines changed

.eslintrc.cjs

+73-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
module.exports = {
22
env: {
3-
browser: true,
43
es6: true,
54
node: true,
65
},
6+
ignorePatterns: ['__test__/*', '__tests__/*', 'example/*', 'coverage/*', 'dist/*'],
7+
parser: '@typescript-eslint/parser',
8+
parserOptions: {
9+
project: 'tsconfig.eslint.json',
10+
tsconfigRootDir: __dirname,
11+
},
712
extends: [
813
'plugin:@typescript-eslint/eslint-recommended',
914
'plugin:@typescript-eslint/recommended-requiring-type-checking',
1015
'plugin:@typescript-eslint/strict',
1116
'airbnb-base',
1217
'airbnb-typescript/base',
18+
'prettier',
1319
'plugin:prettier/recommended',
1420
'plugin:import/errors',
1521
'plugin:import/warnings',
16-
'prettier',
1722
],
18-
parser: '@typescript-eslint/parser',
19-
parserOptions: {
20-
project: ['tsconfig.eslint.json'],
21-
tsconfigRootDir: __dirname,
22-
},
23-
ignorePatterns: ['coverage/**', 'examples/**', 'dist/**', '__test__/**', '__tests__/**'],
2423
plugins: ['@typescript-eslint', 'prettier', 'import'],
2524
rules: {
25+
// ----------------------------------------------------------------------------------------------------------
26+
// eslint
27+
// ----------------------------------------------------------------------------------------------------------
2628
'max-len': [
2729
'error',
2830
{
@@ -34,19 +36,67 @@ module.exports = {
3436
code: 120,
3537
},
3638
],
39+
'no-underscore-dangle': ['error', { allowAfterThis: true }],
40+
'no-restricted-syntax': [
41+
'error',
42+
{
43+
selector: 'TSEnumDeclaration:not([const=true])',
44+
message: "Don't declare non-const enums",
45+
},
46+
],
47+
// ----------------------------------------------------------------------------------------------------------
48+
// @typescript-eslint
49+
// ----------------------------------------------------------------------------------------------------------
50+
'@typescript-eslint/naming-convention': [
51+
'error',
52+
{
53+
selector: 'interface',
54+
format: ['PascalCase'],
55+
custom: {
56+
regex: '^I[A-Z]+',
57+
match: true,
58+
},
59+
},
60+
{
61+
selector: 'typeAlias',
62+
format: ['PascalCase'],
63+
custom: {
64+
regex: '^T[A-Z]+',
65+
match: true,
66+
},
67+
},
68+
],
69+
'@typescript-eslint/member-delimiter-style': [
70+
'off',
71+
{
72+
multiline: {
73+
delimiter: 'none',
74+
requireLast: true,
75+
},
76+
singleline: {
77+
delimiter: 'semi',
78+
requireLast: false,
79+
},
80+
},
81+
],
3782
'@typescript-eslint/no-unused-vars': [
3883
'error',
3984
{
4085
varsIgnorePattern: '^_.+$',
4186
argsIgnorePattern: '^_.+$',
42-
ignoreRestSiblings: true,
4387
},
4488
],
45-
'import/extensions': ['off'],
46-
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
47-
// static function use this: void
48-
'@typescript-eslint/no-invalid-void-type': ['error', { allowAsThisParameter: true }],
49-
'@typescript-eslint/no-unnecessary-boolean-literal-compare': ['off'],
89+
'@typescript-eslint/consistent-type-imports': [
90+
'error',
91+
{
92+
prefer: 'type-imports',
93+
},
94+
],
95+
// ----------------------------------------------------------------------------------------------------------
96+
// eslint-plugin-import
97+
// ----------------------------------------------------------------------------------------------------------
98+
'import/prefer-default-export': ['off'],
99+
'import/no-default-export': ['error'],
50100
},
51101
overrides: [
52102
{
@@ -56,11 +106,19 @@ module.exports = {
56106
},
57107
},
58108
{
59-
files: ['**/__tests__/*.ts', 'jest.config.cjs'],
109+
files: ['**/CE_*.ts'],
110+
rules: {
111+
'@typescript-eslint/no-redeclare': ['off'],
112+
'@typescript-eslint/naming-convention': ['off'],
113+
},
114+
},
115+
{
116+
files: ['**/__tests__/*.ts', 'vitest.config.ts'],
60117
rules: {
61118
'@typescript-eslint/no-unsafe-assignment': ['off'],
62119
'@typescript-eslint/no-unsafe-argument': ['off'],
63120
'@typescript-eslint/no-unsafe-member-access': ['off'],
121+
'@typescript-eslint/ban-ts-comment': ['off'],
64122
'no-console': ['off'],
65123
},
66124
},

README.ko.md

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# fast-maker
2+
3+
![ts](https://flat.badgen.net/badge/Built%20With/TypeScript/blue)
4+
[![Download Status](https://img.shields.io/npm/dw/fast-maker.svg?style=flat-square)](https://npmcharts.com/compare/fast-maker?minimal=true)
5+
[![Github Star](https://img.shields.io/github/stars/imjuni/fast-maker.svg?style=flat-square)](https://github.com/imjuni/fast-maker)
6+
[![Github Issues](https://img.shields.io/github/issues-raw/imjuni/fast-maker.svg?style=flat-square)](https://github.com/imjuni/fast-maker/issues)
7+
[![NPM version](https://img.shields.io/npm/v/fast-maker.svg?style=flat-square)](https://www.npmjs.com/package/fast-maker)
8+
[![License](https://img.shields.io/npm/l/fast-maker.svg?style=flat-square)](https://github.com/imjuni/fast-maker/blob/master/LICENSE)
9+
[![ci](https://github.com/imjuni/fast-maker/actions/workflows/ci.yml/badge.svg?branch=master&style=flat-square)](https://github.com/imjuni/fast-maker/actions/workflows/ci.yml)
10+
[![codecov](https://codecov.io/gh/imjuni/fast-maker/branch/master/graph/badge.svg?token=YrUlnfDbso&style=flat-square)](https://codecov.io/gh/imjuni/fast-maker)
11+
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
12+
13+
`fast-maker` generate fastify.js route configuration using by directory structure.
14+
15+
Why `fast-maker`?
16+
17+
fastify.js already have auto route mechanics using [fastify-autoload](https://github.com/fastify/fastify-autoload). But why you have to use `fast-maker`?
18+
19+
1. [Static analysis](https://en.wikipedia.org/wiki/Static_program_analysis): `fast-maker` generate TypeScript source code. Because it help to find error in compile-time, not runtime
20+
2. Complex Variable: You can use like that: `/person/[kind]-[id]/`. It help to get id and kind of id, for example serial-number and id or db-pk and id
21+
3. Next.js: `fast-maker` use the same mechanics as [Next.js](https://nextjs.org/docs/routing/introduction)
22+
4. `fast-maker` support a beautiful cli-interface
23+
24+
## Table of Contents <!-- omit in toc -->
25+
26+
- [Getting started](#getting-started)
27+
- [How it works?](#how-it-works)
28+
- [Installation](#installation)
29+
- [Usage](#usage)
30+
- [Routing](#routing)
31+
- [HTTP Method](#http-method)
32+
- [Route options](#route-options)
33+
- [Route handler](#route-handler)
34+
- [Variable in Route Path](#variable-in-route-path)
35+
- [Example using fastify.js](#example-using-fastifyjs)
36+
- [Relate To](#relate-to)
37+
- [Roadmaps](#roadmaps)
38+
- [License](#license)
39+
40+
## Getting started
41+
42+
```bash
43+
npx fast-maker init
44+
npx fast-maker route
45+
```
46+
47+
You can create configuration file using init command. And you can run route command, `fast-maker` generate `route.ts` file on your output directory in configuration file.
48+
49+
You can see this mechanics!
50+
51+
![fast-maker-showcase.gif](assets/fast-maker-showcase.gif)
52+
53+
## How it works?
54+
55+
`fast-maker` using **TypeScript Compiler API**. So `fast-maker` exactly know handler function and route option in each file.
56+
57+
```mermaid
58+
graph LR
59+
60+
A[route file] --> fast-maker
61+
subgraph fast-maker
62+
direction TB
63+
C[TypeScript Compiler API]-->|extract <br/>handler function,<br /> option variable|B[fast-maker]
64+
end
65+
fast-maker-->|extract <br />route path|D[route.ts]
66+
```
67+
68+
The image below briefly shows how the directory is converted to route configurations.
69+
70+
| AS-IS (directory structure) | | TO-BE (route function) |
71+
| ---------------------------------------------------------- | --- | -------------------------------------------------- |
72+
| ![directory_structure.png](assets/directory_structure.png) || ![route_config_ts.png](assets/route_config_ts.png) |
73+
74+
## Installation
75+
76+
```basn
77+
npm i fast-maker --save-dev
78+
```
79+
80+
## Usage
81+
82+
You can see help from `--help` option.
83+
84+
```bash
85+
# display help for each commands
86+
npx fast-maker --help
87+
88+
# display help for route commands
89+
npx fast-maker route --help
90+
91+
# display help for watch commands
92+
npx fast-maker watch --help
93+
94+
# display help for init commands
95+
npx fast-maker init --help
96+
```
97+
98+
Also you can see detail option [here](/docs/options.md).
99+
100+
## Routing
101+
102+
`fast-maker` has a file-system based route configuration. This concept borrowed from [Next.js routing system](https://nextjs.org/docs/routing/introduction). But one difference is that _HTTP Method_ is separated by file-system.
103+
104+
### HTTP Method
105+
106+
use file-system.
107+
108+
```text
109+
handlers/
110+
├─ get/
111+
│ ├─ hero/
112+
│ │ ├─ [name].ts
113+
├─ post/
114+
│ ├─ hero.ts
115+
├─ put/
116+
│ ├─ hero/
117+
│ │ ├─ [name].ts
118+
├─ delete/
119+
│ ├─ hero/
120+
│ │ ├─ [name].ts
121+
```
122+
123+
`get`, `post`, `put`, `delete` directory represent _HTTP Method_. Also you can use `options`, `patch`, `head`, `all` directory.
124+
125+
### Route options
126+
127+
You can pass `RouteShorthandOptions` option like that,
128+
129+
```ts
130+
export const option: RouteShorthandOptions = {
131+
schema: {
132+
querystring: schema.properties?.Querystring,
133+
body: schema.properties?.Body,
134+
},
135+
};
136+
```
137+
138+
You have to `named export` and variable name must be a `option`.
139+
140+
### Route handler
141+
142+
You can pass route handler function like that,
143+
144+
```ts
145+
import { FastifyRequest } from 'fastify';
146+
import type { IReqSearchPokemonQuerystring, IReqSearchPokemonParams } from '../../interface/IReqSearchPokemon';
147+
148+
export default async function (
149+
req: FastifyRequest<{ Querystring: IReqSearchPokemonQuerystring; Params: IReqSearchPokemonParams }>,
150+
) {
151+
console.debug(req.query);
152+
console.debug(req.body);
153+
154+
return 'hello';
155+
}
156+
```
157+
158+
You have to `non-named export` (aka default export). Also you can use arrow function and you can use any name under TypeScript function name rule, as well as type arguments perfectly applied on route configuration
159+
160+
### Variable in Route Path
161+
162+
File or Directory name surrounded square bracket like that,
163+
164+
```text
165+
handlers/
166+
├─ get/
167+
│ ├─ hero/
168+
│ │ ├─ [name].ts
169+
```
170+
171+
Complex variable, No problem.
172+
173+
```text
174+
handlers/
175+
├─ get/
176+
│ ├─ hero/
177+
│ │ ├─ [affiliation]-[name].ts
178+
```
179+
180+
This route path access like that: `curl http://localhost:8080/hero/marvel-ironman`
181+
182+
That's it. `fast-maker` takes care of the rest.
183+
184+
## Example using fastify.js
185+
186+
A complete example of using `fast-maker` can be found at [Ma-eum](https://github.com/maeumjs/maeum).
187+
188+
## Relate To
189+
190+
- [ts-morph](https://github.com/dsherret/ts-morph)
191+
- TypeScript Compiler API wrapper
192+
193+
## Roadmaps
194+
195+
- [ ] display each route path in cli-table
196+
- [ ] add new option silent
197+
- [ ] documentation site
198+
- [ ] add more test
199+
200+
## License
201+
202+
This software is licensed under the [MIT](https://github.com/imjuni/fast-maker/blob/master/LICENSE).

0 commit comments

Comments
 (0)