@hotfusion/modeller 0.0.7 → 0.0.9

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 (44) hide show
  1. package/README.md +784 -38
  2. package/dist/View.js +3 -0
  3. package/dist/View.js.map +1 -0
  4. package/dist/connector.js +1 -0
  5. package/dist/connector.js.map +1 -1
  6. package/dist/extensions/oidc/client.js +221 -0
  7. package/dist/extensions/oidc/client.js.map +1 -0
  8. package/dist/extensions/oidc/index.js +192 -0
  9. package/dist/extensions/oidc/index.js.map +1 -0
  10. package/dist/logger.js +129 -0
  11. package/dist/logger.js.map +1 -0
  12. package/dist/model.js +112 -96
  13. package/dist/model.js.map +1 -1
  14. package/dist/server.js +333 -183
  15. package/dist/server.js.map +1 -1
  16. package/dist/types/View.d.ts +2 -0
  17. package/dist/types/View.d.ts.map +1 -0
  18. package/dist/types/connector.d.ts +1 -1
  19. package/dist/types/connector.d.ts.map +1 -1
  20. package/dist/types/extensions/oidc/client.d.ts +32 -0
  21. package/dist/types/extensions/oidc/client.d.ts.map +1 -0
  22. package/dist/types/extensions/oidc/index.d.ts +20 -0
  23. package/dist/types/extensions/oidc/index.d.ts.map +1 -0
  24. package/dist/types/extensions/oidc/oidc.d.ts +20 -0
  25. package/dist/types/extensions/oidc/oidc.d.ts.map +1 -0
  26. package/dist/types/extensions/oidc.d.ts +20 -0
  27. package/dist/types/extensions/oidc.d.ts.map +1 -0
  28. package/dist/types/index.d.ts +2 -0
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/dist/types/logger.d.ts +24 -0
  31. package/dist/types/logger.d.ts.map +1 -0
  32. package/dist/types/model.d.ts +23 -11
  33. package/dist/types/model.d.ts.map +1 -1
  34. package/dist/types/server.d.ts +23 -4
  35. package/dist/types/server.d.ts.map +1 -1
  36. package/dist/types/utils/bundler.d.ts +2 -0
  37. package/dist/types/utils/bundler.d.ts.map +1 -1
  38. package/dist/types/view.d.ts +13 -0
  39. package/dist/types/view.d.ts.map +1 -0
  40. package/dist/utils/bundler.js +138 -39
  41. package/dist/utils/bundler.js.map +1 -1
  42. package/dist/view.js +34 -0
  43. package/dist/view.js.map +1 -0
  44. package/package.json +16 -7
package/dist/server.js CHANGED
@@ -14,14 +14,11 @@ const eventemitter3_1 = require("eventemitter3");
14
14
  const jose_1 = require("jose");
15
15
  const socket_io_1 = require("socket.io");
16
16
  const keygen_js_1 = require("./utils/keygen.js");
17
+ const koa_static_1 = __importDefault(require("koa-static"));
17
18
  class Utils {
18
19
  static trimPath(path) {
19
20
  return '/' + path.split('/').filter((x) => x).join('/');
20
21
  }
21
- static postman(Event) {
22
- if (Event.middleware === 'postman')
23
- return Event.ctx.redirect(`/?access_token=${Event.profile.accessToken}&clientId=${Event.provider.clientId}&providerId=${Event.provider.id}&scopes=${Event.provider.scopes.join(' ')}`);
24
- }
25
22
  }
26
23
  class Server extends eventemitter3_1.EventEmitter {
27
24
  port;
@@ -31,6 +28,18 @@ class Server extends eventemitter3_1.EventEmitter {
31
28
  providers = [];
32
29
  config;
33
30
  io;
31
+ registeredModels = [];
32
+ extensions = [];
33
+ extensionConfigs = new Map();
34
+ API_OPERATIONS = ['insert', 'update', 'delete', 'get', 'find', 'list'];
35
+ OPERATION_METHODS = {
36
+ insert: 'POST',
37
+ update: 'PUT',
38
+ delete: 'DELETE',
39
+ get: 'GET',
40
+ find: 'POST',
41
+ list: 'GET',
42
+ };
34
43
  constructor(port, config) {
35
44
  super();
36
45
  this.app = new koa_1.default();
@@ -52,125 +61,173 @@ class Server extends eventemitter3_1.EventEmitter {
52
61
  this.port = port;
53
62
  this.config = config;
54
63
  }
55
- // TODO: IMPORTANT: Deprecated
64
+ // ?? Register model ??????????????????????????????????????????????????????????
65
+ registerModel(id, scope, model) {
66
+ this.registeredModels.push({ id, scope, model });
67
+ return this;
68
+ }
69
+ // ?? Register extension ??????????????????????????????????????????????????????
70
+ registerExtension(extension) {
71
+ this.extensions.push(extension);
72
+ return this;
73
+ }
74
+ // ?? Setup extensions ??????????????????????????????????????????????????????
75
+ async setupExtensions() {
76
+ console.log('[Server] Setting up extensions...');
77
+ for (const ext of this.extensions) {
78
+ console.log(`[Server] Setting up extension: ${ext.id}`);
79
+ const extConfig = this.extensionConfigs.get(ext.id) || {};
80
+ console.log(`[Server] Extension ${ext.id} config:`, extConfig);
81
+ await ext.setup(this, extConfig);
82
+ console.log(`[Server] Extension ${ext.id} setup complete`);
83
+ }
84
+ console.log('[Server] All extensions setup complete');
85
+ }
86
+ // ?? Auto-mount API routes ?????????????????????????????????????????????????????????
87
+ mountModelRoutes() {
88
+ for (const { id, scope, model } of this.registeredModels) {
89
+ this._mountModelRecursive(id, scope, model);
90
+ }
91
+ }
92
+ _mountModelRecursive(id, scope, model) {
93
+ this._mountModel(id, scope, model);
94
+ for (const ext of model.getExtensions?.() ?? []) {
95
+ this._mountModelRecursive(id, `${scope}/${ext.id}`, ext);
96
+ }
97
+ }
98
+ _mountModel(id, scope, model) {
99
+ // ?? CRUD operations ???????????????????????????????????????????????????
100
+ for (const operation of this.API_OPERATIONS) {
101
+ const routePath = `/${id}/${scope}/${operation}`;
102
+ const handler = async (ctx) => {
103
+ const { private: _priv, ...body } = { ...ctx.query, ...(ctx.request.body ?? {}) };
104
+ try {
105
+ let result;
106
+ if (operation === 'insert') {
107
+ result = await model.insert(body, { private: true });
108
+ }
109
+ else if (operation === 'update') {
110
+ const { key, data } = body;
111
+ result = await model.update(key, data, { private: true });
112
+ }
113
+ else if (operation === 'delete') {
114
+ const query = Object.keys(ctx.request.body ?? {}).length ? ctx.request.body : ctx.query;
115
+ result = await model.delete(query);
116
+ }
117
+ else if (operation === 'get') {
118
+ result = await model.get(body, { private: true });
119
+ }
120
+ else if (operation === 'list') {
121
+ const { private: _p, start, count, ...query } = body;
122
+ result = await model.list(query, { start: Number(start) || 0, count: Number(count) || 10000, private: true });
123
+ }
124
+ else {
125
+ const { private: _p, max, ...query } = body;
126
+ result = await model.find(query, { max, private: true });
127
+ }
128
+ ctx.status = 200;
129
+ ctx.body = { ok: true, entry: result };
130
+ }
131
+ catch (err) {
132
+ ctx.status = err?.status ?? 500;
133
+ ctx.body = { ok: false, error: err?.message ?? err };
134
+ }
135
+ };
136
+ if (operation === 'insert')
137
+ this.router.post(routePath, handler);
138
+ else if (operation === 'update')
139
+ this.router.put(routePath, handler);
140
+ else if (operation === 'delete')
141
+ this.router.delete(routePath, handler);
142
+ else if (operation === 'get')
143
+ this.router.get(routePath, handler);
144
+ else if (operation === 'find')
145
+ this.router.post(routePath, handler);
146
+ else if (operation === 'list')
147
+ this.router.get(routePath, handler);
148
+ }
149
+ // ?? Custom methods ????????????????????????????????????????????????????
150
+ for (const method of model.getMethods?.() ?? []) {
151
+ this.router.post(`/${id}/${scope}/${method}`, async (ctx) => {
152
+ const { _id, ...rest } = ctx.request.body ?? {};
153
+ try {
154
+ const result = await model.call(method, { _id, ...rest });
155
+ ctx.status = 200;
156
+ ctx.body = { ok: true, entry: result };
157
+ }
158
+ catch (err) {
159
+ ctx.status = err?.status ?? 500;
160
+ ctx.body = { ok: false, error: err?.message ?? err };
161
+ }
162
+ });
163
+ }
164
+ // ?? Upload methods (multipart HTTP) ???????????????????????????????????
165
+ for (const uploadId of model.getUploads?.() ?? []) {
166
+ this.upload(`/${id}/${scope}/${uploadId}`, async (ctx, file, fields) => {
167
+ try {
168
+ return await model.callUpload(uploadId, file, fields);
169
+ }
170
+ catch (err) {
171
+ throw err;
172
+ }
173
+ });
174
+ }
175
+ // ?? View routes ??????????????????????????????????????????????????????????????????????
176
+ for (const view of model.getViews?.() ?? []) {
177
+ const routePath = `/${id}/${scope}${view.path}`.replace(/\/$/, '') || '/';
178
+ console.log('[View] Mounting route:', routePath);
179
+ this.router.get(routePath, async (ctx) => {
180
+ try {
181
+ ctx.type = 'text/html';
182
+ ctx.body = await view.render(ctx.query);
183
+ }
184
+ catch (err) {
185
+ ctx.status = err?.status ?? 500;
186
+ ctx.body = { ok: false, error: err?.message ?? err };
187
+ }
188
+ });
189
+ }
190
+ // ?? Static folders ????????????????????????????????????????????????????
191
+ for (const [urlPath, { path: folderPath }] of model.getFolders?.() ?? new Map()) {
192
+ const staticMiddleware = (0, koa_static_1.default)(folderPath);
193
+ this.app.use(async (ctx, next) => {
194
+ if (ctx.path.startsWith(urlPath)) {
195
+ ctx.path = ctx.path.slice(urlPath.length) || '/';
196
+ return staticMiddleware(ctx, next);
197
+ }
198
+ return next();
199
+ });
200
+ }
201
+ // ?? Stream methods (binary socket) ????????????????????????????????????
202
+ for (const streamId of model.getStreams?.() ?? []) {
203
+ // Streams are registered globally in _setupStream
204
+ // Store them for later reference
205
+ }
206
+ }
207
+ // ?? OIDC Providers ?????????????????????????????????????????????????????
208
+ authPath;
56
209
  setOIDCProviders(path, providers) {
210
+ console.log('[Server] setOIDCProviders called with path:', path, 'providers:', providers?.map(p => p.id));
211
+ this.authPath = path;
57
212
  if (this.config.domain)
58
213
  path = `${this.config.domain}/${path}`;
59
- path
60
- = path.split('/').filter((x) => x).join('/');
214
+ path = path.split('/').filter((x) => x).join('/');
61
215
  providers?.forEach?.((provider) => {
62
216
  if (!this.providers.find(x => x.clientId === provider.clientId))
63
217
  this.providers.push({ ...provider });
64
218
  });
65
- if (!this.routes.find(x => x.path === Utils.trimPath(path) + '/:provider')) {
66
- this.routes.push({
67
- method: 'post',
68
- path: Utils.trimPath(path) + '/:provider/logout',
69
- callback: async (ctx, next) => {
70
- if (ctx.params.provider === 'callback' || !ctx.path.includes('/logout'))
71
- return await next();
72
- let provider = this.providers.find(x => x.id === ctx.params.provider);
73
- if (provider) {
74
- let SESSION = ctx.headers.authorization || '';
75
- if (!SESSION)
76
- ctx.throw(401, 'Unauthorized');
77
- if (SESSION) {
78
- SESSION = SESSION.split(' ').pop() || '';
79
- let token;
80
- try {
81
- token = (await (0, jose_1.jwtVerify)(SESSION, new TextEncoder().encode(Array.isArray(this.app?.keys) ? this.app.keys[0] : undefined))).payload;
82
- }
83
- catch (e) {
84
- token = (0, jose_1.decodeJwt)(SESSION);
85
- }
86
- let body = {};
87
- await new Promise(resolve => setTimeout(resolve, 1000));
88
- ctx.body = body;
89
- }
90
- }
91
- }
92
- });
93
- /*this.routes.push({
94
- method: 'get',
95
- path: Utils.trimPath(path) + '/:provider',
96
- callback: async (ctx, next) => {
97
- if (ctx.params.provider === 'callback')
98
- return await next();
99
-
100
- let provider:IOIDCProvider | undefined
101
- = this.providers.find(x => x.id === ctx.params.provider);
102
-
103
- if (provider) {
104
- try{
105
- let {url, code_verifier, state}
106
- = await new OIDCClient(provider as any ).buildURL(provider.scopes.join(' '));
107
-
108
- let {middleware} = ctx.request.query || {};
109
- ctx.session!.oidc = {
110
- __SID : ctx.query.__SID,
111
- provider,
112
- code_verifier,
113
- state,
114
- middleware: middleware || false,
115
- query : (ctx.request.querystring || '').replace(/^\?/, '')
116
- .split('&')
117
- .filter(Boolean)
118
- .reduce<Record<string, string>>((acc, pair) => {
119
- const [key, value = ''] = pair.split('=');
120
- acc[decodeURIComponent(key as any )] = decodeURIComponent(value);
121
- return acc;
122
- }, {})
123
- };
124
-
125
- await ctx.session!.save?.();
126
- ctx.redirect(url.toString());
127
- }catch (e:any){
128
- console.error(e);
129
- ctx.body = e.message;
130
- }
131
- }
132
- }
133
- })*/
134
- /*this.routes.push({
135
- method : 'get',
136
- path : Utils.trimPath(path.replace(this.config.domain + '/', '') + '/callback'),
137
- callback : async (ctx) => {
138
- let origin
139
- = ctx.session?.oidc?.query?.origin || '';
140
-
141
- const session
142
- = ctx.session?.oidc;
143
-
144
- const code
145
- = ctx.query.code as string;
146
-
147
- const oidcClient
148
- = new OIDCClient(session.provider);
149
-
150
- const TokenCollection
151
- = await oidcClient.getToken(code,session.code_verifier)
152
-
153
- this.emit('provider',{token:TokenCollection,sid:session.__SID,session});
154
- ctx.type = 'html';
155
- ctx.body = `<script>window?.close?.()</script>`
156
- }
157
- })*/
158
- }
219
+ // Store OIDC config for extension
220
+ this.extensionConfigs.set('oidc', {
221
+ providers: providers || [],
222
+ authPath: path,
223
+ });
159
224
  return this;
160
225
  }
161
- // ── upload ───────────────────────────────────────────────────────────────
162
- //
163
- // Registers a multipart/form-data route. The handler receives the parsed
164
- // file as a Buffer along with any other form fields.
165
- //
166
- // Example:
167
- // server.upload('/system/filesystem/upload', async (ctx, file, fields) => {
168
- // return { ok: true };
169
- // });
226
+ // ?? Upload ????????????????????????????????????????????????????????????????
170
227
  upload(path, handler) {
171
228
  this.routes.push({
172
229
  method: 'post',
173
- path,
230
+ path: Utils.trimPath(path),
174
231
  callback: async (ctx) => {
175
232
  return new Promise((resolve, reject) => {
176
233
  const fields = {};
@@ -204,17 +261,7 @@ class Server extends eventemitter3_1.EventEmitter {
204
261
  });
205
262
  return this;
206
263
  }
207
- // ── stream ───────────────────────────────────────────────────────────────
208
- //
209
- // Registers socket handlers for chunked binary file streaming with resume.
210
- // The handler receives the complete reassembled Buffer and the upload metadata.
211
- // Call this once — it handles all uploads for any model/scope.
212
- //
213
- // Example:
214
- // server.stream(async (buffer, meta) => {
215
- // // meta = { _id, path, id, scope, ... }
216
- // return { ok: true };
217
- // });
264
+ // ?? Stream ????????????????????????????????????????????????????????????????
218
265
  _streamHandler;
219
266
  _uploadTmp = '/tmp/hotfusion-uploads';
220
267
  stream(handler) {
@@ -224,9 +271,7 @@ class Server extends eventemitter3_1.EventEmitter {
224
271
  _setupStream(socket) {
225
272
  const handler = this._streamHandler;
226
273
  const uploadTmp = this._uploadTmp;
227
- // uploadId → { meta, totalChunks, received }
228
274
  const uploads = new Map();
229
- // Check disk for existing chunks (resume support)
230
275
  socket.on('upload:resume', async ({ uploadId }) => {
231
276
  const uploadDir = `${uploadTmp}/${uploadId}`;
232
277
  let fromChunk = 0;
@@ -240,10 +285,8 @@ class Server extends eventemitter3_1.EventEmitter {
240
285
  catch { }
241
286
  socket.emit(`upload:resume:${uploadId}`, { fromChunk });
242
287
  });
243
- // Client announces upload metadata — make this synchronous so chunks can't race it
244
288
  socket.on('upload:start', ({ uploadId, id, scope, method, meta, totalChunks }) => {
245
289
  const fullMeta = { ...meta, id, scope, method };
246
- // Synchronous mkdir — no awaits before uploads.set()
247
290
  const fs = require('node:fs');
248
291
  fs.mkdirSync(`${uploadTmp}/${uploadId}`, { recursive: true });
249
292
  const received = new Set();
@@ -254,10 +297,8 @@ class Server extends eventemitter3_1.EventEmitter {
254
297
  }
255
298
  catch { }
256
299
  uploads.set(uploadId, { meta: fullMeta, totalChunks, received });
257
- // Ack so client knows it's safe to send chunks
258
300
  socket.emit(`upload:started:${uploadId}`);
259
301
  });
260
- // Client sends a raw binary chunk
261
302
  socket.on('upload:chunk', async ({ uploadId, index, data }) => {
262
303
  const upload = uploads.get(uploadId);
263
304
  if (!upload) {
@@ -292,70 +333,179 @@ class Server extends eventemitter3_1.EventEmitter {
292
333
  }
293
334
  });
294
335
  }
336
+ // ?? Socket subscriptions ????????????????????????????????????????????????????
337
+ _setupSubscriptions(socket) {
338
+ const socketSubs = new Map();
339
+ const resolveModel = (id, scope) => {
340
+ const [baseScope, ext] = scope.split('.');
341
+ const entry = this.registeredModels.find(m => m.id === id && m.scope === baseScope);
342
+ return ext ? entry?.model[ext] : entry?.model;
343
+ };
344
+ socket.on('subscribe', ({ id, scope, query, reqId }) => {
345
+ const model = resolveModel(id, scope);
346
+ if (!model) {
347
+ socket.emit('error', { code: 'MODEL_NOT_FOUND', id, scope });
348
+ return;
349
+ }
350
+ const { subscription, subId } = model.subscribe(query);
351
+ const channel = [id, scope, subId].join('.');
352
+ const existing = socketSubs.get(subId);
353
+ if (existing)
354
+ existing.subscription.off('publish', existing.listener);
355
+ const listener = (payload) => socket.emit(channel, payload);
356
+ subscription.on('publish', listener);
357
+ socketSubs.set(subId, { model, subscription, listener });
358
+ socket.emit('subscribed', { id, scope, query, subId, events: subscription.getEvents(), reqId });
359
+ });
360
+ socket.on('event:call', async ({ id, scope, query, event, args, callId }) => {
361
+ const model = resolveModel(id, scope);
362
+ if (!model) {
363
+ socket.emit('event:result', { callId, error: { code: 'MODEL_NOT_FOUND' } });
364
+ return;
365
+ }
366
+ try {
367
+ const { subscription } = model.subscribe(query);
368
+ const result = await subscription.dispatch(event, args, { socket, scope });
369
+ socket.emit('event:result', { callId, result });
370
+ }
371
+ catch (error) {
372
+ socket.emit('event:result', { callId, error });
373
+ }
374
+ });
375
+ socket.on('unsubscribe', ({ id, scope, query }) => {
376
+ const model = resolveModel(id, scope);
377
+ if (!model)
378
+ return;
379
+ const subId = JSON.stringify(Object.fromEntries(Object.entries(query).sort()));
380
+ const existing = socketSubs.get(subId);
381
+ if (existing) {
382
+ existing.subscription.off('publish', existing.listener);
383
+ socketSubs.delete(subId);
384
+ }
385
+ });
386
+ socket.on('disconnect', () => {
387
+ for (const { subscription, listener } of socketSubs.values()) {
388
+ subscription.off('publish', listener);
389
+ }
390
+ socketSubs.clear();
391
+ this.registeredModels.forEach(m => m.model.emit('disconnect', socket));
392
+ });
393
+ }
394
+ // ?? Metadata endpoint ??????????????????????????????????????????????????????
395
+ _setupMetadataRoute() {
396
+ this.router.get('/@metadata', async (ctx) => {
397
+ const buildMeta = (id, scope, model) => ({
398
+ id,
399
+ scope,
400
+ schema: model.getSchema?.(),
401
+ schemes: model.getSchemes?.(),
402
+ operations: this.API_OPERATIONS.map(op => ({
403
+ operation: op,
404
+ method: this.OPERATION_METHODS[op],
405
+ path: `/${id}/${scope}/${op}`,
406
+ url: `http://localhost:${this.port}/${id}/${scope}/${op}`,
407
+ schema: op === 'insert' || op === 'update' ? model.getSchema?.() : { type: 'object', properties: { _id: { type: 'string' } } },
408
+ })),
409
+ methods: (model.getMethods?.() ?? []).map((m) => ({
410
+ method: m,
411
+ path: `/${id}/${scope}/${m}`,
412
+ url: `http://localhost:${this.port}/${id}/${scope}/${m}`,
413
+ })),
414
+ extensions: (model.getExtensions?.() ?? []).map((ext) => buildMeta(id, `${scope}/${ext.id}`, ext)),
415
+ });
416
+ ctx.body = { api: this.registeredModels.map(m => buildMeta(m.id, m.scope, m.model)) };
417
+ });
418
+ }
419
+ // ?? Route helper (kept for backward compatibility) ??????????????????????????
295
420
  route(route) {
296
421
  route.path = Utils.trimPath(route.path);
297
422
  this.routes.push(route);
298
423
  return this;
299
424
  }
300
- start() {
301
- setTimeout(() => {
302
- this.app.use(async (ctx, next) => {
303
- try {
304
- await next();
305
- }
306
- catch (err) {
307
- ctx.status = err.status || 500;
308
- ctx.body = {
309
- error: err.message || 'Internal error',
310
- status: err.status
425
+ // ?? Start server ????????????????????????????????????????????????????????????
426
+ async start() {
427
+ console.log('[Server] Start called');
428
+ // Wait a bit then start the server setup
429
+ await new Promise(resolve => setTimeout(resolve, 100));
430
+ console.log('[Server] Setting up app');
431
+ // Error handling middleware
432
+ this.app.use(async (ctx, next) => {
433
+ try {
434
+ await next();
435
+ }
436
+ catch (err) {
437
+ ctx.status = err.status || 500;
438
+ ctx.body = {
439
+ error: err.message || 'Internal error',
440
+ status: err.status
441
+ };
442
+ }
443
+ });
444
+ // Mount auto-generated model routes
445
+ this.mountModelRoutes();
446
+ // Setup extensions FIRST (before any routes)
447
+ console.log('[Server] Before setupExtensions');
448
+ await this.setupExtensions();
449
+ console.log('[Server] After setupExtensions');
450
+ // Mount metadata endpoint
451
+ this._setupMetadataRoute();
452
+ // Mount manually registered routes
453
+ for (let i = 0; i < this.routes.length; i++) {
454
+ let { method, path, callback } = this.routes[i] || {};
455
+ if (method && path && callback) {
456
+ const handler = async (ctx, next) => {
457
+ let flags = {
458
+ protected: this.routes?.[i]?.protected || false
311
459
  };
312
- }
313
- });
314
- for (let i = 0; i < this.routes.length; i++) {
315
- let { method, path, callback } = this.routes[i] || {};
316
- if (method && path && callback)
317
- this.router[method](path, async (ctx, next) => {
318
- let flags = {
319
- protected: this.routes?.[i]?.protected || false
320
- };
321
- try {
322
- if (flags.protected) {
323
- let TOKEN = ctx.headers.authorization;
324
- if (!TOKEN)
325
- ctx.throw(401, 'Unauthorized');
326
- ctx.token
327
- = (await (0, jose_1.jwtVerify)(TOKEN.split(' ').pop(), new TextEncoder().encode(Array.isArray(this.app?.keys) ? this.app.keys[0] : undefined))).payload;
328
- }
329
- let body = await callback(ctx, next);
330
- if (!ctx.body) {
331
- ctx.status = 200;
332
- ctx.body = body;
333
- }
460
+ try {
461
+ if (flags.protected) {
462
+ let TOKEN = ctx.headers.authorization;
463
+ if (!TOKEN)
464
+ ctx.throw(401, 'Unauthorized');
465
+ ctx.token = (await (0, jose_1.jwtVerify)(TOKEN.split(' ').pop(), new TextEncoder().encode(Array.isArray(this.app?.keys) ? this.app.keys[0] : undefined))).payload;
334
466
  }
335
- catch (err) {
336
- ctx.status = 500;
337
- ctx.body = {
338
- error: err.message || err.code || err.details || 'Internal error',
339
- };
467
+ let body = await callback(ctx, next);
468
+ if (!ctx.body) {
469
+ ctx.status = 200;
470
+ ctx.body = body;
340
471
  }
341
- });
472
+ }
473
+ catch (err) {
474
+ ctx.status = 500;
475
+ ctx.body = {
476
+ error: err.message || err.code || err.details || 'Internal error',
477
+ };
478
+ }
479
+ };
480
+ if (method === 'get')
481
+ this.router.get(path, handler);
482
+ else if (method === 'post')
483
+ this.router.post(path, handler);
484
+ else if (method === 'put')
485
+ this.router.put(path, handler);
486
+ else if (method === 'delete')
487
+ this.router.delete(path, handler);
488
+ else if (method === 'patch')
489
+ this.router.patch(path, handler);
342
490
  }
343
- this.app.use(this.router.routes());
344
- this.app.use(this.router.allowedMethods());
345
- const server = this.app.listen(this.port, '0.0.0.0', () => {
346
- this.emit("mounted", this);
347
- });
348
- this.io = new socket_io_1.Server(server, {
349
- cors: { origin: "*", methods: ["GET", "POST"] },
350
- });
351
- this.io.use((socket, next) => {
352
- next();
353
- });
354
- this.io.on("connection", (socket) => {
355
- this._setupStream(socket);
356
- this.emit('connection', { socket });
357
- });
358
- }, 100);
491
+ }
492
+ this.app.use(this.router.routes());
493
+ this.app.use(this.router.allowedMethods());
494
+ const server = this.app.listen(this.port, '0.0.0.0', () => {
495
+ this.emit("mounted", this);
496
+ });
497
+ this.io = new socket_io_1.Server(server, {
498
+ cors: { origin: "*", methods: ["GET", "POST"] },
499
+ });
500
+ this.io.use((socket, next) => {
501
+ next();
502
+ });
503
+ this.io.on("connection", (socket) => {
504
+ this._setupStream(socket);
505
+ this._setupSubscriptions(socket);
506
+ this.emit('connection', { socket });
507
+ });
508
+ console.log('[Server] Start complete, listening on port', this.port);
359
509
  return this;
360
510
  }
361
511
  }