From 167bc6087d185749edf8adce742814cd17e6f487 Mon Sep 17 00:00:00 2001 From: David Michon Date: Wed, 7 Aug 2024 18:41:29 +0000 Subject: [PATCH 1/3] Extract LookupByPath -> @rushstack/path-trie --- .../rush/path-trie_2024-08-07-18-41.json | 10 +++ .../path-trie/path-trie_2024-08-07-18-41.json | 10 +++ .../rush/nonbrowser-approved-packages.json | 5 +- .../build-tests-subspace/pnpm-lock.yaml | 37 +++++--- .../build-tests-subspace/repo-state.json | 4 +- .../config/subspaces/default/pnpm-lock.yaml | 15 ++++ common/reviews/api/path-trie.api.md | 25 ++++++ common/reviews/api/rush-lib.api.md | 22 +---- libraries/path-trie/.eslintrc.js | 13 +++ libraries/path-trie/.npmignore | 32 +++++++ libraries/path-trie/LICENSE | 24 +++++ libraries/path-trie/README.md | 14 +++ libraries/path-trie/config/api-extractor.json | 19 ++++ libraries/path-trie/config/jest.config.json | 3 + libraries/path-trie/config/rig.json | 7 ++ libraries/path-trie/package.json | 30 +++++++ .../src/PathTrie.test.ts} | 38 ++++---- .../src/PathTrie.ts} | 87 +++++++++++-------- libraries/path-trie/src/index.ts | 11 +++ libraries/path-trie/tsconfig.json | 7 ++ libraries/rush-lib/package.json | 1 + .../rush-lib/src/api/RushConfiguration.ts | 12 +-- libraries/rush-lib/src/index.ts | 4 +- .../src/logic/ProjectChangeAnalyzer.ts | 7 +- .../logic/test/ProjectChangeAnalyzer.test.ts | 6 +- libraries/rush-sdk/package.json | 1 + rush.json | 6 ++ 27 files changed, 348 insertions(+), 102 deletions(-) create mode 100644 common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json create mode 100644 common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json create mode 100644 common/reviews/api/path-trie.api.md create mode 100644 libraries/path-trie/.eslintrc.js create mode 100644 libraries/path-trie/.npmignore create mode 100644 libraries/path-trie/LICENSE create mode 100644 libraries/path-trie/README.md create mode 100644 libraries/path-trie/config/api-extractor.json create mode 100644 libraries/path-trie/config/jest.config.json create mode 100644 libraries/path-trie/config/rig.json create mode 100644 libraries/path-trie/package.json rename libraries/{rush-lib/src/logic/test/LookupByPath.test.ts => path-trie/src/PathTrie.test.ts} (76%) rename libraries/{rush-lib/src/logic/LookupByPath.ts => path-trie/src/PathTrie.ts} (69%) create mode 100644 libraries/path-trie/src/index.ts create mode 100644 libraries/path-trie/tsconfig.json diff --git a/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json b/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json new file mode 100644 index 00000000000..b00389fb6e0 --- /dev/null +++ b/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "Extract LookupByPath to @rushstack/path-trie and load it from there.", + "type": "none" + } + ], + "packageName": "@microsoft/rush" +} \ No newline at end of file diff --git a/common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json b/common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json new file mode 100644 index 00000000000..1bc98322cd1 --- /dev/null +++ b/common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/path-trie", + "comment": "Extract and rename LookupByPath from @rushstack/rush-lib as PathTrie.", + "type": "minor" + } + ], + "packageName": "@rushstack/path-trie" +} \ No newline at end of file diff --git a/common/config/rush/nonbrowser-approved-packages.json b/common/config/rush/nonbrowser-approved-packages.json index 8288cc0dadf..8689c68dacb 100644 --- a/common/config/rush/nonbrowser-approved-packages.json +++ b/common/config/rush/nonbrowser-approved-packages.json @@ -222,6 +222,10 @@ "name": "@rushstack/package-extractor", "allowedCategories": [ "libraries", "vscode-extensions" ] }, + { + "name": "@rushstack/path-trie", + "allowedCategories": [ "libraries" ] + }, { "name": "@rushstack/rig-package", "allowedCategories": [ "libraries" ] @@ -862,7 +866,6 @@ "name": "tslint", "allowedCategories": [ "libraries", "tests" ] }, - { "name": "typescript", "allowedCategories": [ "libraries", "tests", "vscode-extensions" ] diff --git a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml index 90a2811dde5..fe565ca0b79 100644 --- a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml +++ b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml @@ -110,10 +110,10 @@ importers: version: file:../../../apps/heft(@types/node@18.17.15) '@rushstack/heft-lint-plugin': specifier: file:../../heft-plugins/heft-lint-plugin - version: file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15) + version: file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15) '@rushstack/heft-typescript-plugin': specifier: file:../../heft-plugins/heft-typescript-plugin - version: file:../../../heft-plugins/heft-typescript-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15) + version: file:../../../heft-plugins/heft-typescript-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15) eslint: specifier: ~8.57.0 version: 8.57.0 @@ -6229,7 +6229,7 @@ packages: - typescript dev: true - file:../../../heft-plugins/heft-api-extractor-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15): + file:../../../heft-plugins/heft-api-extractor-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15): resolution: {directory: ../../../heft-plugins/heft-api-extractor-plugin, type: directory} id: file:../../../heft-plugins/heft-api-extractor-plugin name: '@rushstack/heft-api-extractor-plugin' @@ -6244,7 +6244,7 @@ packages: - '@types/node' dev: true - file:../../../heft-plugins/heft-jest-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15)(jest-environment-node@29.5.0): + file:../../../heft-plugins/heft-jest-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15)(jest-environment-node@29.5.0): resolution: {directory: ../../../heft-plugins/heft-jest-plugin, type: directory} id: file:../../../heft-plugins/heft-jest-plugin name: '@rushstack/heft-jest-plugin' @@ -6278,7 +6278,7 @@ packages: - ts-node dev: true - file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15): + file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15): resolution: {directory: ../../../heft-plugins/heft-lint-plugin, type: directory} id: file:../../../heft-plugins/heft-lint-plugin name: '@rushstack/heft-lint-plugin' @@ -6292,7 +6292,7 @@ packages: - '@types/node' dev: true - file:../../../heft-plugins/heft-typescript-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15): + file:../../../heft-plugins/heft-typescript-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15): resolution: {directory: ../../../heft-plugins/heft-typescript-plugin, type: directory} id: file:../../../heft-plugins/heft-typescript-plugin name: '@rushstack/heft-typescript-plugin' @@ -6394,6 +6394,18 @@ packages: transitivePeerDependencies: - '@types/node' + file:../../../libraries/path-trie(@types/node@18.17.15): + resolution: {directory: ../../../libraries/path-trie, type: directory} + id: file:../../../libraries/path-trie + name: '@rushstack/path-trie' + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 18.17.15 + file:../../../libraries/rig-package: resolution: {directory: ../../../libraries/rig-package, type: directory} name: '@rushstack/rig-package' @@ -6413,6 +6425,7 @@ packages: '@rushstack/node-core-library': file:../../../libraries/node-core-library(@types/node@18.17.15) '@rushstack/package-deps-hash': file:../../../libraries/package-deps-hash(@types/node@18.17.15) '@rushstack/package-extractor': file:../../../libraries/package-extractor(@types/node@18.17.15) + '@rushstack/path-trie': file:../../../libraries/path-trie(@types/node@18.17.15) '@rushstack/rig-package': file:../../../libraries/rig-package '@rushstack/stream-collator': file:../../../libraries/stream-collator(@types/node@18.17.15) '@rushstack/terminal': file:../../../libraries/terminal(@types/node@18.17.15) @@ -6502,7 +6515,7 @@ packages: transitivePeerDependencies: - '@types/node' - file:../../../rigs/heft-node-rig(@rushstack/heft@0.66.19)(@types/node@18.17.15): + file:../../../rigs/heft-node-rig(@rushstack/heft@0.66.25)(@types/node@18.17.15): resolution: {directory: ../../../rigs/heft-node-rig, type: directory} id: file:../../../rigs/heft-node-rig name: '@rushstack/heft-node-rig' @@ -6512,10 +6525,10 @@ packages: '@microsoft/api-extractor': file:../../../apps/api-extractor(@types/node@18.17.15) '@rushstack/eslint-config': file:../../../eslint/eslint-config(eslint@8.57.0)(typescript@5.4.5) '@rushstack/heft': file:../../../apps/heft(@types/node@18.17.15) - '@rushstack/heft-api-extractor-plugin': file:../../../heft-plugins/heft-api-extractor-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15) - '@rushstack/heft-jest-plugin': file:../../../heft-plugins/heft-jest-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15)(jest-environment-node@29.5.0) - '@rushstack/heft-lint-plugin': file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15) - '@rushstack/heft-typescript-plugin': file:../../../heft-plugins/heft-typescript-plugin(@rushstack/heft@0.66.19)(@types/node@18.17.15) + '@rushstack/heft-api-extractor-plugin': file:../../../heft-plugins/heft-api-extractor-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15) + '@rushstack/heft-jest-plugin': file:../../../heft-plugins/heft-jest-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15)(jest-environment-node@29.5.0) + '@rushstack/heft-lint-plugin': file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15) + '@rushstack/heft-typescript-plugin': file:../../../heft-plugins/heft-typescript-plugin(@rushstack/heft@0.66.25)(@types/node@18.17.15) '@types/heft-jest': 1.0.1 eslint: 8.57.0 jest-environment-node: 29.5.0 @@ -6535,7 +6548,7 @@ packages: dependencies: '@microsoft/api-extractor': file:../../../apps/api-extractor(@types/node@18.17.15) '@rushstack/heft': file:../../../apps/heft(@types/node@18.17.15) - '@rushstack/heft-node-rig': file:../../../rigs/heft-node-rig(@rushstack/heft@0.66.19)(@types/node@18.17.15) + '@rushstack/heft-node-rig': file:../../../rigs/heft-node-rig(@rushstack/heft@0.66.25)(@types/node@18.17.15) '@types/heft-jest': 1.0.1 '@types/node': 18.17.15 eslint: 8.57.0 diff --git a/common/config/subspaces/build-tests-subspace/repo-state.json b/common/config/subspaces/build-tests-subspace/repo-state.json index 5f991137dbc..e22c309900a 100644 --- a/common/config/subspaces/build-tests-subspace/repo-state.json +++ b/common/config/subspaces/build-tests-subspace/repo-state.json @@ -1,6 +1,6 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "00e9bb9c23e93f1cf44e5989a201680d8a857644", + "pnpmShrinkwrapHash": "292a9e8a4370837e8288a7e359283689923755a7", "preferredVersionsHash": "ce857ea0536b894ec8f346aaea08cfd85a5af648", - "packageJsonInjectedDependenciesHash": "bc9ec80f2538e316952305db6449bf0c8cd35bf6" + "packageJsonInjectedDependenciesHash": "97c61af3a05454ebf76d54ad9588a25d40faaa23" } diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index a58e39fe4b6..7946cbadaa0 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -3230,6 +3230,15 @@ importers: specifier: ~5.82.1 version: 5.82.1 + ../../../libraries/path-trie: + devDependencies: + '@rushstack/heft': + specifier: workspace:* + version: link:../../apps/heft + local-node-rig: + specifier: workspace:* + version: link:../../rigs/local-node-rig + ../../../libraries/rig-package: dependencies: resolve: @@ -3281,6 +3290,9 @@ importers: '@rushstack/package-extractor': specifier: workspace:* version: link:../package-extractor + '@rushstack/path-trie': + specifier: workspace:* + version: link:../path-trie '@rushstack/rig-package': specifier: workspace:* version: link:../rig-package @@ -3454,6 +3466,9 @@ importers: '@rushstack/heft-webpack5-plugin': specifier: workspace:* version: link:../../heft-plugins/heft-webpack5-plugin + '@rushstack/path-trie': + specifier: workspace:* + version: link:../path-trie '@rushstack/stream-collator': specifier: workspace:* version: link:../stream-collator diff --git a/common/reviews/api/path-trie.api.md b/common/reviews/api/path-trie.api.md new file mode 100644 index 00000000000..a55866d7a24 --- /dev/null +++ b/common/reviews/api/path-trie.api.md @@ -0,0 +1,25 @@ +## API Report File for "@rushstack/path-trie" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @beta +export interface IPrefixMatch { + index: number; + value: TItem; +} + +// @beta +export class PathTrie { + constructor(entries?: Iterable<[string, TItem]>, delimiter?: string); + readonly delimiter: string; + findChildPath(childPath: string): TItem | undefined; + findChildPathFromSegments(childPathSegments: Iterable): TItem | undefined; + findLongestPrefixMatch(query: string): IPrefixMatch | undefined; + static iteratePathSegments(serializedPath: string, delimiter?: string): Iterable; + setItem(serializedPath: string, value: TItem): this; + setItemFromSegments(pathSegments: Iterable, value: TItem): this; +} + +``` diff --git a/common/reviews/api/rush-lib.api.md b/common/reviews/api/rush-lib.api.md index 97aba62d33c..df738d218dc 100644 --- a/common/reviews/api/rush-lib.api.md +++ b/common/reviews/api/rush-lib.api.md @@ -15,9 +15,11 @@ import type { CommandLineParameter } from '@rushstack/ts-command-line'; import { CommandLineParameterKind } from '@rushstack/ts-command-line'; import { HookMap } from 'tapable'; import { IPackageJson } from '@rushstack/node-core-library'; +import { IPrefixMatch } from '@rushstack/path-trie'; import { ITerminal } from '@rushstack/terminal'; import { ITerminalProvider } from '@rushstack/terminal'; import { JsonObject } from '@rushstack/node-core-library'; +import { PathTrie as LookupByPath } from '@rushstack/path-trie'; import { PackageNameParser } from '@rushstack/node-core-library'; import type { StdioSummarizer } from '@rushstack/terminal'; import { SyncHook } from 'tapable'; @@ -737,13 +739,7 @@ export interface IPnpmPeerDependencyRules { ignoreMissing?: string[]; } -// @beta -export interface IPrefixMatch { - // (undocumented) - index: number; - // (undocumented) - value: TItem; -} +export { IPrefixMatch } // @internal (undocumented) export interface _IRawRepoState { @@ -894,17 +890,7 @@ export class LockStepVersionPolicy extends VersionPolicy { get version(): string; } -// @beta -export class LookupByPath { - constructor(entries?: Iterable<[string, TItem]>, delimiter?: string); - readonly delimiter: string; - findChildPath(childPath: string): TItem | undefined; - findChildPathFromSegments(childPathSegments: Iterable): TItem | undefined; - findLongestPrefixMatch(query: string): IPrefixMatch | undefined; - static iteratePathSegments(serializedPath: string, delimiter?: string): Iterable; - setItem(serializedPath: string, value: TItem): this; - setItemFromSegments(pathSegments: Iterable, value: TItem): this; -} +export { LookupByPath } // @public export class NpmOptionsConfiguration extends PackageManagerOptionsConfigurationBase { diff --git a/libraries/path-trie/.eslintrc.js b/libraries/path-trie/.eslintrc.js new file mode 100644 index 00000000000..0b04796d1ee --- /dev/null +++ b/libraries/path-trie/.eslintrc.js @@ -0,0 +1,13 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require('local-node-rig/profiles/default/includes/eslint/patch/modern-module-resolution'); +// This is a workaround for https://github.com/microsoft/rushstack/issues/3021 +require('local-node-rig/profiles/default/includes/eslint/patch/custom-config-package-names'); + +module.exports = { + extends: [ + 'local-node-rig/profiles/default/includes/eslint/profile/node', + 'local-node-rig/profiles/default/includes/eslint/mixins/friendly-locals', + 'local-node-rig/profiles/default/includes/eslint/mixins/tsdoc' + ], + parserOptions: { tsconfigRootDir: __dirname } +}; diff --git a/libraries/path-trie/.npmignore b/libraries/path-trie/.npmignore new file mode 100644 index 00000000000..bc349f9a4be --- /dev/null +++ b/libraries/path-trie/.npmignore @@ -0,0 +1,32 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** + +!CHANGELOG.md +!CHANGELOG.json +!heft-plugin.json +!rush-plugin-manifest.json +!ThirdPartyNotice.txt + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README.md +# LICENSE + +# --------------------------------------------------------------------------- +# DO NOT MODIFY ABOVE THIS LINE! Add any project-specific overrides below. +# --------------------------------------------------------------------------- diff --git a/libraries/path-trie/LICENSE b/libraries/path-trie/LICENSE new file mode 100644 index 00000000000..7137f22d95a --- /dev/null +++ b/libraries/path-trie/LICENSE @@ -0,0 +1,24 @@ +@rushstack/path-trie + +Copyright (c) Microsoft Corporation. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/libraries/path-trie/README.md b/libraries/path-trie/README.md new file mode 100644 index 00000000000..c1e9b33107b --- /dev/null +++ b/libraries/path-trie/README.md @@ -0,0 +1,14 @@ +# @rushstack/path-trie + +This library contains a strongly-typed implementation of of a [Trie](https://en.wikipedia.org/wiki/Trie) (a.k.a. prefix tree) data structure optimized for file paths and URLs. + +This package is used by Rush to associate Git hashes with their nearest ancestor Rush project, for example. + +## Links + +- [CHANGELOG.md]( + https://github.com/microsoft/rushstack/blob/main/libraries/path-trie/CHANGELOG.md) - Find + out what's new in the latest version +- [API Reference](https://api.rushstack.io/pages/path-trie/) + +`@rushstack/path-trie` is part of the [Rush Stack](https://rushstack.io/) family of projects. diff --git a/libraries/path-trie/config/api-extractor.json b/libraries/path-trie/config/api-extractor.json new file mode 100644 index 00000000000..996e271d3dd --- /dev/null +++ b/libraries/path-trie/config/api-extractor.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + + "mainEntryPointFilePath": "/lib/index.d.ts", + + "apiReport": { + "enabled": true, + "reportFolder": "../../../common/reviews/api" + }, + + "docModel": { + "enabled": true, + "apiJsonFilePath": "../../../common/temp/api/.api.json" + }, + + "dtsRollup": { + "enabled": true + } +} diff --git a/libraries/path-trie/config/jest.config.json b/libraries/path-trie/config/jest.config.json new file mode 100644 index 00000000000..d1749681d90 --- /dev/null +++ b/libraries/path-trie/config/jest.config.json @@ -0,0 +1,3 @@ +{ + "extends": "local-node-rig/profiles/default/config/jest.config.json" +} diff --git a/libraries/path-trie/config/rig.json b/libraries/path-trie/config/rig.json new file mode 100644 index 00000000000..165ffb001f5 --- /dev/null +++ b/libraries/path-trie/config/rig.json @@ -0,0 +1,7 @@ +{ + // The "rig.json" file directs tools to look for their config files in an external package. + // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + + "rigPackageName": "local-node-rig" +} diff --git a/libraries/path-trie/package.json b/libraries/path-trie/package.json new file mode 100644 index 00000000000..d200fa3baba --- /dev/null +++ b/libraries/path-trie/package.json @@ -0,0 +1,30 @@ +{ + "name": "@rushstack/path-trie", + "version": "0.0.0", + "description": "Strongly typed trie data structure for path and URL-like strings.", + "main": "lib/index.js", + "typings": "dist/path-trie.d.ts", + "license": "MIT", + "repository": { + "url": "https://github.com/microsoft/rushstack.git", + "type": "git", + "directory": "libraries/path-trie" + }, + "scripts": { + "build": "heft build --clean", + "_phase:build": "heft run --only build -- --clean", + "_phase:test": "heft run --only test -- --clean" + }, + "devDependencies": { + "@rushstack/heft": "workspace:*", + "local-node-rig": "workspace:*" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } +} diff --git a/libraries/rush-lib/src/logic/test/LookupByPath.test.ts b/libraries/path-trie/src/PathTrie.test.ts similarity index 76% rename from libraries/rush-lib/src/logic/test/LookupByPath.test.ts rename to libraries/path-trie/src/PathTrie.test.ts index 2d56d082d58..ee3c7532e3e 100644 --- a/libraries/rush-lib/src/logic/test/LookupByPath.test.ts +++ b/libraries/path-trie/src/PathTrie.test.ts @@ -1,40 +1,40 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -import { LookupByPath } from '../LookupByPath'; +import { PathTrie } from './PathTrie'; -describe(LookupByPath.iteratePathSegments.name, () => { +describe(PathTrie.iteratePathSegments.name, () => { it('returns empty for an empty string', () => { - const result = [...LookupByPath.iteratePathSegments('')]; + const result = [...PathTrie.iteratePathSegments('')]; expect(result.length).toEqual(0); }); it('returns the only segment of a trival string', () => { - const result = [...LookupByPath.iteratePathSegments('foo')]; + const result = [...PathTrie.iteratePathSegments('foo')]; expect(result).toEqual(['foo']); }); it('treats backslashes as ordinary characters, per POSIX', () => { - const result = [...LookupByPath.iteratePathSegments('foo\\bar\\baz')]; + const result = [...PathTrie.iteratePathSegments('foo\\bar\\baz')]; expect(result).toEqual(['foo\\bar\\baz']); }); it('iterates segments', () => { - const result = [...LookupByPath.iteratePathSegments('foo/bar/baz')]; + const result = [...PathTrie.iteratePathSegments('foo/bar/baz')]; expect(result).toEqual(['foo', 'bar', 'baz']); }); it('returns correct last single character segment', () => { - const result = [...LookupByPath.iteratePathSegments('foo/a')]; + const result = [...PathTrie.iteratePathSegments('foo/a')]; expect(result).toEqual(['foo', 'a']); }); }); -describe(LookupByPath.prototype.findChildPath.name, () => { +describe(PathTrie.prototype.findChildPath.name, () => { it('returns empty for an empty tree', () => { - expect(new LookupByPath().findChildPath('foo')).toEqual(undefined); + expect(new PathTrie().findChildPath('foo')).toEqual(undefined); }); it('returns the matching node for a trivial tree', () => { - expect(new LookupByPath([['foo', 1]]).findChildPath('foo')).toEqual(1); + expect(new PathTrie([['foo', 1]]).findChildPath('foo')).toEqual(1); }); it('returns the matching node for a single-layer tree', () => { - const tree: LookupByPath = new LookupByPath([ + const tree: PathTrie = new PathTrie([ ['foo', 1], ['bar', 2], ['baz', 3] @@ -46,7 +46,7 @@ describe(LookupByPath.prototype.findChildPath.name, () => { expect(tree.findChildPath('buzz')).toEqual(undefined); }); it('returns the matching parent for multi-layer queries', () => { - const tree: LookupByPath = new LookupByPath([ + const tree: PathTrie = new PathTrie([ ['foo', 1], ['bar', 2], ['baz', 3] @@ -58,7 +58,7 @@ describe(LookupByPath.prototype.findChildPath.name, () => { expect(tree.findChildPath('foo/foo')).toEqual(1); }); it('returns the matching parent for multi-layer queries in multi-layer trees', () => { - const tree: LookupByPath = new LookupByPath([ + const tree: PathTrie = new PathTrie([ ['foo', 1], ['bar', 2], ['baz', 3], @@ -92,7 +92,7 @@ describe(LookupByPath.prototype.findChildPath.name, () => { expect(tree.findChildPath('foo\\bar\\baz')).toEqual(undefined); }); it('handles custom delimiters', () => { - const tree: LookupByPath = new LookupByPath( + const tree: PathTrie = new PathTrie( [ ['foo,bar', 1], ['foo/bar', 2] @@ -106,15 +106,15 @@ describe(LookupByPath.prototype.findChildPath.name, () => { }); }); -describe(LookupByPath.prototype.findLongestPrefixMatch.name, () => { +describe(PathTrie.prototype.findLongestPrefixMatch.name, () => { it('returns empty for an empty tree', () => { - expect(new LookupByPath().findLongestPrefixMatch('foo')).toEqual(undefined); + expect(new PathTrie().findLongestPrefixMatch('foo')).toEqual(undefined); }); it('returns the matching node for a trivial tree', () => { - expect(new LookupByPath([['foo', 1]]).findLongestPrefixMatch('foo')).toEqual({ value: 1, index: 3 }); + expect(new PathTrie([['foo', 1]]).findLongestPrefixMatch('foo')).toEqual({ value: 1, index: 3 }); }); it('returns the matching node for a single-layer tree', () => { - const tree: LookupByPath = new LookupByPath([ + const tree: PathTrie = new PathTrie([ ['foo', 1], ['barbar', 2], ['baz', 3] @@ -126,7 +126,7 @@ describe(LookupByPath.prototype.findLongestPrefixMatch.name, () => { expect(tree.findLongestPrefixMatch('buzz')).toEqual(undefined); }); it('returns the matching parent for multi-layer queries', () => { - const tree: LookupByPath = new LookupByPath([ + const tree: PathTrie = new PathTrie([ ['foo', 1], ['barbar', 2], ['baz', 3], diff --git a/libraries/rush-lib/src/logic/LookupByPath.ts b/libraries/path-trie/src/PathTrie.ts similarity index 69% rename from libraries/rush-lib/src/logic/LookupByPath.ts rename to libraries/path-trie/src/PathTrie.ts index ce209f909e4..40ae2049ce2 100644 --- a/libraries/rush-lib/src/logic/LookupByPath.ts +++ b/libraries/path-trie/src/PathTrie.ts @@ -2,9 +2,9 @@ // See LICENSE in the project root for license information. /** - * A node in the path tree used in LookupByPath + * A node in the path trie used in PathTrie */ -interface IPathTreeNode { +interface IPathTrieNode { /** * The value that exactly matches the current relative path */ @@ -12,11 +12,17 @@ interface IPathTreeNode { /** * Child nodes by subfolder */ - children: Map> | undefined; + children: Map> | undefined; } interface IPrefixEntry { + /** + * The prefix that was matched + */ prefix: string; + /** + * The index of the first character after the matched prefix + */ index: number; } @@ -26,41 +32,50 @@ interface IPrefixEntry { * @beta */ export interface IPrefixMatch { + /** + * The item that matched the prefix + */ value: TItem; + /** + * The index of the first character after the matched prefix + */ index: number; } /** - * This class is used to associate POSIX relative paths, such as those returned by `git` commands, - * with entities that correspond with ancestor folders, such as Rush Projects. + * This class is used to associate path-like-strings, such as those returned by `git` commands, + * with entities that correspond with ancestor folders, such as Rush Projects or npm packages. * * It is optimized for efficiently locating the nearest ancestor path with an associated value. * + * It is implemented as a Trie (https://en.wikipedia.org/wiki/Trie) data structure, with each edge + * being a path segment. + * * @example * ```ts - * const tree = new LookupByPath([['foo', 1], ['bar', 2], ['foo/bar', 3]]); - * tree.findChildPath('foo'); // returns 1 - * tree.findChildPath('foo/baz'); // returns 1 - * tree.findChildPath('baz'); // returns undefined - * tree.findChildPath('foo/bar/baz'); returns 3 - * tree.findChildPath('bar/foo/bar'); returns 2 + * const trie = new PathTrie([['foo', 1], ['bar', 2], ['foo/bar', 3]]); + * trie.findChildPath('foo'); // returns 1 + * trie.findChildPath('foo/baz'); // returns 1 + * trie.findChildPath('baz'); // returns undefined + * trie.findChildPath('foo/bar/baz'); returns 3 + * trie.findChildPath('bar/foo/bar'); returns 2 * ``` * @beta */ -export class LookupByPath { +export class PathTrie { /** * The delimiter used to split paths */ public readonly delimiter: string; /** - * The root node of the tree, corresponding to the path '' + * The root node of the trie, corresponding to the path '' */ - private readonly _root: IPathTreeNode; + private readonly _root: IPathTrieNode; /** - * Constructs a new `LookupByPath` + * Constructs a new `PathTrie` * - * @param entries - Initial path-value pairs to populate the tree. + * @param entries - Initial path-value pairs to populate the trie. */ public constructor(entries?: Iterable<[string, TItem]>, delimiter?: string) { this._root = { @@ -82,9 +97,9 @@ export class LookupByPath { * * @example * - * `LookupByPath.iteratePathSegments('foo/bar/baz')` yields 'foo', 'bar', 'baz' + * `PathTrie.iteratePathSegments('foo/bar/baz')` yields 'foo', 'bar', 'baz' * - * `LookupByPath.iteratePathSegments('foo\\bar\\baz', '\\')` yields 'foo', 'bar', 'baz' + * `PathTrie.iteratePathSegments('foo\\bar\\baz', '\\')` yields 'foo', 'bar', 'baz' */ public static *iteratePathSegments(serializedPath: string, delimiter: string = '/'): Iterable { for (const prefixMatch of this._iteratePrefixes(serializedPath, delimiter)) { @@ -126,7 +141,7 @@ export class LookupByPath { * @returns this, for chained calls */ public setItem(serializedPath: string, value: TItem): this { - return this.setItemFromSegments(LookupByPath.iteratePathSegments(serializedPath, this.delimiter), value); + return this.setItemFromSegments(PathTrie.iteratePathSegments(serializedPath, this.delimiter), value); } /** @@ -136,12 +151,12 @@ export class LookupByPath { * @returns this, for chained calls */ public setItemFromSegments(pathSegments: Iterable, value: TItem): this { - let node: IPathTreeNode = this._root; + let node: IPathTrieNode = this._root; for (const segment of pathSegments) { if (!node.children) { node.children = new Map(); } - let child: IPathTreeNode | undefined = node.children.get(segment); + let child: IPathTrieNode | undefined = node.children.get(segment); if (!child) { node.children.set( segment, @@ -166,13 +181,13 @@ export class LookupByPath { * * @example * ```ts - * const tree = new LookupByPath([['foo', 1], ['foo/bar', 2]]); - * tree.findChildPath('foo/baz'); // returns 1 - * tree.findChildPath('foo/bar/baz'); // returns 2 + * const trie = new PathTrie([['foo', 1], ['foo/bar', 2]]); + * trie.findChildPath('foo/baz'); // returns 1 + * trie.findChildPath('foo/bar/baz'); // returns 2 * ``` */ public findChildPath(childPath: string): TItem | undefined { - return this.findChildPathFromSegments(LookupByPath.iteratePathSegments(childPath, this.delimiter)); + return this.findChildPathFromSegments(PathTrie.iteratePathSegments(childPath, this.delimiter)); } /** @@ -184,13 +199,13 @@ export class LookupByPath { * * @example * ```ts - * const tree = new LookupByPath([['foo', 1], ['foo/bar', 2]]); - * tree.findLongestPrefixMatch('foo/baz'); // returns { item: 1, index: 3 } - * tree.findLongestPrefixMatch('foo/bar/baz'); // returns { item: 2, index: 7 } + * const trie = new PathTrie([['foo', 1], ['foo/bar', 2]]); + * trie.findLongestPrefixMatch('foo/baz'); // returns { item: 1, index: 3 } + * trie.findLongestPrefixMatch('foo/bar/baz'); // returns { item: 2, index: 7 } * ``` */ public findLongestPrefixMatch(query: string): IPrefixMatch | undefined { - return this._findLongestPrefixMatch(LookupByPath._iteratePrefixes(query, this.delimiter)); + return this._findLongestPrefixMatch(PathTrie._iteratePrefixes(query, this.delimiter)); } /** @@ -201,18 +216,18 @@ export class LookupByPath { * * @example * ```ts - * const tree = new LookupByPath([['foo', 1], ['foo/bar', 2]]); - * tree.findChildPathFromSegments(['foo', 'baz']); // returns 1 - * tree.findChildPathFromSegments(['foo','bar', 'baz']); // returns 2 + * const trie = new PathTrie([['foo', 1], ['foo/bar', 2]]); + * trie.findChildPathFromSegments(['foo', 'baz']); // returns 1 + * trie.findChildPathFromSegments(['foo','bar', 'baz']); // returns 2 * ``` */ public findChildPathFromSegments(childPathSegments: Iterable): TItem | undefined { - let node: IPathTreeNode = this._root; + let node: IPathTrieNode = this._root; let best: TItem | undefined = node.value; // Trivial cases if (node.children) { for (const segment of childPathSegments) { - const child: IPathTreeNode | undefined = node.children.get(segment); + const child: IPathTrieNode | undefined = node.children.get(segment); if (!child) { break; } @@ -236,7 +251,7 @@ export class LookupByPath { * @returns the found item, or `undefined` if no item was found */ private _findLongestPrefixMatch(prefixes: Iterable): IPrefixMatch | undefined { - let node: IPathTreeNode = this._root; + let node: IPathTrieNode = this._root; let best: IPrefixMatch | undefined = node.value ? { value: node.value, @@ -246,7 +261,7 @@ export class LookupByPath { // Trivial cases if (node.children) { for (const { prefix: hash, index } of prefixes) { - const child: IPathTreeNode | undefined = node.children.get(hash); + const child: IPathTrieNode | undefined = node.children.get(hash); if (!child) { break; } diff --git a/libraries/path-trie/src/index.ts b/libraries/path-trie/src/index.ts new file mode 100644 index 00000000000..737b72ea894 --- /dev/null +++ b/libraries/path-trie/src/index.ts @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +/** + * Strongly typed trie data structure for path and URL-like strings. + * + * @packageDocumentation + */ + +export type { IPrefixMatch } from './PathTrie'; +export { PathTrie } from './PathTrie'; diff --git a/libraries/path-trie/tsconfig.json b/libraries/path-trie/tsconfig.json new file mode 100644 index 00000000000..9a79fa4af11 --- /dev/null +++ b/libraries/path-trie/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "./node_modules/local-node-rig/profiles/default/tsconfig-base.json", + + "compilerOptions": { + "target": "ES2019" + } +} diff --git a/libraries/rush-lib/package.json b/libraries/rush-lib/package.json index 3a6ed77cb97..a2bd3f0acd1 100644 --- a/libraries/rush-lib/package.json +++ b/libraries/rush-lib/package.json @@ -35,6 +35,7 @@ "@rushstack/node-core-library": "workspace:*", "@rushstack/package-deps-hash": "workspace:*", "@rushstack/package-extractor": "workspace:*", + "@rushstack/path-trie": "workspace:*", "@rushstack/rig-package": "workspace:*", "@rushstack/stream-collator": "workspace:*", "@rushstack/terminal": "workspace:*", diff --git a/libraries/rush-lib/src/api/RushConfiguration.ts b/libraries/rush-lib/src/api/RushConfiguration.ts index 5ab4b13d7a7..2b930b08a20 100644 --- a/libraries/rush-lib/src/api/RushConfiguration.ts +++ b/libraries/rush-lib/src/api/RushConfiguration.ts @@ -14,6 +14,7 @@ import { type FileSystemStats, InternalError } from '@rushstack/node-core-library'; +import { PathTrie } from '@rushstack/path-trie'; import { trueCasePathSync } from 'true-case-path'; import { Rush } from '../api/Rush'; @@ -32,7 +33,6 @@ import { PnpmPackageManager } from './packageManager/PnpmPackageManager'; import { ExperimentsConfiguration } from './ExperimentsConfiguration'; import { PackageNameParsers } from './PackageNameParsers'; import type { RepoStateFile } from '../logic/RepoStateFile'; -import { LookupByPath } from '../logic/LookupByPath'; import { RushPluginsConfiguration } from './RushPluginsConfiguration'; import { type IPnpmOptionsJson, PnpmOptionsConfiguration } from '../logic/pnpm/PnpmOptionsConfiguration'; import { type INpmOptionsJson, NpmOptionsConfiguration } from '../logic/npm/NpmOptionsConfiguration'; @@ -209,7 +209,7 @@ export interface ITryFindRushJsonLocationOptions { export class RushConfiguration { private static _jsonSchema: JsonSchema = JsonSchema.fromLoadedObject(schemaJson); - private readonly _pathTrees: Map>; + private readonly _pathTrees: Map>; // Lazily loaded when the projects() getter is called. private _projects: RushConfigurationProject[] | undefined; @@ -1488,13 +1488,13 @@ export class RushConfiguration { * @returns An optimized lookup engine to find a project by its path relative to the specified root. * @beta */ - public getProjectLookupForRoot(rootPath: string): LookupByPath { - let pathTree: LookupByPath | undefined = this._pathTrees.get(rootPath); + public getProjectLookupForRoot(rootPath: string): PathTrie { + let pathTree: PathTrie | undefined = this._pathTrees.get(rootPath); if (!pathTree) { - this._pathTrees.set(rootPath, (pathTree = new LookupByPath())); + this._pathTrees.set(rootPath, (pathTree = new PathTrie())); for (const project of this.projects) { const relativePath: string = path.relative(rootPath, project.projectFolder); - pathTree.setItemFromSegments(LookupByPath.iteratePathSegments(relativePath, path.sep), project); + pathTree.setItemFromSegments(PathTrie.iteratePathSegments(relativePath, path.sep), project); } } return pathTree; diff --git a/libraries/rush-lib/src/index.ts b/libraries/rush-lib/src/index.ts index b3266a1559e..cd738027876 100644 --- a/libraries/rush-lib/src/index.ts +++ b/libraries/rush-lib/src/index.ts @@ -6,6 +6,9 @@ * @packageDocumentation */ +// For backwards compatibility +export { PathTrie as LookupByPath, type IPrefixMatch } from '@rushstack/path-trie'; + export { ApprovedPackagesPolicy } from './api/ApprovedPackagesPolicy'; export { RushConfiguration, type ITryFindRushJsonLocationOptions } from './api/RushConfiguration'; @@ -88,7 +91,6 @@ export { export { RepoStateFile } from './logic/RepoStateFile'; -export { LookupByPath, type IPrefixMatch } from './logic/LookupByPath'; export { EventHooks, Event } from './api/EventHooks'; export { ChangeManager } from './api/ChangeManager'; diff --git a/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts b/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts index bd128fe2657..367294f7b16 100644 --- a/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts +++ b/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts @@ -20,7 +20,7 @@ import { Git } from './Git'; import { BaseProjectShrinkwrapFile } from './base/BaseProjectShrinkwrapFile'; import type { RushConfigurationProject } from '../api/RushConfigurationProject'; import { RushConstants } from './RushConstants'; -import type { LookupByPath } from './LookupByPath'; +import type { PathTrie } from '@rushstack/path-trie'; import { PnpmShrinkwrapFile } from './pnpm/PnpmShrinkwrapFile'; import { UNINITIALIZED } from '../utilities/Utilities'; @@ -283,8 +283,7 @@ export class ProjectChangeAnalyzer { } const changesByProject: Map> = new Map(); - const lookup: LookupByPath = - rushConfiguration.getProjectLookupForRoot(repoRoot); + const lookup: PathTrie = rushConfiguration.getProjectLookupForRoot(repoRoot); for (const [file, diffStatus] of repoChanges) { const project: RushConfigurationProject | undefined = lookup.findChildPath(file); @@ -341,7 +340,7 @@ export class ProjectChangeAnalyzer { }; } - const lookup: LookupByPath = this._rushConfiguration.getProjectLookupForRoot( + const lookup: PathTrie = this._rushConfiguration.getProjectLookupForRoot( repoState.rootDir ); const projectHashDeps: Map> = new Map(); diff --git a/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts b/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts index c5257354feb..6adf248b244 100644 --- a/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts +++ b/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import { PathTrie } from '@rushstack/path-trie'; import { StringBufferTerminalProvider, Terminal } from '@rushstack/terminal'; import { ProjectChangeAnalyzer } from '../ProjectChangeAnalyzer'; @@ -8,7 +9,6 @@ import type { RushConfiguration } from '../../api/RushConfiguration'; import { EnvironmentConfiguration } from '../../api/EnvironmentConfiguration'; import type { RushConfigurationProject } from '../../api/RushConfigurationProject'; import { RushProjectConfiguration } from '../../api/RushProjectConfiguration'; -import { LookupByPath } from '../LookupByPath'; import { UNINITIALIZED } from '../../utilities/Utilities'; describe(ProjectChangeAnalyzer.name, () => { @@ -32,8 +32,8 @@ describe(ProjectChangeAnalyzer.name, () => { getCommittedShrinkwrapFilename(): string { return 'common/config/rush/pnpm-lock.yaml'; }, - getProjectLookupForRoot(root: string): LookupByPath { - const lookup: LookupByPath = new LookupByPath(); + getProjectLookupForRoot(root: string): PathTrie { + const lookup: PathTrie = new PathTrie(); for (const project of projects) { lookup.setItem(project.projectRelativeFolder, project); } diff --git a/libraries/rush-sdk/package.json b/libraries/rush-sdk/package.json index 52e44a47dba..5ce1d31a094 100644 --- a/libraries/rush-sdk/package.json +++ b/libraries/rush-sdk/package.json @@ -48,6 +48,7 @@ "@rushstack/heft": "workspace:*", "local-node-rig": "workspace:*", "@rushstack/heft-webpack5-plugin": "workspace:*", + "@rushstack/path-trie": "workspace:*", "@rushstack/stream-collator": "workspace:*", "@rushstack/ts-command-line": "workspace:*", "@rushstack/webpack-preserve-dynamic-require-plugin": "workspace:*", diff --git a/rush.json b/rush.json index 84045504de0..60f9aca61dd 100644 --- a/rush.json +++ b/rush.json @@ -1055,6 +1055,12 @@ "reviewCategory": "libraries", "shouldPublish": true }, + { + "packageName": "@rushstack/path-trie", + "projectFolder": "libraries/path-trie", + "reviewCategory": "libraries", + "shouldPublish": true + }, { "packageName": "@rushstack/rig-package", "projectFolder": "libraries/rig-package", From cd87294a2c45b02d30b1d93c59e9bfa9141c7caa Mon Sep 17 00:00:00 2001 From: David Michon Date: Wed, 7 Aug 2024 21:23:02 +0000 Subject: [PATCH 2/3] Update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 020dcada320..a565f3ae73e 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ These GitHub repositories provide supplementary resources for Rush Stack: | [/libraries/operation-graph](./libraries/operation-graph/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Foperation-graph.svg)](https://badge.fury.io/js/%40rushstack%2Foperation-graph) | [changelog](./libraries/operation-graph/CHANGELOG.md) | [@rushstack/operation-graph](https://www.npmjs.com/package/@rushstack/operation-graph) | | [/libraries/package-deps-hash](./libraries/package-deps-hash/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fpackage-deps-hash.svg)](https://badge.fury.io/js/%40rushstack%2Fpackage-deps-hash) | [changelog](./libraries/package-deps-hash/CHANGELOG.md) | [@rushstack/package-deps-hash](https://www.npmjs.com/package/@rushstack/package-deps-hash) | | [/libraries/package-extractor](./libraries/package-extractor/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fpackage-extractor.svg)](https://badge.fury.io/js/%40rushstack%2Fpackage-extractor) | [changelog](./libraries/package-extractor/CHANGELOG.md) | [@rushstack/package-extractor](https://www.npmjs.com/package/@rushstack/package-extractor) | +| [/libraries/path-trie](./libraries/path-trie/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fpath-trie.svg)](https://badge.fury.io/js/%40rushstack%2Fpath-trie) | [changelog](./libraries/path-trie/CHANGELOG.md) | [@rushstack/path-trie](https://www.npmjs.com/package/@rushstack/path-trie) | | [/libraries/rig-package](./libraries/rig-package/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Frig-package.svg)](https://badge.fury.io/js/%40rushstack%2Frig-package) | [changelog](./libraries/rig-package/CHANGELOG.md) | [@rushstack/rig-package](https://www.npmjs.com/package/@rushstack/rig-package) | | [/libraries/rush-lib](./libraries/rush-lib/) | [![npm version](https://badge.fury.io/js/%40microsoft%2Frush-lib.svg)](https://badge.fury.io/js/%40microsoft%2Frush-lib) | | [@microsoft/rush-lib](https://www.npmjs.com/package/@microsoft/rush-lib) | | [/libraries/rush-sdk](./libraries/rush-sdk/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Frush-sdk.svg)](https://badge.fury.io/js/%40rushstack%2Frush-sdk) | | [@rushstack/rush-sdk](https://www.npmjs.com/package/@rushstack/rush-sdk) | From 5b10842734194fb4c5e5a54cac44fe8c14b3a45b Mon Sep 17 00:00:00 2001 From: David Michon Date: Thu, 8 Aug 2024 17:50:20 +0000 Subject: [PATCH 3/3] Revert name to LookupByPath --- README.md | 2 +- .../rush/path-trie_2024-08-07-18-41.json | 2 +- .../path-trie_2024-08-07-18-41.json | 10 +++++ .../path-trie/path-trie_2024-08-07-18-41.json | 10 ----- .../rush/nonbrowser-approved-packages.json | 2 +- .../build-tests-subspace/pnpm-lock.yaml | 26 ++++++------- .../build-tests-subspace/repo-state.json | 4 +- .../config/subspaces/default/pnpm-lock.yaml | 28 +++++++------- ...path-trie.api.md => lookup-by-path.api.md} | 4 +- common/reviews/api/rush-lib.api.md | 4 +- .../.eslintrc.js | 0 .../{path-trie => lookup-by-path}/.npmignore | 0 .../{path-trie => lookup-by-path}/LICENSE | 2 +- .../{path-trie => lookup-by-path}/README.md | 8 ++-- .../config/api-extractor.json | 0 .../config/jest.config.json | 0 .../config/rig.json | 0 .../package.json | 13 +++++-- .../src/LookupByPath.test.ts} | 38 +++++++++---------- .../src/LookupByPath.ts} | 24 ++++++------ .../src/index.ts | 4 +- .../tsconfig.json | 0 libraries/rush-lib/package.json | 2 +- .../rush-lib/src/api/RushConfiguration.ts | 12 +++--- libraries/rush-lib/src/index.ts | 2 +- .../src/logic/ProjectChangeAnalyzer.ts | 7 ++-- .../logic/test/ProjectChangeAnalyzer.test.ts | 6 +-- libraries/rush-sdk/package.json | 2 +- rush.json | 12 +++--- 29 files changed, 116 insertions(+), 108 deletions(-) create mode 100644 common/changes/@rushstack/lookup-by-path/path-trie_2024-08-07-18-41.json delete mode 100644 common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json rename common/reviews/api/{path-trie.api.md => lookup-by-path.api.md} (89%) rename libraries/{path-trie => lookup-by-path}/.eslintrc.js (100%) rename libraries/{path-trie => lookup-by-path}/.npmignore (100%) rename libraries/{path-trie => lookup-by-path}/LICENSE (97%) rename libraries/{path-trie => lookup-by-path}/README.md (55%) rename libraries/{path-trie => lookup-by-path}/config/api-extractor.json (100%) rename libraries/{path-trie => lookup-by-path}/config/jest.config.json (100%) rename libraries/{path-trie => lookup-by-path}/config/rig.json (100%) rename libraries/{path-trie => lookup-by-path}/package.json (75%) rename libraries/{path-trie/src/PathTrie.test.ts => lookup-by-path/src/LookupByPath.test.ts} (76%) rename libraries/{path-trie/src/PathTrie.ts => lookup-by-path/src/LookupByPath.ts} (89%) rename libraries/{path-trie => lookup-by-path}/src/index.ts (72%) rename libraries/{path-trie => lookup-by-path}/tsconfig.json (100%) diff --git a/README.md b/README.md index a565f3ae73e..942474aba62 100644 --- a/README.md +++ b/README.md @@ -76,12 +76,12 @@ These GitHub repositories provide supplementary resources for Rush Stack: | [/libraries/heft-config-file](./libraries/heft-config-file/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-config-file.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-config-file) | [changelog](./libraries/heft-config-file/CHANGELOG.md) | [@rushstack/heft-config-file](https://www.npmjs.com/package/@rushstack/heft-config-file) | | [/libraries/load-themed-styles](./libraries/load-themed-styles/) | [![npm version](https://badge.fury.io/js/%40microsoft%2Fload-themed-styles.svg)](https://badge.fury.io/js/%40microsoft%2Fload-themed-styles) | [changelog](./libraries/load-themed-styles/CHANGELOG.md) | [@microsoft/load-themed-styles](https://www.npmjs.com/package/@microsoft/load-themed-styles) | | [/libraries/localization-utilities](./libraries/localization-utilities/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Flocalization-utilities.svg)](https://badge.fury.io/js/%40rushstack%2Flocalization-utilities) | [changelog](./libraries/localization-utilities/CHANGELOG.md) | [@rushstack/localization-utilities](https://www.npmjs.com/package/@rushstack/localization-utilities) | +| [/libraries/lookup-by-path](./libraries/lookup-by-path/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Flookup-by-path.svg)](https://badge.fury.io/js/%40rushstack%2Flookup-by-path) | [changelog](./libraries/lookup-by-path/CHANGELOG.md) | [@rushstack/lookup-by-path](https://www.npmjs.com/package/@rushstack/lookup-by-path) | | [/libraries/module-minifier](./libraries/module-minifier/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fmodule-minifier.svg)](https://badge.fury.io/js/%40rushstack%2Fmodule-minifier) | [changelog](./libraries/module-minifier/CHANGELOG.md) | [@rushstack/module-minifier](https://www.npmjs.com/package/@rushstack/module-minifier) | | [/libraries/node-core-library](./libraries/node-core-library/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fnode-core-library.svg)](https://badge.fury.io/js/%40rushstack%2Fnode-core-library) | [changelog](./libraries/node-core-library/CHANGELOG.md) | [@rushstack/node-core-library](https://www.npmjs.com/package/@rushstack/node-core-library) | | [/libraries/operation-graph](./libraries/operation-graph/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Foperation-graph.svg)](https://badge.fury.io/js/%40rushstack%2Foperation-graph) | [changelog](./libraries/operation-graph/CHANGELOG.md) | [@rushstack/operation-graph](https://www.npmjs.com/package/@rushstack/operation-graph) | | [/libraries/package-deps-hash](./libraries/package-deps-hash/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fpackage-deps-hash.svg)](https://badge.fury.io/js/%40rushstack%2Fpackage-deps-hash) | [changelog](./libraries/package-deps-hash/CHANGELOG.md) | [@rushstack/package-deps-hash](https://www.npmjs.com/package/@rushstack/package-deps-hash) | | [/libraries/package-extractor](./libraries/package-extractor/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fpackage-extractor.svg)](https://badge.fury.io/js/%40rushstack%2Fpackage-extractor) | [changelog](./libraries/package-extractor/CHANGELOG.md) | [@rushstack/package-extractor](https://www.npmjs.com/package/@rushstack/package-extractor) | -| [/libraries/path-trie](./libraries/path-trie/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fpath-trie.svg)](https://badge.fury.io/js/%40rushstack%2Fpath-trie) | [changelog](./libraries/path-trie/CHANGELOG.md) | [@rushstack/path-trie](https://www.npmjs.com/package/@rushstack/path-trie) | | [/libraries/rig-package](./libraries/rig-package/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Frig-package.svg)](https://badge.fury.io/js/%40rushstack%2Frig-package) | [changelog](./libraries/rig-package/CHANGELOG.md) | [@rushstack/rig-package](https://www.npmjs.com/package/@rushstack/rig-package) | | [/libraries/rush-lib](./libraries/rush-lib/) | [![npm version](https://badge.fury.io/js/%40microsoft%2Frush-lib.svg)](https://badge.fury.io/js/%40microsoft%2Frush-lib) | | [@microsoft/rush-lib](https://www.npmjs.com/package/@microsoft/rush-lib) | | [/libraries/rush-sdk](./libraries/rush-sdk/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Frush-sdk.svg)](https://badge.fury.io/js/%40rushstack%2Frush-sdk) | | [@rushstack/rush-sdk](https://www.npmjs.com/package/@rushstack/rush-sdk) | diff --git a/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json b/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json index b00389fb6e0..5d33e5abf70 100644 --- a/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json +++ b/common/changes/@microsoft/rush/path-trie_2024-08-07-18-41.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@microsoft/rush", - "comment": "Extract LookupByPath to @rushstack/path-trie and load it from there.", + "comment": "Extract LookupByPath to @rushstack/lookup-by-path and load it from there.", "type": "none" } ], diff --git a/common/changes/@rushstack/lookup-by-path/path-trie_2024-08-07-18-41.json b/common/changes/@rushstack/lookup-by-path/path-trie_2024-08-07-18-41.json new file mode 100644 index 00000000000..0f24ffc059a --- /dev/null +++ b/common/changes/@rushstack/lookup-by-path/path-trie_2024-08-07-18-41.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/lookup-by-path", + "comment": "Extract LookupByPath from @rushstack/rush-lib.", + "type": "minor" + } + ], + "packageName": "@rushstack/lookup-by-path" +} \ No newline at end of file diff --git a/common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json b/common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json deleted file mode 100644 index 1bc98322cd1..00000000000 --- a/common/changes/@rushstack/path-trie/path-trie_2024-08-07-18-41.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@rushstack/path-trie", - "comment": "Extract and rename LookupByPath from @rushstack/rush-lib as PathTrie.", - "type": "minor" - } - ], - "packageName": "@rushstack/path-trie" -} \ No newline at end of file diff --git a/common/config/rush/nonbrowser-approved-packages.json b/common/config/rush/nonbrowser-approved-packages.json index 8689c68dacb..0e39d85c27e 100644 --- a/common/config/rush/nonbrowser-approved-packages.json +++ b/common/config/rush/nonbrowser-approved-packages.json @@ -223,7 +223,7 @@ "allowedCategories": [ "libraries", "vscode-extensions" ] }, { - "name": "@rushstack/path-trie", + "name": "@rushstack/lookup-by-path", "allowedCategories": [ "libraries" ] }, { diff --git a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml index fe565ca0b79..f0092ef821d 100644 --- a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml +++ b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml @@ -6334,6 +6334,18 @@ packages: transitivePeerDependencies: - '@types/node' + file:../../../libraries/lookup-by-path(@types/node@18.17.15): + resolution: {directory: ../../../libraries/lookup-by-path, type: directory} + id: file:../../../libraries/lookup-by-path + name: '@rushstack/lookup-by-path' + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 18.17.15 + file:../../../libraries/node-core-library(@types/node@18.17.15): resolution: {directory: ../../../libraries/node-core-library, type: directory} id: file:../../../libraries/node-core-library @@ -6394,18 +6406,6 @@ packages: transitivePeerDependencies: - '@types/node' - file:../../../libraries/path-trie(@types/node@18.17.15): - resolution: {directory: ../../../libraries/path-trie, type: directory} - id: file:../../../libraries/path-trie - name: '@rushstack/path-trie' - peerDependencies: - '@types/node': '*' - peerDependenciesMeta: - '@types/node': - optional: true - dependencies: - '@types/node': 18.17.15 - file:../../../libraries/rig-package: resolution: {directory: ../../../libraries/rig-package, type: directory} name: '@rushstack/rig-package' @@ -6422,10 +6422,10 @@ packages: '@pnpm/dependency-path': 2.1.8 '@pnpm/link-bins': 5.3.25 '@rushstack/heft-config-file': file:../../../libraries/heft-config-file(@types/node@18.17.15) + '@rushstack/lookup-by-path': file:../../../libraries/lookup-by-path(@types/node@18.17.15) '@rushstack/node-core-library': file:../../../libraries/node-core-library(@types/node@18.17.15) '@rushstack/package-deps-hash': file:../../../libraries/package-deps-hash(@types/node@18.17.15) '@rushstack/package-extractor': file:../../../libraries/package-extractor(@types/node@18.17.15) - '@rushstack/path-trie': file:../../../libraries/path-trie(@types/node@18.17.15) '@rushstack/rig-package': file:../../../libraries/rig-package '@rushstack/stream-collator': file:../../../libraries/stream-collator(@types/node@18.17.15) '@rushstack/terminal': file:../../../libraries/terminal(@types/node@18.17.15) diff --git a/common/config/subspaces/build-tests-subspace/repo-state.json b/common/config/subspaces/build-tests-subspace/repo-state.json index e22c309900a..d443a0b9985 100644 --- a/common/config/subspaces/build-tests-subspace/repo-state.json +++ b/common/config/subspaces/build-tests-subspace/repo-state.json @@ -1,6 +1,6 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "292a9e8a4370837e8288a7e359283689923755a7", + "pnpmShrinkwrapHash": "c0913bff408b4b5b4199bb79136507654411840d", "preferredVersionsHash": "ce857ea0536b894ec8f346aaea08cfd85a5af648", - "packageJsonInjectedDependenciesHash": "97c61af3a05454ebf76d54ad9588a25d40faaa23" + "packageJsonInjectedDependenciesHash": "41bcc1ae799e99853393c22bcf0c649e0e330e14" } diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index 7946cbadaa0..5423702e50a 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -3054,6 +3054,15 @@ importers: specifier: workspace:* version: link:../../rigs/local-node-rig + ../../../libraries/lookup-by-path: + devDependencies: + '@rushstack/heft': + specifier: workspace:* + version: link:../../apps/heft + local-node-rig: + specifier: workspace:* + version: link:../../rigs/local-node-rig + ../../../libraries/module-minifier: dependencies: '@rushstack/worker-pool': @@ -3230,15 +3239,6 @@ importers: specifier: ~5.82.1 version: 5.82.1 - ../../../libraries/path-trie: - devDependencies: - '@rushstack/heft': - specifier: workspace:* - version: link:../../apps/heft - local-node-rig: - specifier: workspace:* - version: link:../../rigs/local-node-rig - ../../../libraries/rig-package: dependencies: resolve: @@ -3281,6 +3281,9 @@ importers: '@rushstack/heft-config-file': specifier: workspace:* version: link:../heft-config-file + '@rushstack/lookup-by-path': + specifier: workspace:* + version: link:../lookup-by-path '@rushstack/node-core-library': specifier: workspace:* version: link:../node-core-library @@ -3290,9 +3293,6 @@ importers: '@rushstack/package-extractor': specifier: workspace:* version: link:../package-extractor - '@rushstack/path-trie': - specifier: workspace:* - version: link:../path-trie '@rushstack/rig-package': specifier: workspace:* version: link:../rig-package @@ -3466,9 +3466,9 @@ importers: '@rushstack/heft-webpack5-plugin': specifier: workspace:* version: link:../../heft-plugins/heft-webpack5-plugin - '@rushstack/path-trie': + '@rushstack/lookup-by-path': specifier: workspace:* - version: link:../path-trie + version: link:../lookup-by-path '@rushstack/stream-collator': specifier: workspace:* version: link:../stream-collator diff --git a/common/reviews/api/path-trie.api.md b/common/reviews/api/lookup-by-path.api.md similarity index 89% rename from common/reviews/api/path-trie.api.md rename to common/reviews/api/lookup-by-path.api.md index a55866d7a24..f96f86ad22e 100644 --- a/common/reviews/api/path-trie.api.md +++ b/common/reviews/api/lookup-by-path.api.md @@ -1,4 +1,4 @@ -## API Report File for "@rushstack/path-trie" +## API Report File for "@rushstack/lookup-by-path" > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). @@ -11,7 +11,7 @@ export interface IPrefixMatch { } // @beta -export class PathTrie { +export class LookupByPath { constructor(entries?: Iterable<[string, TItem]>, delimiter?: string); readonly delimiter: string; findChildPath(childPath: string): TItem | undefined; diff --git a/common/reviews/api/rush-lib.api.md b/common/reviews/api/rush-lib.api.md index df738d218dc..42c92b45f12 100644 --- a/common/reviews/api/rush-lib.api.md +++ b/common/reviews/api/rush-lib.api.md @@ -15,11 +15,11 @@ import type { CommandLineParameter } from '@rushstack/ts-command-line'; import { CommandLineParameterKind } from '@rushstack/ts-command-line'; import { HookMap } from 'tapable'; import { IPackageJson } from '@rushstack/node-core-library'; -import { IPrefixMatch } from '@rushstack/path-trie'; +import { IPrefixMatch } from '@rushstack/lookup-by-path'; import { ITerminal } from '@rushstack/terminal'; import { ITerminalProvider } from '@rushstack/terminal'; import { JsonObject } from '@rushstack/node-core-library'; -import { PathTrie as LookupByPath } from '@rushstack/path-trie'; +import { LookupByPath } from '@rushstack/lookup-by-path'; import { PackageNameParser } from '@rushstack/node-core-library'; import type { StdioSummarizer } from '@rushstack/terminal'; import { SyncHook } from 'tapable'; diff --git a/libraries/path-trie/.eslintrc.js b/libraries/lookup-by-path/.eslintrc.js similarity index 100% rename from libraries/path-trie/.eslintrc.js rename to libraries/lookup-by-path/.eslintrc.js diff --git a/libraries/path-trie/.npmignore b/libraries/lookup-by-path/.npmignore similarity index 100% rename from libraries/path-trie/.npmignore rename to libraries/lookup-by-path/.npmignore diff --git a/libraries/path-trie/LICENSE b/libraries/lookup-by-path/LICENSE similarity index 97% rename from libraries/path-trie/LICENSE rename to libraries/lookup-by-path/LICENSE index 7137f22d95a..ad73d857028 100644 --- a/libraries/path-trie/LICENSE +++ b/libraries/lookup-by-path/LICENSE @@ -1,4 +1,4 @@ -@rushstack/path-trie +@rushstack/lookup-by-path Copyright (c) Microsoft Corporation. All rights reserved. diff --git a/libraries/path-trie/README.md b/libraries/lookup-by-path/README.md similarity index 55% rename from libraries/path-trie/README.md rename to libraries/lookup-by-path/README.md index c1e9b33107b..d450300ed73 100644 --- a/libraries/path-trie/README.md +++ b/libraries/lookup-by-path/README.md @@ -1,4 +1,4 @@ -# @rushstack/path-trie +# @rushstack/lookup-by-path This library contains a strongly-typed implementation of of a [Trie](https://en.wikipedia.org/wiki/Trie) (a.k.a. prefix tree) data structure optimized for file paths and URLs. @@ -7,8 +7,8 @@ This package is used by Rush to associate Git hashes with their nearest ancestor ## Links - [CHANGELOG.md]( - https://github.com/microsoft/rushstack/blob/main/libraries/path-trie/CHANGELOG.md) - Find + https://github.com/microsoft/rushstack/blob/main/libraries/lookup-by-path/CHANGELOG.md) - Find out what's new in the latest version -- [API Reference](https://api.rushstack.io/pages/path-trie/) +- [API Reference](https://api.rushstack.io/pages/lookup-by-path/) -`@rushstack/path-trie` is part of the [Rush Stack](https://rushstack.io/) family of projects. +`@rushstack/lookup-by-path` is part of the [Rush Stack](https://rushstack.io/) family of projects. diff --git a/libraries/path-trie/config/api-extractor.json b/libraries/lookup-by-path/config/api-extractor.json similarity index 100% rename from libraries/path-trie/config/api-extractor.json rename to libraries/lookup-by-path/config/api-extractor.json diff --git a/libraries/path-trie/config/jest.config.json b/libraries/lookup-by-path/config/jest.config.json similarity index 100% rename from libraries/path-trie/config/jest.config.json rename to libraries/lookup-by-path/config/jest.config.json diff --git a/libraries/path-trie/config/rig.json b/libraries/lookup-by-path/config/rig.json similarity index 100% rename from libraries/path-trie/config/rig.json rename to libraries/lookup-by-path/config/rig.json diff --git a/libraries/path-trie/package.json b/libraries/lookup-by-path/package.json similarity index 75% rename from libraries/path-trie/package.json rename to libraries/lookup-by-path/package.json index d200fa3baba..7903f04be36 100644 --- a/libraries/path-trie/package.json +++ b/libraries/lookup-by-path/package.json @@ -1,14 +1,21 @@ { - "name": "@rushstack/path-trie", + "name": "@rushstack/lookup-by-path", "version": "0.0.0", "description": "Strongly typed trie data structure for path and URL-like strings.", "main": "lib/index.js", - "typings": "dist/path-trie.d.ts", + "typings": "dist/lookup-by-path.d.ts", + "keywords": [ + "trie", + "path", + "url", + "radix tree", + "prefix tree" + ], "license": "MIT", "repository": { "url": "https://github.com/microsoft/rushstack.git", "type": "git", - "directory": "libraries/path-trie" + "directory": "libraries/lookup-by-path" }, "scripts": { "build": "heft build --clean", diff --git a/libraries/path-trie/src/PathTrie.test.ts b/libraries/lookup-by-path/src/LookupByPath.test.ts similarity index 76% rename from libraries/path-trie/src/PathTrie.test.ts rename to libraries/lookup-by-path/src/LookupByPath.test.ts index ee3c7532e3e..06a30631ae4 100644 --- a/libraries/path-trie/src/PathTrie.test.ts +++ b/libraries/lookup-by-path/src/LookupByPath.test.ts @@ -1,40 +1,40 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -import { PathTrie } from './PathTrie'; +import { LookupByPath } from './LookupByPath'; -describe(PathTrie.iteratePathSegments.name, () => { +describe(LookupByPath.iteratePathSegments.name, () => { it('returns empty for an empty string', () => { - const result = [...PathTrie.iteratePathSegments('')]; + const result = [...LookupByPath.iteratePathSegments('')]; expect(result.length).toEqual(0); }); it('returns the only segment of a trival string', () => { - const result = [...PathTrie.iteratePathSegments('foo')]; + const result = [...LookupByPath.iteratePathSegments('foo')]; expect(result).toEqual(['foo']); }); it('treats backslashes as ordinary characters, per POSIX', () => { - const result = [...PathTrie.iteratePathSegments('foo\\bar\\baz')]; + const result = [...LookupByPath.iteratePathSegments('foo\\bar\\baz')]; expect(result).toEqual(['foo\\bar\\baz']); }); it('iterates segments', () => { - const result = [...PathTrie.iteratePathSegments('foo/bar/baz')]; + const result = [...LookupByPath.iteratePathSegments('foo/bar/baz')]; expect(result).toEqual(['foo', 'bar', 'baz']); }); it('returns correct last single character segment', () => { - const result = [...PathTrie.iteratePathSegments('foo/a')]; + const result = [...LookupByPath.iteratePathSegments('foo/a')]; expect(result).toEqual(['foo', 'a']); }); }); -describe(PathTrie.prototype.findChildPath.name, () => { +describe(LookupByPath.prototype.findChildPath.name, () => { it('returns empty for an empty tree', () => { - expect(new PathTrie().findChildPath('foo')).toEqual(undefined); + expect(new LookupByPath().findChildPath('foo')).toEqual(undefined); }); it('returns the matching node for a trivial tree', () => { - expect(new PathTrie([['foo', 1]]).findChildPath('foo')).toEqual(1); + expect(new LookupByPath([['foo', 1]]).findChildPath('foo')).toEqual(1); }); it('returns the matching node for a single-layer tree', () => { - const tree: PathTrie = new PathTrie([ + const tree: LookupByPath = new LookupByPath([ ['foo', 1], ['bar', 2], ['baz', 3] @@ -46,7 +46,7 @@ describe(PathTrie.prototype.findChildPath.name, () => { expect(tree.findChildPath('buzz')).toEqual(undefined); }); it('returns the matching parent for multi-layer queries', () => { - const tree: PathTrie = new PathTrie([ + const tree: LookupByPath = new LookupByPath([ ['foo', 1], ['bar', 2], ['baz', 3] @@ -58,7 +58,7 @@ describe(PathTrie.prototype.findChildPath.name, () => { expect(tree.findChildPath('foo/foo')).toEqual(1); }); it('returns the matching parent for multi-layer queries in multi-layer trees', () => { - const tree: PathTrie = new PathTrie([ + const tree: LookupByPath = new LookupByPath([ ['foo', 1], ['bar', 2], ['baz', 3], @@ -92,7 +92,7 @@ describe(PathTrie.prototype.findChildPath.name, () => { expect(tree.findChildPath('foo\\bar\\baz')).toEqual(undefined); }); it('handles custom delimiters', () => { - const tree: PathTrie = new PathTrie( + const tree: LookupByPath = new LookupByPath( [ ['foo,bar', 1], ['foo/bar', 2] @@ -106,15 +106,15 @@ describe(PathTrie.prototype.findChildPath.name, () => { }); }); -describe(PathTrie.prototype.findLongestPrefixMatch.name, () => { +describe(LookupByPath.prototype.findLongestPrefixMatch.name, () => { it('returns empty for an empty tree', () => { - expect(new PathTrie().findLongestPrefixMatch('foo')).toEqual(undefined); + expect(new LookupByPath().findLongestPrefixMatch('foo')).toEqual(undefined); }); it('returns the matching node for a trivial tree', () => { - expect(new PathTrie([['foo', 1]]).findLongestPrefixMatch('foo')).toEqual({ value: 1, index: 3 }); + expect(new LookupByPath([['foo', 1]]).findLongestPrefixMatch('foo')).toEqual({ value: 1, index: 3 }); }); it('returns the matching node for a single-layer tree', () => { - const tree: PathTrie = new PathTrie([ + const tree: LookupByPath = new LookupByPath([ ['foo', 1], ['barbar', 2], ['baz', 3] @@ -126,7 +126,7 @@ describe(PathTrie.prototype.findLongestPrefixMatch.name, () => { expect(tree.findLongestPrefixMatch('buzz')).toEqual(undefined); }); it('returns the matching parent for multi-layer queries', () => { - const tree: PathTrie = new PathTrie([ + const tree: LookupByPath = new LookupByPath([ ['foo', 1], ['barbar', 2], ['baz', 3], diff --git a/libraries/path-trie/src/PathTrie.ts b/libraries/lookup-by-path/src/LookupByPath.ts similarity index 89% rename from libraries/path-trie/src/PathTrie.ts rename to libraries/lookup-by-path/src/LookupByPath.ts index 40ae2049ce2..949dceb72b2 100644 --- a/libraries/path-trie/src/PathTrie.ts +++ b/libraries/lookup-by-path/src/LookupByPath.ts @@ -2,7 +2,7 @@ // See LICENSE in the project root for license information. /** - * A node in the path trie used in PathTrie + * A node in the path trie used in LookupByPath */ interface IPathTrieNode { /** @@ -53,7 +53,7 @@ export interface IPrefixMatch { * * @example * ```ts - * const trie = new PathTrie([['foo', 1], ['bar', 2], ['foo/bar', 3]]); + * const trie = new LookupByPath([['foo', 1], ['bar', 2], ['foo/bar', 3]]); * trie.findChildPath('foo'); // returns 1 * trie.findChildPath('foo/baz'); // returns 1 * trie.findChildPath('baz'); // returns undefined @@ -62,7 +62,7 @@ export interface IPrefixMatch { * ``` * @beta */ -export class PathTrie { +export class LookupByPath { /** * The delimiter used to split paths */ @@ -73,7 +73,7 @@ export class PathTrie { private readonly _root: IPathTrieNode; /** - * Constructs a new `PathTrie` + * Constructs a new `LookupByPath` * * @param entries - Initial path-value pairs to populate the trie. */ @@ -97,9 +97,9 @@ export class PathTrie { * * @example * - * `PathTrie.iteratePathSegments('foo/bar/baz')` yields 'foo', 'bar', 'baz' + * `LookupByPath.iteratePathSegments('foo/bar/baz')` yields 'foo', 'bar', 'baz' * - * `PathTrie.iteratePathSegments('foo\\bar\\baz', '\\')` yields 'foo', 'bar', 'baz' + * `LookupByPath.iteratePathSegments('foo\\bar\\baz', '\\')` yields 'foo', 'bar', 'baz' */ public static *iteratePathSegments(serializedPath: string, delimiter: string = '/'): Iterable { for (const prefixMatch of this._iteratePrefixes(serializedPath, delimiter)) { @@ -141,7 +141,7 @@ export class PathTrie { * @returns this, for chained calls */ public setItem(serializedPath: string, value: TItem): this { - return this.setItemFromSegments(PathTrie.iteratePathSegments(serializedPath, this.delimiter), value); + return this.setItemFromSegments(LookupByPath.iteratePathSegments(serializedPath, this.delimiter), value); } /** @@ -181,13 +181,13 @@ export class PathTrie { * * @example * ```ts - * const trie = new PathTrie([['foo', 1], ['foo/bar', 2]]); + * const trie = new LookupByPath([['foo', 1], ['foo/bar', 2]]); * trie.findChildPath('foo/baz'); // returns 1 * trie.findChildPath('foo/bar/baz'); // returns 2 * ``` */ public findChildPath(childPath: string): TItem | undefined { - return this.findChildPathFromSegments(PathTrie.iteratePathSegments(childPath, this.delimiter)); + return this.findChildPathFromSegments(LookupByPath.iteratePathSegments(childPath, this.delimiter)); } /** @@ -199,13 +199,13 @@ export class PathTrie { * * @example * ```ts - * const trie = new PathTrie([['foo', 1], ['foo/bar', 2]]); + * const trie = new LookupByPath([['foo', 1], ['foo/bar', 2]]); * trie.findLongestPrefixMatch('foo/baz'); // returns { item: 1, index: 3 } * trie.findLongestPrefixMatch('foo/bar/baz'); // returns { item: 2, index: 7 } * ``` */ public findLongestPrefixMatch(query: string): IPrefixMatch | undefined { - return this._findLongestPrefixMatch(PathTrie._iteratePrefixes(query, this.delimiter)); + return this._findLongestPrefixMatch(LookupByPath._iteratePrefixes(query, this.delimiter)); } /** @@ -216,7 +216,7 @@ export class PathTrie { * * @example * ```ts - * const trie = new PathTrie([['foo', 1], ['foo/bar', 2]]); + * const trie = new LookupByPath([['foo', 1], ['foo/bar', 2]]); * trie.findChildPathFromSegments(['foo', 'baz']); // returns 1 * trie.findChildPathFromSegments(['foo','bar', 'baz']); // returns 2 * ``` diff --git a/libraries/path-trie/src/index.ts b/libraries/lookup-by-path/src/index.ts similarity index 72% rename from libraries/path-trie/src/index.ts rename to libraries/lookup-by-path/src/index.ts index 737b72ea894..7cc91e2647e 100644 --- a/libraries/path-trie/src/index.ts +++ b/libraries/lookup-by-path/src/index.ts @@ -7,5 +7,5 @@ * @packageDocumentation */ -export type { IPrefixMatch } from './PathTrie'; -export { PathTrie } from './PathTrie'; +export type { IPrefixMatch } from './LookupByPath'; +export { LookupByPath } from './LookupByPath'; diff --git a/libraries/path-trie/tsconfig.json b/libraries/lookup-by-path/tsconfig.json similarity index 100% rename from libraries/path-trie/tsconfig.json rename to libraries/lookup-by-path/tsconfig.json diff --git a/libraries/rush-lib/package.json b/libraries/rush-lib/package.json index a2bd3f0acd1..e0ac87388a7 100644 --- a/libraries/rush-lib/package.json +++ b/libraries/rush-lib/package.json @@ -32,10 +32,10 @@ "@pnpm/dependency-path": "~2.1.2", "@pnpm/link-bins": "~5.3.7", "@rushstack/heft-config-file": "workspace:*", + "@rushstack/lookup-by-path": "workspace:*", "@rushstack/node-core-library": "workspace:*", "@rushstack/package-deps-hash": "workspace:*", "@rushstack/package-extractor": "workspace:*", - "@rushstack/path-trie": "workspace:*", "@rushstack/rig-package": "workspace:*", "@rushstack/stream-collator": "workspace:*", "@rushstack/terminal": "workspace:*", diff --git a/libraries/rush-lib/src/api/RushConfiguration.ts b/libraries/rush-lib/src/api/RushConfiguration.ts index 2b930b08a20..f3fa0cbd6e4 100644 --- a/libraries/rush-lib/src/api/RushConfiguration.ts +++ b/libraries/rush-lib/src/api/RushConfiguration.ts @@ -14,7 +14,7 @@ import { type FileSystemStats, InternalError } from '@rushstack/node-core-library'; -import { PathTrie } from '@rushstack/path-trie'; +import { LookupByPath } from '@rushstack/lookup-by-path'; import { trueCasePathSync } from 'true-case-path'; import { Rush } from '../api/Rush'; @@ -209,7 +209,7 @@ export interface ITryFindRushJsonLocationOptions { export class RushConfiguration { private static _jsonSchema: JsonSchema = JsonSchema.fromLoadedObject(schemaJson); - private readonly _pathTrees: Map>; + private readonly _pathTrees: Map>; // Lazily loaded when the projects() getter is called. private _projects: RushConfigurationProject[] | undefined; @@ -1488,13 +1488,13 @@ export class RushConfiguration { * @returns An optimized lookup engine to find a project by its path relative to the specified root. * @beta */ - public getProjectLookupForRoot(rootPath: string): PathTrie { - let pathTree: PathTrie | undefined = this._pathTrees.get(rootPath); + public getProjectLookupForRoot(rootPath: string): LookupByPath { + let pathTree: LookupByPath | undefined = this._pathTrees.get(rootPath); if (!pathTree) { - this._pathTrees.set(rootPath, (pathTree = new PathTrie())); + this._pathTrees.set(rootPath, (pathTree = new LookupByPath())); for (const project of this.projects) { const relativePath: string = path.relative(rootPath, project.projectFolder); - pathTree.setItemFromSegments(PathTrie.iteratePathSegments(relativePath, path.sep), project); + pathTree.setItemFromSegments(LookupByPath.iteratePathSegments(relativePath, path.sep), project); } } return pathTree; diff --git a/libraries/rush-lib/src/index.ts b/libraries/rush-lib/src/index.ts index cd738027876..63e7e812116 100644 --- a/libraries/rush-lib/src/index.ts +++ b/libraries/rush-lib/src/index.ts @@ -7,7 +7,7 @@ */ // For backwards compatibility -export { PathTrie as LookupByPath, type IPrefixMatch } from '@rushstack/path-trie'; +export { LookupByPath as LookupByPath, type IPrefixMatch } from '@rushstack/lookup-by-path'; export { ApprovedPackagesPolicy } from './api/ApprovedPackagesPolicy'; diff --git a/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts b/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts index 367294f7b16..bc2c1408ce0 100644 --- a/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts +++ b/libraries/rush-lib/src/logic/ProjectChangeAnalyzer.ts @@ -20,7 +20,7 @@ import { Git } from './Git'; import { BaseProjectShrinkwrapFile } from './base/BaseProjectShrinkwrapFile'; import type { RushConfigurationProject } from '../api/RushConfigurationProject'; import { RushConstants } from './RushConstants'; -import type { PathTrie } from '@rushstack/path-trie'; +import type { LookupByPath } from '@rushstack/lookup-by-path'; import { PnpmShrinkwrapFile } from './pnpm/PnpmShrinkwrapFile'; import { UNINITIALIZED } from '../utilities/Utilities'; @@ -283,7 +283,8 @@ export class ProjectChangeAnalyzer { } const changesByProject: Map> = new Map(); - const lookup: PathTrie = rushConfiguration.getProjectLookupForRoot(repoRoot); + const lookup: LookupByPath = + rushConfiguration.getProjectLookupForRoot(repoRoot); for (const [file, diffStatus] of repoChanges) { const project: RushConfigurationProject | undefined = lookup.findChildPath(file); @@ -340,7 +341,7 @@ export class ProjectChangeAnalyzer { }; } - const lookup: PathTrie = this._rushConfiguration.getProjectLookupForRoot( + const lookup: LookupByPath = this._rushConfiguration.getProjectLookupForRoot( repoState.rootDir ); const projectHashDeps: Map> = new Map(); diff --git a/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts b/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts index 6adf248b244..1c328acc28b 100644 --- a/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts +++ b/libraries/rush-lib/src/logic/test/ProjectChangeAnalyzer.test.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -import { PathTrie } from '@rushstack/path-trie'; +import { LookupByPath } from '@rushstack/lookup-by-path'; import { StringBufferTerminalProvider, Terminal } from '@rushstack/terminal'; import { ProjectChangeAnalyzer } from '../ProjectChangeAnalyzer'; @@ -32,8 +32,8 @@ describe(ProjectChangeAnalyzer.name, () => { getCommittedShrinkwrapFilename(): string { return 'common/config/rush/pnpm-lock.yaml'; }, - getProjectLookupForRoot(root: string): PathTrie { - const lookup: PathTrie = new PathTrie(); + getProjectLookupForRoot(root: string): LookupByPath { + const lookup: LookupByPath = new LookupByPath(); for (const project of projects) { lookup.setItem(project.projectRelativeFolder, project); } diff --git a/libraries/rush-sdk/package.json b/libraries/rush-sdk/package.json index 5ce1d31a094..aa25f13aafc 100644 --- a/libraries/rush-sdk/package.json +++ b/libraries/rush-sdk/package.json @@ -48,7 +48,7 @@ "@rushstack/heft": "workspace:*", "local-node-rig": "workspace:*", "@rushstack/heft-webpack5-plugin": "workspace:*", - "@rushstack/path-trie": "workspace:*", + "@rushstack/lookup-by-path": "workspace:*", "@rushstack/stream-collator": "workspace:*", "@rushstack/ts-command-line": "workspace:*", "@rushstack/webpack-preserve-dynamic-require-plugin": "workspace:*", diff --git a/rush.json b/rush.json index 60f9aca61dd..5728d6e9eb8 100644 --- a/rush.json +++ b/rush.json @@ -1029,6 +1029,12 @@ "reviewCategory": "libraries", "shouldPublish": true }, + { + "packageName": "@rushstack/lookup-by-path", + "projectFolder": "libraries/lookup-by-path", + "reviewCategory": "libraries", + "shouldPublish": true + }, { "packageName": "@rushstack/module-minifier", "projectFolder": "libraries/module-minifier", @@ -1055,12 +1061,6 @@ "reviewCategory": "libraries", "shouldPublish": true }, - { - "packageName": "@rushstack/path-trie", - "projectFolder": "libraries/path-trie", - "reviewCategory": "libraries", - "shouldPublish": true - }, { "packageName": "@rushstack/rig-package", "projectFolder": "libraries/rig-package",