@anthonylzq/simba.js 9.0.1 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +59 -30
  2. package/lib/index.js +42 -5
  3. package/lib/src/functions/api/database.js +40 -218
  4. package/lib/src/functions/api/express.js +100 -604
  5. package/lib/src/functions/api/fastify.js +93 -645
  6. package/lib/src/functions/api/hono.js +157 -0
  7. package/lib/src/functions/api/index.js +37 -59
  8. package/lib/src/functions/api/schemas.js +20 -84
  9. package/lib/src/functions/api/services.js +28 -210
  10. package/lib/src/functions/api/utils.js +10 -432
  11. package/lib/src/functions/biome.js +3 -2
  12. package/lib/src/functions/changelog.js +5 -5
  13. package/lib/src/functions/docker.js +7 -39
  14. package/lib/src/functions/ghat.js +12 -94
  15. package/lib/src/functions/gitignore.js +3 -134
  16. package/lib/src/functions/index.js +1 -2
  17. package/lib/src/functions/license.js +10 -2
  18. package/lib/src/functions/packageJson.js +13 -37
  19. package/lib/src/functions/readme.js +6 -5
  20. package/lib/src/functions/tests.js +17 -320
  21. package/lib/src/functions/tsconfig.js +13 -114
  22. package/lib/src/index.js +45 -21
  23. package/lib/src/utils/entity.js +115 -0
  24. package/lib/src/utils/index.js +2 -0
  25. package/lib/src/utils/mkdirs.js +9 -0
  26. package/lib/src/utils/renderTemplate.js +22 -0
  27. package/lib/src/utils/titleCase.js +5 -10
  28. package/lib/src/utils/writeFile.js +3 -10
  29. package/lib/templates/api/database/connection.ts.ejs +40 -0
  30. package/lib/templates/api/database/db-index.ts.ejs +2 -0
  31. package/lib/templates/api/database/index.ts.ejs +1 -0
  32. package/lib/templates/api/database/queries-entity.ts.ejs +98 -0
  33. package/lib/templates/api/database/queries-index.ts.ejs +1 -0
  34. package/lib/templates/api/database/schema.prisma.ejs +25 -0
  35. package/lib/templates/api/express/network/index.ts.ejs +2 -0
  36. package/lib/templates/api/express/network/models/entity.ts.ejs +21 -0
  37. package/lib/templates/api/express/network/models/index.ts.ejs +1 -0
  38. package/lib/templates/api/express/network/resolvers/entity.ts.ejs +41 -0
  39. package/lib/templates/api/express/network/resolvers/index.ts.ejs +13 -0
  40. package/lib/templates/api/express/network/response.ts.ejs +17 -0
  41. package/lib/templates/api/express/network/router.ts.ejs +39 -0
  42. package/lib/templates/api/express/network/routes/docs.ts.ejs +43 -0
  43. package/lib/templates/api/express/network/routes/entity.ts.ejs +165 -0
  44. package/lib/templates/api/express/network/routes/home.ts.ejs +16 -0
  45. package/lib/templates/api/express/network/routes/index.ts.ejs +5 -0
  46. package/lib/templates/api/express/network/server.ts.ejs +139 -0
  47. package/lib/templates/api/express/network/utils/index.ts.ejs +45 -0
  48. package/lib/templates/api/express/types/graphQL/context.d.ts.ejs +3 -0
  49. package/lib/templates/api/express/types/index.d.ts.ejs +4 -0
  50. package/lib/templates/api/fastify/network/index.ts.ejs +2 -0
  51. package/lib/templates/api/fastify/network/models/entity.ts.ejs +21 -0
  52. package/lib/templates/api/fastify/network/models/index.ts.ejs +1 -0
  53. package/lib/templates/api/fastify/network/resolvers/entity.ts.ejs +41 -0
  54. package/lib/templates/api/fastify/network/resolvers/index.ts.ejs +13 -0
  55. package/lib/templates/api/fastify/network/response.ts.ejs +17 -0
  56. package/lib/templates/api/fastify/network/router.ts.ejs +36 -0
  57. package/lib/templates/api/fastify/network/routes/docs.ts.ejs +41 -0
  58. package/lib/templates/api/fastify/network/routes/entity.ts.ejs +116 -0
  59. package/lib/templates/api/fastify/network/routes/home.ts.ejs +15 -0
  60. package/lib/templates/api/fastify/network/routes/index.ts.ejs +5 -0
  61. package/lib/templates/api/fastify/network/server.ts.ejs +129 -0
  62. package/lib/templates/api/fastify/types/graphQL/context.d.ts.ejs +3 -0
  63. package/lib/templates/api/fastify/types/index.d.ts.ejs +4 -0
  64. package/lib/templates/api/hono/network/index.ts.ejs +2 -0
  65. package/lib/templates/api/hono/network/models/entity.ts.ejs +21 -0
  66. package/lib/templates/api/hono/network/models/index.ts.ejs +1 -0
  67. package/lib/templates/api/hono/network/resolvers/entity.ts.ejs +41 -0
  68. package/lib/templates/api/hono/network/resolvers/index.ts.ejs +13 -0
  69. package/lib/templates/api/hono/network/response.ts.ejs +18 -0
  70. package/lib/templates/api/hono/network/router.ts.ejs +45 -0
  71. package/lib/templates/api/hono/network/routes/docs.ts.ejs +39 -0
  72. package/lib/templates/api/hono/network/routes/entity.ts.ejs +104 -0
  73. package/lib/templates/api/hono/network/routes/home.ts.ejs +15 -0
  74. package/lib/templates/api/hono/network/routes/index.ts.ejs +5 -0
  75. package/lib/templates/api/hono/network/server.ts.ejs +160 -0
  76. package/lib/templates/api/hono/network/utils/index.ts.ejs +23 -0
  77. package/lib/templates/api/hono/types/graphQL/context.d.ts.ejs +3 -0
  78. package/lib/templates/api/hono/types/index.d.ts.ejs +4 -0
  79. package/lib/templates/api/schemas/entity.ts.ejs +43 -0
  80. package/lib/templates/api/schemas/id.ts.ejs +11 -0
  81. package/lib/templates/api/schemas/index.ts.ejs +2 -0
  82. package/lib/templates/api/services/BaseHttp.ts.ejs +73 -0
  83. package/lib/templates/api/services/entity.ts.ejs +75 -0
  84. package/lib/templates/api/services/index.ts.ejs +1 -0
  85. package/lib/templates/api/services/utils/index.ts.ejs +1 -0
  86. package/lib/templates/api/services/utils/messages/entity.ts.ejs +11 -0
  87. package/lib/templates/api/services/utils/messages/index.ts.ejs +6 -0
  88. package/lib/templates/api/utils/Logger.ts.ejs +41 -0
  89. package/lib/templates/api/utils/index.ts.ejs +1 -0
  90. package/lib/templates/config/.dockerignore.ejs +20 -0
  91. package/lib/templates/config/.env.ejs +3 -0
  92. package/lib/templates/config/.gitignore.ejs +129 -0
  93. package/lib/templates/config/CHANGELOG.md.ejs +1 -0
  94. package/lib/templates/config/Dockerfile.ejs +13 -0
  95. package/lib/templates/config/README.md.ejs +3 -0
  96. package/lib/templates/config/ghat/lint.yml.ejs +46 -0
  97. package/lib/templates/config/ghat/test.yml.ejs +29 -0
  98. package/lib/templates/config/index.ts.ejs +3 -0
  99. package/lib/templates/config/package.json.ejs +30 -0
  100. package/lib/templates/config/test/index.test.ts.ejs +260 -0
  101. package/lib/templates/config/tsconfig.base.json.ejs +43 -0
  102. package/lib/templates/config/tsconfig.json.ejs +16 -0
  103. package/lib/templates/config/vitest.config.ts.ejs +19 -0
  104. package/package.json +45 -17
  105. package/lib/src/functions/api/types.js +0 -108
  106. package/lib/src/functions/eslint.js +0 -125
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
11
11
  [![Publish](https://github.com/AnthonyLzq/TypeScriptProjectGenerator/actions/workflows/publish.yml/badge.svg)](https://github.com/AnthonyLzq/TypeScriptProjectGenerator/actions/workflows/publish.yml)
12
12
 
13
- Set up a modern backend app by running one command. This project has the goal to create a complete setup for a backend application using `TypeScript` and `Express` or `Fastify`. It will create many files that are usually created manually. Think about Simba.js like a [CRA](https://create-react-app.dev/), but for backend development. Check the [**project structure**](#project-structure) for more information.
13
+ Set up a modern backend app by running one command. This project has the goal to create a complete setup for a backend application using `TypeScript` and `Express`, `Fastify` or `Hono`. It will create many files that are usually created manually. Think about Simba.js like a [CRA](https://create-react-app.dev/), but for backend development. Check the [**project structure**](#project-structure) for more information.
14
14
 
15
15
  ## Installation
16
16
 
@@ -38,8 +38,9 @@ By doing this your prompt will ask you the following questions:
38
38
  - `Project version:` the initial version of the project, `0.1.0` as default.
39
39
  - `License:`, the license you have chosen for the project.
40
40
  - `License year (current year):`, the year where your license starts, current year as default.
41
+ - `Main entity/model name (PascalCase):`, the name of the main entity for the generated project. Default: `User`.
41
42
  - `Would you want to have a basic GitHub Action for the suit of tests and linting? [y/n]:`.
42
- - `Express or Fastify?`, only one of them is valid (lowercase).
43
+ - `Express, Fastify or Hono?`, only one of them is valid (lowercase).
43
44
  - `Will this project use GraphQL? [y/n]:`, yes or no question, only **y** or **n** is accepted. This is not case sensitive.
44
45
  - `Which database do you want to use?`, `MongoDB`, `PostgreSQL`, `MySQL`, `MariaDB`, `Sqlite` and `Microsoft SQL Server` are available.
45
46
 
@@ -68,7 +69,7 @@ Options:
68
69
  and AGPL 3.0, in lowercase without its version.
69
70
  [default: "unlicensed"]
70
71
  -v, --version Project initial version. [default: "0.1.0"]
71
- -y, --licenseYear Year when the license starts. [default: "2023"]
72
+ -y, --licenseYear Year when the license starts. [default: "2026"]
72
73
  -m, --manager Which package manager you want to use,
73
74
  available package managers are: npm, yarn and
74
75
  pnpm. [default: "pnpm"]
@@ -79,12 +80,16 @@ Options:
79
80
  one. [boolean] [default: false]
80
81
  -F, --fastify Whether or not you want to use Fastify for your
81
82
  project. [boolean] [default: false]
83
+ -O, --hono Whether or not you want to use Hono for your
84
+ project. [boolean] [default: false]
82
85
  -g, --graphql Whether or not you want to use GraphQL for your
83
86
  project. [boolean] [default: false]
84
87
  --ghat, --gh-action-tests Whether or not you want to have a GitHub Action
85
88
  with a CI for your tests and linting. If this
86
89
  option is set to true, the tests flag must be
87
90
  set to true. [default: false]
91
+ -E, --entity Name of the main entity/model to generate
92
+ (PascalCase). Default: User. [default: "User"]
88
93
  -d, --database Which database you want to use, available
89
94
  databases are: MongoDB (mongo), PostgreSQL
90
95
  (postgres), MySQL (mysql), MariaDB (mariadb),
@@ -94,37 +99,43 @@ Options:
94
99
 
95
100
  Examples:
96
101
  simba -N 'Project Name' -D 'Project description' -a Anthony -e
97
- sluzquinosa@uni.pe -l mit -F -t -d mongo --ghat
102
+ sluzquinosa@uni.pe -l mit -F -d mongo --ghat
98
103
 
99
104
  Developed by AnthonyLzq
100
105
  ```
101
106
 
102
107
  ### Examples
103
108
 
104
- Let's suppose you want to build a project that will be deployed to Heroku, so should run:
109
+ Let's suppose you want to build a project with Express (the default framework):
105
110
 
106
111
  ```bash
107
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H
112
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com
108
113
  ```
109
114
 
110
- Here we are specifying that we want to create a new project called `myProject` using the `MIT` license, my name and my email are respectively: `myName` and `myEmail@email.com` and I want to use heroku to deploy this server.
115
+ Here we are specifying that we want to create a new project called `myProject` using the `MIT` license, my name and my email are respectively: `myName` and `myEmail@email.com`.
111
116
 
112
117
  As default, `pnpm` is selected as package manager, but if you don't want to use it, you can pass the flag `-m` or `--manager` as follows:
113
118
 
114
119
  ```bash
115
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -m yarn
120
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -m yarn
116
121
  ```
117
122
 
118
123
  What if I want to use Fastify instead Express? Well, you only have to pass the `-F` flag:
119
124
 
120
125
  ```bash
121
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F
126
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -F
127
+ ```
128
+
129
+ And if I want to use Hono? Pass the `-O` flag:
130
+
131
+ ```bash
132
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -O
122
133
  ```
123
134
 
124
135
  If I want to use a relational database instead MongoDB? Well, you only have to pass the `-d` flag:
125
136
 
126
137
  ```bash
127
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F -d postgres
138
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -d postgres
128
139
  ```
129
140
 
130
141
  The available databases are:
@@ -138,18 +149,26 @@ The available databases are:
138
149
  And how can I use GraphQL? Well, you only have to pass the `-g` flag:
139
150
 
140
151
  ```bash
141
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F -g
152
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -F -g
153
+ ```
154
+
155
+ What if I want my project scaffolded around a different entity instead of `User`? Pass the `-E` flag with a PascalCase name:
156
+
157
+ ```bash
158
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -E Product
142
159
  ```
143
160
 
161
+ The default entity (`User`) generates `lastName` and `name` fields. A custom entity generates `name` and `description` fields. Routes, services, schemas, Prisma models, and tests are all scaffolded around the provided entity name.
162
+
144
163
  Finally, you may not want to use a license or one of the available licenses, don't worry, just don't pass the flag `-l` neither `--license` as follows:
145
164
 
146
165
  ```bash
147
- simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
166
+ simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com
148
167
  ```
149
168
 
150
169
  ## <a name="project-structure"></a>Project structure
151
170
 
152
- If you want to check the content of the files, please check the [example](https://github.com/AnthonyLzq/simba.js/tree/master/example) folder, there you will an example for both, Express and Fastify (REST and GraphQL versions). Regardless of the option chosen, a new folder will be generated with the name of the project.
171
+ If you want to check the content of the files, please check the [example](https://github.com/AnthonyLzq/simba.js/tree/master/example) folder, there you will find an example for Express, Fastify and Hono (REST and GraphQL versions). Regardless of the option chosen, a new folder will be generated with the name of the project.
153
172
 
154
173
  Also, if you are interested in the folder structure of each case, please take a look at:
155
174
 
@@ -161,11 +180,15 @@ Also, if you are interested in the folder structure of each case, please take a
161
180
  - [Fastify-GraphQL](./projectStructureExamples/fastify-graphql.txt)
162
181
  - [Fastify-Mongo](./projectStructureExamples/fastify-mongo.txt)
163
182
  - [Fastify-Mongo-GraphQL](./projectStructureExamples/fastify-mongo-graphql.txt)
183
+ - [Hono](./projectStructureExamples/hono.txt)
184
+ - [Hono-GraphQL](./projectStructureExamples/hono-graphql.txt)
185
+ - [Hono-Mongo](./projectStructureExamples/hono-mongo.txt)
186
+ - [Hono-Mongo-GraphQL](./projectStructureExamples/hono-mongo-graphql.txt)
164
187
 
165
188
  ### Some considerations
166
189
 
167
190
  - **Prisma v6**: Generated projects use Prisma v6 (pinned). Prisma v7 is **not** used because it does not support MongoDB. When Prisma v7 adds MongoDB support, Simba.js will be updated accordingly.
168
- - You are able to run a server that has one main route, `home` (`/`), `user` (`api/user` or `api/user/:id`) and `docs` (`api/docs`), in case you are not using GraphQL.
191
+ - You are able to run a server that has one main route, `home` (`/`), your entity route (e.g. `api/user` or `api/user/:id` for the default `User` entity) and `docs` (`api/docs`), in case you are not using GraphQL. The route name is derived from the entity name you provide.
169
192
  - In case you are using GraphQL, there are 3 mutations (`store`, `update`, and `deleteById`) and 1 query available (`getById`), you can find them in the playground under the route `/api`.
170
193
  - To connect your server with your database, you need to provide your database url in the `.env`, except if you choose `sqlite`. By default, Simba will try to connect to a local database. The content of the `.env` file is:
171
194
 
@@ -242,31 +265,26 @@ Please check the [`changelog.md`](https://github.com/AnthonyLzq/simba.js/blob/ma
242
265
 
243
266
  Here is the list of the packages that are being installed, as `dependencies`:
244
267
 
268
+ - [`@prisma/client`](https://www.npmjs.com/package/@prisma/client)
245
269
  - [`debug`](https://www.npmjs.com/package/debug)
246
- - [`zod`](https://www.npmjs.com/package/zod)
247
270
  - [`http-errors`](https://www.npmjs.com/package/http-errors)
248
- - [`@prisma/client`](https://www.npmjs.com/package/@prisma/client)
271
+ - [`zod`](https://www.npmjs.com/package/zod)
249
272
 
250
273
  As `devDependencies`:
251
274
 
252
275
  - [`@biomejs/biome`](https://www.npmjs.com/package/@biomejs/biome)
253
- - [`@jest/types`](https://www.npmjs.com/package/@jest/types)
254
276
  - [`@types/debug`](https://www.npmjs.com/package/@types/debug)
255
277
  - [`@types/http-errors`](https://www.npmjs.com/package/@types/http-errors)
256
- - [`@types/jest`](https://www.npmjs.com/package/@types/jest)
257
278
  - [`@types/node`](https://www.npmjs.com/package/@types/node)
258
279
  - [`axios`](https://www.npmjs.com/package/axios)
259
280
  - [`dotenv`](https://www.npmjs.com/package/dotenv)
260
- - [`jest`](https://www.npmjs.com/package/jest)
261
- - [`jest-unit`](https://www.npmjs.com/package/jest-unit)
262
281
  - [`nodemon`](https://www.npmjs.com/package/nodemon)
263
282
  - [`prisma`](https://www.npmjs.com/package/prisma)
264
- - [`standard-version`](https://www.npmjs.com/package/standard-version)
265
- - [`ts-loader`](https://www.npmjs.com/package/ts-loader)
266
- - [`ts-node`](https://www.npmjs.com/package/ts-node)
267
- - [`tsconfig-paths`](https://www.npmjs.com/package/tsconfig-paths)
268
- - [`ts-jest`](https://www.npmjs.com/package/ts-jest)
283
+ - [`commit-and-tag-version`](https://www.npmjs.com/package/commit-and-tag-version)
284
+ - [`tsx`](https://www.npmjs.com/package/tsx)
269
285
  - [`typescript`](https://www.npmjs.com/package/typescript)
286
+ - [`vite-tsconfig-paths`](https://www.npmjs.com/package/vite-tsconfig-paths)
287
+ - [`vitest`](https://www.npmjs.com/package/vitest)
270
288
 
271
289
  ### In case you are using GraphQL
272
290
 
@@ -278,36 +296,47 @@ As `dependencies`:
278
296
  - [`reflect-metadata`](https://www.npmjs.com/package/reflect-metadata)
279
297
  - [`type-graphql`](https://www.npmjs.com/package/type-graphql/v/2.0.0-rc.3)
280
298
 
299
+ As `devDependencies`:
300
+ - [`@swc/core`](https://www.npmjs.com/package/@swc/core)
301
+ - [`unplugin-swc`](https://www.npmjs.com/package/unplugin-swc)
302
+
281
303
  ### Express case
282
304
 
283
305
  As `dependencies`:
284
306
 
285
307
  - [`@as-integrations/express5`](https://www.npmjs.com/package/@as-integrations/express5) (only when using GraphQL)
308
+ - [`@asteasolutions/zod-to-openapi`](https://www.npmjs.com/package/@asteasolutions/zod-to-openapi)
286
309
  - [`cors`](https://www.npmjs.com/package/cors)
287
310
  - [`express`](https://www.npmjs.com/package/express)
288
311
  - [`swagger-ui-express`](https://www.npmjs.com/package/swagger-ui-express)
289
312
 
290
313
  As `devDependencies`:
291
314
 
292
- - [`@types/express`](https://www.npmjs.com/package/@types/express)
293
315
  - [`@types/cors`](https://www.npmjs.com/package/@types/cors)
316
+ - [`@types/express`](https://www.npmjs.com/package/@types/express)
294
317
  - [`@types/swagger-ui-express`](https://www.npmjs.com/package/@types/swagger-ui-express)
295
318
 
296
319
  ### Fastify case
297
320
 
298
321
  As `dependencies`:
299
322
 
300
- - [`fastify`](https://www.npmjs.com/package/fastify)
323
+ - [`@as-integrations/fastify`](https://www.npmjs.com/package/@as-integrations/fastify) (only when using GraphQL)
324
+ - [`@fastify/cors`](https://www.npmjs.com/package/@fastify/cors)
301
325
  - [`@fastify/swagger`](https://www.npmjs.com/package/@fastify/swagger)
302
326
  - [`@fastify/swagger-ui`](https://www.npmjs.com/package/@fastify/swagger-ui)
303
- - [`@fastify/cors`](https://www.npmjs.com/package/@fastify/cors)
327
+ - [`fastify`](https://www.npmjs.com/package/fastify)
304
328
  - [`fastify-type-provider-zod`](https://www.npmjs.com/package/fastify-type-provider-zod)
305
329
 
306
- #### In case you are using GraphQL
330
+ ### Hono case
307
331
 
308
332
  As `dependencies`:
309
- - [`@as-integrations/fastify`](https://www.npmjs.com/package/@as-integrations/fastify)
310
333
 
334
+ - [`@hono/node-server`](https://www.npmjs.com/package/@hono/node-server)
335
+ - [`@hono/swagger-ui`](https://www.npmjs.com/package/@hono/swagger-ui)
336
+ - [`@hono/zod-openapi`](https://www.npmjs.com/package/@hono/zod-openapi)
337
+ - [`hono`](https://www.npmjs.com/package/hono)
338
+
339
+ ### Database drivers
311
340
 
312
341
  #### PostgreSQL case
313
342
 
package/lib/index.js CHANGED
@@ -12,7 +12,8 @@ const {
12
12
  EMAIL_REGEX,
13
13
  PROJECT_VERSION,
14
14
  MAIN_FILE
15
- }
15
+ },
16
+ entity: { buildEntityContext }
16
17
  } = require('./src/utils')
17
18
  const POSSIBLE_LICENSES = Object.keys(LICENSES)
18
19
 
@@ -67,6 +68,8 @@ const argv = yargs(hideBin(process.argv))
67
68
  )
68
69
  .alias('F', 'fastify')
69
70
  .describe('F', 'Whether or not you want to use Fastify for your project.')
71
+ .alias('O', 'hono')
72
+ .describe('O', 'Whether or not you want to use Hono for your project.')
70
73
  .alias('g', 'graphql')
71
74
  .describe('g', 'Whether or not you want to use GraphQL for your project.')
72
75
  .alias('ghat', 'gh-action-tests')
@@ -74,6 +77,12 @@ const argv = yargs(hideBin(process.argv))
74
77
  'ghat',
75
78
  'Whether or not you want to have a GitHub Action with a CI for your tests and linting. If this option is set to true, the tests flag must be set to true.'
76
79
  )
80
+ .alias('E', 'entity')
81
+ .nargs('E', 1)
82
+ .describe(
83
+ 'E',
84
+ 'Name of the main entity/model to generate (PascalCase). Default: User.'
85
+ )
77
86
  .describe(
78
87
  'd',
79
88
  'Which database you want to use, available databases are: MongoDB (mongo), PostgreSQL (postgres), MySQL (mysql), MariaDB (mariadb), Sqlite (sqlite) and Microsoft SQL Server (sqlServer).'
@@ -87,12 +96,14 @@ const argv = yargs(hideBin(process.argv))
87
96
  f: 'src/index.ts',
88
97
  q: false,
89
98
  F: false,
99
+ O: false,
90
100
  g: false,
91
101
  ghat: false,
102
+ E: 'User',
92
103
  d: 'mongo',
93
104
  m: 'pnpm'
94
105
  })
95
- .boolean(['q', 'F', 'g'])
106
+ .boolean(['q', 'F', 'O', 'g'])
96
107
  .help('h')
97
108
  .alias('h', 'help')
98
109
  .epilog('Developed by AnthonyLzq').argv
@@ -109,10 +120,12 @@ const config = {
109
120
  manager: 'pnpm i',
110
121
  mainFile: MAIN_FILE,
111
122
  fastify: false,
123
+ hono: false,
112
124
  graphql: false,
113
125
  tests: true,
114
126
  ghat: true,
115
- database: 'mongo'
127
+ database: 'mongo',
128
+ entity: 'User'
116
129
  }
117
130
 
118
131
  const main = async () => {
@@ -203,10 +216,11 @@ const main = async () => {
203
216
  {
204
217
  type: 'select',
205
218
  name: 'framework',
206
- message: 'Express or Fastify?',
219
+ message: 'Which framework do you want to use?',
207
220
  choices: [
208
221
  { title: 'Express', value: 'express' },
209
- { title: 'Fastify', value: 'fastify' }
222
+ { title: 'Fastify', value: 'fastify' },
223
+ { title: 'Hono', value: 'hono' }
210
224
  ]
211
225
  },
212
226
  {
@@ -224,6 +238,13 @@ const main = async () => {
224
238
  title: value,
225
239
  value: key
226
240
  }))
241
+ },
242
+ {
243
+ type: 'text',
244
+ name: 'entity',
245
+ message: 'Main entity/model name (PascalCase):',
246
+ initial: 'User',
247
+ format: value => value.charAt(0).toUpperCase() + value.slice(1)
227
248
  }
228
249
  ],
229
250
  {
@@ -244,8 +265,10 @@ const main = async () => {
244
265
  config.manager = responses.manager
245
266
  config.mainFile = responses.mainFile
246
267
  config.fastify = responses.framework === 'fastify'
268
+ config.hono = responses.framework === 'hono'
247
269
  config.graphql = responses.graphql
248
270
  config.database = responses.database
271
+ config.entity = responses.entity
249
272
  config.ghat = responses.ghat
250
273
  } else {
251
274
  if (!argv.author) return console.log('Error! An author is required!')
@@ -271,6 +294,13 @@ const main = async () => {
271
294
 
272
295
  if (argv.fastify) config.fastify = true
273
296
 
297
+ if (argv.hono) config.hono = true
298
+
299
+ if (config.fastify && config.hono)
300
+ return console.log(
301
+ 'Error! You cannot use both Fastify and Hono at the same time.'
302
+ )
303
+
274
304
  if (!argv.license || argv.license === UNLICENSED)
275
305
  console.log('License was not provided')
276
306
  else {
@@ -323,8 +353,12 @@ const main = async () => {
323
353
  if (argv.ghat) config.ghat = true
324
354
 
325
355
  if (argv.database) config.database = argv.database
356
+
357
+ if (argv.entity) config.entity = argv.entity
326
358
  }
327
359
 
360
+ config.entityContext = buildEntityContext(config.entity)
361
+
328
362
  await installation(config)
329
363
  }
330
364
 
@@ -342,6 +376,9 @@ module.exports = main
342
376
  * @property {'yarn add'|'npm i'|'pnpm i'} manager command that will be used to install packages
343
377
  * @property {String} mainFile main file of the project
344
378
  * @property {Boolean} fastify true means that the project will be using Fastify
379
+ * @property {Boolean} hono true means that the project will be using Hono
345
380
  * @property {Boolean} graphql true means that the project will be using GraphQL
346
381
  * @property {'mongo'|'postgres'|'mysql'|'mariadb'|'sqlite'|'sqlServer'} database project database
382
+ * @property {String} entity PascalCase name of the main entity/model (default: 'User')
383
+ * @property {import('./src/utils/entity').EntityContext} entityContext computed entity naming context
347
384
  */
@@ -1,7 +1,6 @@
1
- const { platform } = require('node:os')
2
- const { promisify } = require('node:util')
3
- const exec = promisify(require('node:child_process').exec)
1
+ const mkdirs = require('../../utils/mkdirs')
4
2
  const writeFile = require('../../utils/writeFile')
3
+ const { renderTemplate } = require('../../utils/renderTemplate')
5
4
 
6
5
  const dbPrismaName = {
7
6
  postgres: 'postgresql',
@@ -25,222 +24,49 @@ const dbPrettyName = {
25
24
  * @param {Object} args
26
25
  * @param {String} args.projectName
27
26
  * @param {import('../../../../').Config['database']} args.db
27
+ * @param {import('../../utils/entity').EntityContext} args.entityContext
28
28
  */
29
- const db = async ({ projectName, db }) => {
29
+ const db = async ({ projectName, db, entityContext }) => {
30
30
  const isMongo = db === 'mongo'
31
- const createFoldersCommands = `mkdir ${projectName}/prisma \
32
- ${projectName}/src/database/${db} \
33
- ${projectName}/src/database/${db}/queries`
34
31
 
35
- if (platform() === 'win32')
36
- await exec(createFoldersCommands.replaceAll('/', '\\'))
37
- else await exec(createFoldersCommands)
32
+ await mkdirs(
33
+ `${projectName}/prisma`,
34
+ `${projectName}/src/database/${db}/queries`
35
+ )
38
36
 
39
- const database = {
40
- schema: {
41
- content: `generator client {
42
- provider = "prisma-client-js"
43
- }
44
-
45
- datasource db {
46
- provider = "${dbPrismaName[db]}"
47
- url = ${db !== 'sqlite' ? 'env("DATABASE_URL")' : '"file:./dev.db"'}
48
- }
49
-
50
- model User {
51
- ${
52
- isMongo
53
- ? 'id String @id @default(auto()) @map("_id") @db.ObjectId'
54
- : 'id Int @id @default(autoincrement())'
55
- }
56
- lastName String
57
- name String
58
-
59
- createdAt DateTime @default(now())
60
- updatedAt DateTime @updatedAt
61
-
62
- @@map("users")
63
- }
64
- `,
65
- file: `${projectName}/prisma/schema.prisma`
66
- },
67
- index: {
68
- content: `export * from './${db}'\n`,
69
- file: `${projectName}/src/database/index.ts`
70
- },
71
- [db]: {
72
- index: {
73
- content: `export * from './connection'
74
- export * from './queries'\n`,
75
- file: `${projectName}/src/database/${db}/index.ts`
76
- },
77
- connection: {
78
- content: `import { PrismaClient } from '@prisma/client'
79
- import { type Debugger } from 'debug'
80
-
81
- let dbConnected = false
82
-
83
- declare global {
84
- // eslint-disable-next-line no-var
85
- var __client__: PrismaClient
86
- }
87
-
88
- const dbConnection = (
89
- d?: Debugger
90
- ): {
91
- connect: () => Promise<PrismaClient>
92
- disconnect: () => Promise<boolean>
93
- } => {
94
- return {
95
- connect: async () => {
96
- if (!global.__client__) {
97
- global.__client__ = new PrismaClient()
98
- await global.__client__.$connect()
99
- dbConnected = true
100
- d?.('${dbPrettyName[db]} connection established.')
101
- }
102
-
103
- return global.__client__
104
- },
105
- disconnect: async () => {
106
- if (global.__client__) {
107
- dbConnected = false
108
- await global.__client__.$disconnect()
109
- d?.('${dbPrettyName[db]} connection closed.')
110
- }
111
-
112
- return dbConnected
113
- }
114
- }
115
- }
116
-
117
- export { dbConnection }\n`,
118
- file: `${projectName}/src/database/${db}/connection.ts`
119
- },
120
- queries: {
121
- index: {
122
- content: "export * from './user'\n",
123
- file: `${projectName}/src/database/${db}/queries/index.ts`
124
- },
125
- user: {
126
- content: `import { User } from '@prisma/client'
127
- import debug from 'debug'
128
-
129
- import { dbConnection } from '../connection'
130
- import { Id, User as UserSchema, UserDTO } from 'schemas'
131
- import { Logger } from 'utils'
132
-
133
- const logger = new Logger(debug('App:Database:Queries:User'))
134
-
135
- const userDBOtoDTO = (userDBO: User) =>
136
- ({
137
- ...userDBO,
138
- createdAt: userDBO.createdAt.toISOString(),
139
- updatedAt: userDBO.updatedAt.toISOString()
140
- }) satisfies UserDTO
141
-
142
- const store = async (userData: UserSchema) => {
143
- try {
144
- const client = await dbConnection().connect()
145
- const user = await client.user.create({
146
- data: userData
147
- })
148
-
149
- return userDBOtoDTO(user)
150
- } catch (error) {
151
- logger.log({
152
- origin: 'queries/user.ts',
153
- method: store.name,
154
- value: 'error',
155
- content: error
156
- })
157
-
158
- return null
159
- }
160
- }
161
-
162
- const removeById = async (id: Id) => {
163
- try {
164
- const client = await dbConnection().connect()
165
- await client.user.delete({
166
- where: { id }
167
- })
168
-
169
- return true
170
- } catch (error) {
171
- logger.log({
172
- origin: 'queries/user.ts',
173
- method: removeById.name,
174
- value: 'error',
175
- content: error
176
- })
177
-
178
- return false
179
- }
180
- }
181
-
182
- const getById = async (id: Id) => {
183
- try {
184
- const client = await dbConnection().connect()
185
- const user = await client.user.findUnique({
186
- where: { id }
187
- })
188
-
189
- if (!user) return null
190
-
191
- return userDBOtoDTO(user)
192
- } catch (error) {
193
- logger.log({
194
- origin: 'queries/user.ts',
195
- method: getById.name,
196
- value: 'error',
197
- content: error
198
- })
199
-
200
- return null
201
- }
202
- }
203
-
204
- const update = async (id: Id, user: UserSchema) => {
205
- try {
206
- const client = await dbConnection().connect()
207
- const userUpdated = await client.user.update({
208
- where: { id },
209
- data: user
210
- })
211
-
212
- if (!userUpdated) return null
213
-
214
- return userDBOtoDTO(userUpdated)
215
- } catch (error) {
216
- logger.log({
217
- origin: 'queries/user.ts',
218
- method: update.name,
219
- value: 'error',
220
- content: error
221
- })
222
-
223
- return null
224
- }
225
- }
226
-
227
- export { store, removeById, getById, update }\n`,
228
- file: `${projectName}/src/database/${db}/queries/user.ts`
229
- }
230
- }
231
- }
232
- }
37
+ const t = (templatePath, data = {}) =>
38
+ renderTemplate(`api/database/${templatePath}`, data)
233
39
 
234
40
  await Promise.all([
235
- writeFile(database.schema.file, database.schema.content),
236
- writeFile(database.index.file, database.index.content),
237
- writeFile(database[db].connection.file, database[db].connection.content),
238
- writeFile(database[db].index.file, database[db].index.content),
239
41
  writeFile(
240
- database[db].queries.index.file,
241
- database[db].queries.index.content
42
+ `${projectName}/prisma/schema.prisma`,
43
+ t('schema.prisma.ejs', {
44
+ dbPrismaName: dbPrismaName[db],
45
+ db,
46
+ isMongo,
47
+ ...entityContext
48
+ })
49
+ ),
50
+ writeFile(
51
+ `${projectName}/src/database/index.ts`,
52
+ t('index.ts.ejs', { db })
242
53
  ),
243
- writeFile(database[db].queries.user.file, database[db].queries.user.content)
54
+ writeFile(
55
+ `${projectName}/src/database/${db}/index.ts`,
56
+ t('db-index.ts.ejs')
57
+ ),
58
+ writeFile(
59
+ `${projectName}/src/database/${db}/connection.ts`,
60
+ t('connection.ts.ejs', { dbPrettyName: dbPrettyName[db] })
61
+ ),
62
+ writeFile(
63
+ `${projectName}/src/database/${db}/queries/index.ts`,
64
+ t('queries-index.ts.ejs', entityContext)
65
+ ),
66
+ writeFile(
67
+ `${projectName}/src/database/${db}/queries/${entityContext.entity}.ts`,
68
+ t('queries-entity.ts.ejs', entityContext)
69
+ )
244
70
  ])
245
71
  }
246
72
 
@@ -249,12 +75,8 @@ export { store, removeById, getById, update }\n`,
249
75
  * @param {import('../../../../').Config['database']} args.database
250
76
  * @param {String} args.projectName
251
77
  */
252
- module.exports = async ({ database, projectName }) => {
253
- const createFoldersCommand = `mkdir ${projectName}/src/database`
254
-
255
- if (platform() === 'win32')
256
- await exec(createFoldersCommand.replaceAll('/', '\\'))
257
- else await exec(createFoldersCommand)
78
+ module.exports = async ({ database, projectName, entityContext }) => {
79
+ await mkdirs(`${projectName}/src/database`)
258
80
 
259
- await db({ db: database, projectName })
81
+ await db({ db: database, projectName, entityContext })
260
82
  }