saas-backend-kit 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/README.md +123 -344
- package/copy-dts.js +59 -0
- package/dist/auth/index.js +7 -2
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +7 -2
- package/dist/auth/index.mjs.map +1 -1
- package/dist/config/index.js +6 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/index.mjs +6 -1
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +232 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +231 -42
- package/dist/index.mjs.map +1 -1
- package/dist/logger/index.js +6 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/logger/index.mjs +6 -1
- package/dist/logger/index.mjs.map +1 -1
- package/dist/notifications/index.js +6 -1
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/index.mjs +6 -1
- package/dist/notifications/index.mjs.map +1 -1
- package/dist/queue/index.js +6 -1
- package/dist/queue/index.js.map +1 -1
- package/dist/queue/index.mjs +6 -1
- package/dist/queue/index.mjs.map +1 -1
- package/dist/rate-limit/index.js +7 -1
- package/dist/rate-limit/index.js.map +1 -1
- package/dist/rate-limit/index.mjs +7 -1
- package/dist/rate-limit/index.mjs.map +1 -1
- package/dist/response/index.js +51 -40
- package/dist/response/index.js.map +1 -1
- package/dist/response/index.mjs +51 -40
- package/dist/response/index.mjs.map +1 -1
- package/dist/upload/index.d.ts +57 -0
- package/dist/upload/index.js +344 -0
- package/dist/upload/index.js.map +1 -0
- package/dist/upload/index.mjs +334 -0
- package/dist/upload/index.mjs.map +1 -0
- package/jest-output.json +72 -0
- package/jest.config.js +19 -0
- package/package.json +20 -8
- package/saas-banner.svg +239 -0
- package/src/auth/jwt.ts +1 -1
- package/src/config/index.ts +5 -0
- package/src/index.ts +2 -0
- package/src/rate-limit/express.ts +1 -0
- package/src/response/index.ts +49 -40
- package/src/upload/index.ts +268 -0
- package/tests/auth.test.ts +134 -0
- package/tests/config.test.ts +36 -0
- package/tests/logger.test.ts +47 -0
- package/tests/notifications.test.ts +19 -0
- package/tests/rate-limit.test.ts +50 -0
- package/tests/upload.test.ts +33 -0
- package/tsconfig.test.json +14 -0
- package/tsup.config.ts +2 -1
package/saas-banner.svg
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 320" width="900" height="320">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#0a0a0f"/>
|
|
5
|
+
<stop offset="50%" style="stop-color:#0d1117"/>
|
|
6
|
+
<stop offset="100%" style="stop-color:#111827"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<linearGradient id="pipeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
9
|
+
<stop offset="0%" style="stop-color:#26d97f;stop-opacity:0"/>
|
|
10
|
+
<stop offset="50%" style="stop-color:#26d97f;stop-opacity:1"/>
|
|
11
|
+
<stop offset="100%" style="stop-color:#26d97f;stop-opacity:0"/>
|
|
12
|
+
</linearGradient>
|
|
13
|
+
<linearGradient id="pipeGrad2" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
14
|
+
<stop offset="0%" style="stop-color:#3178c6;stop-opacity:0"/>
|
|
15
|
+
<stop offset="50%" style="stop-color:#3178c6;stop-opacity:1"/>
|
|
16
|
+
<stop offset="100%" style="stop-color:#3178c6;stop-opacity:0"/>
|
|
17
|
+
</linearGradient>
|
|
18
|
+
<linearGradient id="pipeGrad3" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
19
|
+
<stop offset="0%" style="stop-color:#ff9900;stop-opacity:0"/>
|
|
20
|
+
<stop offset="50%" style="stop-color:#ff9900;stop-opacity:1"/>
|
|
21
|
+
<stop offset="100%" style="stop-color:#ff9900;stop-opacity:0"/>
|
|
22
|
+
</linearGradient>
|
|
23
|
+
<filter id="glow-green">
|
|
24
|
+
<feGaussianBlur stdDeviation="4" result="blur"/>
|
|
25
|
+
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
|
26
|
+
</filter>
|
|
27
|
+
<filter id="glow-blue">
|
|
28
|
+
<feGaussianBlur stdDeviation="3" result="blur"/>
|
|
29
|
+
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
|
30
|
+
</filter>
|
|
31
|
+
<filter id="glow-soft">
|
|
32
|
+
<feGaussianBlur stdDeviation="2" result="blur"/>
|
|
33
|
+
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
|
34
|
+
</filter>
|
|
35
|
+
</defs>
|
|
36
|
+
|
|
37
|
+
<!-- Background -->
|
|
38
|
+
<rect width="900" height="320" fill="url(#bg)" rx="14"/>
|
|
39
|
+
|
|
40
|
+
<!-- Subtle dot-grid background -->
|
|
41
|
+
<pattern id="dots" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
|
|
42
|
+
<circle cx="1" cy="1" r="0.8" fill="#1e293b" opacity="0.8"/>
|
|
43
|
+
</pattern>
|
|
44
|
+
<rect width="900" height="320" fill="url(#dots)" rx="14" opacity="0.6"/>
|
|
45
|
+
|
|
46
|
+
<!-- ===================== DATA PIPELINE VISUALIZATION ===================== -->
|
|
47
|
+
<!-- Horizontal pipeline backbone -->
|
|
48
|
+
<line x1="60" y1="160" x2="840" y2="160" stroke="#1e293b" stroke-width="2"/>
|
|
49
|
+
|
|
50
|
+
<!-- Animated data packet 1 - green -->
|
|
51
|
+
<rect x="0" y="154" width="36" height="12" rx="6" fill="url(#pipeGrad)" opacity="0.9">
|
|
52
|
+
<animate attributeName="x" values="-40;900" dur="3.2s" repeatCount="indefinite"/>
|
|
53
|
+
</rect>
|
|
54
|
+
|
|
55
|
+
<!-- Animated data packet 2 - blue -->
|
|
56
|
+
<rect x="0" y="154" width="28" height="12" rx="6" fill="url(#pipeGrad2)" opacity="0.85">
|
|
57
|
+
<animate attributeName="x" values="-40;900" dur="3.2s" begin="-1.1s" repeatCount="indefinite"/>
|
|
58
|
+
</rect>
|
|
59
|
+
|
|
60
|
+
<!-- Animated data packet 3 - orange -->
|
|
61
|
+
<rect x="0" y="154" width="22" height="12" rx="6" fill="url(#pipeGrad3)" opacity="0.8">
|
|
62
|
+
<animate attributeName="x" values="-40;900" dur="3.2s" begin="-2.0s" repeatCount="indefinite"/>
|
|
63
|
+
</rect>
|
|
64
|
+
|
|
65
|
+
<!-- ===================== MODULE NODES (pipeline stops) ===================== -->
|
|
66
|
+
<!-- Each node represents a feature of the library -->
|
|
67
|
+
|
|
68
|
+
<!-- Node 1: AUTH -->
|
|
69
|
+
<g filter="url(#glow-blue)">
|
|
70
|
+
<circle cx="130" cy="160" r="32" fill="#0d1117" stroke="#3178c6" stroke-width="1.8"/>
|
|
71
|
+
<circle cx="130" cy="160" r="32" fill="none" stroke="#3178c6" stroke-width="1">
|
|
72
|
+
<animate attributeName="r" values="32;40;32" dur="3s" repeatCount="indefinite"/>
|
|
73
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="3s" repeatCount="indefinite"/>
|
|
74
|
+
</circle>
|
|
75
|
+
<text x="130" y="155" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#3178c6" font-weight="bold">🔐</text>
|
|
76
|
+
<text x="130" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#3178c6" font-weight="bold">AUTH</text>
|
|
77
|
+
<text x="130" y="204" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#3178c6" opacity="0.6">JWT · RBAC</text>
|
|
78
|
+
</g>
|
|
79
|
+
|
|
80
|
+
<!-- Connector line -->
|
|
81
|
+
<line x1="162" y1="160" x2="218" y2="160" stroke="#1e293b" stroke-width="1.5" stroke-dasharray="4,3"/>
|
|
82
|
+
|
|
83
|
+
<!-- Node 2: QUEUE -->
|
|
84
|
+
<g filter="url(#glow-green)">
|
|
85
|
+
<circle cx="250" cy="160" r="32" fill="#0d1117" stroke="#26d97f" stroke-width="1.8"/>
|
|
86
|
+
<circle cx="250" cy="160" r="32" fill="none" stroke="#26d97f" stroke-width="1">
|
|
87
|
+
<animate attributeName="r" values="32;40;32" dur="3.5s" begin="-0.8s" repeatCount="indefinite"/>
|
|
88
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="3.5s" begin="-0.8s" repeatCount="indefinite"/>
|
|
89
|
+
</circle>
|
|
90
|
+
<text x="250" y="155" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#26d97f" font-weight="bold">⚡</text>
|
|
91
|
+
<text x="250" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#26d97f" font-weight="bold">QUEUE</text>
|
|
92
|
+
<text x="250" y="204" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#26d97f" opacity="0.6">BullMQ</text>
|
|
93
|
+
</g>
|
|
94
|
+
|
|
95
|
+
<!-- Connector line -->
|
|
96
|
+
<line x1="282" y1="160" x2="338" y2="160" stroke="#1e293b" stroke-width="1.5" stroke-dasharray="4,3"/>
|
|
97
|
+
|
|
98
|
+
<!-- Node 3: NOTIFY -->
|
|
99
|
+
<g filter="url(#glow-soft)">
|
|
100
|
+
<circle cx="370" cy="160" r="32" fill="#0d1117" stroke="#f59e0b" stroke-width="1.8"/>
|
|
101
|
+
<circle cx="370" cy="160" r="32" fill="none" stroke="#f59e0b" stroke-width="1">
|
|
102
|
+
<animate attributeName="r" values="32;40;32" dur="4s" begin="-1.5s" repeatCount="indefinite"/>
|
|
103
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="4s" begin="-1.5s" repeatCount="indefinite"/>
|
|
104
|
+
</circle>
|
|
105
|
+
<text x="370" y="155" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#f59e0b" font-weight="bold">🔔</text>
|
|
106
|
+
<text x="370" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#f59e0b" font-weight="bold">NOTIFY</text>
|
|
107
|
+
<text x="370" y="204" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#f59e0b" opacity="0.6">Email · SMS</text>
|
|
108
|
+
</g>
|
|
109
|
+
|
|
110
|
+
<!-- Connector line -->
|
|
111
|
+
<line x1="402" y1="160" x2="458" y2="160" stroke="#1e293b" stroke-width="1.5" stroke-dasharray="4,3"/>
|
|
112
|
+
|
|
113
|
+
<!-- Node 4: UPLOAD (CENTER - largest) -->
|
|
114
|
+
<g filter="url(#glow-soft)">
|
|
115
|
+
<circle cx="490" cy="160" r="36" fill="#0d1117" stroke="#ff9900" stroke-width="2"/>
|
|
116
|
+
<circle cx="490" cy="160" r="36" fill="none" stroke="#ff9900" stroke-width="1.2">
|
|
117
|
+
<animate attributeName="r" values="36;48;36" dur="3s" begin="-0.4s" repeatCount="indefinite"/>
|
|
118
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="3s" begin="-0.4s" repeatCount="indefinite"/>
|
|
119
|
+
</circle>
|
|
120
|
+
<text x="490" y="154" text-anchor="middle" font-family="'Courier New',monospace" font-size="10" fill="#ff9900" font-weight="bold">☁️</text>
|
|
121
|
+
<text x="490" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="10" fill="#ff9900" font-weight="bold">S3</text>
|
|
122
|
+
<text x="490" y="208" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#ff9900" opacity="0.6">AWS Upload</text>
|
|
123
|
+
</g>
|
|
124
|
+
|
|
125
|
+
<!-- Connector line -->
|
|
126
|
+
<line x1="526" y1="160" x2="578" y2="160" stroke="#1e293b" stroke-width="1.5" stroke-dasharray="4,3"/>
|
|
127
|
+
|
|
128
|
+
<!-- Node 5: RATE LIMIT -->
|
|
129
|
+
<g filter="url(#glow-soft)">
|
|
130
|
+
<circle cx="610" cy="160" r="32" fill="#0d1117" stroke="#e11d48" stroke-width="1.8"/>
|
|
131
|
+
<circle cx="610" cy="160" r="32" fill="none" stroke="#e11d48" stroke-width="1">
|
|
132
|
+
<animate attributeName="r" values="32;40;32" dur="2.8s" begin="-2.1s" repeatCount="indefinite"/>
|
|
133
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="2.8s" begin="-2.1s" repeatCount="indefinite"/>
|
|
134
|
+
</circle>
|
|
135
|
+
<text x="610" y="155" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#e11d48" font-weight="bold">🛡️</text>
|
|
136
|
+
<text x="610" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#e11d48" font-weight="bold">LIMIT</text>
|
|
137
|
+
<text x="610" y="204" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#e11d48" opacity="0.6">Rate Guard</text>
|
|
138
|
+
</g>
|
|
139
|
+
|
|
140
|
+
<!-- Connector line -->
|
|
141
|
+
<line x1="642" y1="160" x2="698" y2="160" stroke="#1e293b" stroke-width="1.5" stroke-dasharray="4,3"/>
|
|
142
|
+
|
|
143
|
+
<!-- Node 6: LOGGER -->
|
|
144
|
+
<g filter="url(#glow-soft)">
|
|
145
|
+
<circle cx="730" cy="160" r="32" fill="#0d1117" stroke="#8b5cf6" stroke-width="1.8"/>
|
|
146
|
+
<circle cx="730" cy="160" r="32" fill="none" stroke="#8b5cf6" stroke-width="1">
|
|
147
|
+
<animate attributeName="r" values="32;40;32" dur="3.8s" begin="-1.0s" repeatCount="indefinite"/>
|
|
148
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="3.8s" begin="-1.0s" repeatCount="indefinite"/>
|
|
149
|
+
</circle>
|
|
150
|
+
<text x="730" y="155" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#8b5cf6" font-weight="bold">📋</text>
|
|
151
|
+
<text x="730" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#8b5cf6" font-weight="bold">LOGGER</text>
|
|
152
|
+
<text x="730" y="204" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#8b5cf6" opacity="0.6">Pino · JSON</text>
|
|
153
|
+
</g>
|
|
154
|
+
|
|
155
|
+
<!-- Connector line -->
|
|
156
|
+
<line x1="762" y1="160" x2="818" y2="160" stroke="#1e293b" stroke-width="1.5" stroke-dasharray="4,3"/>
|
|
157
|
+
|
|
158
|
+
<!-- Node 7: CONFIG -->
|
|
159
|
+
<g filter="url(#glow-soft)">
|
|
160
|
+
<circle cx="845" cy="160" r="28" fill="#0d1117" stroke="#06b6d4" stroke-width="1.8"/>
|
|
161
|
+
<circle cx="845" cy="160" r="28" fill="none" stroke="#06b6d4" stroke-width="1">
|
|
162
|
+
<animate attributeName="r" values="28;36;28" dur="3.2s" begin="-2.6s" repeatCount="indefinite"/>
|
|
163
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="3.2s" begin="-2.6s" repeatCount="indefinite"/>
|
|
164
|
+
</circle>
|
|
165
|
+
<text x="845" y="155" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#06b6d4" font-weight="bold">⚙️</text>
|
|
166
|
+
<text x="845" y="168" text-anchor="middle" font-family="'Courier New',monospace" font-size="9" fill="#06b6d4" font-weight="bold">CFG</text>
|
|
167
|
+
<text x="845" y="204" text-anchor="middle" font-family="'Courier New',monospace" font-size="8" fill="#06b6d4" opacity="0.6">Zod · Env</text>
|
|
168
|
+
</g>
|
|
169
|
+
|
|
170
|
+
<!-- ===================== TITLE + SUBTITLE ===================== -->
|
|
171
|
+
<text x="450" y="50" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" font-weight="bold" fill="#f8fafc" letter-spacing="2" filter="url(#glow-soft)">
|
|
172
|
+
saas-backend-kit
|
|
173
|
+
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
|
|
174
|
+
</text>
|
|
175
|
+
|
|
176
|
+
<text x="450" y="76" text-anchor="middle" font-family="'Courier New',monospace" font-size="12" fill="#64748b">
|
|
177
|
+
Production-grade modular backend toolkit · Node.js · Express · Fastify
|
|
178
|
+
</text>
|
|
179
|
+
|
|
180
|
+
<!-- npm install command badge — animated border -->
|
|
181
|
+
<rect x="310" y="88" width="280" height="30" rx="6" fill="#0d1117" stroke="#26d97f" stroke-width="1" opacity="0.9">
|
|
182
|
+
<animate attributeName="stroke-opacity" values="0.4;1;0.4" dur="2s" repeatCount="indefinite"/>
|
|
183
|
+
</rect>
|
|
184
|
+
<text x="450" y="108" text-anchor="middle" font-family="'Courier New',monospace" font-size="12" fill="#26d97f">
|
|
185
|
+
$ npm install saas-backend-kit
|
|
186
|
+
</text>
|
|
187
|
+
|
|
188
|
+
<!-- ===================== FLOATING PARTICLES ===================== -->
|
|
189
|
+
<circle cx="50" cy="50" r="2" fill="#26d97f" opacity="0.5">
|
|
190
|
+
<animate attributeName="cy" values="50;270;50" dur="7s" repeatCount="indefinite"/>
|
|
191
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="7s" repeatCount="indefinite"/>
|
|
192
|
+
</circle>
|
|
193
|
+
<circle cx="870" cy="90" r="1.5" fill="#3178c6" opacity="0.5">
|
|
194
|
+
<animate attributeName="cy" values="90;30;90" dur="5s" repeatCount="indefinite"/>
|
|
195
|
+
<animate attributeName="opacity" values="0.5;0;0.5" dur="5s" repeatCount="indefinite"/>
|
|
196
|
+
</circle>
|
|
197
|
+
<circle cx="200" cy="280" r="2" fill="#f59e0b" opacity="0.4">
|
|
198
|
+
<animate attributeName="cx" values="200;700;200" dur="11s" repeatCount="indefinite"/>
|
|
199
|
+
<animate attributeName="opacity" values="0.4;0;0.4" dur="11s" repeatCount="indefinite"/>
|
|
200
|
+
</circle>
|
|
201
|
+
<circle cx="750" cy="30" r="1.5" fill="#8b5cf6" opacity="0.45">
|
|
202
|
+
<animate attributeName="cx" values="750;200;750" dur="9s" repeatCount="indefinite"/>
|
|
203
|
+
<animate attributeName="opacity" values="0.45;0;0.45" dur="9s" repeatCount="indefinite"/>
|
|
204
|
+
</circle>
|
|
205
|
+
|
|
206
|
+
<!-- ===================== BOTTOM STATUS BAR ===================== -->
|
|
207
|
+
<rect x="0" y="285" width="900" height="35" fill="#080c10" rx="0"/>
|
|
208
|
+
<rect x="0" y="282" width="900" height="3" fill="#26d97f" opacity="0.25"/>
|
|
209
|
+
|
|
210
|
+
<!-- Status indicators -->
|
|
211
|
+
<circle cx="30" cy="302" r="5" fill="#26d97f">
|
|
212
|
+
<animate attributeName="opacity" values="1;0.3;1" dur="1.5s" repeatCount="indefinite"/>
|
|
213
|
+
</circle>
|
|
214
|
+
<text x="42" y="307" font-family="'Courier New',monospace" font-size="10" fill="#26d97f" opacity="0.8">LIVE</text>
|
|
215
|
+
|
|
216
|
+
<text x="90" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b">|</text>
|
|
217
|
+
<text x="100" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b" opacity="0.7">MIT Licensed</text>
|
|
218
|
+
|
|
219
|
+
<text x="210" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b">|</text>
|
|
220
|
+
<text x="220" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b" opacity="0.7">TypeScript Ready</text>
|
|
221
|
+
|
|
222
|
+
<text x="360" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b">|</text>
|
|
223
|
+
<text x="370" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b" opacity="0.7">7 Modular Plugins</text>
|
|
224
|
+
|
|
225
|
+
<text x="520" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b">|</text>
|
|
226
|
+
<text x="530" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b" opacity="0.7">Express · Fastify</text>
|
|
227
|
+
|
|
228
|
+
<text x="670" y="307" font-family="'Courier New',monospace" font-size="10" fill="#64748b">|</text>
|
|
229
|
+
<text x="680" y="307" font-family="'Courier New',monospace" font-size="10" fill="#3178c6" opacity="0.85">by @AshishK-M</text>
|
|
230
|
+
|
|
231
|
+
<!-- Scrolling ticker on right -->
|
|
232
|
+
<clipPath id="tickerClip">
|
|
233
|
+
<rect x="800" y="288" width="95" height="28"/>
|
|
234
|
+
</clipPath>
|
|
235
|
+
<text font-family="'Courier New',monospace" font-size="9" fill="#26d97f" opacity="0.6" clip-path="url(#tickerClip)">
|
|
236
|
+
<tspan x="900" y="305">auth · queue · notify · upload · logger · rateLimit · config</tspan>
|
|
237
|
+
<animate attributeName="x" values="900;600" dur="8s" repeatCount="indefinite"/>
|
|
238
|
+
</text>
|
|
239
|
+
</svg>
|
package/src/auth/jwt.ts
CHANGED
|
@@ -39,7 +39,7 @@ export class JWTService {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
refreshTokens(refreshToken: string): TokenPair {
|
|
42
|
-
const payload = this.verifyRefreshToken(refreshToken);
|
|
42
|
+
const { iat, exp, nbf, ...payload } = this.verifyRefreshToken(refreshToken) as JWTPayload & { iat?: number; exp?: number; nbf?: number };
|
|
43
43
|
return this.generateTokenPair(payload);
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/config/index.ts
CHANGED
|
@@ -24,6 +24,11 @@ export const envSchema = z.object({
|
|
|
24
24
|
RATE_LIMIT_WINDOW: z.string().default('1m'),
|
|
25
25
|
RATE_LIMIT_LIMIT: z.string().default('100'),
|
|
26
26
|
LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),
|
|
27
|
+
AWS_REGION: z.string().default('us-east-1'),
|
|
28
|
+
AWS_ACCESS_KEY_ID: z.string().optional(),
|
|
29
|
+
AWS_SECRET_ACCESS_KEY: z.string().optional(),
|
|
30
|
+
AWS_S3_BUCKET: z.string().optional(),
|
|
31
|
+
AWS_ENDPOINT: z.string().optional(),
|
|
27
32
|
});
|
|
28
33
|
|
|
29
34
|
export type EnvConfig = z.infer<typeof envSchema>;
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { logger } from './logger';
|
|
|
5
5
|
export { rateLimit, createRateLimiter } from './rate-limit';
|
|
6
6
|
export { config } from './config';
|
|
7
7
|
export { ResponseHelper, response } from './response';
|
|
8
|
+
export { upload, s3Service, S3Service } from './upload';
|
|
8
9
|
export { createApp, createExpressApp, SaaSAppBuilder, PluginManager, Plugin, AppOptions } from './plugin';
|
|
9
10
|
|
|
10
11
|
export { AuthOptions, User, JWTPayload, TokenPair, LoginCredentials, RegisterData, Role, Permission, RolePermissions } from './auth/types';
|
|
@@ -14,3 +15,4 @@ export { LoggerConfig, LogLevel } from './logger';
|
|
|
14
15
|
export { RateLimitOptions } from './rate-limit';
|
|
15
16
|
export { EnvConfig, ConfigOptions } from './config';
|
|
16
17
|
export { ApiResponse, PaginatedResponse, ErrorResponse } from './response';
|
|
18
|
+
export { S3Config, UploadOptions, UploadResult, SignedUrlOptions, FileObject } from './upload';
|
package/src/response/index.ts
CHANGED
|
@@ -13,7 +13,8 @@ export interface ApiResponse<T = unknown> {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export interface PaginatedResponse<T> extends ApiResponse<T> {
|
|
16
|
+
export interface PaginatedResponse<T> extends Omit<ApiResponse<T[]>, 'data'> {
|
|
17
|
+
data: T[];
|
|
17
18
|
meta: {
|
|
18
19
|
page: number;
|
|
19
20
|
limit: number;
|
|
@@ -141,57 +142,65 @@ declare global {
|
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
try {
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
147
|
+
const proto = require('express').response;
|
|
148
|
+
if (proto) {
|
|
149
|
+
proto.success = function <T>(this: Response, data?: T, message?: string, statusCode: number = 200) {
|
|
150
|
+
return ResponseHelper.success(this, data, message, statusCode);
|
|
151
|
+
};
|
|
147
152
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
};
|
|
153
|
+
proto.created = function <T>(this: Response, data?: T, message?: string) {
|
|
154
|
+
return ResponseHelper.created(this, data, message);
|
|
155
|
+
};
|
|
151
156
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
};
|
|
157
|
+
proto.updated = function <T>(this: Response, data?: T, message?: string) {
|
|
158
|
+
return ResponseHelper.updated(this, data, message);
|
|
159
|
+
};
|
|
155
160
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
};
|
|
161
|
+
proto.deleted = function (this: Response, message?: string) {
|
|
162
|
+
return ResponseHelper.deleted(this, message);
|
|
163
|
+
};
|
|
159
164
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
};
|
|
165
|
+
proto.error = function (this: Response, error: string, statusCode: number = 400, code?: string, details?: Record<string, unknown>) {
|
|
166
|
+
return ResponseHelper.error(this, error, statusCode, code, details);
|
|
167
|
+
};
|
|
163
168
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
};
|
|
169
|
+
proto.badRequest = function (this: Response, error?: string, code?: string) {
|
|
170
|
+
return ResponseHelper.badRequest(this, error, code);
|
|
171
|
+
};
|
|
167
172
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
};
|
|
173
|
+
proto.unauthorized = function (this: Response, error?: string, code?: string) {
|
|
174
|
+
return ResponseHelper.unauthorized(this, error, code);
|
|
175
|
+
};
|
|
171
176
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
};
|
|
177
|
+
proto.forbidden = function (this: Response, error?: string, code?: string) {
|
|
178
|
+
return ResponseHelper.forbidden(this, error, code);
|
|
179
|
+
};
|
|
175
180
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
};
|
|
181
|
+
proto.notFound = function (this: Response, error?: string, code?: string) {
|
|
182
|
+
return ResponseHelper.notFound(this, error, code);
|
|
183
|
+
};
|
|
179
184
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
};
|
|
185
|
+
proto.conflict = function (this: Response, error?: string, code?: string) {
|
|
186
|
+
return ResponseHelper.conflict(this, error, code);
|
|
187
|
+
};
|
|
183
188
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
};
|
|
189
|
+
proto.validationError = function (this: Response, error: string, details?: Record<string, unknown>) {
|
|
190
|
+
return ResponseHelper.validationError(this, error, details);
|
|
191
|
+
};
|
|
187
192
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
};
|
|
193
|
+
proto.internalError = function (this: Response, error?: string) {
|
|
194
|
+
return ResponseHelper.internalError(this, error);
|
|
195
|
+
};
|
|
191
196
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
};
|
|
197
|
+
proto.paginated = function <T>(this: Response, data: T[], page: number, limit: number, total: number) {
|
|
198
|
+
return ResponseHelper.paginated(this, data, page, limit, total);
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
// express not available at runtime
|
|
203
|
+
}
|
|
195
204
|
|
|
196
205
|
export const response = ResponseHelper;
|
|
197
206
|
export default ResponseHelper;
|