@xenterprises/fastify-xconfig 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +19 -0
- package/.taprc +3 -0
- package/README.md +18 -171
- package/dist/utils/randomUUID.d.ts +1 -1
- package/dist/xConfig.d.ts +2 -1
- package/dist/xConfig.js +7 -2
- package/dist/xConfig.js.map +1 -1
- package/example.ts +13 -0
- package/package.json +41 -22
- package/src/xConfig.ts +20 -0
- package/test/index.test-d.ts +13 -0
- package/test/index.test.js +14 -0
- package/test/xConfig.js +115 -0
- package/tsconfig.json +16 -0
- package/server/app.js +0 -85
- package/src/auth/admin.js +0 -181
- package/src/auth/portal.js +0 -177
- package/src/integrations/cloudinary.js +0 -98
- package/src/integrations/geocode.js +0 -43
- package/src/integrations/prisma.js +0 -30
- package/src/integrations/sendgrid.js +0 -58
- package/src/integrations/twilio.js +0 -146
- package/src/lifecycle/xFastifyAfter.js +0 -27
- package/src/middleware/bugsnag.js +0 -10
- package/src/middleware/cors.js +0 -10
- package/src/middleware/fancyErrors.js +0 -26
- package/src/middleware/multipart.js +0 -6
- package/src/middleware/rateLimit.js +0 -6
- package/src/middleware/underPressure.js +0 -6
- package/src/utils/colorize.js +0 -37
- package/src/utils/cookie.js +0 -5
- package/src/utils/formatBytes.js +0 -16
- package/src/utils/health.js +0 -126
- package/src/utils/xEcho.js +0 -12
- package/src/utils/xSlugify.js +0 -20
- package/src/utils/xUUID.js +0 -14
- package/src/xConfig.js +0 -117
- package/test/index.js +0 -17
- package/xConfigReference.js +0 -1526
- package/xConfigWorkingList.js +0 -720
- /package/{ts-reference → src}/integrations/cloudinary.ts +0 -0
- /package/{ts-reference → src}/integrations/prisma.ts +0 -0
- /package/{ts-reference → src}/integrations/sendgrid.ts +0 -0
- /package/{ts-reference → src}/integrations/stripe.ts +0 -0
- /package/{ts-reference → src}/integrations/twilio.ts +0 -0
- /package/{ts-reference → src}/middleware/bugsnag.ts +0 -0
- /package/{ts-reference → src}/middleware/cors.ts +0 -0
- /package/{ts-reference → src}/middleware/errorHandler.ts +0 -0
- /package/{ts-reference → src}/middleware/multipart.ts +0 -0
- /package/{ts-reference → src}/middleware/rateLimit.ts +0 -0
- /package/{ts-reference → src}/middleware/underPressure.ts +0 -0
- /package/{ts-reference → src}/utils/colorize.ts +0 -0
- /package/{ts-reference → src}/utils/formatBytes.ts +0 -0
- /package/{ts-reference → src}/utils/randomUUID.ts +0 -0
- /package/{ts-reference → src}/utils/statAsync.ts +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: CI workflow
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
test:
|
|
5
|
+
runs-on: ${{ matrix.os }}
|
|
6
|
+
strategy:
|
|
7
|
+
matrix:
|
|
8
|
+
node-version: [10.x, 12.x, 14.x]
|
|
9
|
+
os: [ubuntu-latest, windows-latest]
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v2
|
|
12
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
13
|
+
uses: actions/setup-node@v1
|
|
14
|
+
with:
|
|
15
|
+
node-version: ${{ matrix.node-version }}
|
|
16
|
+
- name: Install Dependencies
|
|
17
|
+
run: npm install --ignore-scripts
|
|
18
|
+
- name: Test
|
|
19
|
+
run: npm run test
|
package/.taprc
ADDED
package/README.md
CHANGED
|
@@ -1,182 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# __MY_PLUGIN__
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](http://standardjs.com/) 
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Supports Fastify versions `4.x`
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- Provides authentication setup for both Admin and User, with Stack Auth integration.
|
|
12
|
-
- Includes Prisma database connection and gracefully handles disconnecting on server shutdown.
|
|
13
|
-
- Adds health check routes and resource usage monitoring, with environment validation.
|
|
14
|
-
- Customizes route listing and applies various performance and security options.
|
|
8
|
+
## Install
|
|
9
|
+
```
|
|
10
|
+
npm i __MY_PLUGIN__
|
|
11
|
+
```
|
|
15
12
|
|
|
16
13
|
## Usage
|
|
14
|
+
Require `__MY_PLUGIN__` and register.
|
|
15
|
+
```js
|
|
16
|
+
const fastify = require('fastify')()
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
import Fastify from "fastify";
|
|
24
|
-
import xConfig from "./path/to/xConfig";
|
|
18
|
+
fastify.register(require('__MY_PLUGIN__'), {
|
|
19
|
+
// put your options here
|
|
20
|
+
})
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
fastify.register(xConfig, {
|
|
28
|
-
prisma: { active: true },
|
|
29
|
-
sendGrid: { apiKey: "your-sendgrid-api-key" },
|
|
30
|
-
twilio: {
|
|
31
|
-
accountSid: "your-account-sid",
|
|
32
|
-
authToken: "your-auth-token",
|
|
33
|
-
phoneNumber: "your-twilio-number",
|
|
34
|
-
},
|
|
35
|
-
cloudinary: {
|
|
36
|
-
cloudName: "your-cloud-name",
|
|
37
|
-
apiKey: "your-api-key",
|
|
38
|
-
apiSecret: "your-api-secret",
|
|
39
|
-
},
|
|
40
|
-
auth: {
|
|
41
|
-
excludedPaths: ["/public", "/portal/auth/register"],
|
|
42
|
-
admin: {
|
|
43
|
-
active: true,
|
|
44
|
-
stackProjectId: "your-admin-stack-project-id",
|
|
45
|
-
publishableKey: "your-admin-stack-publishable-key",
|
|
46
|
-
secretKey: "your-admin-stack-secret-key",
|
|
47
|
-
},
|
|
48
|
-
user: {
|
|
49
|
-
active: true,
|
|
50
|
-
stackProjectId: "your-user-stack-project-id",
|
|
51
|
-
publishableKey: "your-user-stack-publishable-key",
|
|
52
|
-
secretKey: "your-user-stack-secret-key",
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
cors: { origin: ["https://your-frontend.com"], credentials: true },
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
fastify.listen({ port: 3000 });
|
|
22
|
+
fastify.listen({ port: 3000 })
|
|
59
23
|
```
|
|
60
24
|
|
|
61
|
-
##
|
|
62
|
-
|
|
63
|
-
- **prisma**: Prisma Client configuration (optional).
|
|
64
|
-
- **sendGrid**: SendGrid configuration for email services (optional).
|
|
65
|
-
- **twilio**: Twilio configuration for SMS services (optional).
|
|
66
|
-
- **cloudinary**: Cloudinary configuration for media upload services (optional).
|
|
67
|
-
- **auth**: Authentication configuration for Admin and User with Stack Auth integration (optional).
|
|
68
|
-
- **cors**: CORS configuration (optional).
|
|
69
|
-
- **rateLimit**: Rate-limiting options (optional).
|
|
70
|
-
- **multipart**: Multipart handling options for file uploads (optional).
|
|
71
|
-
- **bugsnag**: Bugsnag error reporting configuration (optional).
|
|
72
|
-
- **underPressure**: Under Pressure plugin options for monitoring and throttling under load (optional).
|
|
73
|
-
|
|
74
|
-
## Authentication
|
|
75
|
-
|
|
76
|
-
The plugin provides both Admin and User authentication with Stack Auth integration. It handles token verification, protected routes, and authentication endpoints.
|
|
77
|
-
|
|
78
|
-
### User Authentication
|
|
79
|
-
|
|
80
|
-
- `/portal/auth/login` - User login endpoint
|
|
81
|
-
- `/portal/auth/me` - Get current user information
|
|
82
|
-
- `/portal/auth/verify` - Verify a user token
|
|
83
|
-
|
|
84
|
-
### Admin Authentication
|
|
85
|
-
|
|
86
|
-
- `/admin/auth/login` - Admin login endpoint
|
|
87
|
-
- `/admin/auth/me` - Get current admin information
|
|
88
|
-
- `/admin/auth/verify` - Verify an admin token
|
|
89
|
-
|
|
90
|
-
### Stack Auth Integration
|
|
91
|
-
|
|
92
|
-
The plugin integrates with [Stack Auth](https://stack-auth.com) for secure authentication. You'll need to provide:
|
|
93
|
-
|
|
94
|
-
- `stackProjectId` - Your Stack Auth project ID
|
|
95
|
-
- `publishableKey` - Your Stack Auth publishable client key
|
|
96
|
-
- `secretKey` - Your Stack Auth secret server key
|
|
97
|
-
|
|
98
|
-
These can be provided via environment variables or in the plugin options.
|
|
99
|
-
|
|
100
|
-
## Health Check
|
|
25
|
+
## Acknowledgements
|
|
101
26
|
|
|
102
|
-
|
|
27
|
+
## License
|
|
103
28
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
- **Prisma**: Initializes Prisma Client and decorates the Fastify instance for database queries.
|
|
107
|
-
- **SendGrid**: Provides an email sending service through SendGrid, integrated with the Fastify instance.
|
|
108
|
-
- **Twilio**: Provides SMS sending and phone number validation services.
|
|
109
|
-
- **Cloudinary**: Handles file uploads to Cloudinary and deletion of media files.
|
|
110
|
-
- **Authentication**: Stack Auth integration for secure user and admin authentication.
|
|
111
|
-
|
|
112
|
-
## Hooks
|
|
113
|
-
|
|
114
|
-
- **onRequest**: Validates tokens for protected routes.
|
|
115
|
-
- **onClose**: Gracefully disconnects Prisma and other services on server shutdown.
|
|
116
|
-
|
|
117
|
-
## Error Handling
|
|
118
|
-
|
|
119
|
-
Enhanced error handling is enabled by default, showing detailed error messages during development. Bugsnag integration is optional for real-time error reporting.
|
|
120
|
-
|
|
121
|
-
## Route Listing
|
|
122
|
-
|
|
123
|
-
The plugin prints all routes after registration, color-coded by HTTP method, unless disabled.
|
|
124
|
-
|
|
125
|
-
## Dependencies
|
|
126
|
-
|
|
127
|
-
The following dependencies are used for various services and integrations:
|
|
128
|
-
|
|
129
|
-
- Prisma Client, SendGrid, Twilio, Cloudinary, Fastify CORS, Fastify Rate Limit, Fastify Multipart, Fastify Under Pressure, and Fastify Bugsnag.
|
|
130
|
-
|
|
131
|
-
## Environment Variables
|
|
132
|
-
|
|
133
|
-
### Required for Authentication
|
|
134
|
-
|
|
135
|
-
- `ADMIN_STACK_PROJECT_ID` - Stack Auth project ID for admin authentication
|
|
136
|
-
- `ADMIN_STACK_PUBLISHABLE_CLIENT_KEY` - Stack Auth publishable key for admin authentication
|
|
137
|
-
- `ADMIN_STACK_SECRET_SERVER_KEY` - Stack Auth secret key for admin authentication
|
|
138
|
-
- `USER_STACK_PROJECT_ID` - Stack Auth project ID for user authentication
|
|
139
|
-
- `USER_STACK_PUBLISHABLE_CLIENT_KEY` - Stack Auth publishable key for user authentication
|
|
140
|
-
- `USER_STACK_SECRET_SERVER_KEY` - Stack Auth secret key for user authentication
|
|
141
|
-
|
|
142
|
-
### Other Environment Variables
|
|
143
|
-
|
|
144
|
-
- `DATABASE_URL` - Required for Prisma Client
|
|
145
|
-
- `SENDGRID_API_KEY` - Required for SendGrid integration
|
|
146
|
-
- `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, `TWILIO_PHONE_NUMBER` - Required for Twilio integration
|
|
147
|
-
- `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, `CLOUDINARY_API_SECRET` - Required for Cloudinary integration
|
|
148
|
-
|
|
149
|
-
## Example Configuration
|
|
150
|
-
|
|
151
|
-
```javascript
|
|
152
|
-
fastify.register(xConfig, {
|
|
153
|
-
prisma: { active: true },
|
|
154
|
-
sendGrid: { apiKey: "SG.your_api_key" },
|
|
155
|
-
twilio: {
|
|
156
|
-
accountSid: "ACxxxxxxxxxxxxxxxx",
|
|
157
|
-
authToken: "your_auth_token",
|
|
158
|
-
phoneNumber: "+1234567890",
|
|
159
|
-
},
|
|
160
|
-
cloudinary: {
|
|
161
|
-
cloudName: "your-cloud-name",
|
|
162
|
-
apiKey: "your-api-key",
|
|
163
|
-
apiSecret: "your-api-secret",
|
|
164
|
-
},
|
|
165
|
-
auth: {
|
|
166
|
-
excludedPaths: ["/public", "/portal/auth/login", "/portal/auth/register"],
|
|
167
|
-
admin: {
|
|
168
|
-
active: true,
|
|
169
|
-
stackProjectId: "your-admin-stack-project-id",
|
|
170
|
-
publishableKey: "your-admin-stack-publishable-key",
|
|
171
|
-
secretKey: "your-admin-stack-secret-key",
|
|
172
|
-
},
|
|
173
|
-
user: {
|
|
174
|
-
active: true,
|
|
175
|
-
stackProjectId: "your-user-stack-project-id",
|
|
176
|
-
publishableKey: "your-user-stack-publishable-key",
|
|
177
|
-
secretKey: "your-user-stack-secret-key",
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
cors: { origin: ["https://your-frontend.com"], credentials: true },
|
|
181
|
-
});
|
|
182
|
-
```
|
|
29
|
+
Licensed under [MIT](./LICENSE).<br/>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const generateUUID:
|
|
1
|
+
export declare const generateUUID: () => `${string}-${string}-${string}-${string}-${string}`;
|
package/dist/xConfig.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { FastifyInstance, FastifyPluginOptions } from "fastify";
|
|
2
|
+
declare function xConfig(fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void>;
|
|
2
3
|
declare const _default: typeof xConfig;
|
|
3
4
|
export default _default;
|
package/dist/xConfig.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
//src/xConfig.js
|
|
2
1
|
import fp from "fastify-plugin";
|
|
2
|
+
import { captureRoutes, printRoutes } from "./utils/colorize";
|
|
3
3
|
async function xConfig(fastify, options) {
|
|
4
|
-
|
|
4
|
+
// Capture routes using the hook
|
|
5
|
+
const routes = captureRoutes(fastify);
|
|
6
|
+
// After all plugins are loaded, print the routes
|
|
7
|
+
fastify.ready(() => {
|
|
8
|
+
printRoutes(routes);
|
|
9
|
+
});
|
|
5
10
|
}
|
|
6
11
|
export default fp(xConfig, {
|
|
7
12
|
name: "xConfig",
|
package/dist/xConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xConfig.js","sourceRoot":"","sources":["../src/xConfig.ts"],"names":[],"mappings":"AAAA,gBAAgB;
|
|
1
|
+
{"version":3,"file":"xConfig.js","sourceRoot":"","sources":["../src/xConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE9D,KAAK,UAAU,OAAO,CACpB,OAAwB,EACxB,OAA6B;IAE7B,gCAAgC;IAChC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAEtC,iDAAiD;IACjD,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;QACjB,WAAW,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,eAAe,EAAE,CAAC,OAAO,EAAE;IACzB,IAAI,EAAE,SAAS;CAChB,CAAC,CAAC"}
|
package/example.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FastifyPluginCallback } from 'fastify'
|
|
2
|
+
|
|
3
|
+
declare module 'fastify' {
|
|
4
|
+
export interface FastifyInstance {
|
|
5
|
+
// This is an example decorator type added to fastify
|
|
6
|
+
exampleDecorator: () => string
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare const example: FastifyPluginCallback<() => string>
|
|
11
|
+
|
|
12
|
+
export { example }
|
|
13
|
+
export default example
|
package/package.json
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xenterprises/fastify-xconfig",
|
|
3
|
-
"
|
|
4
|
-
"version": "1.0.0",
|
|
3
|
+
"version": "1.0.2",
|
|
5
4
|
"description": "Fastify configuration plugin for setting up middleware, services, and route handling.",
|
|
6
|
-
"main": "
|
|
5
|
+
"main": "dist/xConfig.js",
|
|
6
|
+
"directories": {
|
|
7
|
+
"test": "test"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
7
10
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"test": "node
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"test": "node dist/xConfig.js",
|
|
14
|
+
"lint": "standard && npm run lint:typescript",
|
|
15
|
+
"lint:typescript": "ts-standard",
|
|
16
|
+
"test:typescript": "tsd",
|
|
17
|
+
"unit": "node --test"
|
|
11
18
|
},
|
|
19
|
+
"keywords": [],
|
|
12
20
|
"author": "Tim Mushen",
|
|
13
|
-
"license": "
|
|
14
|
-
"
|
|
15
|
-
"@types/node": "^22.7.4",
|
|
16
|
-
"c8": "^9.0.0",
|
|
17
|
-
"fastify": "^4.28.1",
|
|
18
|
-
"fastify-plugin": "^4.0.0",
|
|
19
|
-
"fastify-tsconfig": "^2.0.0",
|
|
20
|
-
"typescript": "^5.6.3"
|
|
21
|
-
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"types": "dist/xConfig.d.ts",
|
|
22
23
|
"dependencies": {
|
|
23
|
-
"@fastify/autoload": "^6.0.
|
|
24
|
+
"@fastify/autoload": "^6.0.1",
|
|
24
25
|
"@fastify/cookie": "^9.4.0",
|
|
25
26
|
"@fastify/cors": "^9.0.1",
|
|
26
27
|
"@fastify/jwt": "^8.0.1",
|
|
@@ -28,21 +29,39 @@
|
|
|
28
29
|
"@fastify/rate-limit": "^9.1.0",
|
|
29
30
|
"@fastify/sensible": "^5.6.0",
|
|
30
31
|
"@fastify/under-pressure": "^9.0.1",
|
|
31
|
-
"@prisma/client": "^
|
|
32
|
+
"@prisma/client": "^5.20.0",
|
|
32
33
|
"@sendgrid/client": "^8.1.3",
|
|
33
34
|
"@sendgrid/mail": "^8.1.3",
|
|
34
35
|
"bcrypt": "^5.1.1",
|
|
35
|
-
"check-disk-space": "^3.4.0",
|
|
36
|
-
"fastify": "^4.28.1",
|
|
37
36
|
"fastify-bugsnag": "^4.1.4",
|
|
38
37
|
"fastify-cli": "^6.2.1",
|
|
39
38
|
"fastify-cloudinary": "^2.0.0",
|
|
40
39
|
"fastify-list-routes": "^1.0.0",
|
|
41
40
|
"fastify-multipart": "^5.4.0",
|
|
42
|
-
"fastify-plugin": "^4.0.0",
|
|
43
41
|
"fastify-rate-limit": "^5.9.0",
|
|
44
42
|
"stripe": "^16.12.0",
|
|
45
43
|
"twilio": "^5.3.2",
|
|
46
44
|
"uncrypto": "^0.1.3"
|
|
47
|
-
}
|
|
48
|
-
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^20.17.0",
|
|
48
|
+
"fastify": "^4.28.1",
|
|
49
|
+
"fastify-plugin": "^4.0.0",
|
|
50
|
+
"fastify-tsconfig": "^2.0.0",
|
|
51
|
+
"standard": "^17.0.0",
|
|
52
|
+
"ts-standard": "^12.0.1",
|
|
53
|
+
"tsd": "^0.31.0",
|
|
54
|
+
"typescript": "^5.6.3"
|
|
55
|
+
},
|
|
56
|
+
"tsd": {
|
|
57
|
+
"directory": "test"
|
|
58
|
+
},
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "git+https://github.com/xenterprises/module-fastify-xconfig.git"
|
|
62
|
+
},
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/xenterprises/module-fastify-xconfig/issues"
|
|
65
|
+
},
|
|
66
|
+
"homepage": "https://github.com/xenterprises/module-fastify-xconfig#readme"
|
|
67
|
+
}
|
package/src/xConfig.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fp from "fastify-plugin";
|
|
2
|
+
import type { FastifyInstance, FastifyPluginOptions } from "fastify";
|
|
3
|
+
import { captureRoutes, printRoutes } from "./utils/colorize";
|
|
4
|
+
|
|
5
|
+
async function xConfig(
|
|
6
|
+
fastify: FastifyInstance,
|
|
7
|
+
options: FastifyPluginOptions
|
|
8
|
+
) {
|
|
9
|
+
// Capture routes using the hook
|
|
10
|
+
const routes = captureRoutes(fastify);
|
|
11
|
+
|
|
12
|
+
// After all plugins are loaded, print the routes
|
|
13
|
+
fastify.ready(() => {
|
|
14
|
+
printRoutes(routes);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default fp(xConfig, {
|
|
19
|
+
name: "xConfig",
|
|
20
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fastify from 'fastify'
|
|
2
|
+
import example from '../example'
|
|
3
|
+
import { expectType } from 'tsd'
|
|
4
|
+
|
|
5
|
+
let app
|
|
6
|
+
try {
|
|
7
|
+
app = fastify()
|
|
8
|
+
void app.ready()
|
|
9
|
+
void app.register(example)
|
|
10
|
+
expectType<() => string>(app.exampleDecorator)
|
|
11
|
+
} catch (err) {
|
|
12
|
+
console.error(err)
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const assert = require('node:assert')
|
|
5
|
+
|
|
6
|
+
test('should register the correct decorator', async t => {
|
|
7
|
+
const app = require('fastify')()
|
|
8
|
+
|
|
9
|
+
app.register(require('..'))
|
|
10
|
+
|
|
11
|
+
await app.ready()
|
|
12
|
+
|
|
13
|
+
assert.equal(app.exampleDecorator(), 'decorated')
|
|
14
|
+
})
|
package/test/xConfig.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import * as assert from 'node:assert';
|
|
3
|
+
import Fastify from 'fastify';
|
|
4
|
+
import xConfig from '../path/to/xConfig.js'; // Adjust the path accordingly
|
|
5
|
+
|
|
6
|
+
test('xConfig plugin works standalone', async (t) => {
|
|
7
|
+
const fastify = Fastify();
|
|
8
|
+
|
|
9
|
+
// Register the xConfig plugin with necessary options
|
|
10
|
+
await fastify.register(xConfig, {
|
|
11
|
+
prisma: { active: false }, // Mocked or disabled for testing
|
|
12
|
+
sendGrid: { active: false },
|
|
13
|
+
twilio: { active: false },
|
|
14
|
+
stripe: { active: false },
|
|
15
|
+
auth: {
|
|
16
|
+
admin: { active: false },
|
|
17
|
+
user: { active: false }
|
|
18
|
+
},
|
|
19
|
+
cors: { active: true },
|
|
20
|
+
underPressure: { active: false },
|
|
21
|
+
rateLimit: { active: false }
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await fastify.ready();
|
|
25
|
+
|
|
26
|
+
// Test if the plugin registered correctly
|
|
27
|
+
assert.ok(fastify.prisma === undefined, 'Prisma should not be registered');
|
|
28
|
+
assert.ok(fastify.sendGrid === undefined, 'SendGrid should not be registered');
|
|
29
|
+
assert.ok(fastify.stripe === undefined, 'Stripe should not be registered');
|
|
30
|
+
|
|
31
|
+
// Test if health route is registered and works
|
|
32
|
+
const response = await fastify.inject({
|
|
33
|
+
method: 'GET',
|
|
34
|
+
url: '/health'
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const body = JSON.parse(response.body);
|
|
38
|
+
assert.strictEqual(response.statusCode, 200, 'Health route should return status 200');
|
|
39
|
+
assert.strictEqual(body.status, 'healthy', 'Health status should be healthy');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('xConfig CORS is enabled', async (t) => {
|
|
43
|
+
const fastify = Fastify();
|
|
44
|
+
|
|
45
|
+
// Register the xConfig plugin with CORS enabled
|
|
46
|
+
await fastify.register(xConfig, {
|
|
47
|
+
cors: {
|
|
48
|
+
active: true,
|
|
49
|
+
origin: ['http://localhost:3000'],
|
|
50
|
+
credentials: true
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
await fastify.ready();
|
|
55
|
+
|
|
56
|
+
// Check if the CORS headers are returned correctly
|
|
57
|
+
const response = await fastify.inject({
|
|
58
|
+
method: 'OPTIONS',
|
|
59
|
+
url: '/',
|
|
60
|
+
headers: {
|
|
61
|
+
origin: 'http://localhost:3000'
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
assert.strictEqual(response.headers['access-control-allow-origin'], 'http://localhost:3000');
|
|
66
|
+
assert.strictEqual(response.headers['access-control-allow-credentials'], 'true');
|
|
67
|
+
assert.strictEqual(response.statusCode, 204, 'CORS preflight request should return 204');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('xConfig routes are listed correctly', async (t) => {
|
|
71
|
+
const fastify = Fastify();
|
|
72
|
+
|
|
73
|
+
// Register xConfig plugin with a dummy route to check if routes are listed
|
|
74
|
+
await fastify.register(xConfig, {
|
|
75
|
+
prisma: { active: false },
|
|
76
|
+
auth: { admin: { active: false }, user: { active: false } }
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
fastify.get('/test-route', async (request, reply) => {
|
|
80
|
+
reply.send({ message: 'Test Route' });
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await fastify.ready();
|
|
84
|
+
|
|
85
|
+
// Test if the '/test-route' is available
|
|
86
|
+
const response = await fastify.inject({
|
|
87
|
+
method: 'GET',
|
|
88
|
+
url: '/test-route'
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
assert.strictEqual(response.statusCode, 200, 'Test route should return 200');
|
|
92
|
+
assert.strictEqual(JSON.parse(response.body).message, 'Test Route');
|
|
93
|
+
|
|
94
|
+
// Check if routes are printed correctly (this is more of a manual log observation)
|
|
95
|
+
fastify.ready(() => {
|
|
96
|
+
fastify.printRoutes(); // This will print routes to console
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('xConfig fails if required options are missing', async (t) => {
|
|
101
|
+
const fastify = Fastify();
|
|
102
|
+
|
|
103
|
+
// Test missing required options like SendGrid API Key
|
|
104
|
+
try {
|
|
105
|
+
await fastify.register(xConfig, {
|
|
106
|
+
sendGrid: { active: true }
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
await fastify.ready();
|
|
110
|
+
assert.fail('Should have thrown an error due to missing SendGrid API Key');
|
|
111
|
+
} catch (err) {
|
|
112
|
+
assert.ok(err instanceof Error, 'Should throw an error');
|
|
113
|
+
assert.strictEqual(err.message, 'SendGrid API key must be provided.');
|
|
114
|
+
}
|
|
115
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"declaration": true, // Generates .d.ts files for types
|
|
6
|
+
"outDir": "./dist", // Output directory for compiled files
|
|
7
|
+
"strict": true, // Enable all strict type-checking options
|
|
8
|
+
"moduleResolution": "node", // Proper module resolution
|
|
9
|
+
"esModuleInterop": true, // Allows default imports from CJS modules
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"sourceMap": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"], // Specifies files to include for compilation
|
|
15
|
+
"exclude": ["node_modules", "dist"]
|
|
16
|
+
}
|
package/server/app.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// server/app.js
|
|
2
|
-
import Fastify from 'fastify';
|
|
3
|
-
import xConfig from '../src/xConfig.js'; // Import your plugin correctly
|
|
4
|
-
|
|
5
|
-
const fastify = Fastify();
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export default async function (fastify, opts) {
|
|
9
|
-
fastify.register(xConfig, {
|
|
10
|
-
professional: false,
|
|
11
|
-
fancyErrors: true,
|
|
12
|
-
prisma: {
|
|
13
|
-
active: false,
|
|
14
|
-
},
|
|
15
|
-
bugsnag: {
|
|
16
|
-
apiKey: process.env.BUGSNAG_API_KEY
|
|
17
|
-
},
|
|
18
|
-
rateLimit: {
|
|
19
|
-
max: process.env.RATE_LIMIT_MAX || 100,
|
|
20
|
-
timeWindow: process.env.RATE_LIMIT_TIME_WINDOW || '1 minute'
|
|
21
|
-
},
|
|
22
|
-
stripe: {
|
|
23
|
-
active: false,
|
|
24
|
-
apiKey: process.env.STRIPE_API_KEY
|
|
25
|
-
},
|
|
26
|
-
sendGrid: {
|
|
27
|
-
active: true,
|
|
28
|
-
apiKey: process.env.SENDGRID_API_KEY,
|
|
29
|
-
apiKeyEmailValidation: process.env.SENDGRID_API_EMAIL_VALIDATION_KEY,
|
|
30
|
-
fromEmail: process.env.SENDGRID_FROM_EMAIL || 'ops@getx.io',
|
|
31
|
-
},
|
|
32
|
-
twilio: {
|
|
33
|
-
active: true,
|
|
34
|
-
accountSid: process.env.TWILIO_ACCOUNT_SID,
|
|
35
|
-
authToken: process.env.TWILIO_AUTH_TOKEN,
|
|
36
|
-
phoneNumber: process.env.TWILIO_PHONE_NUMBER
|
|
37
|
-
},
|
|
38
|
-
cloudinary: {
|
|
39
|
-
active: false,
|
|
40
|
-
cloudName: process.env.CLOUDINARY_CLOUD_NAME,
|
|
41
|
-
apiKey: process.env.CLOUDINARY_API_KEY,
|
|
42
|
-
apiSecret: process.env.CLOUDINARY_API_SECRET,
|
|
43
|
-
basePath: process.env.CLOUDINARY_BASE_PATH || 'basepath'
|
|
44
|
-
},
|
|
45
|
-
cors: {
|
|
46
|
-
active: true,
|
|
47
|
-
origin: process.env.CORS_ORIGIN || ['http://localhost:3000', 'https://app.bandmate.io'],
|
|
48
|
-
credentials: true
|
|
49
|
-
},
|
|
50
|
-
auth: {
|
|
51
|
-
excludedPaths: ['/public', '/portal/auth/register'],
|
|
52
|
-
admin: {
|
|
53
|
-
active: true,
|
|
54
|
-
secret: process.env.ADMIN_JWT_SECRET,
|
|
55
|
-
expiresIn: '1h',
|
|
56
|
-
cookieOptions: {
|
|
57
|
-
name: 'adminToken',
|
|
58
|
-
httpOnly: true,
|
|
59
|
-
secure: true, // Set to false if not using HTTPS
|
|
60
|
-
sameSite: 'strict', // Can be 'lax', 'strict', or 'none'
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
user: {
|
|
64
|
-
active: true,
|
|
65
|
-
portalStackProjectId: process.env.STACK_PROJECT_ID,
|
|
66
|
-
me: {
|
|
67
|
-
isOnboarded: true
|
|
68
|
-
},
|
|
69
|
-
registerEmail: {
|
|
70
|
-
subject: 'Welcome to Bandmate!',
|
|
71
|
-
templateId: ''
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
geocode: {
|
|
76
|
-
active: true,
|
|
77
|
-
apiKey: process.env.GEOCODIO_API_KEY
|
|
78
|
-
}
|
|
79
|
-
}); // Register the default export, which should be a function
|
|
80
|
-
fastify.get('/', async (request, reply) => {
|
|
81
|
-
console.log(fastify.xEcho())
|
|
82
|
-
return { status: fastify.xEcho() }
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
};
|