text: /* HELPER TYPES */
  const METHODS = [
      'ACL',
      'BIND',
      'CHECKOUT',
      'CONNECT',
      'COPY',
      'DELETE',
      'GET',
      'HEAD',
      'LINK',
      'LOCK',
      'M-SEARCH',
      'MERGE',
      'MKACTIVITY',
      'MKCALENDAR',
      'MKCOL',
      'MOVE',
      'NOTIFY',
      'OPTIONS',
      'PATCH',
      'POST',
      'PRI',
      'PROPFIND',
      'PROPPATCH',
      'PURGE',
      'PUT',
      'REBIND',
      'REPORT',
      'SEARCH',
      'SOURCE',
      'SUBSCRIBE',
      'TRACE',
      'UNBIND',
      'UNLINK',
      'UNLOCK',
      'UNSUBSCRIBE'
  ];
  /** HELPER METHODS */
  const createMiddlewareFromRoute = ({ path, handler, method }) => ({
      method,
      handler: handler || path,
      path: typeof path === 'string' ? path : '/'
  });
  const pushMiddleware = (mw) => ({ path, handler, method, handlers, type }) => {
      const m = createMiddlewareFromRoute({ path, handler, method, type });
      let waresFromHandlers = [];
      if (handlers) {
          waresFromHandlers = handlers.flat().map((handler) => createMiddlewareFromRoute({
              path,
              handler,
              method,
              type
          }));
      }
      for (const mdw of [m, ...waresFromHandlers])
          mw.push({ ...mdw, type });
  };
  /**
   * tinyhttp Router. Manages middleware and has HTTP methods aliases, e.g. `app.get`, `app.put`
   */
  class Router {
      constructor() {
          this.middleware = [];
          this.mountpath = '/';
          this.apps = {};
          for (const m of METHODS) {
              this[m.toLowerCase()] = this.add(m);
          }
      }
      add(method) {
          return (...args) => {
              const handlers = args.slice(1).flat();
              pushMiddleware(this.middleware)({
                  path: args[0],
                  handler: handlers[0],
                  handlers: handlers.slice(1),
                  method,
                  type: 'route'
              });
              return this;
          };
      }
      msearch(...args) {
          const handlers = args.slice(1).flat();
          pushMiddleware(this.middleware)({
              path: args[0],
              handler: handlers[0],
              handlers: handlers.slice(1),
              method: 'M-SEARCH',
              type: 'route'
          });
          return this;
      }
      all(...args) {
          const handlers = args.slice(1).flat();
          for (const method of METHODS) {
              pushMiddleware(this.middleware)({
                  path: args[0],
                  handler: handlers[0],
                  handlers: handlers.slice(1),
                  method,
                  type: 'route'
              });
          }
          return this;
      }
      /**
       * Return the app's absolute pathname
       * based on the parent(s) that have
       * mounted it.
       *
       * For example if the application was
       * mounted as `"/admin"`, which itself
       * was mounted as `"/blog"` then the
       * return value would be `"/blog/admin"`.
       *
       */
      path() {
          return this.parent ? this.parent.path() + this.mountpath : '';
      }
      /**
       * Push middleware to the stack
       * @param path path that middleware will handle if request URL starts with it
       * @param handler handler function
       * @param handlers the rest handler functions
       */
      use(...args) {
          const path = args[0];
          const handler = args[1];
          const handlers = args.slice(2).flat();
          // app.use('/subapp', subApp)
          if (typeof path === 'string' && handler instanceof Router) {
              // Set mountpath to the specified path
              handler.mountpath = path;
              // Set App parent to current App
              handler.parent = this;
              // Prefix paths with a mountpath
              for (const mw of handler.middleware)
                  mw.path = mw.path === '/' ? handler.mountpath : handler.mountpath + mw.path;
              this.apps[path] = handler;
          }
          // app.use(subApp)
          else if (path instanceof Router) {
              // Set App parent to current App
              path.parent = this;
              // Mount on root
              path.mountpath = '/';
              this.apps['/'] = path;
          }
          else if (!(handler instanceof Router)) {
              let totalHandlers = [];
              if (typeof path !== 'string' && Array.isArray(path)) {
                  for (const h of path.slice(1))
                      totalHandlers.push(h);
              }
              if (handler && Array.isArray(handler)) {
                  if (typeof path === 'string') {
                      for (const h of handler.slice(1))
                          totalHandlers.push(h);
                  }
                  else {
                      for (const h of handler)
                          totalHandlers.push(h);
                  }
              }
              totalHandlers = totalHandlers.concat(handlers);
              let mainHandler;
              if (typeof path === 'string') {
                  if (Array.isArray(handler))
                      mainHandler = handler[0];
                  else
                      mainHandler = handler;
              }
              else {
                  mainHandler = Array.isArray(path) ? path[0] : path;
                  if (typeof handler === 'function')
                      totalHandlers.unshift(handler);
              }
              pushMiddleware(this.middleware)({
                  path: path,
                  handler: mainHandler,
                  handlers: totalHandlers,
                  type: 'mw'
              });
          }
          return this;
      }
  }
  
  export { Router };
  