dolphin-server-modules 2.11.1 โ†’ 2.11.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.
Files changed (115) hide show
  1. package/TUTORIAL_NEPALI.md +181 -0
  2. package/dist/adapters/mongoose/index.test.d.ts +1 -0
  3. package/dist/adapters/mongoose/index.test.js +145 -0
  4. package/dist/adapters/mongoose/index.test.js.map +1 -0
  5. package/dist/adapters/mongoose/integration.test.d.ts +5 -0
  6. package/dist/adapters/mongoose/integration.test.js +217 -0
  7. package/dist/adapters/mongoose/integration.test.js.map +1 -0
  8. package/dist/ai/dolphin-agent/agent.d.ts +5 -0
  9. package/dist/ai/dolphin-agent/agent.js +93 -46
  10. package/dist/ai/dolphin-agent/agent.js.map +1 -1
  11. package/dist/ai/dolphin-agent/config.js +19 -23
  12. package/dist/ai/dolphin-agent/config.js.map +1 -1
  13. package/dist/auth/auth.test.d.ts +1 -0
  14. package/dist/auth/auth.test.js +286 -0
  15. package/dist/auth/auth.test.js.map +1 -0
  16. package/dist/authController/authController.js +1 -1
  17. package/dist/authController/authController.js.map +1 -1
  18. package/dist/authController/authController.test.d.ts +1 -0
  19. package/dist/authController/authController.test.js +359 -0
  20. package/dist/authController/authController.test.js.map +1 -0
  21. package/dist/bin/cli.js +494 -131
  22. package/dist/bin/cli.js.map +1 -1
  23. package/dist/client.test.d.ts +22 -0
  24. package/dist/client.test.js +573 -0
  25. package/dist/client.test.js.map +1 -0
  26. package/dist/controller/controller.test.d.ts +1 -0
  27. package/dist/controller/controller.test.js +37 -0
  28. package/dist/controller/controller.test.js.map +1 -0
  29. package/dist/curd/crud.test.d.ts +1 -0
  30. package/dist/curd/crud.test.js +104 -0
  31. package/dist/curd/crud.test.js.map +1 -0
  32. package/dist/demo-server.d.ts +1 -0
  33. package/dist/demo-server.js +191 -0
  34. package/dist/demo-server.js.map +1 -0
  35. package/dist/djson/djson.test.d.ts +1 -0
  36. package/dist/djson/djson.test.js +200 -0
  37. package/dist/djson/djson.test.js.map +1 -0
  38. package/dist/dolphin-bench.d.ts +1 -0
  39. package/dist/dolphin-bench.js +63 -0
  40. package/dist/dolphin-bench.js.map +1 -0
  41. package/dist/hard-performance-test.d.ts +1 -0
  42. package/dist/hard-performance-test.js +97 -0
  43. package/dist/hard-performance-test.js.map +1 -0
  44. package/dist/index.d.ts +4 -4
  45. package/dist/index.js +4 -4
  46. package/dist/index.js.map +1 -1
  47. package/dist/middleware/zod.test.d.ts +1 -0
  48. package/dist/middleware/zod.test.js +74 -0
  49. package/dist/middleware/zod.test.js.map +1 -0
  50. package/dist/performance-test.d.ts +1 -0
  51. package/dist/performance-test.js +92 -0
  52. package/dist/performance-test.js.map +1 -0
  53. package/dist/real-test-mongoose.d.ts +1 -0
  54. package/dist/real-test-mongoose.js +104 -0
  55. package/dist/real-test-mongoose.js.map +1 -0
  56. package/dist/realtime/camera.d.ts +119 -0
  57. package/dist/realtime/camera.js +299 -0
  58. package/dist/realtime/camera.js.map +1 -0
  59. package/dist/realtime/camera.test.d.ts +1 -0
  60. package/dist/realtime/camera.test.js +345 -0
  61. package/dist/realtime/camera.test.js.map +1 -0
  62. package/dist/realtime/core.d.ts +5 -5
  63. package/dist/realtime/core.js +6 -6
  64. package/dist/realtime/core.js.map +1 -1
  65. package/dist/realtime/index.d.ts +6 -4
  66. package/dist/realtime/index.js +6 -4
  67. package/dist/realtime/index.js.map +1 -1
  68. package/dist/realtime/realtime.test.d.ts +1 -0
  69. package/dist/realtime/realtime.test.js +623 -0
  70. package/dist/realtime/realtime.test.js.map +1 -0
  71. package/dist/realtime/rtsp.d.ts +65 -0
  72. package/dist/realtime/rtsp.js +410 -0
  73. package/dist/realtime/rtsp.js.map +1 -0
  74. package/dist/realtime/rtsp.test.d.ts +1 -0
  75. package/dist/realtime/rtsp.test.js +361 -0
  76. package/dist/realtime/rtsp.test.js.map +1 -0
  77. package/dist/router/router.test.d.ts +1 -0
  78. package/dist/router/router.test.js +45 -0
  79. package/dist/router/router.test.js.map +1 -0
  80. package/dist/server/server.d.ts +8 -8
  81. package/dist/server/server.js +2 -11
  82. package/dist/server/server.js.map +1 -1
  83. package/dist/server/server.test.d.ts +1 -0
  84. package/dist/server/server.test.js +299 -0
  85. package/dist/server/server.test.js.map +1 -0
  86. package/dist/services/ai-service.js +22 -11
  87. package/dist/services/ai-service.js.map +1 -1
  88. package/dist/signaling/index.d.ts +1 -1
  89. package/dist/signaling/signaling.test.d.ts +1 -0
  90. package/dist/signaling/signaling.test.js +112 -0
  91. package/dist/signaling/signaling.test.js.map +1 -0
  92. package/dist/swagger/swagger.test.d.ts +1 -0
  93. package/dist/swagger/swagger.test.js +38 -0
  94. package/dist/swagger/swagger.test.js.map +1 -0
  95. package/dist/templates/index.d.ts +6 -0
  96. package/dist/templates/index.js +247 -70
  97. package/dist/templates/index.js.map +1 -1
  98. package/dist/test-2fa-real.d.ts +1 -0
  99. package/dist/test-2fa-real.js +105 -0
  100. package/dist/test-2fa-real.js.map +1 -0
  101. package/dist/test-dolphin.d.ts +1 -0
  102. package/dist/test-dolphin.js +98 -0
  103. package/dist/test-dolphin.js.map +1 -0
  104. package/dist/utils/ctx.d.ts +50 -0
  105. package/dist/utils/ctx.js +82 -0
  106. package/dist/utils/ctx.js.map +1 -0
  107. package/package.json +156 -65
  108. package/scripts/client.js +838 -703
  109. package/scripts/benchmark.js +0 -12
  110. package/scripts/benchmark.ts +0 -12
  111. package/scripts/list-models.js +0 -34
  112. package/scripts/run-real-ai-test.js +0 -79
  113. package/scripts/test-ai-logic.js +0 -44
  114. package/scripts/test-client.js +0 -105
  115. package/scripts/test-dolphin.js +0 -36
@@ -2,111 +2,288 @@ export const TEMPLATES = {
2
2
  app: `import { createDolphinServer } from 'dolphin-server-modules/server';
3
3
  import { createMongooseAdapter } from 'dolphin-server-modules/adapters/mongoose';
4
4
  import { createDolphinAuthController } from 'dolphin-server-modules/auth-controller';
5
+ import { connectDB } from './config/db.js';
6
+ import { User, RefreshToken } from './models/User.js';
5
7
 
6
8
  const app = createDolphinServer();
7
9
 
8
- // DB Connection & Adapter
9
- const dbAdapter = createMongooseAdapter(process.env.MONGO_URI || 'mongodb://localhost:27017/dolphin_db');
10
+ // Global Error Handler โ€” server crash เคฌเคพเคŸ เคฌเคšเคพเค‰เคเค›
11
+ app.use(async (ctx, next) => {
12
+ try { if (next) await next(); }
13
+ catch (error) {
14
+ console.error('๐Ÿ”ฅ ERROR:', error.message);
15
+ ctx.status(500).json({ success: false, message: 'Internal Server Error' });
16
+ }
17
+ });
18
+
19
+ // DB connect
20
+ connectDB(process.env.MONGO_URI || 'mongodb://localhost:27017/dolphin_db');
10
21
 
11
- // Auth Setup
22
+ // Mongoose Adapter
23
+ const db = createMongooseAdapter({ User, RefreshToken });
24
+
25
+ // Auth
12
26
  const auth = createDolphinAuthController({
13
- adapter: dbAdapter,
14
- jwtSecret: process.env.JWT_SECRET || 'dolphin_secret'
27
+ adapter: db,
28
+ jwtSecret: process.env.JWT_SECRET || 'change_in_production',
15
29
  });
16
30
 
17
31
  app.post('/api/auth/register', auth.register);
18
- app.post('/api/auth/login', auth.login);
32
+ app.post('/api/auth/login', auth.login);
33
+ app.post('/api/auth/refresh', auth.refresh);
34
+ app.post('/api/auth/logout', auth.middleware(), auth.logout);
35
+
36
+ app.get('/health', (ctx) => ({ status: 'ok', ts: new Date().toISOString() }));
19
37
 
20
- app.listen(3000, () => console.log('๐Ÿฌ Dolphin Production Server is swimming on port 3000'));
38
+ const PORT = parseInt(process.env.PORT || '3000');
39
+ app.listen(PORT, () => console.log(\`๐Ÿฌ Dolphin Server swimming on port \${PORT}\`));
21
40
  `,
22
41
  mongoose: `import mongoose from 'mongoose';
42
+
23
43
  export const connectDB = async (uri) => {
24
- try {
25
- await mongoose.connect(uri);
26
- console.log('โœ… MongoDB Connected');
27
- } catch (e) {
28
- console.error('โŒ DB Error:', e);
29
- }
30
- };`,
44
+ try {
45
+ await mongoose.connect(uri, { serverSelectionTimeoutMS: 5000 });
46
+ console.log('โœ… MongoDB Connected:', mongoose.connection.host);
47
+ } catch (e) {
48
+ console.error('โŒ MongoDB Error:', e.message);
49
+ process.exit(1);
50
+ }
51
+ };
52
+
53
+ mongoose.connection.on('disconnected', () => console.warn('โš ๏ธ MongoDB disconnected'));
54
+ mongoose.connection.on('error', (err) => console.error('โŒ MongoDB:', err.message));
55
+ `,
31
56
  sequelize: `import { Sequelize } from 'sequelize';
32
- export const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
33
- host: process.env.DB_HOST || 'localhost',
34
- dialect: 'mysql',
35
- logging: false
36
- });
57
+
58
+ export const sequelize = new Sequelize(
59
+ process.env.DB_NAME || 'dolphin_db',
60
+ process.env.DB_USER || 'root',
61
+ process.env.DB_PASS || '',
62
+ {
63
+ host: process.env.DB_HOST || 'localhost',
64
+ dialect: process.env.DB_DIALECT || 'mysql',
65
+ logging: process.env.NODE_ENV === 'development' ? console.log : false,
66
+ pool: { max: 10, min: 0, acquire: 30000, idle: 10000 },
67
+ }
68
+ );
37
69
 
38
70
  export const connectDB = async () => {
39
- try {
40
- await sequelize.authenticate();
41
- console.log('โœ… MySQL/Sequelize Connected');
42
- } catch (e) {
43
- console.error('โŒ DB Error:', e);
44
- }
45
- };`,
71
+ try {
72
+ await sequelize.authenticate();
73
+ console.log('โœ… Sequelize Connected:', process.env.DB_HOST || 'localhost');
74
+ await sequelize.sync({ alter: process.env.NODE_ENV === 'development' });
75
+ } catch (e) {
76
+ console.error('โŒ Sequelize Error:', e.message); process.exit(1);
77
+ }
78
+ };
79
+ `,
80
+ redis: `import { createClient } from 'redis';
81
+
82
+ const REDIS_URL = process.env.REDIS_URL || 'redis://localhost:6379';
83
+
84
+ export const redisClient = createClient({ url: REDIS_URL });
85
+ redisClient.on('error', (err) => console.error('โŒ Redis:', err.message));
86
+ redisClient.on('connect', () => console.log('โœ… Redis Connected:', REDIS_URL));
87
+ redisClient.on('reconnecting',() => console.warn('โš ๏ธ Redis reconnecting...'));
88
+
89
+ export const connectRedis = async () => {
90
+ await redisClient.connect().catch(e => { console.error('โŒ Redis:', e.message); process.exit(1); });
91
+ };
92
+
93
+ export const cache = {
94
+ set: (key, value, ttl = 3600) => redisClient.setEx(key, ttl, JSON.stringify(value)),
95
+ get: async (key) => { const v = await redisClient.get(key); return v ? JSON.parse(v) : null; },
96
+ del: (key) => redisClient.del(key),
97
+ exists: async (key) => (await redisClient.exists(key)) === 1,
98
+ };
99
+ `,
46
100
  auth: `import { createDolphinAuthController } from 'dolphin-server-modules/auth-controller';
47
- import { User } from '../models/User.js';
101
+ import { db } from './adapter.js'; // เคคเคชเคพเคˆเค‚เค•เฅ‹ createMongooseAdapter instance
48
102
 
49
- // This is a production-ready Auth Controller using Dolphin Modules
50
103
  export const auth = createDolphinAuthController({
51
- secret: process.env.JWT_SECRET || 'your_ultra_secret_key',
52
- model: User, // In a real app, you'd pass a Database Adapter
53
- issuer: 'DolphinApp'
104
+ adapter: db,
105
+ jwtSecret: process.env.JWT_SECRET || 'change_in_production',
106
+ accessTokenExpiry: '15m',
107
+ refreshTokenExpiry: '7d',
54
108
  });
55
109
 
56
- export const register = auth.register;
57
- export const login = auth.login;
110
+ export const { register, login, refresh, logout, middleware } = auth;
58
111
  `,
59
112
  crud: (name) => `import { createCrudController } from 'dolphin-server-modules/crud';
60
- import { ${name} } from '../models/${name}.js';
113
+ import { db } from '../config/adapter.js';
61
114
 
62
- // Fully automated CRUD controller for ${name}
63
- export const ${name.toLowerCase()}Controller = createCrudController(
64
- ${name}, // Mongoose Model
65
- '${name.toLowerCase()}s', // Collection Name
66
- { softDelete: true, enforceOwnership: true }
67
- );
115
+ const ctrl = createCrudController(db, '${name}', {
116
+ softDelete: true,
117
+ enforceOwnership: false,
118
+ });
68
119
 
69
- export const getAll = ${name.toLowerCase()}Controller.getAll;
70
- export const getOne = ${name.toLowerCase()}Controller.getOne;
71
- export const create = ${name.toLowerCase()}Controller.create;
72
- export const update = ${name.toLowerCase()}Controller.update;
73
- export const remove = ${name.toLowerCase()}Controller.delete;
120
+ export const { getAll, getOne, create, update } = ctrl;
121
+ export const remove = ctrl.delete;
74
122
  `,
75
123
  crudModel: (name) => `import mongoose from 'mongoose';
76
124
 
77
- const ${name.toLowerCase()}Schema = new mongoose.Schema({
78
- userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
79
- title: { type: String, required: true },
80
- description: { type: String },
81
- status: { type: String, enum: ['pending', 'completed'], default: 'pending' }
82
- }, { timestamps: true });
125
+ const ${name.toLowerCase()}Schema = new mongoose.Schema(
126
+ {
127
+ title: { type: String, required: true, trim: true },
128
+ description: { type: String, default: '' },
129
+ status: { type: String, enum: ['active','inactive'], default: 'active' },
130
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
131
+ },
132
+ { timestamps: true, versionKey: false }
133
+ );
134
+
135
+ ${name.toLowerCase()}Schema.index({ userId: 1, status: 1 });
136
+ ${name.toLowerCase()}Schema.index({ createdAt: -1 });
83
137
 
84
138
  export const ${name} = mongoose.model('${name}', ${name.toLowerCase()}Schema);
85
139
  `,
86
140
  authModel: `import mongoose from 'mongoose';
87
141
 
88
- const userSchema = new mongoose.Schema({
89
- email: { type: String, required: true, unique: true },
90
- password: { type: String, required: true },
91
- role: { type: String, default: 'user' },
92
- twoFactorEnabled: { type: Boolean, default: false },
93
- twoFactorSecret: { type: String, default: null },
94
- pending2FASecret: { type: String, default: null },
95
- recoveryCodes: { type: [String], default: [] }
96
- }, { timestamps: true });
97
-
142
+ const userSchema = new mongoose.Schema(
143
+ {
144
+ email: { type: String, required: true, unique: true, lowercase: true, trim: true },
145
+ password: { type: String, required: true },
146
+ role: { type: String, enum: ['user','admin','moderator'], default: 'user' },
147
+ twoFactorEnabled: { type: Boolean, default: false },
148
+ twoFactorSecret: { type: String, default: null },
149
+ pending2FASecret: { type: String, default: null },
150
+ recoveryCodes: { type: [String], default: [] },
151
+ isActive: { type: Boolean, default: true },
152
+ lastLoginAt: { type: Date, default: null },
153
+ },
154
+ { timestamps: true, versionKey: false }
155
+ );
156
+ userSchema.index({ email: 1 });
98
157
  export const User = mongoose.model('User', userSchema);
99
158
 
100
- const refreshTokenSchema = new mongoose.Schema({
101
- token: { type: String, required: true, unique: true },
102
- userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
103
- expiresAt: { type: Date, required: true },
104
- twoFactorVerified: { type: Boolean, default: false }
105
- }, { timestamps: true });
159
+ const refreshTokenSchema = new mongoose.Schema(
160
+ {
161
+ token: { type: String, required: true, unique: true, index: true },
162
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
163
+ expiresAt: { type: Date, required: true },
164
+ twoFactorVerified: { type: Boolean, default: false },
165
+ userAgent: { type: String, default: null },
166
+ ip: { type: String, default: null },
167
+ },
168
+ { timestamps: true, versionKey: false }
169
+ );
170
+ refreshTokenSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
171
+ export const RefreshToken = mongoose.model('RefreshToken', refreshTokenSchema);
172
+ `,
173
+ model: (name) => `import mongoose from 'mongoose';
106
174
 
107
- refreshTokenSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 }); // Auto-delete expired tokens
175
+ const ${name.toLowerCase()}Schema = new mongoose.Schema(
176
+ {
177
+ name: { type: String, required: true, trim: true, maxlength: 200 },
178
+ description: { type: String, default: '', maxlength: 2000 },
179
+ isActive: { type: Boolean, default: true },
180
+ },
181
+ {
182
+ timestamps: true,
183
+ versionKey: false,
184
+ toJSON: {
185
+ transform: (_, ret) => { ret.id = ret._id?.toString(); delete ret._id; return ret; }
186
+ }
187
+ }
188
+ );
108
189
 
109
- export const RefreshToken = mongoose.model('RefreshToken', refreshTokenSchema);
110
- `
190
+ ${name.toLowerCase()}Schema.index({ name: 1 });
191
+ ${name.toLowerCase()}Schema.index({ isActive: 1, createdAt: -1 });
192
+
193
+ export const ${name} = mongoose.model('${name}', ${name.toLowerCase()}Schema);
194
+ `,
195
+ middleware: (name) => `/**
196
+ * ${name} Middleware
197
+ * Usage: app.use(${name.toLowerCase()}Middleware) เคตเคพ app.get('/route', ${name.toLowerCase()}Middleware, handler)
198
+ */
199
+ export const ${name.toLowerCase()}Middleware = async (ctx, next) => {
200
+ // TODO: เคคเคชเคพเคˆเค‚เค•เฅ‹ logic เคฏเคนเคพเค เคฒเฅ‡เค–เฅเคจเฅเคนเฅ‹เคธเฅ
201
+ console.log(\`[${name}] \${ctx.req.method} \${ctx.req.url}\`);
202
+ if (next) await next();
203
+ };
204
+ `,
205
+ route: (name) => `import { createDolphinRouter } from 'dolphin-server-modules/router';
206
+
207
+ const router = createDolphinRouter();
208
+ const base = '/${name.toLowerCase()}s';
209
+
210
+ router.get(base, async (ctx) => {
211
+ return { success: true, data: [], message: '${name} list' };
212
+ });
213
+
214
+ router.get(\`\${base}/:id\`, async (ctx) => {
215
+ return { success: true, data: { id: ctx.params.id } };
216
+ });
217
+
218
+ router.post(base, async (ctx) => {
219
+ return ctx.status(201).json({ success: true, data: ctx.body });
220
+ });
221
+
222
+ router.put(\`\${base}/:id\`, async (ctx) => {
223
+ return { success: true, data: { id: ctx.params.id, ...ctx.body } };
224
+ });
225
+
226
+ router.delete(\`\${base}/:id\`, async (ctx) => {
227
+ return { success: true, data: { id: ctx.params.id, deleted: true } };
228
+ });
229
+
230
+ export const ${name.toLowerCase()}Router = router;
231
+ `,
232
+ service: (name) => `/**
233
+ * ${name}Service โ€” Business logic layer
234
+ * Controller เคฐ Database เค•เฅ‹ เคฌเฅ€เคšเค•เฅ‹ layer
235
+ */
236
+ export class ${name}Service {
237
+
238
+ static async getAll(filter = {}) {
239
+ // TODO: DB query
240
+ return [];
241
+ }
242
+
243
+ static async getById(id) {
244
+ // TODO: DB findById
245
+ return null;
246
+ }
247
+
248
+ static async create(data) {
249
+ // TODO: DB create
250
+ return { id: Date.now().toString(), ...data, createdAt: new Date() };
251
+ }
252
+
253
+ static async update(id, data) {
254
+ // TODO: DB update
255
+ return { id, ...data, updatedAt: new Date() };
256
+ }
257
+
258
+ static async delete(id) {
259
+ // TODO: DB delete
260
+ return { id, deleted: true };
261
+ }
262
+ }
263
+ `,
264
+ env: `# ๐Ÿฌ Dolphin Framework โ€” Environment Variables
265
+ # โš ๏ธ เคฏเฅ‹ file .gitignore เคฎเคพ เคฐเคพเค–เฅเคจเฅเคนเฅ‹เคธเฅ โ€” production เคฎเคพ NEVER commit!
266
+
267
+ NODE_ENV=development
268
+ PORT=3000
269
+
270
+ # MongoDB
271
+ MONGO_URI=mongodb://localhost:27017/dolphin_db
272
+
273
+ # JWT Secret (เค•เคฎเฅเคคเฅ€เคฎเคพ 32 chars)
274
+ JWT_SECRET=change_this_ultra_secret_key_in_production_32chars
275
+
276
+ # Redis (optional โ€” realtime scaling)
277
+ # REDIS_URL=redis://localhost:6379
278
+
279
+ # AI Keys (dolphin chat/generate เค•เฅ‹ เคฒเคพเค—เคฟ)
280
+ # GEMINI_API_KEY=your_key_here
281
+ # GROQ_API_KEY=your_key_here
282
+ # OPENAI_API_KEY=your_key_here
283
+
284
+ # Local Ollama (optional)
285
+ # USE_OLLAMA=true
286
+ # OLLAMA_MODEL=gemma3:latest
287
+ `,
111
288
  };
112
289
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG;IACrB,GAAG,EAAE;;;;;;;;;;;;;;;;;;;CAmBR;IACG,QAAQ,EAAE;;;;;;;;GAQX;IACC,SAAS,EAAE;;;;;;;;;;;;;;GAcZ;IACC,IAAI,EAAE;;;;;;;;;;;;CAYT;IACG,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;WACjB,IAAI,sBAAsB,IAAI;;yCAEA,IAAI;eAC9B,IAAI,CAAC,WAAW,EAAE;MAC3B,IAAI;OACH,IAAI,CAAC,WAAW,EAAE;;;;wBAID,IAAI,CAAC,WAAW,EAAE;wBAClB,IAAI,CAAC,WAAW,EAAE;wBAClB,IAAI,CAAC,WAAW,EAAE;wBAClB,IAAI,CAAC,WAAW,EAAE;wBAClB,IAAI,CAAC,WAAW,EAAE;CACzC;IACG,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;QAEzB,IAAI,CAAC,WAAW,EAAE;;;;;;;eAOX,IAAI,sBAAsB,IAAI,MAAM,IAAI,CAAC,WAAW,EAAE;CACpE;IACG,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;CAwBd;CACA,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG;IAErB,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCR;IAEG,QAAQ,EAAE;;;;;;;;;;;;;;CAcb;IAEG,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBd;IAEG,KAAK,EAAE;;;;;;;;;;;;;;;;;;;CAmBV;IAEG,IAAI,EAAE;;;;;;;;;;;CAWT;IAEG,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;;yCAGa,IAAI;;;;;;;CAO5C;IAEG,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;QAEzB,IAAI,CAAC,WAAW,EAAE;;;;;;;;;;EAUxB,IAAI,CAAC,WAAW,EAAE;EAClB,IAAI,CAAC,WAAW,EAAE;;eAEL,IAAI,sBAAsB,IAAI,MAAM,IAAI,CAAC,WAAW,EAAE;CACpE;IAEG,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCd;IAEG,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;QAErB,IAAI,CAAC,WAAW,EAAE;;;;;;;;;;;;;;;EAexB,IAAI,CAAC,WAAW,EAAE;EAClB,IAAI,CAAC,WAAW,EAAE;;eAEL,IAAI,sBAAsB,IAAI,MAAM,IAAI,CAAC,WAAW,EAAE;CACpE;IAEG,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;KAC7B,IAAI;oBACW,IAAI,CAAC,WAAW,EAAE,sCAAsC,IAAI,CAAC,WAAW,EAAE;;eAE/E,IAAI,CAAC,WAAW,EAAE;;mBAEd,IAAI;;;CAGtB;IAEG,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;;iBAGZ,IAAI,CAAC,WAAW,EAAE;;;gDAGa,IAAI;;;;;;;;;;;;;;;;;;;eAmBrC,IAAI,CAAC,WAAW,EAAE;CAChC;IAEG,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;KAC1B,IAAI;;;eAGM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BlB;IAEG,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBR;CACA,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,105 @@
1
+ // test-2fa-real.ts
2
+ import { createAuth } from "./auth/auth";
3
+ import crypto from "node:crypto";
4
+ import argon2 from "argon2";
5
+ // Helper to simulate a TOTP app (reusing logic from auth.ts)
6
+ const BASE32_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
7
+ const base32Decode = (str) => {
8
+ str = str.replace(/=/g, '').toUpperCase();
9
+ let bits = 0, value = 0;
10
+ const bytes = [];
11
+ for (let i = 0; i < str.length; i++) {
12
+ const idx = BASE32_CHARS.indexOf(str[i]);
13
+ value = (value << 5) | idx;
14
+ bits += 5;
15
+ if (bits >= 8) {
16
+ bytes.push((value >>> (bits - 8)) & 255);
17
+ bits -= 8;
18
+ }
19
+ }
20
+ return Buffer.from(bytes);
21
+ };
22
+ const generateTOTP = (secretBase32, timestamp = Date.now()) => {
23
+ const counter = Math.floor(timestamp / 30000);
24
+ const counterBuf = Buffer.alloc(8);
25
+ counterBuf.writeBigInt64BE(BigInt(counter), 0);
26
+ const secret = base32Decode(secretBase32);
27
+ const hmac = crypto.createHmac('sha1', secret);
28
+ hmac.update(counterBuf);
29
+ const hash = hmac.digest();
30
+ const offset = hash[hash.length - 1] & 0xf;
31
+ const code = (hash.readUInt32BE(offset) & 0x7fffffff) % 1000000;
32
+ return code.toString().padStart(6, '0');
33
+ };
34
+ async function run2FATest() {
35
+ console.log("๐Ÿ” Starting 'Real' 2FA Flow Test...\n");
36
+ const auth = createAuth({ secret: 'test-secret' });
37
+ // 1. Mock DB state
38
+ let mockUser = {
39
+ id: "user123",
40
+ email: "test@example.com",
41
+ password: await argon2.hash("password123"),
42
+ twoFactorEnabled: false,
43
+ twoFactorSecret: null,
44
+ pending2FASecret: null,
45
+ recoveryCodes: []
46
+ };
47
+ const db = {
48
+ findUserById: async () => mockUser,
49
+ findUserByEmail: async () => mockUser,
50
+ updateUser: async (id, data) => {
51
+ mockUser = { ...mockUser, ...data };
52
+ return mockUser;
53
+ },
54
+ saveRefreshToken: async () => { },
55
+ findRefreshToken: async () => null,
56
+ deleteRefreshToken: async () => { }
57
+ };
58
+ // --- STEP 1: Enable 2FA ---
59
+ console.log("Step 1: Enabling 2FA (Generating Secret)...");
60
+ const setup = await auth.enable2FA(db, mockUser.id);
61
+ console.log("โœ… Secret Generated:", setup.secret);
62
+ console.log("โœ… URI:", setup.uri);
63
+ // --- STEP 2: Verify 2FA ---
64
+ console.log("\nStep 2: Verifying 2FA with TOTP Token...");
65
+ const realToken = generateTOTP(setup.secret);
66
+ console.log("๐Ÿ“ฑ Simulated App Token:", realToken);
67
+ const verifyResult = await auth.verify2FA(db, mockUser.id, realToken);
68
+ console.log("โœ… 2FA Verified! Recovery Codes:", verifyResult.recoveryCodes);
69
+ console.log("โœ… User 2FA Status:", mockUser.twoFactorEnabled ? "ENABLED" : "FAILED");
70
+ // --- STEP 3: Login without TOTP (Should fail) ---
71
+ console.log("\nStep 3: Attempting Login WITHOUT TOTP...");
72
+ try {
73
+ await auth.login(db, { email: mockUser.email, password: "password123" });
74
+ console.log("โŒ FAILED: Login succeeded without TOTP!");
75
+ }
76
+ catch (err) {
77
+ console.log("โœ… SUCCESS: Login denied as expected:", err.message);
78
+ }
79
+ // --- STEP 4: Login with correct TOTP ---
80
+ console.log("\nStep 4: Attempting Login WITH correct TOTP...");
81
+ const loginToken = generateTOTP(setup.secret);
82
+ const loginResult = await auth.login(db, { email: mockUser.email, password: "password123", totp: loginToken });
83
+ console.log("โœ… SUCCESS: Logged in! Access Token length:", loginResult.accessToken.length);
84
+ // --- STEP 5: Test Recovery Codes ---
85
+ console.log("\nStep 5: Testing Recovery Code Login...");
86
+ const backupCode = verifyResult.recoveryCodes[0];
87
+ const recoveryResult = await auth.login(db, {
88
+ email: mockUser.email,
89
+ password: "password123",
90
+ recovery: backupCode
91
+ });
92
+ console.log("โœ… SUCCESS: Logged in using recovery code!");
93
+ console.log("โœ… Remaining recovery codes count:", mockUser.recoveryCodes.length);
94
+ // --- STEP 6: Disable 2FA ---
95
+ console.log("\nStep 6: Disabling 2FA...");
96
+ const disableToken = generateTOTP(setup.secret);
97
+ await auth.disable2FA(db, mockUser.id, disableToken);
98
+ console.log("โœ… SUCCESS: 2FA Disabled. Status:", mockUser.twoFactorEnabled ? "ENABLED (Error)" : "DISABLED");
99
+ console.log("\n๐ŸŽŠ ALL 2FA FLOWS COMPLETED SUCCESSFULLY! ๐ŸŽŠ");
100
+ }
101
+ run2FATest().catch(err => {
102
+ console.error("โŒ TEST FAILED:", err);
103
+ process.exit(1);
104
+ });
105
+ //# sourceMappingURL=test-2fa-real.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-2fa-real.js","sourceRoot":"","sources":["../src/test-2fa-real.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,6DAA6D;AAC7D,MAAM,YAAY,GAAG,kCAAkC,CAAC;AACxD,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAC3C,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;IACxB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;QAC3B,IAAI,IAAI,CAAC,CAAC;QACV,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,YAAoB,EAAE,YAAoB,IAAI,CAAC,GAAG,EAAE,EAAU,EAAE;IACpF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC;IAChE,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,KAAK,UAAU,UAAU;IACvB,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;IAEnD,mBAAmB;IACnB,IAAI,QAAQ,GAAQ;QAClB,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,kBAAkB;QACzB,QAAQ,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;QAC1C,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,IAAI;QACrB,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,EAAE;KAClB,CAAC;IAEF,MAAM,EAAE,GAAQ;QACd,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ;QAClC,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ;QACrC,UAAU,EAAE,KAAK,EAAE,EAAU,EAAE,IAAS,EAAE,EAAE;YACzC,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC;QACnB,CAAC;QACD,gBAAgB,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAChC,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;QAClC,kBAAkB,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KACnC,CAAC;IAEF,6BAA6B;IAC7B,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAEjC,6BAA6B;IAC7B,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,SAAS,CAAC,CAAC;IAElD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEpF,mDAAmD;IACnD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,0CAA0C;IAC1C,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC/G,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1F,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE;QAC1C,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,QAAQ,EAAE,aAAa;QACvB,QAAQ,EAAE,UAAU;KACrB,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAEhF,8BAA8B;IAC9B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAE5G,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;AAC/D,CAAC;AAED,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACvB,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,98 @@
1
+ // test-dolphin.ts
2
+ import { createDolphinServer } from "./server/server";
3
+ import { createDolphinController } from "./controller/controller";
4
+ import { createDolphinAuthController } from "./authController/authController";
5
+ // Mock Database Connection (Replacing ./config.js)
6
+ const dbConnect = async () => {
7
+ console.log("๐Ÿ› ๏ธ Mock Database Connected");
8
+ };
9
+ // Mock Database Interface (Replacing ./auth/model.js)
10
+ const db = {
11
+ createUser: async (data) => ({ id: "123", ...data }),
12
+ findUserByEmail: async (email) => ({ id: "123", email, password: "hashed_password", role: "admin" }),
13
+ findUserById: async (id) => ({ id, email: "user@example.com", role: "admin" }),
14
+ updateUser: async (id, data) => ({ id, ...data }),
15
+ saveRefreshToken: async () => { },
16
+ findRefreshToken: async () => ({ userId: "123", expiresAt: new Date(Date.now() + 10000) }),
17
+ deleteRefreshToken: async () => { },
18
+ // For CRUD
19
+ read: async () => [{ id: "123", name: "John Doe" }],
20
+ create: async (data) => ({ id: "456", ...data }),
21
+ update: async (id, data) => ({ id, ...data }),
22
+ delete: async (id) => ({ id })
23
+ };
24
+ async function main() {
25
+ const app = createDolphinServer();
26
+ await dbConnect();
27
+ // ============ SETUP AUTH ============
28
+ const auth = createDolphinAuthController(db, {
29
+ secret: process.env.JWT_SECRET || 'my-super-secret-key',
30
+ cookieMaxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
31
+ issuer: 'MyApp'
32
+ });
33
+ // ============ CRUD CONTROLLER ============
34
+ const userController = createDolphinController(db, "User");
35
+ // ============ PUBLIC ROUTES (No Auth) ============
36
+ app.post("/auth/register", async (ctx) => {
37
+ const result = await auth.register(ctx);
38
+ return result; // Using the new auto-reply feature!
39
+ });
40
+ app.post("/auth/login", async (ctx) => {
41
+ return await auth.login(ctx);
42
+ });
43
+ app.post("/auth/refresh", async (ctx) => {
44
+ return await auth.refresh(ctx);
45
+ });
46
+ // ============ PROTECTED ROUTES (Auth Required) ============
47
+ // โœ… NOW SUPPORTED: Multiple handlers (middleware + final handler)
48
+ app.get("/auth/me", auth.requireAuth, async (ctx) => {
49
+ const result = await auth.me(ctx);
50
+ return result;
51
+ });
52
+ app.post("/auth/logout", auth.requireAuth, async (ctx) => {
53
+ return await auth.logout(ctx);
54
+ });
55
+ // ============ PROTECTED CRUD ROUTES (Auth Required) ============
56
+ app.get("/user", auth.requireAuth, async (ctx) => {
57
+ const users = await userController.list(ctx, ctx.req.user?.id);
58
+ return users.map((user) => auth.sanitize(user));
59
+ });
60
+ app.post("/user", auth.requireAuth, async (ctx) => {
61
+ const user = await userController.create(ctx, ctx.req.user?.id);
62
+ return auth.sanitize(user);
63
+ });
64
+ // ============ ADMIN ROUTES ============
65
+ app.get("/admin/users", auth.requireAdmin, async (ctx) => {
66
+ const users = await userController.list(ctx);
67
+ return users.map(auth.sanitize);
68
+ });
69
+ // ============ START SERVER ============
70
+ const PORT = 3000;
71
+ app.listen(PORT, () => {
72
+ console.log(`
73
+ ๐Ÿš€ Dolphin Server running on port ${PORT}
74
+
75
+ ๐Ÿ“‹ Available Routes:
76
+
77
+ ๐Ÿ”“ PUBLIC ROUTES:
78
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
79
+ โ”‚ POST /auth/register โ”‚
80
+ โ”‚ POST /auth/login โ”‚
81
+ โ”‚ POST /auth/refresh โ”‚
82
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
83
+ โ”‚ ๐Ÿ”’ PROTECTED ROUTES (Auth Required): โ”‚
84
+ โ”‚ GET /auth/me โ”‚
85
+ โ”‚ POST /auth/logout โ”‚
86
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
87
+ โ”‚ ๐Ÿ‘ค USER CRUD (Protected): โ”‚
88
+ โ”‚ GET /user โ”‚
89
+ โ”‚ POST /user โ”‚
90
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
91
+ โ”‚ ๐Ÿ‘‘ ADMIN ROUTES: โ”‚
92
+ โ”‚ GET /admin/users โ”‚
93
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
94
+ `);
95
+ });
96
+ }
97
+ main().catch(console.error);
98
+ //# sourceMappingURL=test-dolphin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-dolphin.js","sourceRoot":"","sources":["../src/test-dolphin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Dolphin Universal Context Builder
3
+ *
4
+ * Dolphin modules (auth-controller, crud, router) เคฒเฅ‡ ctx object use เค—เคฐเฅเค›เคจเฅเฅค
5
+ * เคฏเฅ‹ helper เคฒเฅ‡ เค•เฅเคจเฅˆ เคชเคจเคฟ framework เค•เฅ‹ req/res เคฌเคพเคŸ ctx เคฌเคจเคพเค‰เคเค›เฅค
6
+ *
7
+ * โ”€โ”€โ”€ Express โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
8
+ * import { createCtx } from 'dolphin-server-modules/utils/ctx';
9
+ * app.post('/login', (req, res) => auth.login(createCtx(req, res)));
10
+ *
11
+ * โ”€โ”€โ”€ Fastify โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
12
+ * fastify.post('/login', (req, reply) =>
13
+ * auth.login(createCtx(req.raw, reply.raw, req.body, req.params, req.query))
14
+ * );
15
+ *
16
+ * โ”€โ”€โ”€ Next.js API Route โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
17
+ * export default async function handler(req, res) {
18
+ * return auth.login(createCtx(req, res));
19
+ * }
20
+ *
21
+ * โ”€โ”€โ”€ Hono โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
22
+ * app.post('/login', async (c) => {
23
+ * const ctx = createCtx(c.req.raw, c.res, await c.req.json(), c.req.param());
24
+ * return auth.login(ctx);
25
+ * });
26
+ */
27
+ export interface DolphinCtx {
28
+ req: any;
29
+ res: any;
30
+ params: Record<string, string>;
31
+ query: Record<string, string>;
32
+ body: any;
33
+ state: Record<string, any>;
34
+ json: (data: any, status?: number) => DolphinCtx;
35
+ text: (data: any, status?: number) => DolphinCtx;
36
+ html: (data: any, status?: number) => DolphinCtx;
37
+ status: (code: number) => DolphinCtx;
38
+ setHeader: (name: string, value: string) => DolphinCtx;
39
+ getHeader: (name: string) => string | undefined;
40
+ }
41
+ /**
42
+ * เค•เฅเคจเฅˆ เคชเคจเคฟ framework เค•เฅ‹ req/res เคฌเคพเคŸ Dolphin ctx เคฌเคจเคพเค‰เคจเฅ‡
43
+ * @param req - Express req / Fastify request.raw / Next.js req / Node.js IncomingMessage
44
+ * @param res - Express res / Fastify reply.raw / Next.js res / Node.js ServerResponse
45
+ * @param body - parsed body (req.body เคตเคพ await req.json())
46
+ * @param params - route params ({ id: '123' })
47
+ * @param query - query string params
48
+ */
49
+ export declare function createCtx(req: any, res: any, body?: any, params?: Record<string, string>, query?: Record<string, string>): DolphinCtx;
50
+ export default createCtx;