saas-backend-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/PUBLISHING.md +133 -0
- package/README.md +459 -0
- package/copy-dts.js +255 -0
- package/dist/auth/index.d.ts +58 -0
- package/dist/auth/index.js +584 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +569 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/config/index.d.ts +22 -0
- package/dist/config/index.js +106 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +100 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +1303 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1281 -0
- package/dist/index.mjs.map +1 -0
- package/dist/logger/index.d.ts +18 -0
- package/dist/logger/index.js +188 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/index.mjs +178 -0
- package/dist/logger/index.mjs.map +1 -0
- package/dist/notifications/index.d.ts +35 -0
- package/dist/notifications/index.js +339 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/index.mjs +328 -0
- package/dist/notifications/index.mjs.map +1 -0
- package/dist/queue/index.d.ts +33 -0
- package/dist/queue/index.js +306 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/index.mjs +293 -0
- package/dist/queue/index.mjs.map +1 -0
- package/dist/rate-limit/index.d.ts +11 -0
- package/dist/rate-limit/index.js +290 -0
- package/dist/rate-limit/index.js.map +1 -0
- package/dist/rate-limit/index.mjs +286 -0
- package/dist/rate-limit/index.mjs.map +1 -0
- package/dist/response/index.d.ts +29 -0
- package/dist/response/index.js +120 -0
- package/dist/response/index.js.map +1 -0
- package/dist/response/index.mjs +114 -0
- package/dist/response/index.mjs.map +1 -0
- package/examples/express/.env.example +41 -0
- package/examples/express/app.ts +203 -0
- package/package.json +109 -0
- package/src/auth/express.ts +250 -0
- package/src/auth/fastify.ts +65 -0
- package/src/auth/index.ts +6 -0
- package/src/auth/jwt.ts +47 -0
- package/src/auth/oauth.ts +117 -0
- package/src/auth/rbac.ts +82 -0
- package/src/auth/types.ts +69 -0
- package/src/config/index.ts +120 -0
- package/src/index.ts +16 -0
- package/src/logger/index.ts +110 -0
- package/src/notifications/index.ts +262 -0
- package/src/plugin.ts +192 -0
- package/src/queue/index.ts +208 -0
- package/src/rate-limit/express.ts +144 -0
- package/src/rate-limit/fastify.ts +47 -0
- package/src/rate-limit/index.ts +2 -0
- package/src/response/index.ts +197 -0
- package/src/utils/index.ts +180 -0
- package/tsconfig.json +30 -0
- package/tsup.config.ts +24 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2024-01-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Authentication module with JWT support
|
|
12
|
+
- Role-Based Access Control (RBAC)
|
|
13
|
+
- Google OAuth integration
|
|
14
|
+
- Task Queue System based on BullMQ
|
|
15
|
+
- Notification Service (Email, SMS, Webhooks, Slack)
|
|
16
|
+
- Structured Logger using Pino
|
|
17
|
+
- Rate Limiting middleware
|
|
18
|
+
- Config Manager with Zod validation
|
|
19
|
+
- API Response Helpers
|
|
20
|
+
- Plugin Architecture
|
|
21
|
+
- Full TypeScript support
|
|
22
|
+
- Tree-shakeable modules
|
|
23
|
+
- Express and Fastify support
|
|
24
|
+
|
|
25
|
+
## [1.0.0-beta.1] - 2024-12-01
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- Initial beta release
|
|
29
|
+
- Core authentication features
|
|
30
|
+
- Basic queue implementation
|
|
31
|
+
- Email notifications
|
package/PUBLISHING.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# npm Publishing Instructions
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
1. Node.js 18+ installed
|
|
6
|
+
2. npm account (https://www.npmjs.com)
|
|
7
|
+
3. Git repository initialized
|
|
8
|
+
|
|
9
|
+
## Preparation
|
|
10
|
+
|
|
11
|
+
1. Update `package.json`:
|
|
12
|
+
- Update `version` (follow semver)
|
|
13
|
+
- Update `author` field
|
|
14
|
+
- Update `repository` field
|
|
15
|
+
- Update `keywords`
|
|
16
|
+
|
|
17
|
+
2. Build the package:
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
npm run build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
3. Test locally:
|
|
24
|
+
```bash
|
|
25
|
+
npm link
|
|
26
|
+
# In a test project
|
|
27
|
+
npm link saas-backend-kit
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Publishing
|
|
31
|
+
|
|
32
|
+
### Option 1: Publish to npm (public)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm login
|
|
36
|
+
npm publish --access public
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Option 2: Publish to npm (private - paid plan)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm login
|
|
43
|
+
npm publish
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Option 3: Publish to GitHub Package Registry
|
|
47
|
+
|
|
48
|
+
Add to `.npmrc`:
|
|
49
|
+
```
|
|
50
|
+
@yourusername:registry=https://npm.pkg.github.com
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm login --registry=https://npm.pkg.github.com
|
|
55
|
+
npm publish
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Version Management
|
|
59
|
+
|
|
60
|
+
Use semantic versioning:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Patch release
|
|
64
|
+
npm version patch
|
|
65
|
+
|
|
66
|
+
# Minor release
|
|
67
|
+
npm version minor
|
|
68
|
+
|
|
69
|
+
# Major release
|
|
70
|
+
npm version major
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This will:
|
|
74
|
+
1. Update version in package.json
|
|
75
|
+
2. Create a git tag
|
|
76
|
+
3. Commit changes
|
|
77
|
+
|
|
78
|
+
Then publish:
|
|
79
|
+
```bash
|
|
80
|
+
git push && git push --tags
|
|
81
|
+
npm publish
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## After Publishing
|
|
85
|
+
|
|
86
|
+
1. Create a GitHub release with the new version tag
|
|
87
|
+
2. Update CHANGELOG.md
|
|
88
|
+
3. Announce on social media
|
|
89
|
+
|
|
90
|
+
## Automation with GitHub Actions
|
|
91
|
+
|
|
92
|
+
Create `.github/workflows/publish.yml`:
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
name: Publish to npm
|
|
96
|
+
|
|
97
|
+
on:
|
|
98
|
+
release:
|
|
99
|
+
types: [created]
|
|
100
|
+
|
|
101
|
+
jobs:
|
|
102
|
+
publish:
|
|
103
|
+
runs-on: ubuntu-latest
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/checkout@v4
|
|
106
|
+
|
|
107
|
+
- uses: actions/setup-node@v4
|
|
108
|
+
with:
|
|
109
|
+
node-version: '20'
|
|
110
|
+
registry-url: 'https://registry.npmjs.org'
|
|
111
|
+
|
|
112
|
+
- run: npm ci
|
|
113
|
+
- run: npm run build
|
|
114
|
+
- run: npm test
|
|
115
|
+
|
|
116
|
+
- run: npm publish --access public
|
|
117
|
+
env:
|
|
118
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Troubleshooting
|
|
122
|
+
|
|
123
|
+
### Error: "You do not have permission to publish"
|
|
124
|
+
|
|
125
|
+
- Make sure you're logged in to the correct npm account
|
|
126
|
+
- Check if the package name is available
|
|
127
|
+
- Verify your npm account has publishing rights for scoped packages
|
|
128
|
+
|
|
129
|
+
### Error: "Token not recognized"
|
|
130
|
+
|
|
131
|
+
- Regenerate your npm token
|
|
132
|
+
- Ensure the token has publish permissions
|
|
133
|
+
- Check your `.npmrc` file for correct configuration
|
package/README.md
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
# SaaS Backend Kit
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/saas-backend-kit">
|
|
5
|
+
<img src="https://img.shields.io/npm/v/saas-backend-kit.svg" alt="npm version">
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/saas-backend-kit">
|
|
8
|
+
<img src="https://img.shields.io/npm/dt/saas-backend-kit.svg" alt="npm downloads">
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://opensource.org/licenses/MIT">
|
|
11
|
+
<img src="https://img.shields.io/npm/l/saas-backend-kit.svg" alt="MIT License">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://github.com/yourusername/saas-backend-kit/actions">
|
|
14
|
+
<img src="https://github.com/yourusername/saas-backend-kit/workflows/CI/badge.svg" alt="CI">
|
|
15
|
+
</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
> Production-grade modular backend toolkit for building scalable SaaS applications with Node.js
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- **Authentication Module** - JWT authentication, RBAC, Google OAuth
|
|
23
|
+
- **Task Queue System** - Redis-based job queue (BullMQ)
|
|
24
|
+
- **Notification Service** - Email, SMS (Twilio), Webhooks, Slack
|
|
25
|
+
- **Logger** - Structured JSON logging with Pino
|
|
26
|
+
- **Rate Limiting** - Configurable API rate limiting
|
|
27
|
+
- **Config Manager** - Environment variable validation with Zod
|
|
28
|
+
- **API Response Helpers** - Standardized response format
|
|
29
|
+
- **Plugin Architecture** - Modular enable/disable features
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install saas-backend-kit
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import express from 'express';
|
|
41
|
+
import { auth, rateLimit, logger, config, queue, notify, response, createApp } from 'saas-backend-kit';
|
|
42
|
+
|
|
43
|
+
config.load();
|
|
44
|
+
|
|
45
|
+
const app = express();
|
|
46
|
+
app.use(express.json());
|
|
47
|
+
|
|
48
|
+
// Initialize auth
|
|
49
|
+
const authMiddleware = auth.initialize({
|
|
50
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
51
|
+
jwtExpiresIn: '7d',
|
|
52
|
+
});
|
|
53
|
+
app.use(authMiddleware);
|
|
54
|
+
|
|
55
|
+
// Apply rate limiting
|
|
56
|
+
app.use(rateLimit({ window: '1m', limit: 100 }));
|
|
57
|
+
|
|
58
|
+
// Protected route
|
|
59
|
+
app.get('/dashboard', auth.requireUser(), (req, res) => {
|
|
60
|
+
res.success({ message: 'Welcome to your dashboard', user: req.user });
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
app.listen(3000, () => logger.info('Server running'));
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Modules
|
|
67
|
+
|
|
68
|
+
### Authentication
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { auth } from 'saas-backend-kit';
|
|
72
|
+
|
|
73
|
+
const authMiddleware = auth.initialize({
|
|
74
|
+
jwtSecret: 'your-secret-key',
|
|
75
|
+
jwtExpiresIn: '7d',
|
|
76
|
+
refreshExpiresIn: '30d',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
app.use(authMiddleware);
|
|
80
|
+
|
|
81
|
+
// Registration
|
|
82
|
+
app.post('/auth/register', async (req, res) => {
|
|
83
|
+
const { email, password, name } = req.body;
|
|
84
|
+
const result = await auth().register({ email, password, name });
|
|
85
|
+
res.success(result.tokens, 'Registration successful');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Login
|
|
89
|
+
app.post('/auth/login', async (req, res) => {
|
|
90
|
+
const { email, password } = req.body;
|
|
91
|
+
const result = await auth().login({ email, password });
|
|
92
|
+
res.success(result.tokens, 'Login successful');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Route protection
|
|
96
|
+
app.get('/dashboard', auth.requireUser(), (req, res) => {
|
|
97
|
+
res.success({ user: req.user });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
app.get('/admin', auth.requireRole('admin'), (req, res) => {
|
|
101
|
+
res.success({ message: 'Admin area' });
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
app.get('/protected', auth.requirePermission('read'), (req, res) => {
|
|
105
|
+
res.success({ message: 'Access granted' });
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Role-Based Access Control (RBAC)
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { rbacService } from 'saas-backend-kit/auth';
|
|
113
|
+
|
|
114
|
+
rbacService.setPermissions({
|
|
115
|
+
admin: ['*'],
|
|
116
|
+
manager: ['read', 'write', 'delete:own'],
|
|
117
|
+
user: ['read', 'write:own'],
|
|
118
|
+
guest: ['read:public'],
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Check permissions
|
|
122
|
+
if (rbacService.hasPermission(user.role, 'write:own')) {
|
|
123
|
+
// Allow action
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Google OAuth
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Get Google auth URL
|
|
131
|
+
app.get('/auth/google', async (req, res) => {
|
|
132
|
+
const url = await auth().getGoogleAuthUrl();
|
|
133
|
+
res.redirect(url);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Handle callback
|
|
137
|
+
app.get('/auth/google/callback', async (req, res) => {
|
|
138
|
+
const { code } = req.query;
|
|
139
|
+
const result = await auth().handleGoogleCallback(code as string);
|
|
140
|
+
res.success(result.tokens);
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Task Queue
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { queue } from 'saas-backend-kit';
|
|
148
|
+
|
|
149
|
+
// Create a queue
|
|
150
|
+
const emailQueue = queue.create('email', {
|
|
151
|
+
defaultJobOptions: {
|
|
152
|
+
attempts: 3,
|
|
153
|
+
backoff: { type: 'exponential', delay: 1000 },
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Add jobs
|
|
158
|
+
await emailQueue.add('sendWelcomeEmail', { userId: '123', email: 'user@example.com' });
|
|
159
|
+
|
|
160
|
+
// Delayed job
|
|
161
|
+
await emailQueue.add('sendReminder', { userId: '123' }, { delay: 3600000 });
|
|
162
|
+
|
|
163
|
+
// Process jobs
|
|
164
|
+
queue.process('email', async (job) => {
|
|
165
|
+
logger.info(`Processing ${job.name}`, { jobId: job.id });
|
|
166
|
+
await notify.email({
|
|
167
|
+
to: job.data.email,
|
|
168
|
+
subject: 'Welcome!',
|
|
169
|
+
template: 'welcome',
|
|
170
|
+
templateData: { name: 'User' },
|
|
171
|
+
});
|
|
172
|
+
return { sent: true };
|
|
173
|
+
}, { concurrency: 5 });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Notifications
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { notify } from 'saas-backend-kit';
|
|
180
|
+
|
|
181
|
+
// Email
|
|
182
|
+
await notify.email({
|
|
183
|
+
to: 'user@example.com',
|
|
184
|
+
subject: 'Welcome',
|
|
185
|
+
template: 'welcome',
|
|
186
|
+
templateData: { name: 'John', appName: 'MyApp' },
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// SMS
|
|
190
|
+
await notify.sms({
|
|
191
|
+
to: '+1234567890',
|
|
192
|
+
message: 'Your verification code is 123456',
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Webhook
|
|
196
|
+
await notify.webhook({
|
|
197
|
+
url: 'https://api.example.com/webhook',
|
|
198
|
+
method: 'POST',
|
|
199
|
+
body: { event: 'user.created', data: { id: '123' } },
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Slack
|
|
203
|
+
await notify.slack({
|
|
204
|
+
text: 'New user registered!',
|
|
205
|
+
blocks: [
|
|
206
|
+
{
|
|
207
|
+
type: 'section',
|
|
208
|
+
text: { type: 'mrkdwn', text: 'New user registered: *john@example.com*' }
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Logger
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { logger } from 'saas-backend-kit';
|
|
218
|
+
|
|
219
|
+
logger.info('Server started', { port: 3000 });
|
|
220
|
+
logger.error('Connection failed', { error: err.message });
|
|
221
|
+
logger.warn('Rate limit approaching', { ip: req.ip });
|
|
222
|
+
|
|
223
|
+
// Child logger
|
|
224
|
+
const childLogger = logger.child({ module: 'auth' });
|
|
225
|
+
childLogger.info('User logged in', { userId: '123' });
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Rate Limiting
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { rateLimit } from 'saas-backend-kit';
|
|
232
|
+
|
|
233
|
+
// Global rate limit
|
|
234
|
+
app.use(rateLimit({
|
|
235
|
+
window: '1m',
|
|
236
|
+
limit: 100,
|
|
237
|
+
}));
|
|
238
|
+
|
|
239
|
+
// Per-route rate limit
|
|
240
|
+
app.get('/api/expensive', rateLimit({ window: '1m', limit: 10 }), (req, res) => {
|
|
241
|
+
res.success({ data: 'expensive operation' });
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Custom key generator
|
|
245
|
+
app.use(rateLimit({
|
|
246
|
+
window: '1m',
|
|
247
|
+
limit: 100,
|
|
248
|
+
keyGenerator: (req) => req.user?.id || req.ip,
|
|
249
|
+
}));
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Config Manager
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { config } from 'saas-backend-kit';
|
|
256
|
+
|
|
257
|
+
// Load and validate env vars
|
|
258
|
+
config.load();
|
|
259
|
+
|
|
260
|
+
// Get values
|
|
261
|
+
const port = config.int('PORT');
|
|
262
|
+
const isProduction = config.isProduction();
|
|
263
|
+
const dbUrl = config.get('DATABASE_URL');
|
|
264
|
+
|
|
265
|
+
// Custom schema
|
|
266
|
+
const customConfig = config.create({
|
|
267
|
+
schema: z.object({
|
|
268
|
+
API_KEY: z.string(),
|
|
269
|
+
MAX_CONNECTIONS: z.number().default(100),
|
|
270
|
+
}),
|
|
271
|
+
validate: true,
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### API Response Helpers
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Success responses
|
|
279
|
+
res.success({ user }, 'User found');
|
|
280
|
+
res.created({ id: '123' }, 'User created');
|
|
281
|
+
res.updated(user, 'User updated');
|
|
282
|
+
res.deleted Paginated response('User deleted');
|
|
283
|
+
|
|
284
|
+
//
|
|
285
|
+
res.pag, limit, total);
|
|
286
|
+
|
|
287
|
+
// Error responses
|
|
288
|
+
inated(users, pageres.badInvalid inputauthorized('Please');
|
|
289
|
+
res.unRequest(' login');
|
|
290
|
+
res.forbidden('Access denied');
|
|
291
|
+
res.notFound('User not found');
|
|
292
|
+
res failed', { fields.validationError('Validation: errors('Something });
|
|
293
|
+
res.internalError went wrong');
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Plugin Architecture
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { createApp, Plugin } from 'saas-backend-kit';
|
|
300
|
+
|
|
301
|
+
const myPlugin: Plugin = {
|
|
302
|
+
name: 'my-plugin',
|
|
303
|
+
initialize: (app) => {
|
|
304
|
+
console.log('Plugin initialized');
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const app = createApp({
|
|
309
|
+
auth: true,
|
|
310
|
+
queue: { redisUrl: 'redis://localhost:6379' },
|
|
311
|
+
notifications: true,
|
|
312
|
+
rateLimit: { window: '1m', limit: 100 },
|
|
313
|
+
})
|
|
314
|
+
.use(myPlugin);
|
|
315
|
+
|
|
316
|
+
await app.initialize(expressApp);
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Framework Support
|
|
320
|
+
|
|
321
|
+
### Express
|
|
322
|
+
|
|
323
|
+
All examples above use Express. The library automatically extends the Response object with helper methods.
|
|
324
|
+
|
|
325
|
+
### Fastify
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import Fastify from 'fastify';
|
|
329
|
+
import { registerAuthPlugin, registerRateLimitPlugin, auth } from 'saas-backend-kit';
|
|
330
|
+
|
|
331
|
+
const fastify = Fastify();
|
|
332
|
+
|
|
333
|
+
fastify.register(registerAuthPlugin, { authService: auth() });
|
|
334
|
+
fastify.register(registerRateLimitPlugin, { window: '1m', limit: 100 });
|
|
335
|
+
|
|
336
|
+
fastify.get('/dashboard', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
|
337
|
+
return { user: request.user };
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Environment Variables
|
|
342
|
+
|
|
343
|
+
```env
|
|
344
|
+
NODE_ENV=development
|
|
345
|
+
PORT=3000
|
|
346
|
+
|
|
347
|
+
# JWT
|
|
348
|
+
JWT_SECRET=your-secret-key-min-32-chars
|
|
349
|
+
JWT_EXPIRES_IN=7d
|
|
350
|
+
JWT_REFRESH_SECRET=your-refresh-secret
|
|
351
|
+
JWT_REFRESH_EXPIRES_IN=30d
|
|
352
|
+
|
|
353
|
+
# Redis
|
|
354
|
+
REDIS_URL=redis://localhost:6379
|
|
355
|
+
|
|
356
|
+
# Google OAuth
|
|
357
|
+
GOOGLE_CLIENT_ID=
|
|
358
|
+
GOOGLE_CLIENT_SECRET=
|
|
359
|
+
GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback
|
|
360
|
+
|
|
361
|
+
# SMTP
|
|
362
|
+
SMTP_HOST=smtp.example.com
|
|
363
|
+
SMTP_PORT=587
|
|
364
|
+
SMTP_USER=
|
|
365
|
+
SMTP_PASS=
|
|
366
|
+
SMTP_FROM=noreply@domain.com
|
|
367
|
+
|
|
368
|
+
# Twilio
|
|
369
|
+
TWILIO_ACCOUNT_SID=
|
|
370
|
+
TWILIO_AUTH_TOKEN=
|
|
371
|
+
TWILIO_PHONE_NUMBER=
|
|
372
|
+
|
|
373
|
+
# Slack
|
|
374
|
+
SLACK_WEBHOOK_URL=
|
|
375
|
+
|
|
376
|
+
# Rate Limiting
|
|
377
|
+
RATE_LIMIT_WINDOW=1m
|
|
378
|
+
RATE_LIMIT_LIMIT=100
|
|
379
|
+
|
|
380
|
+
# Logger
|
|
381
|
+
LOG_LEVEL=info
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Project Structure
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
saas-backend-kit/
|
|
388
|
+
├── src/
|
|
389
|
+
│ ├── auth/ # Authentication module
|
|
390
|
+
│ │ ├── types.ts
|
|
391
|
+
│ │ ├── jwt.ts
|
|
392
|
+
│ │ ├── rbac.ts
|
|
393
|
+
│ │ ├── oauth.ts
|
|
394
|
+
│ │ ├── express.ts
|
|
395
|
+
│ │ ├── fastify.ts
|
|
396
|
+
│ │ └── index.ts
|
|
397
|
+
│ ├── queue/ # Task queue (BullMQ)
|
|
398
|
+
│ ├── notifications/ # Email, SMS, Webhooks, Slack
|
|
399
|
+
│ ├── logger/ # Pino logger
|
|
400
|
+
│ ├── rate-limit/ # Rate limiting
|
|
401
|
+
│ ├── config/ # Config manager
|
|
402
|
+
│ ├── response/ # Response helpers
|
|
403
|
+
│ ├── utils/ # Utilities
|
|
404
|
+
│ ├── plugin.ts # Plugin architecture
|
|
405
|
+
│ └── index.ts # Main exports
|
|
406
|
+
├── examples/
|
|
407
|
+
│ └── express/
|
|
408
|
+
├── package.json
|
|
409
|
+
├── tsconfig.json
|
|
410
|
+
└── tsup.config.ts
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## TypeScript
|
|
414
|
+
|
|
415
|
+
This library is written in TypeScript and provides full type definitions out of the box.
|
|
416
|
+
|
|
417
|
+
## Tree Shaking
|
|
418
|
+
|
|
419
|
+
All modules are exported separately for optimal tree shaking:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
import { auth } from 'saas-backend-kit/auth';
|
|
423
|
+
import { queue } from 'saas-backend-kit/queue';
|
|
424
|
+
import { logger } from 'saas-backend-kit/logger';
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Testing
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
npm test
|
|
431
|
+
npm run test:watch
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Linting
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
npm run lint
|
|
438
|
+
npm run typecheck
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Building
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
npm run build
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## License
|
|
448
|
+
|
|
449
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
450
|
+
|
|
451
|
+
## Contributing
|
|
452
|
+
|
|
453
|
+
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
Built with ❤️ for the SaaS community
|
|
458
|
+
# saas-backend-kit
|
|
459
|
+
|