├── .gitignore
├── CMD.md
├── README.md
├── api-json.json
├── drizzle.config.json
├── img
├── data-flow.png
├── diagram.png
└── neon.svg
├── migrations
├── 0000_remarkable_katie_power.sql
├── 0001_mute_true_believers.sql
├── 0002_common_tyger_tiger.sql
├── 0003_secret_forge.sql
└── meta
│ ├── 0000_snapshot.json
│ ├── 0001_snapshot.json
│ ├── 0002_snapshot.json
│ ├── 0003_snapshot.json
│ └── _journal.json
├── package.json
├── pnpm-lock.yaml
├── src
├── config
│ ├── env.ts
│ └── permissions.ts
├── db
│ ├── index.ts
│ └── schema.ts
├── main.ts
├── modules
│ ├── applications
│ │ ├── applications.controllers.ts
│ │ ├── applications.routes.ts
│ │ ├── applications.schemas.ts
│ │ └── applications.services.ts
│ ├── roles
│ │ ├── role.controllers.ts
│ │ ├── role.routes.ts
│ │ ├── role.schemas.ts
│ │ └── roles.services.ts
│ └── users
│ │ ├── users.controllers.ts
│ │ ├── users.routes.ts
│ │ ├── users.schemas.ts
│ │ └── users.services.ts
└── utils
│ ├── logger.ts
│ └── server.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
--------------------------------------------------------------------------------
/CMD.md:
--------------------------------------------------------------------------------
1 | ## Install dependencies
2 |
3 | ```bash
4 | pnpm add argon2 drizzle-orm pg pino pino-pretty zennv zod jsonwebtoken fastify-zod fastify-guard fastify
5 | ```
6 |
7 | ## Install dev dependencies
8 | ```bash
9 | pnpm add zod-to-json-schema @types/jsonwebtoken typescript tsx drizzle-kit @types/pg -D
10 | ```
11 | ## Initialize TypeScript
12 | ```bash
13 | npx tsc --init
14 | ```
15 |
16 | ## Run migrations
17 | ```bash
18 | pnpm run migrate
19 | ```
20 |
21 | ## Run the application
22 | ```bash
23 | pnpm run dev
24 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Multi Tenant Role Based Access Control (RBAC) Authentication API
2 |
3 | ## Sponsor
4 |
5 |
6 | Thank you to [Neon](https://bit.ly/tomdoestech) for sponsoring this video!
7 |
8 | ## Features
9 | * Create an application
10 | * Register a user for an application
11 | * Login
12 | * Create a role
13 | * Assign a role to a user
14 |
15 | * Check user permissions with a guard
16 |
17 | ## What are we using?
18 | * [Drizzle ORM](https://github.com/drizzle-team/drizzle-orm)
19 | * [Fastify](https://www.fastify.io/)
20 | * [PostgreSQL](https://www.postgresql.org/)
21 | * [TypeScript](https://www.typescriptlang.org/)
22 |
23 | ## What you'll need
24 | * Editor - [VS Code](https://code.visualstudio.com/download)
25 | * Node.js - [Download](https://nodejs.org/en/download/)
26 | * A database - [PostgreSQL by Neon](https://bit.ly/tomdoestech)
27 | * A REST client - [Thunder Client](https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client)
28 |
29 | ## What you will learn
30 | * How to create a multi tenant application
31 | * How to create a role based access control system
32 | * Some basic relational database concepts
33 | * A nice and neat file structure for backend services
34 | * TypeScript
35 | * Fastify
36 | * RESTful API design
37 | * How to use Drizzle ORM
38 |
39 | ## Data structure
40 |
41 |
42 | ## Data flow
43 |
44 |
45 | ## Video structure
46 | 1. Setup the initial application
47 | 2. Create a database with Neon
48 | 3. Create database schemas
49 | 4. Run migrations
50 | 5. Register an application
51 | 6. Register a user
52 | 7. Login
53 | 8. Create a role
54 | 9. Assign a role to a user
55 | 10. Check user permissions with a guard
56 |
57 | ## Helpful files
58 | * CMD - Commands used in the video
59 | * api.json - Thunder Client collection
60 |
61 | ## Tips
62 | * Infer the applicationId from the JWT where possible
63 | * Include the applicationId in queries
64 |
--------------------------------------------------------------------------------
/api-json.json:
--------------------------------------------------------------------------------
1 | {
2 | "client": "Thunder Client",
3 | "collectionName": "User API",
4 | "dateExported": "2023-05-17T08:03:32.677Z",
5 | "version": "1.1",
6 | "folders": [],
7 | "requests": [
8 | {
9 | "_id": "5f4eb36c-c5fe-4bd7-9e68-76c25486d4fb",
10 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
11 | "containerId": "",
12 | "name": "Create application",
13 | "url": "{{host}}/api/applications",
14 | "method": "POST",
15 | "sortNum": 5000,
16 | "created": "2023-04-29T21:56:06.725Z",
17 | "modified": "2023-05-03T10:47:42.539Z",
18 | "headers": [],
19 | "params": [],
20 | "body": {
21 | "type": "json",
22 | "raw": "{\n \"name\":\"App three\",\n \"description\":\"hello\"\n}",
23 | "form": []
24 | },
25 | "tests": []
26 | },
27 | {
28 | "_id": "a1834b3a-fea5-4117-961b-c4ae62c839b6",
29 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
30 | "containerId": "",
31 | "name": "Get applications",
32 | "url": "http://0.0.0.0:3000/api/applications",
33 | "method": "GET",
34 | "sortNum": 10000,
35 | "created": "2023-04-29T21:55:41.812Z",
36 | "modified": "2023-04-29T22:06:13.213Z",
37 | "headers": [],
38 | "params": [],
39 | "body": {
40 | "type": "formdata",
41 | "raw": "",
42 | "form": [],
43 | "files": [
44 | {
45 | "name": "",
46 | "value": "/home/tom/projects/media-api/test/mailchimp-6kajEqr84iY-unsplash.jpg"
47 | }
48 | ]
49 | },
50 | "tests": []
51 | },
52 | {
53 | "_id": "ad7da438-77ec-42c0-996b-c376e70fe555",
54 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
55 | "containerId": "",
56 | "name": "Get me",
57 | "url": "http://0.0.0.0:3000/api/users/me",
58 | "method": "GET",
59 | "sortNum": 15000,
60 | "created": "2023-05-05T08:43:58.471Z",
61 | "modified": "2023-05-05T08:44:48.938Z",
62 | "headers": [
63 | {
64 | "name": "Authorization",
65 | "value": "{{authorization}}"
66 | }
67 | ],
68 | "params": [],
69 | "body": {
70 | "type": "formdata",
71 | "raw": "",
72 | "form": [],
73 | "files": [
74 | {
75 | "name": "",
76 | "value": "/home/tom/projects/media-api/test/mailchimp-6kajEqr84iY-unsplash.jpg"
77 | }
78 | ]
79 | },
80 | "tests": []
81 | },
82 | {
83 | "_id": "35e68843-0c17-45db-a2af-e109b688cfd5",
84 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
85 | "containerId": "",
86 | "name": "Create user 1",
87 | "url": "{{host}}/api/users",
88 | "method": "POST",
89 | "sortNum": 20000,
90 | "created": "2023-04-29T21:55:53.376Z",
91 | "modified": "2023-05-03T10:42:08.788Z",
92 | "headers": [],
93 | "params": [],
94 | "body": {
95 | "type": "json",
96 | "raw": "{\n \"email\": \"{{email}}\",\n \"name\": \"Jane Doe\",\n \"password\": \"{{password}}\",\n \"applicationId\": \"{{applicationId}}\",\n \"initialUser\": true\n}",
97 | "form": []
98 | },
99 | "tests": []
100 | },
101 | {
102 | "_id": "04983f5e-8ac4-4666-8a3e-937e45d3e644",
103 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
104 | "containerId": "",
105 | "name": "Create user 2",
106 | "url": "{{host}}/api/users",
107 | "method": "POST",
108 | "sortNum": 30000,
109 | "created": "2023-05-05T08:41:15.855Z",
110 | "modified": "2023-05-05T08:47:29.408Z",
111 | "headers": [],
112 | "params": [],
113 | "body": {
114 | "type": "json",
115 | "raw": "{\n \"email\": \"{{email2}}\",\n \"name\": \"Second User\",\n \"password\": \"{{password}}\",\n \"applicationId\": \"{{applicationId}}\"\n}",
116 | "form": []
117 | },
118 | "tests": []
119 | },
120 | {
121 | "_id": "724af579-846c-4ca1-b657-ee15b8983e31",
122 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
123 | "containerId": "",
124 | "name": "Login",
125 | "url": "{{host}}/api/users/login",
126 | "method": "POST",
127 | "sortNum": 35000,
128 | "created": "2023-05-02T07:59:27.052Z",
129 | "modified": "2023-05-14T08:27:40.373Z",
130 | "headers": [],
131 | "params": [],
132 | "body": {
133 | "type": "json",
134 | "raw": "{\n \"email\": \"{{email}}\",\n \"password\": \"{{password}}\",\n \"applicationId\": \"{{applicationId}}\"\n}",
135 | "form": []
136 | },
137 | "tests": []
138 | },
139 | {
140 | "_id": "5681c22b-e87b-4391-94c6-057567dbeef5",
141 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
142 | "containerId": "",
143 | "name": "Create role",
144 | "url": "{{host}}/api/roles",
145 | "method": "POST",
146 | "sortNum": 40000,
147 | "created": "2023-04-29T21:56:11.563Z",
148 | "modified": "2023-05-03T10:52:53.455Z",
149 | "headers": [
150 | {
151 | "name": "Authorization",
152 | "value": "{{authorization}}"
153 | }
154 | ],
155 | "params": [],
156 | "body": {
157 | "type": "json",
158 | "raw": "{\n \"applicationId\": \"{{applicationId}}\",\n \"permissions\": [\n \"role:read\",\n \"role:write\"\n ],\n \"name\": \"Some role\"\n}",
159 | "form": []
160 | },
161 | "tests": []
162 | },
163 | {
164 | "_id": "f44270d5-013b-4a4c-8d0b-bba15e0414d9",
165 | "colId": "ef71f144-c718-4fd5-874e-e9c14db58c6c",
166 | "containerId": "",
167 | "name": "Assign role to user",
168 | "url": "http://0.0.0.0:3000/api/users/roles",
169 | "method": "POST",
170 | "sortNum": 55000,
171 | "created": "2023-05-03T08:55:00.372Z",
172 | "modified": "2023-05-14T08:27:37.591Z",
173 | "headers": [],
174 | "params": [],
175 | "body": {
176 | "type": "json",
177 | "raw": "{\n \"applicationId\": \"{{applicationId}}\",\n \"userId\": \"{{userId}}\",\n \"roleId\": \"5ebe38d0-ed08-4f90-924e-6684ca9eb0b3\"\n}",
178 | "form": []
179 | },
180 | "tests": []
181 | }
182 | ]
183 | }
184 |
--------------------------------------------------------------------------------
/drizzle.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "out": "./migrations",
3 | "schema": "./src/db/schema.ts",
4 | "breakpoints": false
5 | }
--------------------------------------------------------------------------------
/img/data-flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TomDoesTech/user-api/46d37be1204e94fb74c9bd947f4477a6963a85d8/img/data-flow.png
--------------------------------------------------------------------------------
/img/diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TomDoesTech/user-api/46d37be1204e94fb74c9bd947f4477a6963a85d8/img/diagram.png
--------------------------------------------------------------------------------
/img/neon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/migrations/0000_remarkable_katie_power.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS "applications" (
2 | "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3 | "name" varchar(256) NOT NULL,
4 | "created_at" timestamp DEFAULT now() NOT NULL,
5 | "updated_at" timestamp DEFAULT now() NOT NULL
6 | );
7 |
--------------------------------------------------------------------------------
/migrations/0001_mute_true_believers.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS "users" (
2 | "id" uuid DEFAULT gen_random_uuid() NOT NULL,
3 | "email" varchar(256) NOT NULL,
4 | "name" varchar(256) NOT NULL,
5 | "applicationId" uuid,
6 | "password" varchar(256) NOT NULL,
7 | "created_at" timestamp DEFAULT now() NOT NULL,
8 | "updated_at" timestamp DEFAULT now() NOT NULL
9 | );
10 | --> statement-breakpoint
11 | ALTER TABLE "users" ADD CONSTRAINT "users_email_applicationId" PRIMARY KEY("email","applicationId");
12 |
13 | DO $$ BEGIN
14 | ALTER TABLE "users" ADD CONSTRAINT "users_applicationId_applications_id_fk" FOREIGN KEY ("applicationId") REFERENCES "applications"("id") ON DELETE no action ON UPDATE no action;
15 | EXCEPTION
16 | WHEN duplicate_object THEN null;
17 | END $$;
18 |
19 | CREATE UNIQUE INDEX IF NOT EXISTS "users_id_index" ON "users" ("id");
--------------------------------------------------------------------------------
/migrations/0002_common_tyger_tiger.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS "roles" (
2 | "id" uuid DEFAULT gen_random_uuid() NOT NULL,
3 | "name" varchar(256) NOT NULL,
4 | "applicationId" uuid,
5 | "permissions" text[],
6 | "created_at" timestamp DEFAULT now() NOT NULL,
7 | "updated_at" timestamp DEFAULT now() NOT NULL
8 | );
9 | --> statement-breakpoint
10 | ALTER TABLE "roles" ADD CONSTRAINT "roles_name_applicationId" PRIMARY KEY("name","applicationId");
11 |
12 | DO $$ BEGIN
13 | ALTER TABLE "roles" ADD CONSTRAINT "roles_applicationId_applications_id_fk" FOREIGN KEY ("applicationId") REFERENCES "applications"("id") ON DELETE no action ON UPDATE no action;
14 | EXCEPTION
15 | WHEN duplicate_object THEN null;
16 | END $$;
17 |
18 | CREATE UNIQUE INDEX IF NOT EXISTS "roles_id_index" ON "roles" ("id");
--------------------------------------------------------------------------------
/migrations/0003_secret_forge.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS "usersToRoles" (
2 | "applicationId" uuid NOT NULL,
3 | "roledId" uuid NOT NULL,
4 | "userId" uuid NOT NULL
5 | );
6 | --> statement-breakpoint
7 | ALTER TABLE "usersToRoles" ADD CONSTRAINT "usersToRoles_applicationId_roledId_userId" PRIMARY KEY("applicationId","roledId","userId");
8 |
9 | DO $$ BEGIN
10 | ALTER TABLE "usersToRoles" ADD CONSTRAINT "usersToRoles_applicationId_applications_id_fk" FOREIGN KEY ("applicationId") REFERENCES "applications"("id") ON DELETE no action ON UPDATE no action;
11 | EXCEPTION
12 | WHEN duplicate_object THEN null;
13 | END $$;
14 |
15 | DO $$ BEGIN
16 | ALTER TABLE "usersToRoles" ADD CONSTRAINT "usersToRoles_roledId_roles_id_fk" FOREIGN KEY ("roledId") REFERENCES "roles"("id") ON DELETE no action ON UPDATE no action;
17 | EXCEPTION
18 | WHEN duplicate_object THEN null;
19 | END $$;
20 |
21 | DO $$ BEGIN
22 | ALTER TABLE "usersToRoles" ADD CONSTRAINT "usersToRoles_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE no action ON UPDATE no action;
23 | EXCEPTION
24 | WHEN duplicate_object THEN null;
25 | END $$;
26 |
--------------------------------------------------------------------------------
/migrations/meta/0000_snapshot.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "dialect": "pg",
4 | "id": "c4595e94-56a5-4f18-ad77-4c7f5b2e29b4",
5 | "prevId": "00000000-0000-0000-0000-000000000000",
6 | "tables": {
7 | "applications": {
8 | "name": "applications",
9 | "schema": "",
10 | "columns": {
11 | "id": {
12 | "name": "id",
13 | "type": "uuid",
14 | "primaryKey": true,
15 | "notNull": true,
16 | "default": "gen_random_uuid()"
17 | },
18 | "name": {
19 | "name": "name",
20 | "type": "varchar(256)",
21 | "primaryKey": false,
22 | "notNull": true
23 | },
24 | "created_at": {
25 | "name": "created_at",
26 | "type": "timestamp",
27 | "primaryKey": false,
28 | "notNull": true,
29 | "default": "now()"
30 | },
31 | "updated_at": {
32 | "name": "updated_at",
33 | "type": "timestamp",
34 | "primaryKey": false,
35 | "notNull": true,
36 | "default": "now()"
37 | }
38 | },
39 | "indexes": {},
40 | "foreignKeys": {},
41 | "compositePrimaryKeys": {}
42 | }
43 | },
44 | "enums": {},
45 | "schemas": {},
46 | "_meta": {
47 | "schemas": {},
48 | "tables": {},
49 | "columns": {}
50 | }
51 | }
--------------------------------------------------------------------------------
/migrations/meta/0001_snapshot.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "dialect": "pg",
4 | "id": "5054de4c-7142-47fe-81ab-c29b378c18ca",
5 | "prevId": "c4595e94-56a5-4f18-ad77-4c7f5b2e29b4",
6 | "tables": {
7 | "applications": {
8 | "name": "applications",
9 | "schema": "",
10 | "columns": {
11 | "id": {
12 | "name": "id",
13 | "type": "uuid",
14 | "primaryKey": true,
15 | "notNull": true,
16 | "default": "gen_random_uuid()"
17 | },
18 | "name": {
19 | "name": "name",
20 | "type": "varchar(256)",
21 | "primaryKey": false,
22 | "notNull": true
23 | },
24 | "created_at": {
25 | "name": "created_at",
26 | "type": "timestamp",
27 | "primaryKey": false,
28 | "notNull": true,
29 | "default": "now()"
30 | },
31 | "updated_at": {
32 | "name": "updated_at",
33 | "type": "timestamp",
34 | "primaryKey": false,
35 | "notNull": true,
36 | "default": "now()"
37 | }
38 | },
39 | "indexes": {},
40 | "foreignKeys": {},
41 | "compositePrimaryKeys": {}
42 | },
43 | "users": {
44 | "name": "users",
45 | "schema": "",
46 | "columns": {
47 | "id": {
48 | "name": "id",
49 | "type": "uuid",
50 | "primaryKey": false,
51 | "notNull": true,
52 | "default": "gen_random_uuid()"
53 | },
54 | "email": {
55 | "name": "email",
56 | "type": "varchar(256)",
57 | "primaryKey": false,
58 | "notNull": true
59 | },
60 | "name": {
61 | "name": "name",
62 | "type": "varchar(256)",
63 | "primaryKey": false,
64 | "notNull": true
65 | },
66 | "applicationId": {
67 | "name": "applicationId",
68 | "type": "uuid",
69 | "primaryKey": false,
70 | "notNull": false
71 | },
72 | "password": {
73 | "name": "password",
74 | "type": "varchar(256)",
75 | "primaryKey": false,
76 | "notNull": true
77 | },
78 | "created_at": {
79 | "name": "created_at",
80 | "type": "timestamp",
81 | "primaryKey": false,
82 | "notNull": true,
83 | "default": "now()"
84 | },
85 | "updated_at": {
86 | "name": "updated_at",
87 | "type": "timestamp",
88 | "primaryKey": false,
89 | "notNull": true,
90 | "default": "now()"
91 | }
92 | },
93 | "indexes": {
94 | "users_id_index": {
95 | "name": "users_id_index",
96 | "columns": [
97 | "id"
98 | ],
99 | "isUnique": true
100 | }
101 | },
102 | "foreignKeys": {
103 | "users_applicationId_applications_id_fk": {
104 | "name": "users_applicationId_applications_id_fk",
105 | "tableFrom": "users",
106 | "tableTo": "applications",
107 | "columnsFrom": [
108 | "applicationId"
109 | ],
110 | "columnsTo": [
111 | "id"
112 | ],
113 | "onDelete": "no action",
114 | "onUpdate": "no action"
115 | }
116 | },
117 | "compositePrimaryKeys": {
118 | "users_email_applicationId": {
119 | "name": "users_email_applicationId",
120 | "columns": [
121 | "email",
122 | "applicationId"
123 | ]
124 | }
125 | }
126 | }
127 | },
128 | "enums": {},
129 | "schemas": {},
130 | "_meta": {
131 | "schemas": {},
132 | "tables": {},
133 | "columns": {}
134 | }
135 | }
--------------------------------------------------------------------------------
/migrations/meta/0002_snapshot.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "dialect": "pg",
4 | "id": "76e5b141-f614-4188-a33b-368f74e8b2fe",
5 | "prevId": "5054de4c-7142-47fe-81ab-c29b378c18ca",
6 | "tables": {
7 | "applications": {
8 | "name": "applications",
9 | "schema": "",
10 | "columns": {
11 | "id": {
12 | "name": "id",
13 | "type": "uuid",
14 | "primaryKey": true,
15 | "notNull": true,
16 | "default": "gen_random_uuid()"
17 | },
18 | "name": {
19 | "name": "name",
20 | "type": "varchar(256)",
21 | "primaryKey": false,
22 | "notNull": true
23 | },
24 | "created_at": {
25 | "name": "created_at",
26 | "type": "timestamp",
27 | "primaryKey": false,
28 | "notNull": true,
29 | "default": "now()"
30 | },
31 | "updated_at": {
32 | "name": "updated_at",
33 | "type": "timestamp",
34 | "primaryKey": false,
35 | "notNull": true,
36 | "default": "now()"
37 | }
38 | },
39 | "indexes": {},
40 | "foreignKeys": {},
41 | "compositePrimaryKeys": {}
42 | },
43 | "roles": {
44 | "name": "roles",
45 | "schema": "",
46 | "columns": {
47 | "id": {
48 | "name": "id",
49 | "type": "uuid",
50 | "primaryKey": false,
51 | "notNull": true,
52 | "default": "gen_random_uuid()"
53 | },
54 | "name": {
55 | "name": "name",
56 | "type": "varchar(256)",
57 | "primaryKey": false,
58 | "notNull": true
59 | },
60 | "applicationId": {
61 | "name": "applicationId",
62 | "type": "uuid",
63 | "primaryKey": false,
64 | "notNull": false
65 | },
66 | "permissions": {
67 | "name": "permissions",
68 | "type": "text[]",
69 | "primaryKey": false,
70 | "notNull": false
71 | },
72 | "created_at": {
73 | "name": "created_at",
74 | "type": "timestamp",
75 | "primaryKey": false,
76 | "notNull": true,
77 | "default": "now()"
78 | },
79 | "updated_at": {
80 | "name": "updated_at",
81 | "type": "timestamp",
82 | "primaryKey": false,
83 | "notNull": true,
84 | "default": "now()"
85 | }
86 | },
87 | "indexes": {
88 | "roles_id_index": {
89 | "name": "roles_id_index",
90 | "columns": [
91 | "id"
92 | ],
93 | "isUnique": true
94 | }
95 | },
96 | "foreignKeys": {
97 | "roles_applicationId_applications_id_fk": {
98 | "name": "roles_applicationId_applications_id_fk",
99 | "tableFrom": "roles",
100 | "tableTo": "applications",
101 | "columnsFrom": [
102 | "applicationId"
103 | ],
104 | "columnsTo": [
105 | "id"
106 | ],
107 | "onDelete": "no action",
108 | "onUpdate": "no action"
109 | }
110 | },
111 | "compositePrimaryKeys": {
112 | "roles_name_applicationId": {
113 | "name": "roles_name_applicationId",
114 | "columns": [
115 | "name",
116 | "applicationId"
117 | ]
118 | }
119 | }
120 | },
121 | "users": {
122 | "name": "users",
123 | "schema": "",
124 | "columns": {
125 | "id": {
126 | "name": "id",
127 | "type": "uuid",
128 | "primaryKey": false,
129 | "notNull": true,
130 | "default": "gen_random_uuid()"
131 | },
132 | "email": {
133 | "name": "email",
134 | "type": "varchar(256)",
135 | "primaryKey": false,
136 | "notNull": true
137 | },
138 | "name": {
139 | "name": "name",
140 | "type": "varchar(256)",
141 | "primaryKey": false,
142 | "notNull": true
143 | },
144 | "applicationId": {
145 | "name": "applicationId",
146 | "type": "uuid",
147 | "primaryKey": false,
148 | "notNull": false
149 | },
150 | "password": {
151 | "name": "password",
152 | "type": "varchar(256)",
153 | "primaryKey": false,
154 | "notNull": true
155 | },
156 | "created_at": {
157 | "name": "created_at",
158 | "type": "timestamp",
159 | "primaryKey": false,
160 | "notNull": true,
161 | "default": "now()"
162 | },
163 | "updated_at": {
164 | "name": "updated_at",
165 | "type": "timestamp",
166 | "primaryKey": false,
167 | "notNull": true,
168 | "default": "now()"
169 | }
170 | },
171 | "indexes": {
172 | "users_id_index": {
173 | "name": "users_id_index",
174 | "columns": [
175 | "id"
176 | ],
177 | "isUnique": true
178 | }
179 | },
180 | "foreignKeys": {
181 | "users_applicationId_applications_id_fk": {
182 | "name": "users_applicationId_applications_id_fk",
183 | "tableFrom": "users",
184 | "tableTo": "applications",
185 | "columnsFrom": [
186 | "applicationId"
187 | ],
188 | "columnsTo": [
189 | "id"
190 | ],
191 | "onDelete": "no action",
192 | "onUpdate": "no action"
193 | }
194 | },
195 | "compositePrimaryKeys": {
196 | "users_email_applicationId": {
197 | "name": "users_email_applicationId",
198 | "columns": [
199 | "email",
200 | "applicationId"
201 | ]
202 | }
203 | }
204 | }
205 | },
206 | "enums": {},
207 | "schemas": {},
208 | "_meta": {
209 | "schemas": {},
210 | "tables": {},
211 | "columns": {}
212 | }
213 | }
--------------------------------------------------------------------------------
/migrations/meta/0003_snapshot.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "dialect": "pg",
4 | "id": "3919a618-0315-4ce5-81f1-df247d2d5099",
5 | "prevId": "76e5b141-f614-4188-a33b-368f74e8b2fe",
6 | "tables": {
7 | "applications": {
8 | "name": "applications",
9 | "schema": "",
10 | "columns": {
11 | "id": {
12 | "name": "id",
13 | "type": "uuid",
14 | "primaryKey": true,
15 | "notNull": true,
16 | "default": "gen_random_uuid()"
17 | },
18 | "name": {
19 | "name": "name",
20 | "type": "varchar(256)",
21 | "primaryKey": false,
22 | "notNull": true
23 | },
24 | "created_at": {
25 | "name": "created_at",
26 | "type": "timestamp",
27 | "primaryKey": false,
28 | "notNull": true,
29 | "default": "now()"
30 | },
31 | "updated_at": {
32 | "name": "updated_at",
33 | "type": "timestamp",
34 | "primaryKey": false,
35 | "notNull": true,
36 | "default": "now()"
37 | }
38 | },
39 | "indexes": {},
40 | "foreignKeys": {},
41 | "compositePrimaryKeys": {}
42 | },
43 | "roles": {
44 | "name": "roles",
45 | "schema": "",
46 | "columns": {
47 | "id": {
48 | "name": "id",
49 | "type": "uuid",
50 | "primaryKey": false,
51 | "notNull": true,
52 | "default": "gen_random_uuid()"
53 | },
54 | "name": {
55 | "name": "name",
56 | "type": "varchar(256)",
57 | "primaryKey": false,
58 | "notNull": true
59 | },
60 | "applicationId": {
61 | "name": "applicationId",
62 | "type": "uuid",
63 | "primaryKey": false,
64 | "notNull": false
65 | },
66 | "permissions": {
67 | "name": "permissions",
68 | "type": "text[]",
69 | "primaryKey": false,
70 | "notNull": false
71 | },
72 | "created_at": {
73 | "name": "created_at",
74 | "type": "timestamp",
75 | "primaryKey": false,
76 | "notNull": true,
77 | "default": "now()"
78 | },
79 | "updated_at": {
80 | "name": "updated_at",
81 | "type": "timestamp",
82 | "primaryKey": false,
83 | "notNull": true,
84 | "default": "now()"
85 | }
86 | },
87 | "indexes": {
88 | "roles_id_index": {
89 | "name": "roles_id_index",
90 | "columns": [
91 | "id"
92 | ],
93 | "isUnique": true
94 | }
95 | },
96 | "foreignKeys": {
97 | "roles_applicationId_applications_id_fk": {
98 | "name": "roles_applicationId_applications_id_fk",
99 | "tableFrom": "roles",
100 | "tableTo": "applications",
101 | "columnsFrom": [
102 | "applicationId"
103 | ],
104 | "columnsTo": [
105 | "id"
106 | ],
107 | "onDelete": "no action",
108 | "onUpdate": "no action"
109 | }
110 | },
111 | "compositePrimaryKeys": {
112 | "roles_name_applicationId": {
113 | "name": "roles_name_applicationId",
114 | "columns": [
115 | "name",
116 | "applicationId"
117 | ]
118 | }
119 | }
120 | },
121 | "users": {
122 | "name": "users",
123 | "schema": "",
124 | "columns": {
125 | "id": {
126 | "name": "id",
127 | "type": "uuid",
128 | "primaryKey": false,
129 | "notNull": true,
130 | "default": "gen_random_uuid()"
131 | },
132 | "email": {
133 | "name": "email",
134 | "type": "varchar(256)",
135 | "primaryKey": false,
136 | "notNull": true
137 | },
138 | "name": {
139 | "name": "name",
140 | "type": "varchar(256)",
141 | "primaryKey": false,
142 | "notNull": true
143 | },
144 | "applicationId": {
145 | "name": "applicationId",
146 | "type": "uuid",
147 | "primaryKey": false,
148 | "notNull": false
149 | },
150 | "password": {
151 | "name": "password",
152 | "type": "varchar(256)",
153 | "primaryKey": false,
154 | "notNull": true
155 | },
156 | "created_at": {
157 | "name": "created_at",
158 | "type": "timestamp",
159 | "primaryKey": false,
160 | "notNull": true,
161 | "default": "now()"
162 | },
163 | "updated_at": {
164 | "name": "updated_at",
165 | "type": "timestamp",
166 | "primaryKey": false,
167 | "notNull": true,
168 | "default": "now()"
169 | }
170 | },
171 | "indexes": {
172 | "users_id_index": {
173 | "name": "users_id_index",
174 | "columns": [
175 | "id"
176 | ],
177 | "isUnique": true
178 | }
179 | },
180 | "foreignKeys": {
181 | "users_applicationId_applications_id_fk": {
182 | "name": "users_applicationId_applications_id_fk",
183 | "tableFrom": "users",
184 | "tableTo": "applications",
185 | "columnsFrom": [
186 | "applicationId"
187 | ],
188 | "columnsTo": [
189 | "id"
190 | ],
191 | "onDelete": "no action",
192 | "onUpdate": "no action"
193 | }
194 | },
195 | "compositePrimaryKeys": {
196 | "users_email_applicationId": {
197 | "name": "users_email_applicationId",
198 | "columns": [
199 | "email",
200 | "applicationId"
201 | ]
202 | }
203 | }
204 | },
205 | "usersToRoles": {
206 | "name": "usersToRoles",
207 | "schema": "",
208 | "columns": {
209 | "applicationId": {
210 | "name": "applicationId",
211 | "type": "uuid",
212 | "primaryKey": false,
213 | "notNull": true
214 | },
215 | "roledId": {
216 | "name": "roledId",
217 | "type": "uuid",
218 | "primaryKey": false,
219 | "notNull": true
220 | },
221 | "userId": {
222 | "name": "userId",
223 | "type": "uuid",
224 | "primaryKey": false,
225 | "notNull": true
226 | }
227 | },
228 | "indexes": {},
229 | "foreignKeys": {
230 | "usersToRoles_applicationId_applications_id_fk": {
231 | "name": "usersToRoles_applicationId_applications_id_fk",
232 | "tableFrom": "usersToRoles",
233 | "tableTo": "applications",
234 | "columnsFrom": [
235 | "applicationId"
236 | ],
237 | "columnsTo": [
238 | "id"
239 | ],
240 | "onDelete": "no action",
241 | "onUpdate": "no action"
242 | },
243 | "usersToRoles_roledId_roles_id_fk": {
244 | "name": "usersToRoles_roledId_roles_id_fk",
245 | "tableFrom": "usersToRoles",
246 | "tableTo": "roles",
247 | "columnsFrom": [
248 | "roledId"
249 | ],
250 | "columnsTo": [
251 | "id"
252 | ],
253 | "onDelete": "no action",
254 | "onUpdate": "no action"
255 | },
256 | "usersToRoles_userId_users_id_fk": {
257 | "name": "usersToRoles_userId_users_id_fk",
258 | "tableFrom": "usersToRoles",
259 | "tableTo": "users",
260 | "columnsFrom": [
261 | "userId"
262 | ],
263 | "columnsTo": [
264 | "id"
265 | ],
266 | "onDelete": "no action",
267 | "onUpdate": "no action"
268 | }
269 | },
270 | "compositePrimaryKeys": {
271 | "usersToRoles_applicationId_roledId_userId": {
272 | "name": "usersToRoles_applicationId_roledId_userId",
273 | "columns": [
274 | "applicationId",
275 | "roledId",
276 | "userId"
277 | ]
278 | }
279 | }
280 | }
281 | },
282 | "enums": {},
283 | "schemas": {},
284 | "_meta": {
285 | "schemas": {},
286 | "tables": {},
287 | "columns": {}
288 | }
289 | }
--------------------------------------------------------------------------------
/migrations/meta/_journal.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "dialect": "pg",
4 | "entries": [
5 | {
6 | "idx": 0,
7 | "version": "5",
8 | "when": 1684312706166,
9 | "tag": "0000_remarkable_katie_power",
10 | "breakpoints": false
11 | },
12 | {
13 | "idx": 1,
14 | "version": "5",
15 | "when": 1684313093833,
16 | "tag": "0001_mute_true_believers",
17 | "breakpoints": false
18 | },
19 | {
20 | "idx": 2,
21 | "version": "5",
22 | "when": 1684313333317,
23 | "tag": "0002_common_tyger_tiger",
24 | "breakpoints": false
25 | },
26 | {
27 | "idx": 3,
28 | "version": "5",
29 | "when": 1684313670786,
30 | "tag": "0003_secret_forge",
31 | "breakpoints": false
32 | }
33 | ]
34 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "dev": "tsx watch src/main.ts",
4 | "migrate": "drizzle-kit generate:pg"
5 | },
6 | "dependencies": {
7 | "argon2": "^0.30.3",
8 | "drizzle-orm": "^0.25.4",
9 | "fastify": "^4.17.0",
10 | "fastify-guard": "^2.0.0",
11 | "fastify-zod": "^1.3.2",
12 | "jsonwebtoken": "^9.0.0",
13 | "pg": "^8.11.0",
14 | "pino": "^8.14.1",
15 | "pino-pretty": "^10.0.0",
16 | "zennv": "^0.1.1",
17 | "zod": "^3.21.4"
18 | },
19 | "devDependencies": {
20 | "@types/jsonwebtoken": "^9.0.2",
21 | "@types/pg": "^8.6.6",
22 | "drizzle-kit": "^0.17.6",
23 | "tsx": "^3.12.7",
24 | "typescript": "^5.0.4",
25 | "zod-to-json-schema": "^3.21.1"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | '@types/jsonwebtoken': ^9.0.2
5 | '@types/pg': ^8.6.6
6 | argon2: ^0.30.3
7 | drizzle-kit: ^0.17.6
8 | drizzle-orm: ^0.25.4
9 | fastify: ^4.17.0
10 | fastify-guard: ^2.0.0
11 | fastify-zod: ^1.3.2
12 | jsonwebtoken: ^9.0.0
13 | pg: ^8.11.0
14 | pino: ^8.14.1
15 | pino-pretty: ^10.0.0
16 | tsx: ^3.12.7
17 | typescript: ^5.0.4
18 | zennv: ^0.1.1
19 | zod: ^3.21.4
20 | zod-to-json-schema: ^3.21.1
21 |
22 | dependencies:
23 | argon2: 0.30.3
24 | drizzle-orm: 0.25.4_@types+pg@8.6.6+pg@8.11.0
25 | fastify: 4.17.0
26 | fastify-guard: 2.0.0
27 | fastify-zod: 1.3.2_fastify@4.17.0
28 | jsonwebtoken: 9.0.0
29 | pg: 8.11.0
30 | pino: 8.14.1
31 | pino-pretty: 10.0.0
32 | zennv: 0.1.1
33 | zod: 3.21.4
34 |
35 | devDependencies:
36 | '@types/jsonwebtoken': 9.0.2
37 | '@types/pg': 8.6.6
38 | drizzle-kit: 0.17.6
39 | tsx: 3.12.7
40 | typescript: 5.0.4
41 | zod-to-json-schema: 3.21.1_zod@3.21.4
42 |
43 | packages:
44 |
45 | /@esbuild-kit/cjs-loader/2.4.2:
46 | resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
47 | dependencies:
48 | '@esbuild-kit/core-utils': 3.1.0
49 | get-tsconfig: 4.5.0
50 | dev: true
51 |
52 | /@esbuild-kit/core-utils/3.1.0:
53 | resolution: {integrity: sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==}
54 | dependencies:
55 | esbuild: 0.17.19
56 | source-map-support: 0.5.21
57 | dev: true
58 |
59 | /@esbuild-kit/esm-loader/2.5.5:
60 | resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==}
61 | dependencies:
62 | '@esbuild-kit/core-utils': 3.1.0
63 | get-tsconfig: 4.5.0
64 | dev: true
65 |
66 | /@esbuild/android-arm/0.15.18:
67 | resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==}
68 | engines: {node: '>=12'}
69 | cpu: [arm]
70 | os: [android]
71 | requiresBuild: true
72 | dev: true
73 | optional: true
74 |
75 | /@esbuild/android-arm/0.17.19:
76 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
77 | engines: {node: '>=12'}
78 | cpu: [arm]
79 | os: [android]
80 | requiresBuild: true
81 | dev: true
82 | optional: true
83 |
84 | /@esbuild/android-arm64/0.17.19:
85 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
86 | engines: {node: '>=12'}
87 | cpu: [arm64]
88 | os: [android]
89 | requiresBuild: true
90 | dev: true
91 | optional: true
92 |
93 | /@esbuild/android-x64/0.17.19:
94 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
95 | engines: {node: '>=12'}
96 | cpu: [x64]
97 | os: [android]
98 | requiresBuild: true
99 | dev: true
100 | optional: true
101 |
102 | /@esbuild/darwin-arm64/0.17.19:
103 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
104 | engines: {node: '>=12'}
105 | cpu: [arm64]
106 | os: [darwin]
107 | requiresBuild: true
108 | dev: true
109 | optional: true
110 |
111 | /@esbuild/darwin-x64/0.17.19:
112 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
113 | engines: {node: '>=12'}
114 | cpu: [x64]
115 | os: [darwin]
116 | requiresBuild: true
117 | dev: true
118 | optional: true
119 |
120 | /@esbuild/freebsd-arm64/0.17.19:
121 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
122 | engines: {node: '>=12'}
123 | cpu: [arm64]
124 | os: [freebsd]
125 | requiresBuild: true
126 | dev: true
127 | optional: true
128 |
129 | /@esbuild/freebsd-x64/0.17.19:
130 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
131 | engines: {node: '>=12'}
132 | cpu: [x64]
133 | os: [freebsd]
134 | requiresBuild: true
135 | dev: true
136 | optional: true
137 |
138 | /@esbuild/linux-arm/0.17.19:
139 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
140 | engines: {node: '>=12'}
141 | cpu: [arm]
142 | os: [linux]
143 | requiresBuild: true
144 | dev: true
145 | optional: true
146 |
147 | /@esbuild/linux-arm64/0.17.19:
148 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
149 | engines: {node: '>=12'}
150 | cpu: [arm64]
151 | os: [linux]
152 | requiresBuild: true
153 | dev: true
154 | optional: true
155 |
156 | /@esbuild/linux-ia32/0.17.19:
157 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
158 | engines: {node: '>=12'}
159 | cpu: [ia32]
160 | os: [linux]
161 | requiresBuild: true
162 | dev: true
163 | optional: true
164 |
165 | /@esbuild/linux-loong64/0.15.18:
166 | resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==}
167 | engines: {node: '>=12'}
168 | cpu: [loong64]
169 | os: [linux]
170 | requiresBuild: true
171 | dev: true
172 | optional: true
173 |
174 | /@esbuild/linux-loong64/0.17.19:
175 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
176 | engines: {node: '>=12'}
177 | cpu: [loong64]
178 | os: [linux]
179 | requiresBuild: true
180 | dev: true
181 | optional: true
182 |
183 | /@esbuild/linux-mips64el/0.17.19:
184 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
185 | engines: {node: '>=12'}
186 | cpu: [mips64el]
187 | os: [linux]
188 | requiresBuild: true
189 | dev: true
190 | optional: true
191 |
192 | /@esbuild/linux-ppc64/0.17.19:
193 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
194 | engines: {node: '>=12'}
195 | cpu: [ppc64]
196 | os: [linux]
197 | requiresBuild: true
198 | dev: true
199 | optional: true
200 |
201 | /@esbuild/linux-riscv64/0.17.19:
202 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
203 | engines: {node: '>=12'}
204 | cpu: [riscv64]
205 | os: [linux]
206 | requiresBuild: true
207 | dev: true
208 | optional: true
209 |
210 | /@esbuild/linux-s390x/0.17.19:
211 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
212 | engines: {node: '>=12'}
213 | cpu: [s390x]
214 | os: [linux]
215 | requiresBuild: true
216 | dev: true
217 | optional: true
218 |
219 | /@esbuild/linux-x64/0.17.19:
220 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
221 | engines: {node: '>=12'}
222 | cpu: [x64]
223 | os: [linux]
224 | requiresBuild: true
225 | dev: true
226 | optional: true
227 |
228 | /@esbuild/netbsd-x64/0.17.19:
229 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
230 | engines: {node: '>=12'}
231 | cpu: [x64]
232 | os: [netbsd]
233 | requiresBuild: true
234 | dev: true
235 | optional: true
236 |
237 | /@esbuild/openbsd-x64/0.17.19:
238 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
239 | engines: {node: '>=12'}
240 | cpu: [x64]
241 | os: [openbsd]
242 | requiresBuild: true
243 | dev: true
244 | optional: true
245 |
246 | /@esbuild/sunos-x64/0.17.19:
247 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
248 | engines: {node: '>=12'}
249 | cpu: [x64]
250 | os: [sunos]
251 | requiresBuild: true
252 | dev: true
253 | optional: true
254 |
255 | /@esbuild/win32-arm64/0.17.19:
256 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
257 | engines: {node: '>=12'}
258 | cpu: [arm64]
259 | os: [win32]
260 | requiresBuild: true
261 | dev: true
262 | optional: true
263 |
264 | /@esbuild/win32-ia32/0.17.19:
265 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
266 | engines: {node: '>=12'}
267 | cpu: [ia32]
268 | os: [win32]
269 | requiresBuild: true
270 | dev: true
271 | optional: true
272 |
273 | /@esbuild/win32-x64/0.17.19:
274 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
275 | engines: {node: '>=12'}
276 | cpu: [x64]
277 | os: [win32]
278 | requiresBuild: true
279 | dev: true
280 | optional: true
281 |
282 | /@fastify/accept-negotiator/1.1.0:
283 | resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==}
284 | engines: {node: '>=14'}
285 | dev: false
286 |
287 | /@fastify/ajv-compiler/3.5.0:
288 | resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==}
289 | dependencies:
290 | ajv: 8.12.0
291 | ajv-formats: 2.1.1
292 | fast-uri: 2.2.0
293 | dev: false
294 |
295 | /@fastify/deepmerge/1.3.0:
296 | resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==}
297 | dev: false
298 |
299 | /@fastify/error/3.2.0:
300 | resolution: {integrity: sha512-KAfcLa+CnknwVi5fWogrLXgidLic+GXnLjijXdpl8pvkvbXU5BGa37iZO9FGvsh9ZL4y+oFi5cbHBm5UOG+dmQ==}
301 | dev: false
302 |
303 | /@fastify/fast-json-stringify-compiler/4.3.0:
304 | resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==}
305 | dependencies:
306 | fast-json-stringify: 5.7.0
307 | dev: false
308 |
309 | /@fastify/send/2.1.0:
310 | resolution: {integrity: sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==}
311 | dependencies:
312 | '@lukeed/ms': 2.0.1
313 | escape-html: 1.0.3
314 | fast-decode-uri-component: 1.0.1
315 | http-errors: 2.0.0
316 | mime: 3.0.0
317 | dev: false
318 |
319 | /@fastify/static/6.10.1:
320 | resolution: {integrity: sha512-DNnG+5QenQcTQw37qk0/191STThnN6SbU+2XMpWtpYR3gQUfUvMax14jTT/jqNINNbCkQJaKMnPtpFPKo4/68g==}
321 | dependencies:
322 | '@fastify/accept-negotiator': 1.1.0
323 | '@fastify/send': 2.1.0
324 | content-disposition: 0.5.4
325 | fastify-plugin: 4.5.0
326 | glob: 8.1.0
327 | p-limit: 3.1.0
328 | readable-stream: 4.4.0
329 | dev: false
330 |
331 | /@fastify/swagger-ui/1.8.1:
332 | resolution: {integrity: sha512-XMfLGZMXi5dl0Gy6R6tlistA4d0XlJJweUfQkPNVeeBq2hO03DmvtM5yrp8adF392Xoi+6rlGHFaneL9EQdsoA==}
333 | dependencies:
334 | '@fastify/static': 6.10.1
335 | fastify-plugin: 4.5.0
336 | openapi-types: 12.1.0
337 | rfdc: 1.3.0
338 | yaml: 2.2.2
339 | dev: false
340 |
341 | /@fastify/swagger/8.4.0:
342 | resolution: {integrity: sha512-bgTXEIW8HPfBH9ENER410aI81I2iSoHsHkVs8JJU3gzdVoq+ZVZvnwNYYSXB83K6xdTXMKTEiv8GKAimte49lw==}
343 | dependencies:
344 | fastify-plugin: 4.5.0
345 | json-schema-resolver: 2.0.0
346 | openapi-types: 12.1.0
347 | rfdc: 1.3.0
348 | yaml: 2.2.2
349 | transitivePeerDependencies:
350 | - supports-color
351 | dev: false
352 |
353 | /@lukeed/ms/2.0.1:
354 | resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==}
355 | engines: {node: '>=8'}
356 | dev: false
357 |
358 | /@mapbox/node-pre-gyp/1.0.10:
359 | resolution: {integrity: sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==}
360 | hasBin: true
361 | dependencies:
362 | detect-libc: 2.0.1
363 | https-proxy-agent: 5.0.1
364 | make-dir: 3.1.0
365 | node-fetch: 2.6.11
366 | nopt: 5.0.0
367 | npmlog: 5.0.1
368 | rimraf: 3.0.2
369 | semver: 7.5.1
370 | tar: 6.1.15
371 | transitivePeerDependencies:
372 | - encoding
373 | - supports-color
374 | dev: false
375 |
376 | /@phc/format/1.0.0:
377 | resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==}
378 | engines: {node: '>=10'}
379 | dev: false
380 |
381 | /@types/js-yaml/4.0.5:
382 | resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==}
383 | dev: false
384 |
385 | /@types/jsonwebtoken/9.0.2:
386 | resolution: {integrity: sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==}
387 | dependencies:
388 | '@types/node': 20.1.7
389 | dev: true
390 |
391 | /@types/node/20.1.7:
392 | resolution: {integrity: sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg==}
393 |
394 | /@types/pg/8.6.6:
395 | resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
396 | dependencies:
397 | '@types/node': 20.1.7
398 | pg-protocol: 1.6.0
399 | pg-types: 2.2.0
400 |
401 | /abbrev/1.1.1:
402 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
403 | dev: false
404 |
405 | /abort-controller/3.0.0:
406 | resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
407 | engines: {node: '>=6.5'}
408 | dependencies:
409 | event-target-shim: 5.0.1
410 | dev: false
411 |
412 | /abstract-logging/2.0.1:
413 | resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
414 | dev: false
415 |
416 | /agent-base/6.0.2:
417 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
418 | engines: {node: '>= 6.0.0'}
419 | dependencies:
420 | debug: 4.3.4
421 | transitivePeerDependencies:
422 | - supports-color
423 | dev: false
424 |
425 | /ajv-formats/2.1.1:
426 | resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
427 | peerDependenciesMeta:
428 | ajv:
429 | optional: true
430 | dependencies:
431 | ajv: 8.12.0
432 | dev: false
433 |
434 | /ajv/8.12.0:
435 | resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
436 | dependencies:
437 | fast-deep-equal: 3.1.3
438 | json-schema-traverse: 1.0.0
439 | require-from-string: 2.0.2
440 | uri-js: 4.4.1
441 | dev: false
442 |
443 | /ansi-regex/5.0.1:
444 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
445 | engines: {node: '>=8'}
446 | dev: false
447 |
448 | /aproba/2.0.0:
449 | resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
450 | dev: false
451 |
452 | /archy/1.0.0:
453 | resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==}
454 | dev: false
455 |
456 | /are-we-there-yet/2.0.0:
457 | resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
458 | engines: {node: '>=10'}
459 | dependencies:
460 | delegates: 1.0.0
461 | readable-stream: 3.6.2
462 | dev: false
463 |
464 | /argon2/0.30.3:
465 | resolution: {integrity: sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==}
466 | engines: {node: '>=14.0.0'}
467 | requiresBuild: true
468 | dependencies:
469 | '@mapbox/node-pre-gyp': 1.0.10
470 | '@phc/format': 1.0.0
471 | node-addon-api: 5.1.0
472 | transitivePeerDependencies:
473 | - encoding
474 | - supports-color
475 | dev: false
476 |
477 | /argparse/2.0.1:
478 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
479 | dev: false
480 |
481 | /atomic-sleep/1.0.0:
482 | resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
483 | engines: {node: '>=8.0.0'}
484 | dev: false
485 |
486 | /avvio/8.2.1:
487 | resolution: {integrity: sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==}
488 | dependencies:
489 | archy: 1.0.0
490 | debug: 4.3.4
491 | fastq: 1.15.0
492 | transitivePeerDependencies:
493 | - supports-color
494 | dev: false
495 |
496 | /balanced-match/1.0.2:
497 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
498 |
499 | /base64-js/1.5.1:
500 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
501 | dev: false
502 |
503 | /brace-expansion/1.1.11:
504 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
505 | dependencies:
506 | balanced-match: 1.0.2
507 | concat-map: 0.0.1
508 | dev: false
509 |
510 | /brace-expansion/2.0.1:
511 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
512 | dependencies:
513 | balanced-match: 1.0.2
514 |
515 | /buffer-equal-constant-time/1.0.1:
516 | resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
517 | dev: false
518 |
519 | /buffer-from/1.1.2:
520 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
521 | dev: true
522 |
523 | /buffer-writer/2.0.0:
524 | resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==}
525 | engines: {node: '>=4'}
526 | dev: false
527 |
528 | /buffer/6.0.3:
529 | resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
530 | dependencies:
531 | base64-js: 1.5.1
532 | ieee754: 1.2.1
533 | dev: false
534 |
535 | /camel-case/4.1.2:
536 | resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
537 | dependencies:
538 | pascal-case: 3.1.2
539 | tslib: 2.5.0
540 | dev: false
541 |
542 | /camelcase/7.0.1:
543 | resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
544 | engines: {node: '>=14.16'}
545 | dev: true
546 |
547 | /capital-case/1.0.4:
548 | resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
549 | dependencies:
550 | no-case: 3.0.4
551 | tslib: 2.5.0
552 | upper-case-first: 2.0.2
553 | dev: false
554 |
555 | /chalk/5.2.0:
556 | resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==}
557 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
558 | dev: true
559 |
560 | /change-case/4.1.2:
561 | resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==}
562 | dependencies:
563 | camel-case: 4.1.2
564 | capital-case: 1.0.4
565 | constant-case: 3.0.4
566 | dot-case: 3.0.4
567 | header-case: 2.0.4
568 | no-case: 3.0.4
569 | param-case: 3.0.4
570 | pascal-case: 3.1.2
571 | path-case: 3.0.4
572 | sentence-case: 3.0.4
573 | snake-case: 3.0.4
574 | tslib: 2.5.0
575 | dev: false
576 |
577 | /chownr/2.0.0:
578 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
579 | engines: {node: '>=10'}
580 | dev: false
581 |
582 | /cli-color/2.0.3:
583 | resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==}
584 | engines: {node: '>=0.10'}
585 | dependencies:
586 | d: 1.0.1
587 | es5-ext: 0.10.62
588 | es6-iterator: 2.0.3
589 | memoizee: 0.4.15
590 | timers-ext: 0.1.7
591 | dev: true
592 |
593 | /color-support/1.1.3:
594 | resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
595 | hasBin: true
596 | dev: false
597 |
598 | /colorette/2.0.20:
599 | resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
600 | dev: false
601 |
602 | /commander/9.5.0:
603 | resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
604 | engines: {node: ^12.20.0 || >=14}
605 | dev: true
606 |
607 | /concat-map/0.0.1:
608 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
609 | dev: false
610 |
611 | /console-control-strings/1.1.0:
612 | resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
613 | dev: false
614 |
615 | /constant-case/3.0.4:
616 | resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==}
617 | dependencies:
618 | no-case: 3.0.4
619 | tslib: 2.5.0
620 | upper-case: 2.0.2
621 | dev: false
622 |
623 | /content-disposition/0.5.4:
624 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
625 | engines: {node: '>= 0.6'}
626 | dependencies:
627 | safe-buffer: 5.2.1
628 | dev: false
629 |
630 | /cookie/0.5.0:
631 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
632 | engines: {node: '>= 0.6'}
633 | dev: false
634 |
635 | /d/1.0.1:
636 | resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==}
637 | dependencies:
638 | es5-ext: 0.10.62
639 | type: 1.2.0
640 | dev: true
641 |
642 | /dateformat/4.6.3:
643 | resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
644 | dev: false
645 |
646 | /debug/4.3.4:
647 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
648 | engines: {node: '>=6.0'}
649 | peerDependencies:
650 | supports-color: '*'
651 | peerDependenciesMeta:
652 | supports-color:
653 | optional: true
654 | dependencies:
655 | ms: 2.1.2
656 |
657 | /delegates/1.0.0:
658 | resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
659 | dev: false
660 |
661 | /depd/2.0.0:
662 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
663 | engines: {node: '>= 0.8'}
664 | dev: false
665 |
666 | /detect-libc/2.0.1:
667 | resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==}
668 | engines: {node: '>=8'}
669 | dev: false
670 |
671 | /difflib/0.2.4:
672 | resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==}
673 | dependencies:
674 | heap: 0.2.7
675 | dev: true
676 |
677 | /dot-case/3.0.4:
678 | resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
679 | dependencies:
680 | no-case: 3.0.4
681 | tslib: 2.5.0
682 | dev: false
683 |
684 | /dotenv/16.0.3:
685 | resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
686 | engines: {node: '>=12'}
687 | dev: false
688 |
689 | /dreamopt/0.8.0:
690 | resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==}
691 | engines: {node: '>=0.4.0'}
692 | dependencies:
693 | wordwrap: 1.0.0
694 | dev: true
695 |
696 | /drizzle-kit/0.17.6:
697 | resolution: {integrity: sha512-diNslu/ItzLv+++7l2noevXaCOrsfDXv+ZxMJWOy061Gs1BeEhP0t+mBKqeOPy8LsEo0aitNKOe+gPltEScmWQ==}
698 | hasBin: true
699 | dependencies:
700 | camelcase: 7.0.1
701 | chalk: 5.2.0
702 | commander: 9.5.0
703 | esbuild: 0.15.18
704 | esbuild-register: 3.4.2_esbuild@0.15.18
705 | glob: 8.1.0
706 | hanji: 0.0.5
707 | json-diff: 0.9.0
708 | zod: 3.21.4
709 | transitivePeerDependencies:
710 | - supports-color
711 | dev: true
712 |
713 | /drizzle-orm/0.25.4_@types+pg@8.6.6+pg@8.11.0:
714 | resolution: {integrity: sha512-vURs2SqDh5pk81WWE4hR8gFKDTRmCK4FbaUGsZoljKnjKvMrjlA5xFPGiCih4/1XKqnOgSuh+I6T9KGBjYcPAA==}
715 | peerDependencies:
716 | '@aws-sdk/client-rds-data': '>=3'
717 | '@cloudflare/workers-types': '>=3'
718 | '@libsql/client': '*'
719 | '@neondatabase/serverless': '>=0.1'
720 | '@planetscale/database': '>=1'
721 | '@types/better-sqlite3': '*'
722 | '@types/pg': '*'
723 | '@types/sql.js': '*'
724 | '@vercel/postgres': '*'
725 | better-sqlite3: '>=7'
726 | bun-types: '*'
727 | knex: '*'
728 | kysely: '*'
729 | mysql2: '>=2'
730 | pg: '>=8'
731 | postgres: '>=3'
732 | sql.js: '>=1'
733 | sqlite3: '>=5'
734 | peerDependenciesMeta:
735 | '@aws-sdk/client-rds-data':
736 | optional: true
737 | '@cloudflare/workers-types':
738 | optional: true
739 | '@libsql/client':
740 | optional: true
741 | '@neondatabase/serverless':
742 | optional: true
743 | '@planetscale/database':
744 | optional: true
745 | '@types/better-sqlite3':
746 | optional: true
747 | '@types/pg':
748 | optional: true
749 | '@types/sql.js':
750 | optional: true
751 | '@vercel/postgres':
752 | optional: true
753 | better-sqlite3:
754 | optional: true
755 | bun-types:
756 | optional: true
757 | knex:
758 | optional: true
759 | kysely:
760 | optional: true
761 | mysql2:
762 | optional: true
763 | pg:
764 | optional: true
765 | postgres:
766 | optional: true
767 | sql.js:
768 | optional: true
769 | sqlite3:
770 | optional: true
771 | dependencies:
772 | '@types/pg': 8.6.6
773 | pg: 8.11.0
774 | dev: false
775 |
776 | /ecdsa-sig-formatter/1.0.11:
777 | resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
778 | dependencies:
779 | safe-buffer: 5.2.1
780 | dev: false
781 |
782 | /emoji-regex/8.0.0:
783 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
784 | dev: false
785 |
786 | /end-of-stream/1.4.4:
787 | resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
788 | dependencies:
789 | once: 1.4.0
790 | dev: false
791 |
792 | /es5-ext/0.10.62:
793 | resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==}
794 | engines: {node: '>=0.10'}
795 | requiresBuild: true
796 | dependencies:
797 | es6-iterator: 2.0.3
798 | es6-symbol: 3.1.3
799 | next-tick: 1.1.0
800 | dev: true
801 |
802 | /es6-iterator/2.0.3:
803 | resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
804 | dependencies:
805 | d: 1.0.1
806 | es5-ext: 0.10.62
807 | es6-symbol: 3.1.3
808 | dev: true
809 |
810 | /es6-symbol/3.1.3:
811 | resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==}
812 | dependencies:
813 | d: 1.0.1
814 | ext: 1.7.0
815 | dev: true
816 |
817 | /es6-weak-map/2.0.3:
818 | resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==}
819 | dependencies:
820 | d: 1.0.1
821 | es5-ext: 0.10.62
822 | es6-iterator: 2.0.3
823 | es6-symbol: 3.1.3
824 | dev: true
825 |
826 | /esbuild-android-64/0.15.18:
827 | resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==}
828 | engines: {node: '>=12'}
829 | cpu: [x64]
830 | os: [android]
831 | requiresBuild: true
832 | dev: true
833 | optional: true
834 |
835 | /esbuild-android-arm64/0.15.18:
836 | resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==}
837 | engines: {node: '>=12'}
838 | cpu: [arm64]
839 | os: [android]
840 | requiresBuild: true
841 | dev: true
842 | optional: true
843 |
844 | /esbuild-darwin-64/0.15.18:
845 | resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==}
846 | engines: {node: '>=12'}
847 | cpu: [x64]
848 | os: [darwin]
849 | requiresBuild: true
850 | dev: true
851 | optional: true
852 |
853 | /esbuild-darwin-arm64/0.15.18:
854 | resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==}
855 | engines: {node: '>=12'}
856 | cpu: [arm64]
857 | os: [darwin]
858 | requiresBuild: true
859 | dev: true
860 | optional: true
861 |
862 | /esbuild-freebsd-64/0.15.18:
863 | resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==}
864 | engines: {node: '>=12'}
865 | cpu: [x64]
866 | os: [freebsd]
867 | requiresBuild: true
868 | dev: true
869 | optional: true
870 |
871 | /esbuild-freebsd-arm64/0.15.18:
872 | resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==}
873 | engines: {node: '>=12'}
874 | cpu: [arm64]
875 | os: [freebsd]
876 | requiresBuild: true
877 | dev: true
878 | optional: true
879 |
880 | /esbuild-linux-32/0.15.18:
881 | resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==}
882 | engines: {node: '>=12'}
883 | cpu: [ia32]
884 | os: [linux]
885 | requiresBuild: true
886 | dev: true
887 | optional: true
888 |
889 | /esbuild-linux-64/0.15.18:
890 | resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==}
891 | engines: {node: '>=12'}
892 | cpu: [x64]
893 | os: [linux]
894 | requiresBuild: true
895 | dev: true
896 | optional: true
897 |
898 | /esbuild-linux-arm/0.15.18:
899 | resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==}
900 | engines: {node: '>=12'}
901 | cpu: [arm]
902 | os: [linux]
903 | requiresBuild: true
904 | dev: true
905 | optional: true
906 |
907 | /esbuild-linux-arm64/0.15.18:
908 | resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==}
909 | engines: {node: '>=12'}
910 | cpu: [arm64]
911 | os: [linux]
912 | requiresBuild: true
913 | dev: true
914 | optional: true
915 |
916 | /esbuild-linux-mips64le/0.15.18:
917 | resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==}
918 | engines: {node: '>=12'}
919 | cpu: [mips64el]
920 | os: [linux]
921 | requiresBuild: true
922 | dev: true
923 | optional: true
924 |
925 | /esbuild-linux-ppc64le/0.15.18:
926 | resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==}
927 | engines: {node: '>=12'}
928 | cpu: [ppc64]
929 | os: [linux]
930 | requiresBuild: true
931 | dev: true
932 | optional: true
933 |
934 | /esbuild-linux-riscv64/0.15.18:
935 | resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==}
936 | engines: {node: '>=12'}
937 | cpu: [riscv64]
938 | os: [linux]
939 | requiresBuild: true
940 | dev: true
941 | optional: true
942 |
943 | /esbuild-linux-s390x/0.15.18:
944 | resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==}
945 | engines: {node: '>=12'}
946 | cpu: [s390x]
947 | os: [linux]
948 | requiresBuild: true
949 | dev: true
950 | optional: true
951 |
952 | /esbuild-netbsd-64/0.15.18:
953 | resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==}
954 | engines: {node: '>=12'}
955 | cpu: [x64]
956 | os: [netbsd]
957 | requiresBuild: true
958 | dev: true
959 | optional: true
960 |
961 | /esbuild-openbsd-64/0.15.18:
962 | resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==}
963 | engines: {node: '>=12'}
964 | cpu: [x64]
965 | os: [openbsd]
966 | requiresBuild: true
967 | dev: true
968 | optional: true
969 |
970 | /esbuild-register/3.4.2_esbuild@0.15.18:
971 | resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==}
972 | peerDependencies:
973 | esbuild: '>=0.12 <1'
974 | dependencies:
975 | debug: 4.3.4
976 | esbuild: 0.15.18
977 | transitivePeerDependencies:
978 | - supports-color
979 | dev: true
980 |
981 | /esbuild-sunos-64/0.15.18:
982 | resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==}
983 | engines: {node: '>=12'}
984 | cpu: [x64]
985 | os: [sunos]
986 | requiresBuild: true
987 | dev: true
988 | optional: true
989 |
990 | /esbuild-windows-32/0.15.18:
991 | resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==}
992 | engines: {node: '>=12'}
993 | cpu: [ia32]
994 | os: [win32]
995 | requiresBuild: true
996 | dev: true
997 | optional: true
998 |
999 | /esbuild-windows-64/0.15.18:
1000 | resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==}
1001 | engines: {node: '>=12'}
1002 | cpu: [x64]
1003 | os: [win32]
1004 | requiresBuild: true
1005 | dev: true
1006 | optional: true
1007 |
1008 | /esbuild-windows-arm64/0.15.18:
1009 | resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==}
1010 | engines: {node: '>=12'}
1011 | cpu: [arm64]
1012 | os: [win32]
1013 | requiresBuild: true
1014 | dev: true
1015 | optional: true
1016 |
1017 | /esbuild/0.15.18:
1018 | resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==}
1019 | engines: {node: '>=12'}
1020 | hasBin: true
1021 | requiresBuild: true
1022 | optionalDependencies:
1023 | '@esbuild/android-arm': 0.15.18
1024 | '@esbuild/linux-loong64': 0.15.18
1025 | esbuild-android-64: 0.15.18
1026 | esbuild-android-arm64: 0.15.18
1027 | esbuild-darwin-64: 0.15.18
1028 | esbuild-darwin-arm64: 0.15.18
1029 | esbuild-freebsd-64: 0.15.18
1030 | esbuild-freebsd-arm64: 0.15.18
1031 | esbuild-linux-32: 0.15.18
1032 | esbuild-linux-64: 0.15.18
1033 | esbuild-linux-arm: 0.15.18
1034 | esbuild-linux-arm64: 0.15.18
1035 | esbuild-linux-mips64le: 0.15.18
1036 | esbuild-linux-ppc64le: 0.15.18
1037 | esbuild-linux-riscv64: 0.15.18
1038 | esbuild-linux-s390x: 0.15.18
1039 | esbuild-netbsd-64: 0.15.18
1040 | esbuild-openbsd-64: 0.15.18
1041 | esbuild-sunos-64: 0.15.18
1042 | esbuild-windows-32: 0.15.18
1043 | esbuild-windows-64: 0.15.18
1044 | esbuild-windows-arm64: 0.15.18
1045 | dev: true
1046 |
1047 | /esbuild/0.17.19:
1048 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
1049 | engines: {node: '>=12'}
1050 | hasBin: true
1051 | requiresBuild: true
1052 | optionalDependencies:
1053 | '@esbuild/android-arm': 0.17.19
1054 | '@esbuild/android-arm64': 0.17.19
1055 | '@esbuild/android-x64': 0.17.19
1056 | '@esbuild/darwin-arm64': 0.17.19
1057 | '@esbuild/darwin-x64': 0.17.19
1058 | '@esbuild/freebsd-arm64': 0.17.19
1059 | '@esbuild/freebsd-x64': 0.17.19
1060 | '@esbuild/linux-arm': 0.17.19
1061 | '@esbuild/linux-arm64': 0.17.19
1062 | '@esbuild/linux-ia32': 0.17.19
1063 | '@esbuild/linux-loong64': 0.17.19
1064 | '@esbuild/linux-mips64el': 0.17.19
1065 | '@esbuild/linux-ppc64': 0.17.19
1066 | '@esbuild/linux-riscv64': 0.17.19
1067 | '@esbuild/linux-s390x': 0.17.19
1068 | '@esbuild/linux-x64': 0.17.19
1069 | '@esbuild/netbsd-x64': 0.17.19
1070 | '@esbuild/openbsd-x64': 0.17.19
1071 | '@esbuild/sunos-x64': 0.17.19
1072 | '@esbuild/win32-arm64': 0.17.19
1073 | '@esbuild/win32-ia32': 0.17.19
1074 | '@esbuild/win32-x64': 0.17.19
1075 | dev: true
1076 |
1077 | /escape-html/1.0.3:
1078 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
1079 | dev: false
1080 |
1081 | /event-emitter/0.3.5:
1082 | resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
1083 | dependencies:
1084 | d: 1.0.1
1085 | es5-ext: 0.10.62
1086 | dev: true
1087 |
1088 | /event-target-shim/5.0.1:
1089 | resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
1090 | engines: {node: '>=6'}
1091 | dev: false
1092 |
1093 | /events/3.3.0:
1094 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
1095 | engines: {node: '>=0.8.x'}
1096 | dev: false
1097 |
1098 | /ext/1.7.0:
1099 | resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
1100 | dependencies:
1101 | type: 2.7.2
1102 | dev: true
1103 |
1104 | /fast-content-type-parse/1.0.0:
1105 | resolution: {integrity: sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA==}
1106 | dev: false
1107 |
1108 | /fast-copy/3.0.1:
1109 | resolution: {integrity: sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==}
1110 | dev: false
1111 |
1112 | /fast-decode-uri-component/1.0.1:
1113 | resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
1114 | dev: false
1115 |
1116 | /fast-deep-equal/3.1.3:
1117 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
1118 | dev: false
1119 |
1120 | /fast-json-stringify/5.7.0:
1121 | resolution: {integrity: sha512-sBVPTgnAZseLu1Qgj6lUbQ0HfjFhZWXAmpZ5AaSGkyLh5gAXBga/uPJjQPHpDFjC9adWIpdOcCLSDTgrZ7snoQ==}
1122 | dependencies:
1123 | '@fastify/deepmerge': 1.3.0
1124 | ajv: 8.12.0
1125 | ajv-formats: 2.1.1
1126 | fast-deep-equal: 3.1.3
1127 | fast-uri: 2.2.0
1128 | rfdc: 1.3.0
1129 | dev: false
1130 |
1131 | /fast-querystring/1.1.1:
1132 | resolution: {integrity: sha512-qR2r+e3HvhEFmpdHMv//U8FnFlnYjaC6QKDuaXALDkw2kvHO8WDjxH+f/rHGR4Me4pnk8p9JAkRNTjYHAKRn2Q==}
1133 | dependencies:
1134 | fast-decode-uri-component: 1.0.1
1135 | dev: false
1136 |
1137 | /fast-redact/3.2.0:
1138 | resolution: {integrity: sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==}
1139 | engines: {node: '>=6'}
1140 | dev: false
1141 |
1142 | /fast-safe-stringify/2.1.1:
1143 | resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
1144 | dev: false
1145 |
1146 | /fast-uri/2.2.0:
1147 | resolution: {integrity: sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==}
1148 | dev: false
1149 |
1150 | /fastify-guard/2.0.0:
1151 | resolution: {integrity: sha512-1NGzfCcjnD2oEs0cWJQKpldlzUQvVWbcIqjYL2Zsj5URENcn95shqLyZHHIAkrYs8R/yTevnRKFT2/etTiQE+g==}
1152 | engines: {node: '>=14.0.0'}
1153 | dependencies:
1154 | fastify-plugin: 3.0.1
1155 | http-errors: 2.0.0
1156 | lodash.get: 4.4.2
1157 | dev: false
1158 |
1159 | /fastify-plugin/3.0.1:
1160 | resolution: {integrity: sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==}
1161 | dev: false
1162 |
1163 | /fastify-plugin/4.5.0:
1164 | resolution: {integrity: sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg==}
1165 | dev: false
1166 |
1167 | /fastify-zod/1.3.2_fastify@4.17.0:
1168 | resolution: {integrity: sha512-Gwug3n9/F8kmT9+eUVrnQfqsXkhEf6QGQpyKWMhs1Wg3m2mhomBOHUrikSMyh2LpAVRxUYg6Hk/M3IkEuOnDZw==}
1169 | peerDependencies:
1170 | fastify: ^4.15.0
1171 | dependencies:
1172 | '@fastify/swagger': 8.4.0
1173 | '@fastify/swagger-ui': 1.8.1
1174 | '@types/js-yaml': 4.0.5
1175 | change-case: 4.1.2
1176 | fast-deep-equal: 3.1.3
1177 | fastify: 4.17.0
1178 | js-yaml: 4.1.0
1179 | tslib: 2.5.0
1180 | zod: 3.21.4
1181 | zod-to-json-schema: 3.21.1_zod@3.21.4
1182 | transitivePeerDependencies:
1183 | - supports-color
1184 | dev: false
1185 |
1186 | /fastify/4.17.0:
1187 | resolution: {integrity: sha512-tzuY1tgWJo2Y6qEKwmLhFvACUmr68Io2pqP/sDKU71KRM6A6R3DrCDqLGqANbeLZcKUfdfY58ut35CGqemcTgg==}
1188 | dependencies:
1189 | '@fastify/ajv-compiler': 3.5.0
1190 | '@fastify/error': 3.2.0
1191 | '@fastify/fast-json-stringify-compiler': 4.3.0
1192 | abstract-logging: 2.0.1
1193 | avvio: 8.2.1
1194 | fast-content-type-parse: 1.0.0
1195 | fast-json-stringify: 5.7.0
1196 | find-my-way: 7.6.2
1197 | light-my-request: 5.9.1
1198 | pino: 8.14.1
1199 | process-warning: 2.2.0
1200 | proxy-addr: 2.0.7
1201 | rfdc: 1.3.0
1202 | secure-json-parse: 2.7.0
1203 | semver: 7.5.1
1204 | tiny-lru: 11.0.1
1205 | transitivePeerDependencies:
1206 | - supports-color
1207 | dev: false
1208 |
1209 | /fastq/1.15.0:
1210 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
1211 | dependencies:
1212 | reusify: 1.0.4
1213 | dev: false
1214 |
1215 | /find-my-way/7.6.2:
1216 | resolution: {integrity: sha512-0OjHn1b1nCX3eVbm9ByeEHiscPYiHLfhei1wOUU9qffQkk98wE0Lo8VrVYfSGMgnSnDh86DxedduAnBf4nwUEw==}
1217 | engines: {node: '>=14'}
1218 | dependencies:
1219 | fast-deep-equal: 3.1.3
1220 | fast-querystring: 1.1.1
1221 | safe-regex2: 2.0.0
1222 | dev: false
1223 |
1224 | /forwarded/0.2.0:
1225 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
1226 | engines: {node: '>= 0.6'}
1227 | dev: false
1228 |
1229 | /fs-minipass/2.1.0:
1230 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
1231 | engines: {node: '>= 8'}
1232 | dependencies:
1233 | minipass: 3.3.6
1234 | dev: false
1235 |
1236 | /fs.realpath/1.0.0:
1237 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
1238 |
1239 | /fsevents/2.3.2:
1240 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
1241 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
1242 | os: [darwin]
1243 | requiresBuild: true
1244 | dev: true
1245 | optional: true
1246 |
1247 | /gauge/3.0.2:
1248 | resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
1249 | engines: {node: '>=10'}
1250 | dependencies:
1251 | aproba: 2.0.0
1252 | color-support: 1.1.3
1253 | console-control-strings: 1.1.0
1254 | has-unicode: 2.0.1
1255 | object-assign: 4.1.1
1256 | signal-exit: 3.0.7
1257 | string-width: 4.2.3
1258 | strip-ansi: 6.0.1
1259 | wide-align: 1.1.5
1260 | dev: false
1261 |
1262 | /get-tsconfig/4.5.0:
1263 | resolution: {integrity: sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==}
1264 | dev: true
1265 |
1266 | /glob/7.2.3:
1267 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
1268 | dependencies:
1269 | fs.realpath: 1.0.0
1270 | inflight: 1.0.6
1271 | inherits: 2.0.4
1272 | minimatch: 3.1.2
1273 | once: 1.4.0
1274 | path-is-absolute: 1.0.1
1275 | dev: false
1276 |
1277 | /glob/8.1.0:
1278 | resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
1279 | engines: {node: '>=12'}
1280 | dependencies:
1281 | fs.realpath: 1.0.0
1282 | inflight: 1.0.6
1283 | inherits: 2.0.4
1284 | minimatch: 5.1.6
1285 | once: 1.4.0
1286 |
1287 | /hanji/0.0.5:
1288 | resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==}
1289 | dependencies:
1290 | lodash.throttle: 4.1.1
1291 | sisteransi: 1.0.5
1292 | dev: true
1293 |
1294 | /has-unicode/2.0.1:
1295 | resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
1296 | dev: false
1297 |
1298 | /header-case/2.0.4:
1299 | resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==}
1300 | dependencies:
1301 | capital-case: 1.0.4
1302 | tslib: 2.5.0
1303 | dev: false
1304 |
1305 | /heap/0.2.7:
1306 | resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==}
1307 | dev: true
1308 |
1309 | /help-me/4.2.0:
1310 | resolution: {integrity: sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==}
1311 | dependencies:
1312 | glob: 8.1.0
1313 | readable-stream: 3.6.2
1314 | dev: false
1315 |
1316 | /http-errors/2.0.0:
1317 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
1318 | engines: {node: '>= 0.8'}
1319 | dependencies:
1320 | depd: 2.0.0
1321 | inherits: 2.0.4
1322 | setprototypeof: 1.2.0
1323 | statuses: 2.0.1
1324 | toidentifier: 1.0.1
1325 | dev: false
1326 |
1327 | /https-proxy-agent/5.0.1:
1328 | resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
1329 | engines: {node: '>= 6'}
1330 | dependencies:
1331 | agent-base: 6.0.2
1332 | debug: 4.3.4
1333 | transitivePeerDependencies:
1334 | - supports-color
1335 | dev: false
1336 |
1337 | /ieee754/1.2.1:
1338 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
1339 | dev: false
1340 |
1341 | /inflight/1.0.6:
1342 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
1343 | dependencies:
1344 | once: 1.4.0
1345 | wrappy: 1.0.2
1346 |
1347 | /inherits/2.0.4:
1348 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
1349 |
1350 | /ipaddr.js/1.9.1:
1351 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
1352 | engines: {node: '>= 0.10'}
1353 | dev: false
1354 |
1355 | /is-fullwidth-code-point/3.0.0:
1356 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
1357 | engines: {node: '>=8'}
1358 | dev: false
1359 |
1360 | /is-promise/2.2.2:
1361 | resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
1362 | dev: true
1363 |
1364 | /joycon/3.1.1:
1365 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
1366 | engines: {node: '>=10'}
1367 | dev: false
1368 |
1369 | /js-yaml/4.1.0:
1370 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
1371 | hasBin: true
1372 | dependencies:
1373 | argparse: 2.0.1
1374 | dev: false
1375 |
1376 | /json-diff/0.9.0:
1377 | resolution: {integrity: sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==}
1378 | hasBin: true
1379 | dependencies:
1380 | cli-color: 2.0.3
1381 | difflib: 0.2.4
1382 | dreamopt: 0.8.0
1383 | dev: true
1384 |
1385 | /json-schema-resolver/2.0.0:
1386 | resolution: {integrity: sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==}
1387 | engines: {node: '>=10'}
1388 | dependencies:
1389 | debug: 4.3.4
1390 | rfdc: 1.3.0
1391 | uri-js: 4.4.1
1392 | transitivePeerDependencies:
1393 | - supports-color
1394 | dev: false
1395 |
1396 | /json-schema-traverse/1.0.0:
1397 | resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
1398 | dev: false
1399 |
1400 | /jsonwebtoken/9.0.0:
1401 | resolution: {integrity: sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==}
1402 | engines: {node: '>=12', npm: '>=6'}
1403 | dependencies:
1404 | jws: 3.2.2
1405 | lodash: 4.17.21
1406 | ms: 2.1.3
1407 | semver: 7.5.1
1408 | dev: false
1409 |
1410 | /jwa/1.4.1:
1411 | resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
1412 | dependencies:
1413 | buffer-equal-constant-time: 1.0.1
1414 | ecdsa-sig-formatter: 1.0.11
1415 | safe-buffer: 5.2.1
1416 | dev: false
1417 |
1418 | /jws/3.2.2:
1419 | resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
1420 | dependencies:
1421 | jwa: 1.4.1
1422 | safe-buffer: 5.2.1
1423 | dev: false
1424 |
1425 | /light-my-request/5.9.1:
1426 | resolution: {integrity: sha512-UT7pUk8jNCR1wR7w3iWfIjx32DiB2f3hFdQSOwy3/EPQ3n3VocyipUxcyRZR0ahoev+fky69uA+GejPa9KuHKg==}
1427 | dependencies:
1428 | cookie: 0.5.0
1429 | process-warning: 2.2.0
1430 | set-cookie-parser: 2.6.0
1431 | dev: false
1432 |
1433 | /lodash.get/4.4.2:
1434 | resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
1435 | dev: false
1436 |
1437 | /lodash.throttle/4.1.1:
1438 | resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
1439 | dev: true
1440 |
1441 | /lodash/4.17.21:
1442 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
1443 | dev: false
1444 |
1445 | /lower-case/2.0.2:
1446 | resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
1447 | dependencies:
1448 | tslib: 2.5.0
1449 | dev: false
1450 |
1451 | /lru-cache/6.0.0:
1452 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
1453 | engines: {node: '>=10'}
1454 | dependencies:
1455 | yallist: 4.0.0
1456 | dev: false
1457 |
1458 | /lru-queue/0.1.0:
1459 | resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==}
1460 | dependencies:
1461 | es5-ext: 0.10.62
1462 | dev: true
1463 |
1464 | /make-dir/3.1.0:
1465 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
1466 | engines: {node: '>=8'}
1467 | dependencies:
1468 | semver: 6.3.0
1469 | dev: false
1470 |
1471 | /memoizee/0.4.15:
1472 | resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==}
1473 | dependencies:
1474 | d: 1.0.1
1475 | es5-ext: 0.10.62
1476 | es6-weak-map: 2.0.3
1477 | event-emitter: 0.3.5
1478 | is-promise: 2.2.2
1479 | lru-queue: 0.1.0
1480 | next-tick: 1.1.0
1481 | timers-ext: 0.1.7
1482 | dev: true
1483 |
1484 | /mime/3.0.0:
1485 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
1486 | engines: {node: '>=10.0.0'}
1487 | hasBin: true
1488 | dev: false
1489 |
1490 | /minimatch/3.1.2:
1491 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
1492 | dependencies:
1493 | brace-expansion: 1.1.11
1494 | dev: false
1495 |
1496 | /minimatch/5.1.6:
1497 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
1498 | engines: {node: '>=10'}
1499 | dependencies:
1500 | brace-expansion: 2.0.1
1501 |
1502 | /minimist/1.2.8:
1503 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
1504 | dev: false
1505 |
1506 | /minipass/3.3.6:
1507 | resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
1508 | engines: {node: '>=8'}
1509 | dependencies:
1510 | yallist: 4.0.0
1511 | dev: false
1512 |
1513 | /minipass/5.0.0:
1514 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
1515 | engines: {node: '>=8'}
1516 | dev: false
1517 |
1518 | /minizlib/2.1.2:
1519 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
1520 | engines: {node: '>= 8'}
1521 | dependencies:
1522 | minipass: 3.3.6
1523 | yallist: 4.0.0
1524 | dev: false
1525 |
1526 | /mkdirp/1.0.4:
1527 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
1528 | engines: {node: '>=10'}
1529 | hasBin: true
1530 | dev: false
1531 |
1532 | /ms/2.1.2:
1533 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
1534 |
1535 | /ms/2.1.3:
1536 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1537 | dev: false
1538 |
1539 | /next-tick/1.1.0:
1540 | resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
1541 | dev: true
1542 |
1543 | /no-case/3.0.4:
1544 | resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
1545 | dependencies:
1546 | lower-case: 2.0.2
1547 | tslib: 2.5.0
1548 | dev: false
1549 |
1550 | /node-addon-api/5.1.0:
1551 | resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
1552 | dev: false
1553 |
1554 | /node-fetch/2.6.11:
1555 | resolution: {integrity: sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==}
1556 | engines: {node: 4.x || >=6.0.0}
1557 | peerDependencies:
1558 | encoding: ^0.1.0
1559 | peerDependenciesMeta:
1560 | encoding:
1561 | optional: true
1562 | dependencies:
1563 | whatwg-url: 5.0.0
1564 | dev: false
1565 |
1566 | /nopt/5.0.0:
1567 | resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
1568 | engines: {node: '>=6'}
1569 | hasBin: true
1570 | dependencies:
1571 | abbrev: 1.1.1
1572 | dev: false
1573 |
1574 | /npmlog/5.0.1:
1575 | resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
1576 | dependencies:
1577 | are-we-there-yet: 2.0.0
1578 | console-control-strings: 1.1.0
1579 | gauge: 3.0.2
1580 | set-blocking: 2.0.0
1581 | dev: false
1582 |
1583 | /object-assign/4.1.1:
1584 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
1585 | engines: {node: '>=0.10.0'}
1586 | dev: false
1587 |
1588 | /on-exit-leak-free/2.1.0:
1589 | resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==}
1590 | dev: false
1591 |
1592 | /once/1.4.0:
1593 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
1594 | dependencies:
1595 | wrappy: 1.0.2
1596 |
1597 | /openapi-types/12.1.0:
1598 | resolution: {integrity: sha512-XpeCy01X6L5EpP+6Hc3jWN7rMZJ+/k1lwki/kTmWzbVhdPie3jd5O2ZtedEx8Yp58icJ0osVldLMrTB/zslQXA==}
1599 | dev: false
1600 |
1601 | /p-limit/3.1.0:
1602 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
1603 | engines: {node: '>=10'}
1604 | dependencies:
1605 | yocto-queue: 0.1.0
1606 | dev: false
1607 |
1608 | /packet-reader/1.0.0:
1609 | resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
1610 | dev: false
1611 |
1612 | /param-case/3.0.4:
1613 | resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==}
1614 | dependencies:
1615 | dot-case: 3.0.4
1616 | tslib: 2.5.0
1617 | dev: false
1618 |
1619 | /pascal-case/3.1.2:
1620 | resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
1621 | dependencies:
1622 | no-case: 3.0.4
1623 | tslib: 2.5.0
1624 | dev: false
1625 |
1626 | /path-case/3.0.4:
1627 | resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==}
1628 | dependencies:
1629 | dot-case: 3.0.4
1630 | tslib: 2.5.0
1631 | dev: false
1632 |
1633 | /path-is-absolute/1.0.1:
1634 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
1635 | engines: {node: '>=0.10.0'}
1636 | dev: false
1637 |
1638 | /pg-cloudflare/1.1.0:
1639 | resolution: {integrity: sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==}
1640 | requiresBuild: true
1641 | dev: false
1642 | optional: true
1643 |
1644 | /pg-connection-string/2.6.0:
1645 | resolution: {integrity: sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg==}
1646 | dev: false
1647 |
1648 | /pg-int8/1.0.1:
1649 | resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
1650 | engines: {node: '>=4.0.0'}
1651 |
1652 | /pg-pool/3.6.0_pg@8.11.0:
1653 | resolution: {integrity: sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==}
1654 | peerDependencies:
1655 | pg: '>=8.0'
1656 | dependencies:
1657 | pg: 8.11.0
1658 | dev: false
1659 |
1660 | /pg-protocol/1.6.0:
1661 | resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==}
1662 |
1663 | /pg-types/2.2.0:
1664 | resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
1665 | engines: {node: '>=4'}
1666 | dependencies:
1667 | pg-int8: 1.0.1
1668 | postgres-array: 2.0.0
1669 | postgres-bytea: 1.0.0
1670 | postgres-date: 1.0.7
1671 | postgres-interval: 1.2.0
1672 |
1673 | /pg/8.11.0:
1674 | resolution: {integrity: sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==}
1675 | engines: {node: '>= 8.0.0'}
1676 | peerDependencies:
1677 | pg-native: '>=3.0.1'
1678 | peerDependenciesMeta:
1679 | pg-native:
1680 | optional: true
1681 | dependencies:
1682 | buffer-writer: 2.0.0
1683 | packet-reader: 1.0.0
1684 | pg-connection-string: 2.6.0
1685 | pg-pool: 3.6.0_pg@8.11.0
1686 | pg-protocol: 1.6.0
1687 | pg-types: 2.2.0
1688 | pgpass: 1.0.5
1689 | optionalDependencies:
1690 | pg-cloudflare: 1.1.0
1691 | dev: false
1692 |
1693 | /pgpass/1.0.5:
1694 | resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
1695 | dependencies:
1696 | split2: 4.2.0
1697 | dev: false
1698 |
1699 | /pino-abstract-transport/1.0.0:
1700 | resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==}
1701 | dependencies:
1702 | readable-stream: 4.4.0
1703 | split2: 4.2.0
1704 | dev: false
1705 |
1706 | /pino-pretty/10.0.0:
1707 | resolution: {integrity: sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==}
1708 | hasBin: true
1709 | dependencies:
1710 | colorette: 2.0.20
1711 | dateformat: 4.6.3
1712 | fast-copy: 3.0.1
1713 | fast-safe-stringify: 2.1.1
1714 | help-me: 4.2.0
1715 | joycon: 3.1.1
1716 | minimist: 1.2.8
1717 | on-exit-leak-free: 2.1.0
1718 | pino-abstract-transport: 1.0.0
1719 | pump: 3.0.0
1720 | readable-stream: 4.4.0
1721 | secure-json-parse: 2.7.0
1722 | sonic-boom: 3.3.0
1723 | strip-json-comments: 3.1.1
1724 | dev: false
1725 |
1726 | /pino-std-serializers/6.2.1:
1727 | resolution: {integrity: sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ==}
1728 | dev: false
1729 |
1730 | /pino/8.14.1:
1731 | resolution: {integrity: sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==}
1732 | hasBin: true
1733 | dependencies:
1734 | atomic-sleep: 1.0.0
1735 | fast-redact: 3.2.0
1736 | on-exit-leak-free: 2.1.0
1737 | pino-abstract-transport: 1.0.0
1738 | pino-std-serializers: 6.2.1
1739 | process-warning: 2.2.0
1740 | quick-format-unescaped: 4.0.4
1741 | real-require: 0.2.0
1742 | safe-stable-stringify: 2.4.3
1743 | sonic-boom: 3.3.0
1744 | thread-stream: 2.3.0
1745 | dev: false
1746 |
1747 | /postgres-array/2.0.0:
1748 | resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
1749 | engines: {node: '>=4'}
1750 |
1751 | /postgres-bytea/1.0.0:
1752 | resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
1753 | engines: {node: '>=0.10.0'}
1754 |
1755 | /postgres-date/1.0.7:
1756 | resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
1757 | engines: {node: '>=0.10.0'}
1758 |
1759 | /postgres-interval/1.2.0:
1760 | resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
1761 | engines: {node: '>=0.10.0'}
1762 | dependencies:
1763 | xtend: 4.0.2
1764 |
1765 | /process-warning/2.2.0:
1766 | resolution: {integrity: sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==}
1767 | dev: false
1768 |
1769 | /process/0.11.10:
1770 | resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
1771 | engines: {node: '>= 0.6.0'}
1772 | dev: false
1773 |
1774 | /proxy-addr/2.0.7:
1775 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
1776 | engines: {node: '>= 0.10'}
1777 | dependencies:
1778 | forwarded: 0.2.0
1779 | ipaddr.js: 1.9.1
1780 | dev: false
1781 |
1782 | /pump/3.0.0:
1783 | resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
1784 | dependencies:
1785 | end-of-stream: 1.4.4
1786 | once: 1.4.0
1787 | dev: false
1788 |
1789 | /punycode/2.3.0:
1790 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
1791 | engines: {node: '>=6'}
1792 | dev: false
1793 |
1794 | /quick-format-unescaped/4.0.4:
1795 | resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
1796 | dev: false
1797 |
1798 | /readable-stream/3.6.2:
1799 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
1800 | engines: {node: '>= 6'}
1801 | dependencies:
1802 | inherits: 2.0.4
1803 | string_decoder: 1.3.0
1804 | util-deprecate: 1.0.2
1805 | dev: false
1806 |
1807 | /readable-stream/4.4.0:
1808 | resolution: {integrity: sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==}
1809 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1810 | dependencies:
1811 | abort-controller: 3.0.0
1812 | buffer: 6.0.3
1813 | events: 3.3.0
1814 | process: 0.11.10
1815 | dev: false
1816 |
1817 | /real-require/0.2.0:
1818 | resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
1819 | engines: {node: '>= 12.13.0'}
1820 | dev: false
1821 |
1822 | /require-from-string/2.0.2:
1823 | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
1824 | engines: {node: '>=0.10.0'}
1825 | dev: false
1826 |
1827 | /ret/0.2.2:
1828 | resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==}
1829 | engines: {node: '>=4'}
1830 | dev: false
1831 |
1832 | /reusify/1.0.4:
1833 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
1834 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
1835 | dev: false
1836 |
1837 | /rfdc/1.3.0:
1838 | resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
1839 | dev: false
1840 |
1841 | /rimraf/3.0.2:
1842 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
1843 | hasBin: true
1844 | dependencies:
1845 | glob: 7.2.3
1846 | dev: false
1847 |
1848 | /safe-buffer/5.2.1:
1849 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
1850 | dev: false
1851 |
1852 | /safe-regex2/2.0.0:
1853 | resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==}
1854 | dependencies:
1855 | ret: 0.2.2
1856 | dev: false
1857 |
1858 | /safe-stable-stringify/2.4.3:
1859 | resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==}
1860 | engines: {node: '>=10'}
1861 | dev: false
1862 |
1863 | /secure-json-parse/2.7.0:
1864 | resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
1865 | dev: false
1866 |
1867 | /semver/6.3.0:
1868 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
1869 | hasBin: true
1870 | dev: false
1871 |
1872 | /semver/7.5.1:
1873 | resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==}
1874 | engines: {node: '>=10'}
1875 | hasBin: true
1876 | dependencies:
1877 | lru-cache: 6.0.0
1878 | dev: false
1879 |
1880 | /sentence-case/3.0.4:
1881 | resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==}
1882 | dependencies:
1883 | no-case: 3.0.4
1884 | tslib: 2.5.0
1885 | upper-case-first: 2.0.2
1886 | dev: false
1887 |
1888 | /set-blocking/2.0.0:
1889 | resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
1890 | dev: false
1891 |
1892 | /set-cookie-parser/2.6.0:
1893 | resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==}
1894 | dev: false
1895 |
1896 | /setprototypeof/1.2.0:
1897 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
1898 | dev: false
1899 |
1900 | /signal-exit/3.0.7:
1901 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
1902 | dev: false
1903 |
1904 | /sisteransi/1.0.5:
1905 | resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
1906 | dev: true
1907 |
1908 | /snake-case/3.0.4:
1909 | resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==}
1910 | dependencies:
1911 | dot-case: 3.0.4
1912 | tslib: 2.5.0
1913 | dev: false
1914 |
1915 | /sonic-boom/3.3.0:
1916 | resolution: {integrity: sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==}
1917 | dependencies:
1918 | atomic-sleep: 1.0.0
1919 | dev: false
1920 |
1921 | /source-map-support/0.5.21:
1922 | resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
1923 | dependencies:
1924 | buffer-from: 1.1.2
1925 | source-map: 0.6.1
1926 | dev: true
1927 |
1928 | /source-map/0.6.1:
1929 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
1930 | engines: {node: '>=0.10.0'}
1931 | dev: true
1932 |
1933 | /split2/4.2.0:
1934 | resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
1935 | engines: {node: '>= 10.x'}
1936 | dev: false
1937 |
1938 | /statuses/2.0.1:
1939 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
1940 | engines: {node: '>= 0.8'}
1941 | dev: false
1942 |
1943 | /string-width/4.2.3:
1944 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
1945 | engines: {node: '>=8'}
1946 | dependencies:
1947 | emoji-regex: 8.0.0
1948 | is-fullwidth-code-point: 3.0.0
1949 | strip-ansi: 6.0.1
1950 | dev: false
1951 |
1952 | /string_decoder/1.3.0:
1953 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
1954 | dependencies:
1955 | safe-buffer: 5.2.1
1956 | dev: false
1957 |
1958 | /strip-ansi/6.0.1:
1959 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
1960 | engines: {node: '>=8'}
1961 | dependencies:
1962 | ansi-regex: 5.0.1
1963 | dev: false
1964 |
1965 | /strip-json-comments/3.1.1:
1966 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
1967 | engines: {node: '>=8'}
1968 | dev: false
1969 |
1970 | /tar/6.1.15:
1971 | resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==}
1972 | engines: {node: '>=10'}
1973 | dependencies:
1974 | chownr: 2.0.0
1975 | fs-minipass: 2.1.0
1976 | minipass: 5.0.0
1977 | minizlib: 2.1.2
1978 | mkdirp: 1.0.4
1979 | yallist: 4.0.0
1980 | dev: false
1981 |
1982 | /thread-stream/2.3.0:
1983 | resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==}
1984 | dependencies:
1985 | real-require: 0.2.0
1986 | dev: false
1987 |
1988 | /timers-ext/0.1.7:
1989 | resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==}
1990 | dependencies:
1991 | es5-ext: 0.10.62
1992 | next-tick: 1.1.0
1993 | dev: true
1994 |
1995 | /tiny-lru/11.0.1:
1996 | resolution: {integrity: sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==}
1997 | engines: {node: '>=12'}
1998 | dev: false
1999 |
2000 | /toidentifier/1.0.1:
2001 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
2002 | engines: {node: '>=0.6'}
2003 | dev: false
2004 |
2005 | /tr46/0.0.3:
2006 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
2007 | dev: false
2008 |
2009 | /tslib/2.5.0:
2010 | resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
2011 | dev: false
2012 |
2013 | /tsx/3.12.7:
2014 | resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==}
2015 | hasBin: true
2016 | dependencies:
2017 | '@esbuild-kit/cjs-loader': 2.4.2
2018 | '@esbuild-kit/core-utils': 3.1.0
2019 | '@esbuild-kit/esm-loader': 2.5.5
2020 | optionalDependencies:
2021 | fsevents: 2.3.2
2022 | dev: true
2023 |
2024 | /type/1.2.0:
2025 | resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==}
2026 | dev: true
2027 |
2028 | /type/2.7.2:
2029 | resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==}
2030 | dev: true
2031 |
2032 | /typescript/5.0.4:
2033 | resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
2034 | engines: {node: '>=12.20'}
2035 | hasBin: true
2036 | dev: true
2037 |
2038 | /upper-case-first/2.0.2:
2039 | resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==}
2040 | dependencies:
2041 | tslib: 2.5.0
2042 | dev: false
2043 |
2044 | /upper-case/2.0.2:
2045 | resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==}
2046 | dependencies:
2047 | tslib: 2.5.0
2048 | dev: false
2049 |
2050 | /uri-js/4.4.1:
2051 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
2052 | dependencies:
2053 | punycode: 2.3.0
2054 | dev: false
2055 |
2056 | /util-deprecate/1.0.2:
2057 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
2058 | dev: false
2059 |
2060 | /webidl-conversions/3.0.1:
2061 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
2062 | dev: false
2063 |
2064 | /whatwg-url/5.0.0:
2065 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
2066 | dependencies:
2067 | tr46: 0.0.3
2068 | webidl-conversions: 3.0.1
2069 | dev: false
2070 |
2071 | /wide-align/1.1.5:
2072 | resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
2073 | dependencies:
2074 | string-width: 4.2.3
2075 | dev: false
2076 |
2077 | /wordwrap/1.0.0:
2078 | resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
2079 | dev: true
2080 |
2081 | /wrappy/1.0.2:
2082 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
2083 |
2084 | /xtend/4.0.2:
2085 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
2086 | engines: {node: '>=0.4'}
2087 |
2088 | /yallist/4.0.0:
2089 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
2090 | dev: false
2091 |
2092 | /yaml/2.2.2:
2093 | resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==}
2094 | engines: {node: '>= 14'}
2095 | dev: false
2096 |
2097 | /yocto-queue/0.1.0:
2098 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
2099 | engines: {node: '>=10'}
2100 | dev: false
2101 |
2102 | /zennv/0.1.1:
2103 | resolution: {integrity: sha512-yAszZBjMYY97kuQ7pVQm5FLz/amtOpzyyhaF7+CwdJZ3Kz9f60pLy2LRqygdcWcV3LcxsUcngfWXxk5ZO98XRQ==}
2104 | engines: {node: '>=10'}
2105 | dependencies:
2106 | dotenv: 16.0.3
2107 | zod: 3.21.4
2108 | dev: false
2109 |
2110 | /zod-to-json-schema/3.21.1_zod@3.21.4:
2111 | resolution: {integrity: sha512-y5g0MPxDq+YG/T+cHGPYH4PcBpyCqwK6wxeJ76MR563y0gk/14HKfebq8xHiItY7lkc9GDFygCnkvNDTvAhYAg==}
2112 | peerDependencies:
2113 | zod: ^3.21.4
2114 | dependencies:
2115 | zod: 3.21.4
2116 |
2117 | /zod/3.21.4:
2118 | resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
2119 |
--------------------------------------------------------------------------------
/src/config/env.ts:
--------------------------------------------------------------------------------
1 | import zennv from "zennv";
2 | import { z } from "zod";
3 |
4 | export const env = zennv({
5 | dotenv: true,
6 | schema: z.object({
7 | PORT: z.number().default(3000),
8 | HOST: z.string().default("0.0.0.0"),
9 | DATABASE_CONNECTION: z.string(),
10 | }),
11 | });
12 |
--------------------------------------------------------------------------------
/src/config/permissions.ts:
--------------------------------------------------------------------------------
1 | export const ALL_PERMISSIONS = [
2 | // users
3 | "users:roles:write", // Allowed to add a role to a user
4 | "users:roles:delete", // Allowed to remove a role from a user
5 |
6 | // roles
7 | "roles:write",
8 |
9 | // posts
10 | "posts:write",
11 | "posts:read",
12 | "post:delete",
13 | "post:edit-own",
14 | ] as const;
15 |
16 | export const PERMISSIONS = ALL_PERMISSIONS.reduce((acc, permission) => {
17 | acc[permission] = permission;
18 |
19 | return acc;
20 | }, {} as Record<(typeof ALL_PERMISSIONS)[number], (typeof ALL_PERMISSIONS)[number]>);
21 |
22 | export const USER_ROLE_PERMISSIONS = [
23 | PERMISSIONS["posts:write"],
24 | PERMISSIONS["posts:read"],
25 | ];
26 |
27 | export const SYSTEM_ROLES = {
28 | SUPER_ADMIN: "SUPER_ADMIN",
29 | APPLICATION_USER: "APPLICATION_USER",
30 | };
31 |
--------------------------------------------------------------------------------
/src/db/index.ts:
--------------------------------------------------------------------------------
1 | import { Pool } from "pg";
2 | import { drizzle } from "drizzle-orm/node-postgres";
3 | import { env } from "../config/env";
4 |
5 | const pool = new Pool({
6 | connectionString: env.DATABASE_CONNECTION,
7 | ssl: true,
8 | });
9 |
10 | export const db = drizzle(pool);
11 |
--------------------------------------------------------------------------------
/src/db/schema.ts:
--------------------------------------------------------------------------------
1 | import {
2 | pgTable,
3 | primaryKey,
4 | text,
5 | timestamp,
6 | uniqueIndex,
7 | uuid,
8 | varchar,
9 | } from "drizzle-orm/pg-core";
10 |
11 | export const applications = pgTable("applications", {
12 | id: uuid("id").primaryKey().defaultRandom(),
13 | name: varchar("name", { length: 256 }).notNull(),
14 | createdAt: timestamp("created_at").defaultNow().notNull(),
15 | updatedAt: timestamp("updated_at").defaultNow().notNull(),
16 | });
17 |
18 | export const users = pgTable(
19 | "users",
20 | {
21 | id: uuid("id").defaultRandom().notNull(),
22 | email: varchar("email", { length: 256 }).notNull(),
23 | name: varchar("name", { length: 256 }).notNull(),
24 | applicationId: uuid("applicationId").references(() => applications.id),
25 | password: varchar("password", { length: 256 }).notNull(),
26 | createdAt: timestamp("created_at").defaultNow().notNull(),
27 | updatedAt: timestamp("updated_at").defaultNow().notNull(),
28 | },
29 | (users) => {
30 | return {
31 | cpk: primaryKey(users.email, users.applicationId),
32 | idIndex: uniqueIndex("users_id_index").on(users.id),
33 | };
34 | }
35 | );
36 |
37 | export const roles = pgTable(
38 | "roles",
39 | {
40 | id: uuid("id").defaultRandom().notNull(),
41 | name: varchar("name", { length: 256 }).notNull(),
42 | applicationId: uuid("applicationId").references(() => applications.id),
43 | permissions: text("permissions").array().$type>(),
44 | createdAt: timestamp("created_at").defaultNow().notNull(),
45 | updatedAt: timestamp("updated_at").defaultNow().notNull(),
46 | },
47 | (roles) => {
48 | return {
49 | cpk: primaryKey(roles.name, roles.applicationId),
50 | idIndex: uniqueIndex("roles_id_index").on(roles.id),
51 | };
52 | }
53 | );
54 |
55 | export const usersToRoles = pgTable(
56 | "usersToRoles",
57 | {
58 | applicationId: uuid("applicationId")
59 | .references(() => applications.id)
60 | .notNull(),
61 |
62 | roleId: uuid("roledId")
63 | .references(() => roles.id)
64 | .notNull(),
65 |
66 | userId: uuid("userId")
67 | .references(() => users.id)
68 | .notNull(),
69 | },
70 | (usersToRoles) => {
71 | return {
72 | cpk: primaryKey(
73 | usersToRoles.applicationId,
74 | usersToRoles.roleId,
75 | usersToRoles.userId
76 | ),
77 | };
78 | }
79 | );
80 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { migrate } from "drizzle-orm/node-postgres/migrator";
2 | import { env } from "./config/env";
3 | import { logger } from "./utils/logger";
4 | import { buildServer } from "./utils/server";
5 | import { db } from "./db";
6 |
7 | async function gracefulShutdown({
8 | app,
9 | }: {
10 | app: Awaited>;
11 | }) {
12 | await app.close();
13 | }
14 |
15 | async function main() {
16 | const app = await buildServer();
17 |
18 | await app.listen({
19 | port: env.PORT,
20 | host: env.HOST,
21 | });
22 |
23 | await migrate(db, {
24 | migrationsFolder: "./migrations",
25 | });
26 |
27 | const signals = ["SIGINT", "SIGTERM"];
28 |
29 | logger.debug(env, "using env");
30 |
31 | for (const signal of signals) {
32 | process.on(signal, () => {
33 | gracefulShutdown({
34 | app,
35 | });
36 | });
37 | }
38 | }
39 |
40 | main();
41 |
--------------------------------------------------------------------------------
/src/modules/applications/applications.controllers.ts:
--------------------------------------------------------------------------------
1 | import { FastifyReply, FastifyRequest } from "fastify";
2 | import { CreateApplicationBody } from "./applications.schemas";
3 | import { createApplication, getApplications } from "./applications.services";
4 | import { createRole } from "../roles/roles.services";
5 | import {
6 | ALL_PERMISSIONS,
7 | SYSTEM_ROLES,
8 | USER_ROLE_PERMISSIONS,
9 | } from "../../config/permissions";
10 |
11 | export async function createApplicationHandler(
12 | request: FastifyRequest<{
13 | Body: CreateApplicationBody;
14 | }>,
15 | reply: FastifyReply
16 | ) {
17 | const { name } = request.body;
18 |
19 | const application = await createApplication({
20 | name,
21 | });
22 |
23 | const superAdminRolePromise = createRole({
24 | applicationId: application.id,
25 | name: SYSTEM_ROLES.SUPER_ADMIN,
26 | permissions: ALL_PERMISSIONS as unknown as Array,
27 | });
28 |
29 | const applicationUserRolePromise = createRole({
30 | applicationId: application.id,
31 | name: SYSTEM_ROLES.APPLICATION_USER,
32 | permissions: USER_ROLE_PERMISSIONS,
33 | });
34 |
35 | const [superAdminRole, applicationUserRole] = await Promise.allSettled([
36 | superAdminRolePromise,
37 | applicationUserRolePromise,
38 | ]);
39 |
40 | if (superAdminRole.status === "rejected") {
41 | throw new Error("Error creating super admin role");
42 | }
43 |
44 | if (applicationUserRole.status === "rejected") {
45 | throw new Error("Error creating application user role");
46 | }
47 |
48 | return {
49 | application,
50 | superAdminRole: superAdminRole.value,
51 | applicationUserRole: applicationUserRole.value,
52 | };
53 | }
54 |
55 | export async function getApplicationshandler() {
56 | return getApplications();
57 | }
58 |
--------------------------------------------------------------------------------
/src/modules/applications/applications.routes.ts:
--------------------------------------------------------------------------------
1 | import { FastifyInstance } from "fastify";
2 | import {
3 | createApplicationHandler,
4 | getApplicationshandler,
5 | } from "./applications.controllers";
6 | import { createApplicationJsonSchema } from "./applications.schemas";
7 |
8 | export async function applicationRoutes(app: FastifyInstance) {
9 | app.post(
10 | "/",
11 | {
12 | schema: createApplicationJsonSchema,
13 | },
14 | createApplicationHandler
15 | );
16 |
17 | app.get("/", getApplicationshandler);
18 | }
19 |
--------------------------------------------------------------------------------
/src/modules/applications/applications.schemas.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import zodToJsonSchema from "zod-to-json-schema";
3 |
4 | const createApplicationBodySchema = z.object({
5 | name: z.string({
6 | required_error: "Name is required",
7 | }),
8 | });
9 |
10 | export type CreateApplicationBody = z.infer;
11 |
12 | export const createApplicationJsonSchema = {
13 | body: zodToJsonSchema(
14 | createApplicationBodySchema,
15 | "createApplicationBodySchema"
16 | ),
17 | };
18 |
--------------------------------------------------------------------------------
/src/modules/applications/applications.services.ts:
--------------------------------------------------------------------------------
1 | import { InferModel } from "drizzle-orm";
2 | import { db } from "../../db";
3 | import { applications } from "../../db/schema";
4 |
5 | export async function createApplication(
6 | data: InferModel
7 | ) {
8 | const result = await db.insert(applications).values(data).returning();
9 |
10 | return result[0];
11 | }
12 |
13 | export async function getApplications() {
14 | // SELECT * FROM applications;
15 | // SELECT id, name, createdAt from applications;
16 | const result = await db
17 | .select({
18 | id: applications.id,
19 | name: applications.name,
20 | createdAt: applications.createdAt,
21 | })
22 | .from(applications);
23 |
24 | return result;
25 | }
26 |
--------------------------------------------------------------------------------
/src/modules/roles/role.controllers.ts:
--------------------------------------------------------------------------------
1 | import { FastifyReply, FastifyRequest } from "fastify";
2 | import { CreateRoleBody } from "./role.schemas";
3 | import { createRole } from "./roles.services";
4 |
5 | export async function createRoleHandler(
6 | request: FastifyRequest<{
7 | Body: CreateRoleBody;
8 | }>,
9 | reply: FastifyReply
10 | ) {
11 | const user = request.user;
12 | const applicationId = user.applicationId;
13 | const { name, permissions } = request.body;
14 |
15 | const role = await createRole({
16 | name,
17 | permissions,
18 | applicationId,
19 | });
20 |
21 | return role;
22 | }
23 |
--------------------------------------------------------------------------------
/src/modules/roles/role.routes.ts:
--------------------------------------------------------------------------------
1 | import { FastifyInstance } from "fastify";
2 | import { CreateRoleBody, createRoleJsonSchema } from "./role.schemas";
3 | import { createRoleHandler } from "./role.controllers";
4 | import { PERMISSIONS } from "../../config/permissions";
5 |
6 | export async function roleRoutes(app: FastifyInstance) {
7 | app.post<{
8 | Body: CreateRoleBody;
9 | }>(
10 | "/",
11 | {
12 | schema: createRoleJsonSchema,
13 | preHandler: [app.guard.scope([PERMISSIONS["roles:write"]])],
14 | },
15 | createRoleHandler
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/src/modules/roles/role.schemas.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { ALL_PERMISSIONS } from "../../config/permissions";
3 | import zodToJsonSchema from "zod-to-json-schema";
4 |
5 | const createRoleBodySchema = z.object({
6 | name: z.string(),
7 | permissions: z.array(z.enum(ALL_PERMISSIONS)),
8 | // applicationId: z.string().uuid(),
9 | });
10 |
11 | export type CreateRoleBody = z.infer;
12 |
13 | export const createRoleJsonSchema = {
14 | body: zodToJsonSchema(createRoleBodySchema, "createRoleBodySchema"),
15 | };
16 |
--------------------------------------------------------------------------------
/src/modules/roles/roles.services.ts:
--------------------------------------------------------------------------------
1 | import { InferModel, and, eq } from "drizzle-orm";
2 | import { db } from "../../db";
3 | import { roles } from "../../db/schema";
4 |
5 | export async function createRole(data: InferModel) {
6 | const result = await db.insert(roles).values(data).returning();
7 |
8 | return result[0];
9 | }
10 |
11 | export async function getRoleByName({
12 | name,
13 | applicationId,
14 | }: {
15 | name: string;
16 | applicationId: string;
17 | }) {
18 | const result = await db
19 | // SELECT *
20 | .select()
21 | // FROM roles
22 | .from(roles)
23 | // WHERE name = ? AND applicationId ?
24 | .where(and(eq(roles.name, name), eq(roles.applicationId, applicationId)))
25 | .limit(1);
26 |
27 | return result[0];
28 | }
29 |
--------------------------------------------------------------------------------
/src/modules/users/users.controllers.ts:
--------------------------------------------------------------------------------
1 | import { FastifyReply, FastifyRequest } from "fastify";
2 | import {
3 | AssignRoleToUserBody,
4 | CreateUserBody,
5 | LoginBody,
6 | } from "./users.schemas";
7 | import { SYSTEM_ROLES } from "../../config/permissions";
8 | import { getRoleByName } from "../roles/roles.services";
9 | import {
10 | assignRoleTouser,
11 | createUser,
12 | getUserByEmail,
13 | getUsersByApplication,
14 | } from "./users.services";
15 | import jwt from "jsonwebtoken";
16 | import { P } from "pino";
17 | import { logger } from "../../utils/logger";
18 |
19 | export async function createUserHandler(
20 | request: FastifyRequest<{
21 | Body: CreateUserBody;
22 | }>,
23 | reply: FastifyReply
24 | ) {
25 | const { initialUser, ...data } = request.body;
26 |
27 | const roleName = initialUser
28 | ? SYSTEM_ROLES.SUPER_ADMIN
29 | : SYSTEM_ROLES.APPLICATION_USER;
30 |
31 | if (roleName === SYSTEM_ROLES.SUPER_ADMIN) {
32 | const appUsers = await getUsersByApplication(data.applicationId);
33 |
34 | if (appUsers.length > 0) {
35 | return reply.code(400).send({
36 | message: "Application already has super admin user",
37 | extensions: {
38 | code: "APPLICATION_ALRADY_SUPER_USER",
39 | applicationId: data.applicationId,
40 | },
41 | });
42 | }
43 | }
44 |
45 | const role = await getRoleByName({
46 | name: roleName,
47 | applicationId: data.applicationId,
48 | });
49 |
50 | if (!role) {
51 | return reply.code(404).send({
52 | message: "Role not found",
53 | });
54 | }
55 |
56 | try {
57 | const user = await createUser(data);
58 |
59 | // assign a role to the user
60 |
61 | await assignRoleTouser({
62 | userId: user.id,
63 | roleId: role.id,
64 | applicationId: data.applicationId,
65 | });
66 |
67 | return user;
68 | } catch (e) {}
69 | }
70 |
71 | export async function loginHandler(
72 | request: FastifyRequest<{
73 | Body: LoginBody;
74 | }>,
75 | reply: FastifyReply
76 | ) {
77 | const { applicationId, email, password } = request.body;
78 |
79 | const user = await getUserByEmail({
80 | applicationId,
81 | email,
82 | });
83 |
84 | if (!user) {
85 | return reply.code(400).send({
86 | message: "Invalid email or password",
87 | });
88 | }
89 |
90 | const token = jwt.sign(
91 | {
92 | id: user.id,
93 | email,
94 | applicationId,
95 | scopes: user.permissions,
96 | },
97 | "secret"
98 | ); // change this secret or signing method, or get fired
99 |
100 | return { token };
101 | }
102 |
103 | export async function assignRoleTouserHandler(
104 | request: FastifyRequest<{
105 | Body: AssignRoleToUserBody;
106 | }>,
107 | reply: FastifyReply
108 | ) {
109 | const applicationId = request.user.applicationId;
110 | const { userId, roleId } = request.body;
111 |
112 | try {
113 | const result = await assignRoleTouser({
114 | userId,
115 | applicationId,
116 | roleId,
117 | });
118 |
119 | return result;
120 | } catch (e) {
121 | logger.error(e, `error assigning role to user`);
122 | return reply.code(400).send({
123 | message: "could not assign role to user",
124 | });
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/modules/users/users.routes.ts:
--------------------------------------------------------------------------------
1 | import { FastifyInstance } from "fastify";
2 | import {
3 | assignRoleTouserHandler,
4 | createUserHandler,
5 | loginHandler,
6 | } from "./users.controllers";
7 | import {
8 | AssignRoleToUserBody,
9 | assignRoleTouserJsonSchema,
10 | createUserJsonSchema,
11 | loginJsonSchema,
12 | } from "./users.schemas";
13 | import { PERMISSIONS } from "../../config/permissions";
14 |
15 | export async function usersRoutes(app: FastifyInstance) {
16 | app.post(
17 | "/",
18 | {
19 | schema: createUserJsonSchema,
20 | },
21 | createUserHandler
22 | );
23 |
24 | app.post(
25 | "/login",
26 | {
27 | schema: loginJsonSchema,
28 | },
29 | loginHandler
30 | );
31 |
32 | app.post<{
33 | Body: AssignRoleToUserBody;
34 | }>(
35 | "/roles",
36 | {
37 | schema: assignRoleTouserJsonSchema,
38 | preHandler: [app.guard.scope(PERMISSIONS["users:roles:write"])],
39 | },
40 | assignRoleTouserHandler
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/src/modules/users/users.schemas.ts:
--------------------------------------------------------------------------------
1 | import { S } from "drizzle-orm/column.d-8b137277";
2 | import { z } from "zod";
3 | import zodToJsonSchema from "zod-to-json-schema";
4 |
5 | // Create user
6 | const createUserBodySchema = z.object({
7 | email: z.string().email(),
8 | name: z.string(),
9 | applicationId: z.string().uuid(),
10 | password: z.string().min(6),
11 | initialUser: z.boolean().optional(),
12 | });
13 |
14 | export type CreateUserBody = z.infer;
15 |
16 | export const createUserJsonSchema = {
17 | body: zodToJsonSchema(createUserBodySchema, "createUserBodySchema"),
18 | };
19 |
20 | // Login
21 | const loginSchema = z.object({
22 | email: z.string().email(),
23 | password: z.string(),
24 | applicationId: z.string(),
25 | });
26 |
27 | export type LoginBody = z.infer;
28 |
29 | export const loginJsonSchema = {
30 | body: zodToJsonSchema(loginSchema, "loginSchema"),
31 | };
32 |
33 | // Assign role to user
34 | const assignRoleToUserBody = z.object({
35 | userId: z.string().uuid(),
36 | roleId: z.string().uuid(),
37 | // applicationId: z.string().uuid(),
38 | });
39 |
40 | export type AssignRoleToUserBody = z.infer;
41 |
42 | export const assignRoleTouserJsonSchema = {
43 | body: zodToJsonSchema(assignRoleToUserBody, "assignRoleToUserBody"),
44 | };
45 |
--------------------------------------------------------------------------------
/src/modules/users/users.services.ts:
--------------------------------------------------------------------------------
1 | import { InferModel, and, eq } from "drizzle-orm";
2 | import argon2 from "argon2";
3 | import { applications, roles, users } from "../../db/schema";
4 | import { db } from "../../db";
5 | import { usersToRoles } from "../../db/schema";
6 | import { PgJsonBuilder } from "drizzle-orm/pg-core";
7 |
8 | export async function createUser(data: InferModel) {
9 | const hashedPassword = await argon2.hash(data.password);
10 |
11 | const result = await db
12 | .insert(users)
13 | .values({
14 | ...data,
15 | password: hashedPassword,
16 | })
17 | .returning({
18 | id: users.id,
19 | email: users.email,
20 | name: users.name,
21 | applicationId: applications.id,
22 | });
23 |
24 | return result[0];
25 | }
26 |
27 | export async function getUsersByApplication(applicationId: string) {
28 | const result = await db
29 | .select()
30 | .from(users)
31 | .where(eq(users.applicationId, applicationId));
32 |
33 | return result;
34 | }
35 |
36 | export async function assignRoleTouser(
37 | data: InferModel
38 | ) {
39 | const result = await db.insert(usersToRoles).values(data).returning();
40 |
41 | return result[0];
42 | }
43 |
44 | export async function getUserByEmail({
45 | email,
46 | applicationId,
47 | }: {
48 | email: string;
49 | applicationId: string;
50 | }) {
51 | const result = await db
52 | .select({
53 | id: users.id,
54 | email: users.email,
55 | name: users.name,
56 | applicationId: users.applicationId,
57 | roleId: roles.id,
58 | password: users.password,
59 | permissions: roles.permissions,
60 | })
61 | .from(users)
62 | .where(and(eq(users.email, email), eq(users.applicationId, applicationId)))
63 | // LEFT JOIN
64 | // FROM usersToRoles
65 | // ON usersToRoles.userId = users.id
66 | // AND usersToRoles.applicationId = users.application
67 | .leftJoin(
68 | usersToRoles,
69 | and(
70 | eq(usersToRoles.userId, users.id),
71 | eq(usersToRoles.applicationId, users.applicationId)
72 | )
73 | )
74 | // LEFT JOIN
75 | // FROM roles
76 | // ON roles.id = usersToRoles.roleId
77 | .leftJoin(roles, eq(roles.id, usersToRoles.roleId));
78 |
79 | if (!result.length) {
80 | return null;
81 | }
82 |
83 | const user = result.reduce((acc, curr) => {
84 | if (!acc.id) {
85 | return {
86 | ...curr,
87 | permissions: new Set(curr.permissions),
88 | };
89 | }
90 |
91 | if (!curr.permissions) {
92 | return acc;
93 | }
94 |
95 | for (const permission of curr.permissions) {
96 | acc.permissions.add(permission);
97 | }
98 |
99 | return acc;
100 | }, {} as Omit<(typeof result)[number], "permissions"> & { permissions: Set });
101 |
102 | return {
103 | ...user,
104 | permissions: Array.from(user.permissions),
105 | };
106 | }
107 |
--------------------------------------------------------------------------------
/src/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import pino from "pino";
2 |
3 | export const logger = pino({
4 | redact: ["DATABASE_CONNECTION"],
5 | level: "debug",
6 | transport: {
7 | target: "pino-pretty",
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/src/utils/server.ts:
--------------------------------------------------------------------------------
1 | import fastify from "fastify";
2 | import guard from "fastify-guard";
3 | import { logger } from "./logger";
4 | import { applicationRoutes } from "../modules/applications/applications.routes";
5 | import { usersRoutes } from "../modules/users/users.routes";
6 | import { roleRoutes } from "../modules/roles/role.routes";
7 | import jwt from "jsonwebtoken";
8 |
9 | type User = {
10 | id: string;
11 | applicationId: string;
12 | scopes: Array;
13 | };
14 |
15 | declare module "fastify" {
16 | interface FastifyRequest {
17 | user: User;
18 | }
19 | }
20 |
21 | export async function buildServer() {
22 | const app = fastify({
23 | logger,
24 | });
25 |
26 | app.decorateRequest("user", null);
27 |
28 | app.addHook("onRequest", async function (request, reply) {
29 | const authHeader = request.headers.authorization;
30 |
31 | if (!authHeader) {
32 | return;
33 | }
34 |
35 | try {
36 | const token = authHeader.replace("Bearer ", "");
37 | const decoded = jwt.verify(token, "secret") as User;
38 |
39 | console.log("user", decoded);
40 |
41 | request.user = decoded;
42 | } catch (e) {}
43 | });
44 |
45 | // register plugins
46 | app.register(guard, {
47 | requestProperty: "user",
48 | scopeProperty: "scopes",
49 | errorHandler: (result, request, reply) => {
50 | return reply.send("you can not do that");
51 | },
52 | });
53 |
54 | // register routes
55 | app.register(applicationRoutes, { prefix: "/api/applications" });
56 | app.register(usersRoutes, { prefix: "/api/users" });
57 | app.register(roleRoutes, { prefix: "/api/roles" });
58 |
59 | return app;
60 | }
61 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | // "rootDir": "./", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | // "outDir": "./", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------