path-to-regexp#pathToRegexp TypeScript Examples

The following examples show how to use path-to-regexp#pathToRegexp. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From uni-cloud-router with Apache License 2.0 7 votes vote down vote up
function routeMatch(pattern: Condition) {
  if (typeof pattern === 'string') {
    const reg = pathToRegexp(pattern, [], { end: false })
    if (reg.global) reg.lastIndex = 0
    return (ctx: any) => reg.test(ctx.event.action)
  }
  if (pattern instanceof RegExp) {
    return (ctx: any) => {
      if (pattern.global) pattern.lastIndex = 0
      return pattern.test(ctx.event.action)
    }
  }
  if (typeof pattern === 'function') return pattern
  if (Array.isArray(pattern)) {
    const matchs = pattern.map((item) => routeMatch(item)) as any
    return (ctx: any) => matchs.some((match: Function) => match(ctx))
  }
  throw new Error(
    'match/ignore pattern must be RegExp, Array or String, but got ' + pattern
  )
}
Example #2
Source File: operation.ts    From openapi-mock-express-middleware with MIT License 6 votes vote down vote up
constructor({
    method,
    path,
    operation,
    securitySchemes,
    generator,
    parentParams,
  }: {
    path: string;
    method: string;
    operation: OpenAPIV3.OperationObject;
    generator: JSF;
    securitySchemes?: { [key: string]: OpenAPIV3.SecuritySchemeObject };
    parentParams?: (OpenAPIV3.ReferenceObject | OpenAPIV3.ParameterObject)[];
  }) {
    this.pathPattern = path.replace(/\{([^/}]+)\}/g, (p1: string, p2: string): string => `:${p2}`);
    this.parentParams = parentParams || null;

    this.method = method.toUpperCase();
    this.operation = operation;
    this.securitySchemes = securitySchemes || null;
    this.generator = generator;

    this.pathRegexp = pathToRegexp(this.pathPattern);
  }
Example #3
Source File: matchPath.ts    From next-core with GNU General Public License v3.0 6 votes vote down vote up
function compilePath(path: string, options: CompileOptions): CompileResult {
  const cacheKey = `${options.end}${options.strict}${options.sensitive}`;
  if (!cache.has(cacheKey)) {
    cache.set(cacheKey, new Map());
  }
  const pathCache = cache.get(cacheKey);

  if (pathCache.has(path)) {
    return pathCache.get(path);
  }

  const keys: Key[] = [];
  const regexp = pathToRegexp(path, keys, options);
  const result = { regexp, keys };

  if (cacheCount < cacheLimit) {
    pathCache.set(path, result);
    cacheCount++;
  }

  return result;
}
Example #4
Source File: index.ts    From erda-ui with GNU Affero General Public License v3.0 6 votes vote down vote up
extractPathParams = (path: string, params?: Obj<any>) => {
  const keys: Key[] = [];
  pathToRegexp(path, keys);
  const pathParams = {} as Obj<string>;
  const bodyOrQuery = { ...params };
  if (keys.length > 0) {
    keys.forEach(({ name }) => {
      pathParams[name] = bodyOrQuery[name];
      delete bodyOrQuery[name];
    });
  }
  return {
    pathParams,
    bodyOrQuery,
  };
}
Example #5
Source File: index.ts    From erda-ui with GNU Affero General Public License v3.0 6 votes vote down vote up
extractPathParams = (path: string, params?: Obj) => {
  const keys: Key[] = [];
  pathToRegexp(path, keys);
  const pathParams = {};
  const bodyOrQuery = { ...params };
  if (keys.length > 0) {
    keys.forEach(({ name }) => {
      pathParams[name] = bodyOrQuery[name];
      delete bodyOrQuery[name];
    });
  }
  return {
    pathParams,
    bodyOrQuery,
  };
}
Example #6
Source File: page.ts    From native with MIT License 6 votes vote down vote up
ignoreURLs = (urlString: string, ignoreList: boolean | TypeIgnoreURLsList) => {
    if (typeof ignoreList == "boolean")
        return ignoreList;

    let _keys = [];
    return !(ignoreList as TypeIgnoreURLsList)
        .every(val => pathToRegexp(val, _keys, {
            start: false,
            end: false
        }).exec(urlString) == null);
}
Example #7
Source File: router.ts    From native with MIT License 6 votes vote down vote up
/** Convert strings into path match functions */
    public parsePath(path: TypeRouteStyle): RegExp | boolean {
        if (typeof path === "string" || path instanceof RegExp || Array.isArray(path)) {
            let _keys = [];
            return pathToRegexp(path as Path, _keys, {
                start: false,
                end: false
            });
        } else if (typeof path === "boolean")
            return path ? /.*/ : path;

        throw "[Router] only regular expressions, strings, booleans and arrays of regular expressions and strings are accepted as paths.";
    }
Example #8
Source File: Server.ts    From double-agent with MIT License 6 votes vote down vote up
constructor(collect: Collect, httpServerPort: number) {
    this.collect = collect;
    this.httpServerPort = httpServerPort;
    this.httpServer = new http.Server(this.handleRequest.bind(this));

    Object.keys(this.endpointsByRoute).forEach(route => {
      const keys = [];
      const regexp = pathToRegexp(route, keys);
      this.routeMetaByRegexp.set(regexp, { route, keys });
    });
  }
Example #9
Source File: route.ts    From erda-ui with GNU Affero General Public License v3.0 4 votes vote down vote up
routeInfoStore = createStore({
  name: 'routeInfo',
  state: initRouteInfo,
  reducers: {
    $_updateRouteInfo(
      state,
      location: { pathname: string; search: string; key: string },
      extraData?: any,
      extraPayload?: { force?: boolean },
    ) {
      const { pathname, search, key: urlKey } = location;
      const { force = false } = extraPayload || {};
      const prevRouteInfo = state;
      if (!force && prevPath === pathname && search === prevSearch) {
        return prevRouteInfo;
      }
      prevPath = pathname;
      prevSearch = search;
      const query = { ...parse(search, { arrayFormat: 'bracket' }) }; // parse出来的对象prototype为null,fast-deep-equal判断时报错
      let routes: IRouteInfo[] = [];
      const params: Obj = {};
      const { routePatterns, routeMap, parsed } = extraData || prevRouteInfo;
      let currentRoute = null;
      let routeMarks: string[] = [];
      const findParent = (item: any) => {
        const { _parent, mark } = item;
        if (mark) {
          routeMarks.push(mark);
        }
        if (_parent) {
          routes.push(_parent);
          findParent(_parent);
        }
      };

      for (let i = 0; i < routePatterns?.length; i++) {
        const pattern = routePatterns[i];

        const keys: Key[] = [];
        const match = pathToRegexp(pattern, keys).exec(pathname);

        if (match) {
          keys.forEach((k, j) => {
            if (k.name !== 0) {
              // 移除 * 号匹配时的0字段
              params[k.name] = match[j + 1];
            }
          });
          currentRoute = routeMap[pattern].route;
          const routeLevel = pattern.split('/').length;
          Object.keys(queryLevelMap).forEach((level) => {
            // 清除大于当前层级(更深)的路由的query
            if (routeLevel < level) {
              Object.values(queryLevelMap[level]).forEach((r) => {
                r.routeQuery = {};
              });
            }
          });

          // 如果需要保持路由query
          if (currentRoute.keepQuery) {
            currentRoute.routeQuery = { ...currentRoute.routeQuery, ...query };
            queryLevelMap[routeLevel] = queryLevelMap[routeLevel] || {};
            queryLevelMap[routeLevel][pattern] = currentRoute;
          }
          routes = [currentRoute];
          routeMarks = [];
          findParent(currentRoute);
          break;
        }
      }

      const curUrlPaths = [...state.urlPathRecord];
      const curUrlFull = new Set(state.urlFullRecord);

      let urlState = 'new';
      if (curUrlFull.has(urlKey) && curUrlPaths.length > 1) {
        if (curUrlPaths.includes(urlKey)) {
          urlState = 'back';
          curUrlPaths.pop();
        } else {
          urlState = 'forward';
          curUrlPaths.push(urlKey);
        }
      } else if (!(curUrlPaths.length === 1 && curUrlPaths.includes(urlKey))) {
        // forbidden first time execute $_updateRouteInfo more than once;
        curUrlPaths.push(urlKey);
      }

      curUrlFull.add(urlKey);

      const markedRoutePreview = {
        ...state.markedRoutePreview,
        ...(currentRoute?.searchMark ? { [currentRoute.searchMark]: search } : {}),
      };
      const routeInfo = {
        prevRouteInfo,
        params,
        query,
        routes,
        currentRoute,
        markedRoutePreview,
        urlFullRecord: curUrlFull,
        urlPathRecord: curUrlPaths,
        urlState,
        routePatterns,
        routeMap,
        parsed,
        routeMarks,
        isIn: (level: string) => routeMarks.includes(level),
        isMatch: (pattern: string) => !!pathToRegexp(pattern, []).exec(pathname),
        isEntering: (level: string) => routeMarks.includes(level) && !prevRouteInfo.routeMarks.includes(level),
        isLeaving: (level: string) => !routeMarks.includes(level) && prevRouteInfo.routeMarks.includes(level),
      };
      return routeInfo;
    },
  },
})
Example #10
Source File: config.tsx    From next-translate-routes with MIT License 4 votes vote down vote up
getPageReRoutes = <L extends string>({
  locales,
  routeSegments,
  defaultLocale,
}: {
  locales: L[]
  routeSegments: TRouteSegment<L>[]
  defaultLocale?: L
}): TReRoutes => {
  /** If there is only one path possible: it is common to all locales and to files. No redirection nor rewrite is needed. */
  if (!routeSegments.some(({ paths }) => Object.keys(paths).length > 1)) {
    return { rewrites: [], redirects: [] }
  }

  /** Get a translated path or base path */
  const getPath = (locale: L | 'default') =>
    `/${routeSegments
      .map(({ paths }) => paths[locale] || paths.default)
      .filter((pathPart) => pathPart && !ignoreSegmentPathRegex.test(pathPart))
      .join('/')}`

  /** File path in path-to-regexp syntax (cannot be customised in routes data files) */
  const basePath = `/${routeSegments
    .map(({ name, paths: { default: defaultPath } }) => {
      const match = defaultPath.match(ignoreSegmentPathRegex) || []
      // If a pattern is added to the ignore token "."
      return fileNameToPath(name) + (match[1] || '')
    })
    .filter((pathPart) => pathPart)
    .join('/')}`

  /**
   * ```
   * [
   *   { locales: ['en'], path: '/english/path/without/locale/prefix' },
   *   { locales: ['fr'], path: '/french/path/without/locale/prefix' },
   *   { locales: ['es', 'pt'], path: '/path/common/to/several/locales' },
   * ]
   * ```
   * Each locale cannot appear more than once. Item is ignored if its path would be the same as basePath.
   */
  const sourceList = locales.reduce((acc, locale) => {
    const source = getPath(locale)
    if (source === basePath) {
      return acc
    }
    const { sourceLocales = [] } = acc.find((sourceItem) => sourceItem.source === source) || {}
    return [
      ...acc.filter((sourceItem) => sourceItem.source !== source),
      { source, sourceLocales: [...sourceLocales, locale] },
    ]
  }, [] as { sourceLocales: L[]; source: string }[])

  const redirects = locales.reduce((acc, locale) => {
    const localePath = getPath(locale)
    const destination = `${locale === defaultLocale ? '' : `/${locale}`}${sourceToDestination(localePath)}`

    return [
      ...acc,
      ...sourceList
        .filter(({ sourceLocales }) => !sourceLocales.includes(locale))
        // Redirect from base path so that it does not display the page but only the translated path does
        .concat(...(localePath === basePath ? [] : [{ sourceLocales: [], source: basePath }]))
        .reduce((acc, { source: rawSource }) => {
          const source = `/${locale}${rawSource}`
          const sourceSegments = source.split('/')

          // Look for similar redirects
          const similarIndex = getSimilarIndex(sourceSegments, acc)

          // If similar redirect exist, merge the new one
          if (similarIndex >= 0) {
            const similar = acc[similarIndex]
            const mergedWithSimilar = {
              ...similar,
              source: similar.source
                .split('/')
                .map((similarSegment, index) =>
                  sourceSegments[index] === similarSegment
                    ? similarSegment
                    : mergeOrRegex(similarSegment, sourceSegments[index]),
                )
                .join('/'),
            }

            // Avoid to merge path that would introduce redirect loop
            if (!pathToRegexp(mergedWithSimilar.source).test(destination)) {
              return [...acc.slice(0, similarIndex), mergedWithSimilar, ...acc.slice(similarIndex + 1)]
            }
          }

          // Else append the new redirect
          return [
            ...acc,
            {
              source,
              destination,
              locale: false as const,
              permanent: true,
            },
          ]
        }, [] as Redirect[])
        .filter(({ source, destination }) => sourceToDestination(source) !== destination),
    ]
  }, [] as Redirect[])

  const destination = sourceToDestination(basePath)

  const rewrites: Rewrite[] = sourceList.reduce((acc, { source }) => {
    if (sourceToDestination(source) === destination) {
      return acc
    }

    const sourceSegments = source.split('/')

    // Look for similar rewrites
    const similarIndex = getSimilarIndex(sourceSegments, acc)

    // If similar rewrite exist, merge the new one
    if (similarIndex >= 0) {
      const similar = acc[similarIndex]
      return [
        ...acc.slice(0, similarIndex),
        {
          ...similar,
          source: similar.source
            .split('/')
            .map((similarSegment, index) =>
              similarSegment === sourceSegments[index]
                ? similarSegment
                : `(${similarSegment.replace(/\(|\)/g, '').split('|').concat(sourceSegments[index]).join('|')})`,
            )
            .join('/'),
        },
        ...acc.slice(similarIndex + 1),
      ]
    }

    // Else append a new rewrite
    return [
      ...acc,
      {
        source,
        destination,
      },
    ]
  }, [] as Rewrite[])

  return { redirects, rewrites }
}