shokupan 0.3.0 → 0.4.5

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/dist/index.js CHANGED
@@ -1376,6 +1376,7 @@ const ready = db.connect(engine, { namespace: "vendor", database: "shokupan" }).
1376
1376
  DEFINE TABLE OVERWRITE users SCHEMALESS COMMENT "Created by Shokupan";
1377
1377
  DEFINE TABLE OVERWRITE idempotency_keys SCHEMALESS COMMENT "Created by Shokupan";
1378
1378
  DEFINE TABLE OVERWRITE middleware_tracking SCHEMALESS COMMENT "Created by Shokupan";
1379
+ DEFINE TABLE OVERWRITE requests SCHEMALESS COMMENT "Created by Shokupan";
1379
1380
  `);
1380
1381
  });
1381
1382
  const datastore = {
@@ -1485,17 +1486,28 @@ class ShokupanRouter {
1485
1486
  currentGuards = [];
1486
1487
  // Registry Accessor
1487
1488
  getComponentRegistry() {
1488
- const routes = this[$routes].map((r) => ({
1489
- type: "route",
1490
- path: r.path,
1491
- method: r.method,
1492
- metadata: r.metadata,
1493
- handlerName: r.handler.name,
1494
- tags: r.handlerSpec?.tags,
1495
- order: r.order,
1496
- _fn: r.handler
1497
- // Expose handler for debugging instrumentation
1498
- }));
1489
+ const controllerRoutesMap = /* @__PURE__ */ new Map();
1490
+ const localRoutes = [];
1491
+ for (const r of this[$routes]) {
1492
+ const entry = {
1493
+ type: "route",
1494
+ path: r.path,
1495
+ method: r.method,
1496
+ metadata: r.metadata,
1497
+ handlerName: r.handler.name,
1498
+ tags: r.handlerSpec?.tags,
1499
+ order: r.order,
1500
+ _fn: r.handler
1501
+ };
1502
+ if (r.controller) {
1503
+ if (!controllerRoutesMap.has(r.controller)) {
1504
+ controllerRoutesMap.set(r.controller, []);
1505
+ }
1506
+ controllerRoutesMap.get(r.controller).push(entry);
1507
+ } else {
1508
+ localRoutes.push(entry);
1509
+ }
1510
+ }
1499
1511
  const mw = this.middleware;
1500
1512
  const middleware = mw ? mw.map((m) => ({
1501
1513
  name: m.name || "middleware",
@@ -1511,18 +1523,19 @@ class ShokupanRouter {
1511
1523
  children: r.getComponentRegistry()
1512
1524
  }));
1513
1525
  const controllers = this[$childControllers].map((c) => {
1526
+ const routes = controllerRoutesMap.get(c) || [];
1514
1527
  return {
1515
1528
  type: "controller",
1516
1529
  path: c[$mountPath] || "/",
1517
1530
  name: c.constructor.name,
1518
- metadata: c.metadata
1519
- // Check if we can store this
1531
+ metadata: c.metadata,
1532
+ children: { routes }
1520
1533
  };
1521
1534
  });
1522
1535
  return {
1523
1536
  metadata: this.metadata,
1524
1537
  middleware,
1525
- routes,
1538
+ routes: localRoutes,
1526
1539
  routers,
1527
1540
  controllers
1528
1541
  };
@@ -1612,7 +1625,7 @@ class ShokupanRouter {
1612
1625
  const decoratedArgs = instance[$routeArgs] || proto && proto[$routeArgs];
1613
1626
  const methodMiddlewareMap = instance[$middleware] || proto && proto[$middleware];
1614
1627
  let routesAttached = 0;
1615
- for (const name of methods) {
1628
+ for (const name of Array.from(methods)) {
1616
1629
  if (name === "constructor") continue;
1617
1630
  if (["arguments", "caller", "callee"].includes(name)) continue;
1618
1631
  const originalHandler = instance[name];
@@ -1746,7 +1759,7 @@ class ShokupanRouter {
1746
1759
  const decoratedSpecs = instance[$routeSpec] || proto && proto[$routeSpec];
1747
1760
  const userSpec = decoratedSpecs && decoratedSpecs.get(name);
1748
1761
  const spec = { tags: [tagName], ...userSpec };
1749
- this.add({ method, path: normalizedPath, handler: finalHandler, spec });
1762
+ this.add({ method, path: normalizedPath, handler: finalHandler, spec, controller: instance });
1750
1763
  }
1751
1764
  }
1752
1765
  if (routesAttached === 0) {
@@ -1967,8 +1980,23 @@ class ShokupanRouter {
1967
1980
  * @param handler - Route handler function
1968
1981
  * @param requestTimeout - Timeout for this route in milliseconds
1969
1982
  */
1970
- add({ method, path, spec, handler, regex: customRegex, group, requestTimeout, renderer }) {
1983
+ add({ method, path, spec, handler, regex: customRegex, group, requestTimeout, renderer, controller }) {
1971
1984
  const { regex, keys } = customRegex ? { regex: customRegex, keys: [] } : this.parsePath(path);
1985
+ if (this.currentGuards.length > 0) {
1986
+ spec = spec || {};
1987
+ for (const guard of this.currentGuards) {
1988
+ if (guard.spec) {
1989
+ if (guard.spec.responses) {
1990
+ spec.responses = spec.responses || {};
1991
+ Object.assign(spec.responses, guard.spec.responses);
1992
+ }
1993
+ if (guard.spec.security) {
1994
+ spec.security = spec.security || [];
1995
+ spec.security.push(...guard.spec.security);
1996
+ }
1997
+ }
1998
+ }
1999
+ }
1972
2000
  let wrappedHandler = handler;
1973
2001
  const routeGuards = [...this.currentGuards];
1974
2002
  const effectiveTimeout = requestTimeout ?? this.requestTimeout ?? this.rootConfig?.requestTimeout;
@@ -2094,7 +2122,8 @@ class ShokupanRouter {
2094
2122
  metadata: {
2095
2123
  file,
2096
2124
  line
2097
- }
2125
+ },
2126
+ controller
2098
2127
  });
2099
2128
  this.trie.insert(method, path, bakedHandler);
2100
2129
  return this;
@@ -2328,12 +2357,21 @@ class Shokupan extends ShokupanRouter {
2328
2357
  const c = ctx;
2329
2358
  if (c.handlerStack && c.app?.applicationConfig.enableMiddlewareTracking) {
2330
2359
  const metadata = middleware.metadata || {};
2331
- c.handlerStack.push({
2360
+ const start = performance.now();
2361
+ const item = {
2332
2362
  name: metadata.pluginName ? `${metadata.pluginName} (${metadata.name})` : metadata.name || middleware.name || "middleware",
2333
2363
  file: metadata.file || file,
2334
2364
  line: metadata.line || line,
2335
- isBuiltin: metadata.isBuiltin
2336
- });
2365
+ isBuiltin: metadata.isBuiltin,
2366
+ startTime: start,
2367
+ duration: -1
2368
+ };
2369
+ c.handlerStack.push(item);
2370
+ try {
2371
+ return await middleware(ctx, next);
2372
+ } finally {
2373
+ item.duration = performance.now() - start;
2374
+ }
2337
2375
  }
2338
2376
  return middleware(ctx, next);
2339
2377
  };
@@ -2874,14 +2912,14 @@ function Compression(options = {}) {
2874
2912
  if (ctx._rawBody !== void 0) {
2875
2913
  if (typeof ctx._rawBody === "string") {
2876
2914
  const encoded = new TextEncoder().encode(ctx._rawBody);
2877
- body = encoded.buffer;
2915
+ body = encoded;
2878
2916
  bodySize = encoded.byteLength;
2879
2917
  } else if (ctx._rawBody instanceof Uint8Array) {
2880
- body = ctx._rawBody.buffer;
2918
+ body = ctx._rawBody;
2881
2919
  bodySize = ctx._rawBody.byteLength;
2882
2920
  } else {
2883
2921
  body = ctx._rawBody;
2884
- bodySize = ctx._rawBody.byteLength;
2922
+ bodySize = body.byteLength;
2885
2923
  }
2886
2924
  } else {
2887
2925
  body = await response.arrayBuffer();
@@ -2891,7 +2929,7 @@ function Compression(options = {}) {
2891
2929
  return new Response(body, {
2892
2930
  status: response.status,
2893
2931
  statusText: response.statusText,
2894
- headers: response.headers
2932
+ headers: new Headers(response.headers)
2895
2933
  });
2896
2934
  }
2897
2935
  let compressed;
@@ -3414,7 +3452,8 @@ function enableOpenApiValidation(app) {
3414
3452
  }
3415
3453
  const eta = new Eta();
3416
3454
  class ScalarPlugin extends ShokupanRouter {
3417
- constructor(pluginOptions) {
3455
+ constructor(pluginOptions = {}) {
3456
+ pluginOptions.config ??= {};
3418
3457
  super();
3419
3458
  this.pluginOptions = pluginOptions;
3420
3459
  this.init();