beech-api 3.8.0 → 3.9.0-beta.8-rc

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.
package/README.md CHANGED
@@ -1,22 +1,74 @@
1
1
  [![N|Solid](https://i.ibb.co/NKxx9NQ/beech320.jpg)](https://github.com/bombkiml)
2
2
 
3
3
  # Beech API framework
4
- #### Stable v.3.8.0 (LTS)
4
+ #### Auto endpoint v.3.9.0 (LTS)
5
5
 
6
- [![beech-api release](https://img.shields.io/github/v/release/bombkiml/beech-api)](https://github.com/bombkiml/beech-api/releases/tag/3.8.0)
6
+ [![beech-api release](https://img.shields.io/github/v/release/bombkiml/beech-api)](https://github.com/bombkiml/beech-api/releases/)
7
7
  [![PyPI license](https://shields.io/pypi/l/ansicolortags.svg)](https://github.com/bombkiml/beech-api/blob/master/README.md)
8
8
 
9
9
  # What is Beech API ?
10
10
 
11
11
  The Beech API is API framework, It's help you with very easy to create API project under [Node.js](https://nodejs.org)
12
12
 
13
+ ## Let's go
14
+ - <b>[Installation](#installation)</b>
15
+ - <b>[Creating a project](#creating-a-project)</b>
16
+ - <b>[Upgrade to latest version](#upgrade-to-latest-version)</b>
17
+ - <b>[Beech CLI tool available](#beech-cli-tool-available)</b>
18
+ - ✨ <b>Automation Endpoints with CRUD</b>
19
+ - [Database Connection](#database-connection)
20
+ - [Model](#model)
21
+ - [Retrieving data with Query String](#retrieving-data-with-query-string)
22
+ - Conditions
23
+ - Grouping
24
+ - Ordering
25
+ - Timestamps (Add-on in Store and Update)
26
+ - [Transactions](#transactions)
27
+ - [Disorganized transactions](#way-1---disorganized-transactions-)
28
+ - [Organized transactions](#way-2---organized-transactions-)
29
+ - [Transactions set Isolation levels](#way-3---transactions-set-isolation-levels-)
30
+ - [Endpoints](#endpoints)
31
+ - [Helpers](#helpers)
32
+ - 🔐 <b>System Management of Authentication</b>
33
+ - [Authentication Manegement](#authentication-passport-jwt)
34
+ - [Request Token](#request-token)
35
+ - [Beech Guard](#beech-guard)
36
+ - Verify Identity Management
37
+ - Two Factor (2fa, OTP, etc.)
38
+ - [Beech User Authentication Managements](#-beech-user-authentication-managements)
39
+ - Create Auth
40
+ - Update Auth
41
+ - 🛠️ <b>Safe Endpoints Request</b>
42
+ - [Rate Limit](#-custom-endpoint-specific-rate-limit)
43
+ - [Slow Down](#-custom-endpoint-specific-slow-down)
44
+ - [Block Duplicate Request per Window](#-custom-endpoint-specific-duplicate-request)
45
+ - [JWT Broken Role](#jwt-broken-role)
46
+ - [Advance Guard (Timimg)](#-beech-advanced-guard-timing)
47
+ - 🙂 <b>Hight Security under passport-jwt, oauth2</b>
48
+ - 🌐 <b>Supported Official Strategy</b>
49
+ - [Google](#-google-strategy)
50
+ - [Facebook](#-facebook-strategy)
51
+ - 🖥️ <b>CORS Origin & Server Configuration</b>
52
+ - [Config Base public path `./`](#cors-origin--server-configuration)
53
+ - [Allow origin whitelist](#cors-origin--server-configuration)
54
+ - 📚 <b>Databases Managements</b>
55
+ - [Migrations](#databases-managements)
56
+ - [Seeder](#-creating-first-seeder)
57
+ - ☕ <b>Testing</b>
58
+ - [Jest](#testing)
59
+ - 🏃 <b>Implementration</b>
60
+ - [Docker](#implementation)
61
+ - [PM2](#-implement-with-pm2)
62
+
13
63
  # Environment
14
64
 
15
- - [`Node.js`](https://nodejs.org) >= 14.19.0+ (recommended)
65
+ - [`Node.js`](https://nodejs.org) >= 18.17.1+ (recommended)
16
66
 
17
67
  # Installation
18
68
 
19
- Beech API requires Node.js version 14.19.0 or above. You can manage multiple versions of Node on the same machine with [nvm](https://github.com/creationix/nvm) or [nvm-windows](https://github.com/coreybutler/nvm-windows). So, Let's go to install `beech-api`
69
+ Beech API needed Node.js version 18.17.1 or above. You can management multiple versions on the same machine with [nvm](https://github.com/creationix/nvm) or [nvm-windows](https://github.com/coreybutler/nvm-windows).
70
+
71
+ <b>So, Let's go to install</b> `beech-api`
20
72
 
21
73
  ```sh
22
74
  # NPM
@@ -98,7 +150,9 @@ The following commands are available:
98
150
  $ beech key:generate, key:gen Re-Generate application key (Dangerous!).
99
151
  $ beech hash:<text> Hash text for Access to Database connection.
100
152
  ```
101
- ❓ **Note:** Every to create new project will be generated new ``app_key`` in ``app.config.js`` file, If you can re-generate. Can use command ``$ beech key:generate`` or ``$ beech key:gen``
153
+ ❓ **Note:** Every to create new project will be generated new ``app_key`` in ``app.config.js`` file.
154
+
155
+ ❓ **Note:** If you can re-generate. Can use command ``$ beech key:generate`` or ``$ beech key:gen``
102
156
 
103
157
  # Database connection
104
158
 
@@ -121,7 +175,7 @@ $ beech hash:password
121
175
  Output: FjgcgJPylkV7EeQJjea_EeifPwaHVO9onD3ATk3YYAyvjtMGu3dcDS0ejA
122
176
 
123
177
  ```
124
- Example:
178
+ ***For Example :***
125
179
 
126
180
  📂 app.config.js
127
181
  ```js
@@ -150,9 +204,9 @@ database_config: [
150
204
  // or use a named timezone supported by Intl.Locale
151
205
  // timezone: 'America/Los_Angeles',
152
206
 
153
- logging: console.log, // SQL trace logs
207
+ logging: console.log, // SQL trace logs. Learn more: https://sequelize.org/docs/v6/getting-started/#logging
154
208
 
155
- is_connect: true, // boolean, Turn ON/OFF to connect
209
+ is_connect: true, // Boolean, Turn ON/OFF to connect
156
210
  },
157
211
 
158
212
  ...
@@ -163,113 +217,24 @@ database_config: [
163
217
  ```
164
218
  ❓ **Caution! :** Every re-new generate `app_key`. Must to new Hash your Access and change to ALL Database connections.
165
219
 
166
- # Part of generate file
220
+ # Models
167
221
 
168
- ## # Generate Endpoints
169
-
170
- The `endpoints` keep the endpoints basic request files currently support `GET`, `POST`, `PUT`, `PATCH` and `DELETE`.
171
-
172
- So, you might create new endpoints with constant `endpoint` object variable in `src/endpoints/` folder and file neme must be end with `-endpoints.js`
222
+ The `models` keep the files of function(s) data managemnets for Retriving, Creating, Updating and Destroying (CRUD). for understanding you might make model name same your table name inside `src/models` folder.
173
223
 
174
224
  ```sh
175
- $ beech make endpointName
176
- ```
177
- You might using [special] `-R, --require` for choose Model(s) used for that endpoint.
178
-
179
- ### Example ***(Basic)*** : Fruit endpoints.
180
-
181
- 📂 fruit-endpoints.js
182
- ```js
183
- exports.init = () => {
184
-
185
- // GET method
186
- endpoint.get("/fruit", Credentials, (req, res) => {
187
- // @response
188
- res.json({
189
- code: 200,
190
- status: "SUCCESS",
191
- message: "GET /fruit request.",
192
- });
193
- });
194
-
195
-
196
- // POST method
197
- endpoint.post("/fruit", Credentials, (req, res) => {
198
- // @response
199
- res.json({
200
- code: 200,
201
- status: "SUCCESS",
202
- message: "POST request at /fruit",
203
- result: {
204
- id: req.body.id,
205
- name: req.body.name,
206
- },
207
- });
208
- });
209
-
210
-
211
- // PUT method
212
- endpoint.put("/fruit/:id", Credentials, (req, res) => {
213
- // @response
214
- res.json({
215
- code: 200,
216
- status: "SUCCESS",
217
- message: "PUT request at /fruit/" + req.params.id,
218
- });
219
- });
220
-
221
-
222
- // DELETE method
223
- endpoint.delete("/fruit/:id", Credentials, (req, res) => {
224
- // @response
225
- res.json({
226
- code: 200,
227
- status: "SUCCESS",
228
- message: "DELETE request at /fruit/" + req.params.id,
229
- });
230
- });
231
-
232
- ...
233
-
234
- }
235
- ```
236
-
237
- ### Example ***(Sequelize)*** : Fruit endpoints.
238
-
239
- 📂 fruit-endpoints.js
240
- ```js
241
- // Require Model schema, Function & Others
242
- const { Fruit } = require("@/models/Fruit");
243
-
244
- exports.init = () => {
245
-
246
- // GET method
247
- endpoint.get('/fruit', async (req, res) => {
248
- // example call Fruit model for get data
249
- res.json({
250
- code: 200,
251
- status: "SUCCESS",
252
- results: await Fruit.findAll();
253
- });
254
- });
255
-
256
- ...
257
-
258
- }
225
+ $ beech make modelName --model
259
226
  ```
260
227
 
228
+ ## # Model (Basic)
261
229
 
262
- ## # Generate Models ###
230
+ Basic model only support `MySQL` Raw Query format and freedom of your SQL query
263
231
 
264
- The `models` keep the files of function(s) data managemnets for Retriving, Creating, Updating and Destroying (CRUD). for understanding you might make model name same your table name inside `src/models` folder.
232
+ ❓ **Note:** The Basic pool engine it's not support auto Endpoints.
265
233
 
266
- ```sh
267
- $ beech make modelName --model
268
- ```
269
234
 
270
- ### Example ***(Basic)*** : Fruit model.
235
+ ***For example :***
271
236
 
272
- 📂 Fruit.js
237
+ 📂 models/Fruit.js
273
238
  ```js
274
239
  module.exports = {
275
240
 
@@ -299,11 +264,17 @@ module.exports = {
299
264
  };
300
265
  ```
301
266
 
302
- ### Example ***(Sequelize)*** : Fruit model.
267
+ ## # Model (Sequelize)
303
268
 
269
+ Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Oracle Database, Amazon Redshift and Snowflake’s Data Cloud. It features solid transaction support, relations, eager and lazy loading, read replication and more. <br/>You can learn more: [Sequelize docs](https://sequelize.org/docs/v6)
270
+
304
271
  You can asign more DataTypes, Learn more : [Sequelize docs](https://sequelize.org/docs/v6/core-concepts/model-basics/#data-types)
305
272
 
306
- 📂Fruit.js
273
+ ❓ **Note:** When you generate a model it's create table structure for automatically for you.
274
+
275
+ ***For example :***
276
+
277
+ 📂 models/Fruit.js
307
278
  ```js
308
279
  const { Schema } = require("beech-api");
309
280
 
@@ -327,6 +298,7 @@ const Fruit = Schema(sql.default_db).define("fruit", {
327
298
  type: DataTypes.INTEGER,
328
299
  allowNull: false, // Allow null feilds
329
300
  },
301
+ sort: DataTypes.STRING,
330
302
  createdAt: {
331
303
  type: DataTypes.DATE,
332
304
  allowNull: false,
@@ -350,7 +322,7 @@ Fruit.options = {
350
322
  // Option 1: Allow all methods
351
323
  defaultEndpoint: true,
352
324
 
353
- // Option 2: Allow with specific per methods
325
+ // Option 2: Allow with specific per methods
354
326
  defaultEndpoint: {
355
327
  GET: true,
356
328
  POST: false,
@@ -367,7 +339,6 @@ Fruit.options = {
367
339
  },
368
340
 
369
341
  limitRows: 100, // Limit rows default 100
370
-
371
342
  };
372
343
 
373
344
  // Example Finder by id (ORM), Learn more: https://sequelize.org/docs/v6/core-concepts/model-querying-finders/
@@ -375,7 +346,6 @@ function exampleFindOneFruitById(id) {
375
346
  return Fruit.findOne({ where: { id: id } });
376
347
  }
377
348
 
378
-
379
349
  // Example Raw Query with Model Instances. This allows you to easily map a query to a predefined model
380
350
  function exampleGetAllFruitWithModelInstance(id) {
381
351
  return Fruit.query("SELECT * FROM fruit", {
@@ -400,19 +370,98 @@ module.exports = {
400
370
  ...
401
371
  };
402
372
  ```
403
- #### That's cool! It's like magic creating The endpoints for you (CRUD) ✨
404
373
 
405
- Now! you can request to `/fruit` with methods GET, POST, PATCH and DELETE like this.
374
+ ## Retrieving data with Query String
375
+
376
+ Now you can add Query String with Conditional, Grouping and Ordering (Now Support Readonly for GET method)
377
+
378
+ ### ✨ That's cool! It's like magic Creating The Endpoints for you (CRUD) ✨
379
+
380
+ <b style="font-size:12pt">For Example, Now!</b>, You can request to `/fruit` with methods GET, POST, PATCH and DELETE like this.
406
381
 
407
382
  | Efficacy | Method | Endpoint | Body |
408
383
  |:---------|:---------|:-----------------------|:-----------|
409
384
  | Create | POST | /fruit | { } |
410
385
  | Read | GET | /fruit | No |
411
- | Read | GET | /fruit/:id | No |
412
386
  | Read | GET | /fruit/:limit/:offset | No |
387
+ | Read | GET | /fruit?someField=1 | No |
388
+ | Read | GET | /fruit?orderby=sort | No |
389
+ | Read | GET | /fruit?groupby=id | No |
413
390
  | Update | PATCH | /fruit/:id | { } |
414
391
  | Delete | DELETE | /fruit/:id | No |
415
392
 
393
+ Add some Basic Conditions, Grouping and Ordering with `QUERY STRING` under GET methods<br/>
394
+
395
+ Retrieving `fruit` data with GET : `/fruit?someField=[eq,1]&groupby=[id]&orderby=[id,desc]`
396
+
397
+ ***For Example :***
398
+
399
+ ```java
400
+ // WHERE Conditions
401
+ GET: /fruit?id=1 // id = 1
402
+ GET: /fruit?isActived=[eq,1] // isActived = 1
403
+ GET: /fruit?fruitName=[like,Banana%] // fruitName LIKE 'Banana%' (Not allow with date, time)
404
+ GET: /fruit?cost=[gt,50]&qty=[lt,10] // cost > 50 AND qty < 10
405
+ GET: /fruit/10/0?qty=[lt,10] // qty < 10 LIMIT 0,10
406
+
407
+ // Grouping
408
+ GET: /fruit?groupby=id // GROUP BY id
409
+ GET: /fruit?groupby=[id,fruitName] // GROUP BY id, fruitName
410
+
411
+ // Ordering
412
+ GET: /fruit?oderby=id // ORDER BY id ASC
413
+ GET: /fruit?oderby=[sort,desc] // ORDER BY sort DESC
414
+ ```
415
+
416
+ For usage avariable:
417
+
418
+ ```java
419
+ // Basics conditions
420
+ 3 // = 3
421
+ [eq, 3] // = 3
422
+ [ne, 20] // != 20
423
+ [is, null] // IS NULL
424
+ [not, null] // IS NOT NULL
425
+ [or, [5, 6]] // (someField = 5) OR (someField = 6) // Not support NULL value
426
+
427
+ // Number comparisons conditions
428
+ [gt, 6] // > 6
429
+ [gte, 6] // >= 6
430
+ [lt, 10] // < 10
431
+ [lte, 10] // <= 10
432
+ [between, [6, 10]] // BETWEEN 6 AND 10
433
+ [between, [2025-01-01, 2025-04-30]] // BETWEEN '2025-01-01 00:00:00' AND '2025-04-30 23:59:59'
434
+ // When assign Datetime format will only support field datatype is `Date`, `Datetime`, `Time`
435
+
436
+ // OR You can assign Datetime like this.
437
+ [between, [2025-01-01 12:00:00, 2025-04-30 15:00:00]] // BETWEEN '2025-01-01 12:00:00' AND '2025-04-30 15:00:00'
438
+
439
+ [notBetween, [11, 15]] // NOT BETWEEN 11 AND 15
440
+
441
+ // Other operators conditions
442
+ [in, [1, 2, 3]], // IN [1, 2, 3]
443
+ [notIn, [1, 2, 3]], // NOT IN [1, 2, 3]
444
+ [like, %hat] // LIKE '%hat' (Avoid use #, % and %<Number> between wording)
445
+ // Becuase URL will be decoded it, Reccommand use startsWith, endsWith and substring when you need assing Number value)
446
+ // And NOT SUPPORT field datatype is `date`, `datetime`, `time`. Should be use with datatype is `String` or `Number` it work!.
447
+
448
+ [notLike, %hat] // NOT LIKE '%hat'
449
+ [startsWith, hat] // LIKE 'hat%'
450
+ [endsWith, hat] // LIKE '%hat'
451
+ [substring, hat] // LIKE '%hat%'
452
+
453
+ // Grouping
454
+ groupby=id // GROUP BY id
455
+ groupby=[id] // ORDER BY id
456
+ groupby=[id, fruitName] // ORDER BY id, fruitName
457
+
458
+ // Ordering
459
+ oderby=id // ORDER BY id ASC (Basic usage default Ascending)
460
+ oderby=[id, asc] // ORDER BY id ASC
461
+ oderby=[id, desc] // ORDER BY id ASC
462
+ oderby=[[id, desc], [sort, asc]] // ORDER BY id DESC, sort ASC
463
+ ```
464
+
416
465
  ## # Transactions
417
466
 
418
467
  Sequelize does not use transactions by default. However, for production-ready usage of Sequelize, you should definitely configure Sequelize to use transactions.
@@ -500,7 +549,306 @@ Fruit.transaction(
500
549
  });
501
550
  ```
502
551
 
503
- ## # Generate Helpers ###
552
+ # Endpoints
553
+
554
+ The `endpoints` keep the endpoints basic request files currently support `GET`, `POST`, `PUT`, `PATCH` and `DELETE`.
555
+
556
+ So, you might create new endpoints with constant `endpoint` object variable in `src/endpoints/` folder and file neme must be end with `-endpoints.js`
557
+
558
+ ```sh
559
+ $ beech make endpointName
560
+ ```
561
+ You might using [special] `-R, --require` for choose Model(s) used for that endpoint.
562
+
563
+ ***For Example :***
564
+
565
+ 📂 endpoints/fruit-endpoints.js
566
+ ```js
567
+ // Require Model schema, Function & Others
568
+ const { Fruit } = require("@/models/Fruit");
569
+
570
+ exports.init = () => {
571
+
572
+ // GET method
573
+ endpoint.get("/fruit", Credentials, async (req, res) => {
574
+ // example call Fruit model for get data
575
+ res.json({
576
+ code: 200,
577
+ status: "SUCCESS",
578
+ results: await Fruit.findAll();
579
+ });
580
+ });
581
+
582
+
583
+ // POST method
584
+ endpoint.post("/fruit", Credentials, (req, res) => {
585
+ // @response
586
+ res.json({
587
+ code: 200,
588
+ status: "SUCCESS",
589
+ message: "POST request at /fruit",
590
+ result: {
591
+ id: req.body.id,
592
+ name: req.body.name,
593
+ },
594
+ });
595
+ });
596
+
597
+
598
+ // PUT method
599
+ endpoint.put("/fruit/:id", Credentials, (req, res) => {
600
+ // @response
601
+ res.json({
602
+ code: 200,
603
+ status: "SUCCESS",
604
+ message: "PUT request at /fruit/" + req.params.id,
605
+ });
606
+ });
607
+
608
+
609
+ // DELETE method
610
+ endpoint.delete("/fruit/:id", Credentials, (req, res) => {
611
+ // @response
612
+ res.json({
613
+ code: 200,
614
+ status: "SUCCESS",
615
+ message: "DELETE request at /fruit/" + req.params.id,
616
+ });
617
+ });
618
+
619
+ ...
620
+
621
+ }
622
+ ```
623
+
624
+ # JWT Broken Role
625
+
626
+ The **JWT Broken Role** mechanism provides a flexible way to bypass or override role-based authorization rules when using JWT.
627
+
628
+ #### It can be applied in three different levels, depending on your use case.
629
+
630
+ | Level | Scope | Best For |
631
+ |:--------------------------------|:------------------------|:--------------------------------|
632
+ | Global (``passport.config.js``) | All endpoints | Common authorization exceptions |
633
+ | Model-level options | Per model & HTTP method | Structured, reusable rules |
634
+ | Endpoint middleware | Single endpoint | Custom or special cases |
635
+
636
+ This multi-layer approach allows you to design **secure, flexible, and maintainable JWT authorization flows**.
637
+
638
+ ### 1. Global Configuration (passport.config.js)
639
+
640
+ You can define global JWT Broken Role rules that apply to all endpoints by configuring them in ``passport.config.js``.
641
+ ```js
642
+ module.exports = {
643
+ // Enable JWT authentication
644
+ jwt_allow: true,
645
+
646
+ ...
647
+
648
+ // Global JWT broken role configuration
649
+ jwt_broken_role: [
650
+ {
651
+ role: [0, 2, 4],
652
+ email: "john.doe@company.com",
653
+ }, // Basic role matching
654
+
655
+ {
656
+ role: { $in: [0, 2, 4] },
657
+ email: { $regex: /@company\.com$/ },
658
+ }, // Advanced matching using operators
659
+ ],
660
+
661
+ ...
662
+ };
663
+ ```
664
+
665
+ **Use cases**
666
+
667
+ - Apply common authorization exceptions across the entire application
668
+ - Support both simple role arrays and advanced operators (``$in``, ``$regex``, etc.)
669
+
670
+ ### 2. Model-Level Configuration (Per HTTP Method)
671
+
672
+ You can configure JWT and Broken Role rules per model and per HTTP method using model options.
673
+
674
+ 📂 src/models/Fruit.js
675
+ ```js
676
+ Fruit.options = {
677
+ ...
678
+
679
+ // Auto-endpoint configuration by HTTP method
680
+ defaultEndpoint: {
681
+ GET: true, // Enable auto-generated GET endpoint
682
+
683
+ POST: {
684
+ allow: true,
685
+ jwt: {
686
+ allow: true,
687
+ broken_role: [
688
+ { role: [5, 6] },
689
+ ],
690
+ },
691
+ },
692
+
693
+ PATCH: {
694
+ allow: true,
695
+ jwt: {
696
+ allow: true,
697
+ broken_role: [
698
+ { role: [5, 6, 9] },
699
+ { department: "IT" },
700
+ ],
701
+ },
702
+ },
703
+
704
+ DELETE: false, // Disable auto-generated DELETE endpoint
705
+ },
706
+
707
+ ...
708
+ };
709
+ ```
710
+
711
+ **Use cases**
712
+
713
+ - Fine-grained access control per HTTP method
714
+ - Different role requirements for POST, PATCH, etc.
715
+ - Combine role-based and attribute-based conditions
716
+
717
+ ### 3. Endpoint-Level Configuration (Credentials Middleware)
718
+
719
+ For maximum flexibility, you can define Broken Role rules directly on a specific endpoint using the Credentials middleware.
720
+
721
+ 📂 endpoints/custom-fruit-endpoints.js
722
+ ```js
723
+ const { Fruit } = require("@/models/Fruit");
724
+
725
+ endpoint.delete(
726
+ "/destroy-fruit-by-id/:id",
727
+ Credentials([{ role: [5, 9] }]),
728
+ async (req, res) => {
729
+
730
+ // Only JWT tokens with role level 5 or 9 are allowed
731
+
732
+ const deleted = await Fruit.destroy({
733
+ where: {
734
+ id: req.params.id,
735
+ },
736
+ });
737
+
738
+ console.log("result:", deleted);
739
+
740
+ // @response
741
+ }
742
+ );
743
+ ```
744
+
745
+ **Use cases**
746
+
747
+ - One-off or custom endpoints
748
+ - Highly specific authorization rules
749
+ - Override global or model-level behavior when necessary
750
+
751
+ ## Supported Basic & Operators Usage
752
+
753
+ The JWT Broken Role system supports both basic value matching and advanced operators for flexible authorization rules.
754
+
755
+ | Operator | Meaning | Description |
756
+ |:---------|:-------------------|:--------------------------------------------------------------|
757
+ | $eq | equal | Matches when the value is equal |
758
+ | $ne | not equal | Matches when the value is not equal |
759
+ | $in | value IN array | Matches when the value exists in the specified array |
760
+ | $not | value NOT IN array | Matches when the value does not exist in the specified array |
761
+ | $regex | regex match | Matches using a regular expression |
762
+ | $fn | custom function | Matches using a custom evaluation function |
763
+
764
+ ## Evaluation Logic (Very Important !)
765
+ ```js
766
+ [
767
+ { rule1 AND rule1 },
768
+ { rule2 AND rule2 }
769
+ ]
770
+
771
+ OR
772
+ ```
773
+
774
+ ## Basic Usage for Examples :
775
+
776
+ ```js
777
+ Credentials([
778
+ { role: [9] }, // Only role check
779
+ { email: 'a@b.com' }, // OR email
780
+ ])
781
+
782
+ // Common Matching Patterns
783
+ { role: [1, 2, 3] } // IN
784
+ { role: 1 } // Equal
785
+ { email: 'a@b.com' }
786
+ { department: 'IT' }
787
+ { status: ['active'] } // Dynamic key
788
+ ```
789
+
790
+ ## Operators Usage for Examples :
791
+
792
+ ```js
793
+ // Equal with Role
794
+ Credentials([
795
+ {
796
+ role: { $eq: [1, 2, 5] }
797
+ }
798
+ ])
799
+
800
+ // Not Equal with Role
801
+ Credentials([
802
+ {
803
+ role: { $ne: [0, 3] }
804
+ }
805
+ ])
806
+
807
+ // Regex with Email domain
808
+ Credentials([
809
+ {
810
+ email: { $regex: /@company\.com$/ }
811
+ }
812
+ ])
813
+
814
+ // IN with Role
815
+ Credentials([
816
+ {
817
+ role: { $in: [1, 2, 4] }
818
+ }
819
+ ])
820
+
821
+ // NOT IN with Role
822
+ Credentials([
823
+ {
824
+ role: { $not: [0, 3] }
825
+ }
826
+ ])
827
+
828
+ // Multiple OR rules
829
+ Credentials([
830
+ {
831
+ role: { $in: [1] },
832
+ email: 'john.doe@company.com'
833
+ },
834
+ // OR
835
+ {
836
+ role: { $in: [4] },
837
+ email: { $regex: /@company\.com$/ }
838
+ },
839
+ ])
840
+
841
+ // Custom Function
842
+ Credentials([
843
+ {
844
+ role: {
845
+ $fn: (value, user) => value >= 4 && user.department === 'IT'
846
+ }
847
+ }
848
+ ])
849
+ ```
850
+
851
+ # Helpers
504
852
 
505
853
  The `helpers` keep the files of functions for process specific something in the project. So, you might create the `helpers` in path `src/helpers` folder.
506
854
 
@@ -508,9 +856,9 @@ The `helpers` keep the files of functions for process specific something in the
508
856
  $ beech make helperName --helper
509
857
  ```
510
858
 
511
- ***Example:*** Text editor helper.
859
+ ***For Example :***
512
860
 
513
- 📂 TextEditor.js
861
+ 📂 helpers/TextEditor.js
514
862
  ```js
515
863
  module.exports = {
516
864
 
@@ -598,7 +946,7 @@ module.exports = {
598
946
 
599
947
  };
600
948
  ```
601
-
949
+ ### Request Token
602
950
  **Authentication structure :** Simple ``users`` table:
603
951
  ```
604
952
  ==============================================================
@@ -647,10 +995,10 @@ headers: Authorization: Bearer <your_token>
647
995
  }
648
996
  ```
649
997
 
650
- # Beech Two Factor (2FA)
998
+ # Beech Guard
651
999
  You can easy using 2 Factor authenticate with ```guard_field``` inside ```passport.config.js``` file and add your Guard field ex: ```2fa``` field for Authenticate Conditions.
652
1000
 
653
- ## # Usage guard (2FA, Other)
1001
+ ## # Guard (2FA, Other)
654
1002
 
655
1003
  📂 passport.config.js
656
1004
  ```js
@@ -659,7 +1007,7 @@ module.exports = {
659
1007
 
660
1008
  guard: {
661
1009
  // Other fields add for authenticate, exmaple ["pin", "hint", "2fa"]
662
- guard_field: ["2fa"], 👈 // your feild guard.
1010
+ guard_field: ["2fa"], 👈 // your feild guard. (Disabled to remove it.)
663
1011
 
664
1012
  ...
665
1013
  },
@@ -680,7 +1028,7 @@ module.exports = {
680
1028
  guard: {
681
1029
  ...
682
1030
 
683
- // Advanced guard jwt request (needed some logical from front-end)
1031
+ // Advanced guard to Request (Needed some logical from front-end)
684
1032
  advanced_guard: {
685
1033
  allow: false, 👈 // advanced guard allow for All Endpoint.
686
1034
  entity: "", // default entity `timing`
@@ -709,26 +1057,42 @@ $ npm install --save beech-auth0 moment
709
1057
  # Yarn
710
1058
  $ yarn add beech-auth0 moment
711
1059
  ```
712
- Now! you can add some logic.
1060
+ Now! you can add some logic like this.
1061
+
1062
+ - Import packages
1063
+
713
1064
  ```js
1065
+ // CommonJS
714
1066
  const { Auth0 } = require("beech-auth0");
715
1067
  const moment = require("moment");
716
1068
 
1069
+ // ES6
1070
+ import { Auth0 } from "beech-auth0";
1071
+ import moment from "moment";
1072
+ ```
1073
+
1074
+ - Get unix time with momentJS
1075
+
1076
+ ```js
717
1077
  // Get UNIX TIME with moment
718
1078
  let unix_time = moment().unix();
1079
+ ```
719
1080
 
1081
+ - Get hashing with Beech Auth0
1082
+
1083
+ ```js
720
1084
  // Auth0 Policy.
721
1085
  Auth0(unix_time, 'your_advance_guard_secret', (error, hashing) => {
722
-
1086
+
723
1087
  // Your XHR request for All Endpoint.
724
1088
  POST: "/authentication"
725
- headers: timing: hashing, 👈 // Assign advance guard entity to headers with callback hashing.
1089
+ headers: { timing: hashing } 👈 // Assign advance guard entity to headers with callback hashing.
726
1090
 
727
1091
  });
728
1092
 
729
1093
  ```
730
1094
 
731
- ## # Beech User Auth Managements ###
1095
+ ## # Beech User Authentication Managements ###
732
1096
  You can easy management `users` data with Beech, Only ```Store, Update``` NO ```Delete```, Anything you can make DELETE endpoint by yourself
733
1097
 
734
1098
  ```js
@@ -1014,8 +1378,6 @@ endpoint.get("/banana", specificDup1, (req, res) => {
1014
1378
  ...
1015
1379
  ```
1016
1380
 
1017
-
1018
-
1019
1381
  # Databases managements
1020
1382
 
1021
1383
  ## # Migrations & Seeder
@@ -1050,6 +1412,7 @@ Before continuing further we will need to tell CLI how to connect to database. T
1050
1412
  "password": null,
1051
1413
  "database": "database_development",
1052
1414
  "host": "127.0.0.1",
1415
+ "port": 3306, // IF your another port
1053
1416
  "dialect": "mysql"
1054
1417
  },
1055
1418
  "test": {
@@ -1098,7 +1461,12 @@ Until this step, we haven't inserted anything into the database. We have just cr
1098
1461
 
1099
1462
  - **Migrate Down** : you can use `db:migrate:undo`, this command will revert most recent migration.
1100
1463
  ```sh
1464
+ // Step to undo
1101
1465
  $ npx sequelize-cli db:migrate:undo
1466
+
1467
+ // All to undo
1468
+ $ npx sequelize-cli db:migrate:undo:all
1469
+
1102
1470
  ```
1103
1471
 
1104
1472
  ## # Creating First Seeder
@@ -1147,9 +1515,9 @@ Test using [Jest](https://jestjs.io/en/) for testing the project. Jest is a deli
1147
1515
 
1148
1516
  So, When you make the new endpoints it's automatic create test file end with `.spec.js` in `__test__` folder with constant `baseUrl` variable and `axios` package.
1149
1517
 
1150
- Example endpoints testing :
1518
+ ***For Example :***
1151
1519
 
1152
- 📂 fruit-endpoints.spec.js
1520
+ 📂 \_\_test\_\_/unit/endpoints/fruit-endpoints.spec.js
1153
1521
  ```js
1154
1522
  const endpoint = baseUrl.concat("/fruit");
1155
1523
 
@@ -1180,7 +1548,7 @@ Docker builds images automatically by reading the instructions from a Dockerfile
1180
1548
 
1181
1549
  📂 Dockerfile
1182
1550
  ```js
1183
- FROM node:14.19-alpine
1551
+ FROM node:18-alpine
1184
1552
  ENV NODE_ENV=production
1185
1553
  WORKDIR /usr/src/api
1186
1554
  COPY ["package.json", "package-lock.json*", "./"]