@rushstack/eslint-plugin-packlets 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +24 -0
- package/CHANGELOG.md +15 -1
- package/lib/DependencyAnalyzer.d.ts +1 -1
- package/lib/DependencyAnalyzer.d.ts.map +1 -1
- package/lib/DependencyAnalyzer.js.map +1 -1
- package/lib/PackletAnalyzer.d.ts.map +1 -1
- package/lib/PackletAnalyzer.js +1 -1
- package/lib/PackletAnalyzer.js.map +1 -1
- package/lib/Path.d.ts +1 -1
- package/lib/Path.d.ts.map +1 -1
- package/lib/Path.js +2 -2
- package/lib/Path.js.map +1 -1
- package/lib/circular-deps.d.ts.map +1 -1
- package/lib/circular-deps.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/mechanics.d.ts +1 -1
- package/lib/mechanics.d.ts.map +1 -1
- package/lib/mechanics.js.map +1 -1
- package/lib/readme.d.ts.map +1 -1
- package/lib/readme.js +2 -2
- package/lib/readme.js.map +1 -1
- package/package.json +8 -14
package/CHANGELOG.json
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rushstack/eslint-plugin-packlets",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.13.0",
|
|
6
|
+
"tag": "@rushstack/eslint-plugin-packlets_v0.13.0",
|
|
7
|
+
"date": "Fri, 03 Oct 2025 20:09:59 GMT",
|
|
8
|
+
"comments": {
|
|
9
|
+
"minor": [
|
|
10
|
+
{
|
|
11
|
+
"comment": "Normalize import of builtin modules to use the `node:` protocol."
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"version": "0.12.0",
|
|
18
|
+
"tag": "@rushstack/eslint-plugin-packlets_v0.12.0",
|
|
19
|
+
"date": "Thu, 26 Jun 2025 18:57:04 GMT",
|
|
20
|
+
"comments": {
|
|
21
|
+
"minor": [
|
|
22
|
+
{
|
|
23
|
+
"comment": "Update for compatibility with ESLint 9"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
4
28
|
{
|
|
5
29
|
"version": "0.11.0",
|
|
6
30
|
"tag": "@rushstack/eslint-plugin-packlets_v0.11.0",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# Change Log - @rushstack/eslint-plugin-packlets
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Fri, 03 Oct 2025 20:09:59 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 0.13.0
|
|
6
|
+
Fri, 03 Oct 2025 20:09:59 GMT
|
|
7
|
+
|
|
8
|
+
### Minor changes
|
|
9
|
+
|
|
10
|
+
- Normalize import of builtin modules to use the `node:` protocol.
|
|
11
|
+
|
|
12
|
+
## 0.12.0
|
|
13
|
+
Thu, 26 Jun 2025 18:57:04 GMT
|
|
14
|
+
|
|
15
|
+
### Minor changes
|
|
16
|
+
|
|
17
|
+
- Update for compatibility with ESLint 9
|
|
4
18
|
|
|
5
19
|
## 0.11.0
|
|
6
20
|
Tue, 11 Mar 2025 02:12:33 GMT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DependencyAnalyzer.d.ts","sourceRoot":"","sources":["../src/DependencyAnalyzer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"DependencyAnalyzer.d.ts","sourceRoot":"","sources":["../src/DependencyAnalyzer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA4DzD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAYD,qBAAa,kBAAkB;IAC7B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAwG3B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;WACW,gCAAgC,CAC5C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,EAAE,CAAC,OAAO,GAClB,cAAc,EAAE,GAAG,SAAS;CA4ChC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DependencyAnalyzer.js","sourceRoot":"","sources":["../src/DependencyAnalyzer.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAI3D,iCAA8B;AAG9B,IAAK,WAIJ;AAJD,WAAK,WAAW;IACd,iDAAM,CAAA;IACN,+DAAa,CAAA;IACb,iFAAsB,CAAA;AACxB,CAAC,EAJI,WAAW,KAAX,WAAW,QAIf;AAmBD,gCAAgC;AAChC,yBAAyB;AACzB,oHAAoH;AACpH,IAAK,eAUJ;AAVD,WAAK,eAAe;IAClB,6DAAQ,CAAA;IACR,iGAA0B,CAAA;IAC1B,iGAA0B,CAAA;IAC1B,yDAAM,CAAA;IACN,uEAAa,CAAA;IACb,yFAAsB,CAAA;IACtB,2DAAO,CAAA;IACP,uFAAqB,CAAA;IACrB,iGAA0B,CAAA;AAC5B,CAAC,EAVI,eAAe,KAAf,eAAe,QAUnB;AA+CD,MAAa,kBAAkB;IAC7B;;;;;;;;;;OAUG;IACK,MAAM,CAAC,YAAY,CACzB,WAAmB,EACnB,mBAA2B,EAC3B,UAA+C,EAC/C,qBAAoE,EACpE,OAAmB,EACnB,kBAA0B,EAC1B,eAA4B,EAC5B,YAAyC;QAEzC,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAEjC,MAAM,iBAAiB,GAAW,WAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAEtF,MAAM,YAAY,GAChB,OAAO,CAAC,aAAa,CAAC,iBAAiB,GAAG,KAAK,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,iBAAiB,GAAG,MAAM,CAAC,CAAC;QACxG,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,oBAAoB,GAAa,EAAE,CAAC;QAE1C,IAAI,UAAU,EAAE,CAAC;YACf,+CAA+C;YAC/C,8DAA8D;YAC9D,MAAM,QAAQ,GAA2B,UAAU,CAAC,GAAG,CAAE,YAAoB,CAAC,IAAI,CAAC,CAAC;YACpF,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC;wBACxC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAC1C,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,IAAI,qBAAqB,EAAE,CAAC;YACjC,oCAAoC;YACpC,MAAM,kBAAkB,GAAqC,qBAAqB,CAAC,GAAG;YACpF,8DAA8D;YAC7D,YAAoB,CAAC,IAAI,CAC3B,CAAC;YACF,IAAI,kBAAkB,EAAE,CAAC;gBACvB,KAAK,MAAM,iBAAiB,IAAI,kBAAkB,EAAE,CAAC;oBACnD,IAAI,iBAAiB,CAAC,IAAI,KAAK,eAAe,CAAC,MAAM,EAAE,CAAC;wBACtD,IAAI,iBAAiB,CAAC,IAAI,EAAE,CAAC;4BAC3B,oBAAoB,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;wBACpD,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,KAAK,MAAM,mBAAmB,IAAI,oBAAoB,EAAE,CAAC;YACvD,kCAAkC;YAClC,IAAI,WAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,EAAE,CAAC;gBAC1D,MAAM,uBAAuB,GAAW,WAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;gBAC/F,MAAM,oBAAoB,GAAa,uBAAuB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAChF,MAAM,sBAAsB,GAAW,oBAAoB,CAAC,CAAC,CAAC,CAAC;gBAE/D,0CAA0C;gBAC1C,IAAI,sBAAsB,KAAK,mBAAmB,EAAE,CAAC;oBACnD,qEAAqE;oBACrE,gEAAgE;oBAChE,IAAI,YAAY,EAAE,CAAC;wBACjB,mEAAmE;wBACnE,MAAM,cAAc,GAAoB;4BACtC,YAAY,EAAE,YAAY;4BAC1B,YAAY,EAAE,mBAAmB;4BACjC,WAAW,EAAE,WAAW;yBACzB,CAAC;wBAEF,kEAAkE;wBAClE,oDAAoD;wBACpD,OAAO,cAAc,CAAC;oBACxB,CAAC;gBACH,CAAC;gBAED,yCAAyC;gBACzC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAAC;oBACjD,mEAAmE;oBACnE,MAAM,cAAc,GAAoB;wBACtC,YAAY,EAAE,YAAY;wBAC1B,YAAY,EAAE,mBAAmB;wBACjC,WAAW,EAAE,WAAW;qBACzB,CAAC;oBAEF,MAAM,MAAM,GAAgC,kBAAkB,CAAC,YAAY,CACzE,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,EACV,qBAAqB,EACrB,OAAO,EACP,kBAAkB,EAClB,eAAe,EACf,cAAc,CACf,CAAC;oBACF,IAAI,MAAM,EAAE,CAAC;wBACX,OAAO,MAAM,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,MAAM,CAAC,gCAAgC,CAC5C,WAAmB,EACnB,eAAgC,EAChC,OAAmB;QAEnB,MAAM,gBAAgB,GAAwB,OAAO,CAAC;QAEtD,IAAI,UAA+C,CAAC;QACpD,IAAI,qBAAoE,CAAC;QAEzE,IAAI,gBAAgB,CAAC,aAAa,EAAE,CAAC;YACnC,+CAA+C;YAC/C,UAAU,GAAG,gBAAgB,CAAC,aAAa,EAAE,CAAC;QAChD,CAAC;aAAM,IAAI,gBAAgB,CAAC,qBAAqB,EAAE,CAAC;YAClD,oCAAoC;YACpC,qBAAqB,GAAG,gBAAgB,CAAC,qBAAqB,EAAE,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,mDAAmD;YACnD,MAAM,IAAI,KAAK,CACb,qGAAqG;gBACnG,2BAA2B,CAC9B,CAAC;QACJ,CAAC;QAED,MAAM,eAAe,GAAgB,IAAI,GAAG,EAAE,CAAC;QAE/C,MAAM,QAAQ,GAAgC,kBAAkB,CAAC,YAAY,CAC3E,WAAW,EACX,WAAW,EACX,UAAU,EACV,qBAAqB,EACrB,OAAO,EACP,eAAe,CAAC,kBAAmB,EACnC,eAAe,EACf,SAAS,CAAC,eAAe;SAC1B,CAAC;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,sCAAsC;YACtC,MAAM,cAAc,GAAqB,EAAE,CAAC;YAC5C,KAAK,IAAI,OAAO,GAAgC,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;gBAClG,cAAc,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;YAChG,CAAC;YACD,OAAO,cAAc,CAAC;QACxB,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AA9LD,gDA8LC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type * as ts from 'typescript';\n\nimport { Path } from './Path';\nimport { PackletAnalyzer } from './PackletAnalyzer';\n\nenum RefFileKind {\n Import,\n ReferenceFile,\n TypeReferenceDirective\n}\n\n// TypeScript compiler internal:\n// Version range: >= 3.6.0, <= 4.2.0\n// https://github.com/microsoft/TypeScript/blob/5ecdcef4cecfcdc86bd681b377636422447507d7/src/compiler/program.ts#L541\ninterface IRefFile {\n // The absolute path of the module that was imported.\n // (Normalized to an all lowercase ts.Path string.)\n referencedFileName: string;\n // The kind of reference.\n kind: RefFileKind;\n // An index indicating the order in which items occur in a compound expression\n index: number;\n\n // The absolute path of the source file containing the import statement.\n // (Normalized to an all lowercase ts.Path string.)\n file: string;\n}\n\n// TypeScript compiler internal:\n// Version range: > 4.2.0\n// https://github.com/microsoft/TypeScript/blob/2eca17d7c1a3fb2b077f3a910d5019d74b6f07a0/src/compiler/types.ts#L3693\nenum FileIncludeKind {\n RootFile,\n SourceFromProjectReference,\n OutputFromProjectReference,\n Import,\n ReferenceFile,\n TypeReferenceDirective,\n LibFile,\n LibReferenceDirective,\n AutomaticTypeDirectiveFile\n}\n\n// TypeScript compiler internal:\n// Version range: > 4.2.0\n// https://github.com/microsoft/TypeScript/blob/2eca17d7c1a3fb2b077f3a910d5019d74b6f07a0/src/compiler/types.ts#L3748\ninterface IFileIncludeReason {\n kind: FileIncludeKind;\n file: string | undefined;\n}\n\ninterface ITsProgramInternals extends ts.Program {\n // TypeScript compiler internal:\n // Version range: >= 3.6.0, <= 4.2.0\n // https://github.com/microsoft/TypeScript/blob/5ecdcef4cecfcdc86bd681b377636422447507d7/src/compiler/types.ts#L3723\n getRefFileMap?: () => Map<string, IRefFile[]> | undefined;\n\n // TypeScript compiler internal:\n // Version range: > 4.2.0\n // https://github.com/microsoft/TypeScript/blob/2eca17d7c1a3fb2b077f3a910d5019d74b6f07a0/src/compiler/types.ts#L3871\n getFileIncludeReasons?: () => Map<string, IFileIncludeReason[]>;\n}\n\n/**\n * Represents a packlet that imports another packlet.\n */\nexport interface IPackletImport {\n /**\n * The name of the packlet being imported.\n */\n packletName: string;\n\n /**\n * The absolute path of the file that imports the packlet.\n */\n fromFilePath: string;\n}\n\n/**\n * Used to build a linked list of imports that represent a circular dependency.\n */\ninterface IImportListNode extends IPackletImport {\n /**\n * The previous link in the linked list.\n */\n previousNode: IImportListNode | undefined;\n}\n\nexport class DependencyAnalyzer {\n /**\n * @param packletName - the packlet to be checked next in our traversal\n * @param startingPackletName - the packlet that we started with; if the traversal reaches this packlet,\n * then a circular dependency has been detected\n * @param refFileMap - the compiler's `refFileMap` data structure describing import relationships\n * @param fileIncludeReasonsMap - the compiler's data structure describing import relationships\n * @param program - the compiler's `ts.Program` object\n * @param packletsFolderPath - the absolute path of the \"src/packlets\" folder.\n * @param visitedPacklets - the set of packlets that have already been visited in this traversal\n * @param previousNode - a linked list of import statements that brought us to this step in the traversal\n */\n private static _walkImports(\n packletName: string,\n startingPackletName: string,\n refFileMap: Map<string, IRefFile[]> | undefined,\n fileIncludeReasonsMap: Map<string, IFileIncludeReason[]> | undefined,\n program: ts.Program,\n packletsFolderPath: string,\n visitedPacklets: Set<string>,\n previousNode: IImportListNode | undefined\n ): IImportListNode | undefined {\n visitedPacklets.add(packletName);\n\n const packletEntryPoint: string = Path.join(packletsFolderPath, packletName, 'index');\n\n const tsSourceFile: ts.SourceFile | undefined =\n program.getSourceFile(packletEntryPoint + '.ts') || program.getSourceFile(packletEntryPoint + '.tsx');\n if (!tsSourceFile) {\n return undefined;\n }\n\n const referencingFilePaths: string[] = [];\n\n if (refFileMap) {\n // TypeScript version range: >= 3.6.0, <= 4.2.0\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const refFiles: IRefFile[] | undefined = refFileMap.get((tsSourceFile as any).path);\n if (refFiles) {\n for (const refFile of refFiles) {\n if (refFile.kind === RefFileKind.Import) {\n referencingFilePaths.push(refFile.file);\n }\n }\n }\n } else if (fileIncludeReasonsMap) {\n // Typescript version range: > 4.2.0\n const fileIncludeReasons: IFileIncludeReason[] | undefined = fileIncludeReasonsMap.get(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (tsSourceFile as any).path\n );\n if (fileIncludeReasons) {\n for (const fileIncludeReason of fileIncludeReasons) {\n if (fileIncludeReason.kind === FileIncludeKind.Import) {\n if (fileIncludeReason.file) {\n referencingFilePaths.push(fileIncludeReason.file);\n }\n }\n }\n }\n }\n\n for (const referencingFilePath of referencingFilePaths) {\n // Is it a reference to a packlet?\n if (Path.isUnder(referencingFilePath, packletsFolderPath)) {\n const referencingRelativePath: string = Path.relative(packletsFolderPath, referencingFilePath);\n const referencingPathParts: string[] = referencingRelativePath.split(/[\\/\\\\]+/);\n const referencingPackletName: string = referencingPathParts[0];\n\n // Did we return to where we started from?\n if (referencingPackletName === startingPackletName) {\n // Ignore the degenerate case where the starting node imports itself,\n // since @rushstack/packlets/mechanics will already report that.\n if (previousNode) {\n // Make a new linked list node to record this step of the traversal\n const importListNode: IImportListNode = {\n previousNode: previousNode,\n fromFilePath: referencingFilePath,\n packletName: packletName\n };\n\n // The traversal has returned to the packlet that we started from;\n // this means we have detected a circular dependency\n return importListNode;\n }\n }\n\n // Have we already analyzed this packlet?\n if (!visitedPacklets.has(referencingPackletName)) {\n // Make a new linked list node to record this step of the traversal\n const importListNode: IImportListNode = {\n previousNode: previousNode,\n fromFilePath: referencingFilePath,\n packletName: packletName\n };\n\n const result: IImportListNode | undefined = DependencyAnalyzer._walkImports(\n referencingPackletName,\n startingPackletName,\n refFileMap,\n fileIncludeReasonsMap,\n program,\n packletsFolderPath,\n visitedPacklets,\n importListNode\n );\n if (result) {\n return result;\n }\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * For the specified packlet, trace all modules that import it, looking for a circular dependency\n * between packlets. If found, an array is returned describing the import statements that cause\n * the problem.\n *\n * @remarks\n * For example, suppose we have files like this:\n *\n * ```\n * src/packlets/logging/index.ts\n * src/packlets/logging/Logger.ts --> imports \"../data-model\"\n * src/packlets/data-model/index.ts\n * src/packlets/data-model/DataModel.ts --> imports \"../logging\"\n * ```\n *\n * The returned array would be:\n * ```ts\n * [\n * { packletName: \"logging\", fromFilePath: \"/path/to/src/packlets/data-model/DataModel.ts\" },\n * { packletName: \"data-model\", fromFilePath: \"/path/to/src/packlets/logging/Logger.ts\" },\n * ]\n * ```\n *\n * If there is more than one circular dependency chain, only the first one that is encountered\n * will be returned.\n */\n public static checkEntryPointForCircularImport(\n packletName: string,\n packletAnalyzer: PackletAnalyzer,\n program: ts.Program\n ): IPackletImport[] | undefined {\n const programInternals: ITsProgramInternals = program;\n\n let refFileMap: Map<string, IRefFile[]> | undefined;\n let fileIncludeReasonsMap: Map<string, IFileIncludeReason[]> | undefined;\n\n if (programInternals.getRefFileMap) {\n // TypeScript version range: >= 3.6.0, <= 4.2.0\n refFileMap = programInternals.getRefFileMap();\n } else if (programInternals.getFileIncludeReasons) {\n // Typescript version range: > 4.2.0\n fileIncludeReasonsMap = programInternals.getFileIncludeReasons();\n } else {\n // If you encounter this error, please report a bug\n throw new Error(\n 'Your TypeScript compiler version is not supported; please upgrade @rushstack/eslint-plugin-packlets' +\n ' or report a GitHub issue'\n );\n }\n\n const visitedPacklets: Set<string> = new Set();\n\n const listNode: IImportListNode | undefined = DependencyAnalyzer._walkImports(\n packletName,\n packletName,\n refFileMap,\n fileIncludeReasonsMap,\n program,\n packletAnalyzer.packletsFolderPath!,\n visitedPacklets,\n undefined // previousNode\n );\n\n if (listNode) {\n // Convert the linked list to an array\n const packletImports: IPackletImport[] = [];\n for (let current: IImportListNode | undefined = listNode; current; current = current.previousNode) {\n packletImports.push({ fromFilePath: current.fromFilePath, packletName: current.packletName });\n }\n return packletImports;\n }\n\n return undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DependencyAnalyzer.js","sourceRoot":"","sources":["../src/DependencyAnalyzer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type * as ts from 'typescript';\n\nimport { Path } from './Path';\nimport type { PackletAnalyzer } from './PackletAnalyzer';\n\nenum RefFileKind {\n Import,\n ReferenceFile,\n TypeReferenceDirective\n}\n\n// TypeScript compiler internal:\n// Version range: >= 3.6.0, <= 4.2.0\n// https://github.com/microsoft/TypeScript/blob/5ecdcef4cecfcdc86bd681b377636422447507d7/src/compiler/program.ts#L541\ninterface IRefFile {\n // The absolute path of the module that was imported.\n // (Normalized to an all lowercase ts.Path string.)\n referencedFileName: string;\n // The kind of reference.\n kind: RefFileKind;\n // An index indicating the order in which items occur in a compound expression\n index: number;\n\n // The absolute path of the source file containing the import statement.\n // (Normalized to an all lowercase ts.Path string.)\n file: string;\n}\n\n// TypeScript compiler internal:\n// Version range: > 4.2.0\n// https://github.com/microsoft/TypeScript/blob/2eca17d7c1a3fb2b077f3a910d5019d74b6f07a0/src/compiler/types.ts#L3693\nenum FileIncludeKind {\n RootFile,\n SourceFromProjectReference,\n OutputFromProjectReference,\n Import,\n ReferenceFile,\n TypeReferenceDirective,\n LibFile,\n LibReferenceDirective,\n AutomaticTypeDirectiveFile\n}\n\n// TypeScript compiler internal:\n// Version range: > 4.2.0\n// https://github.com/microsoft/TypeScript/blob/2eca17d7c1a3fb2b077f3a910d5019d74b6f07a0/src/compiler/types.ts#L3748\ninterface IFileIncludeReason {\n kind: FileIncludeKind;\n file: string | undefined;\n}\n\ninterface ITsProgramInternals extends ts.Program {\n // TypeScript compiler internal:\n // Version range: >= 3.6.0, <= 4.2.0\n // https://github.com/microsoft/TypeScript/blob/5ecdcef4cecfcdc86bd681b377636422447507d7/src/compiler/types.ts#L3723\n getRefFileMap?: () => Map<string, IRefFile[]> | undefined;\n\n // TypeScript compiler internal:\n // Version range: > 4.2.0\n // https://github.com/microsoft/TypeScript/blob/2eca17d7c1a3fb2b077f3a910d5019d74b6f07a0/src/compiler/types.ts#L3871\n getFileIncludeReasons?: () => Map<string, IFileIncludeReason[]>;\n}\n\n/**\n * Represents a packlet that imports another packlet.\n */\nexport interface IPackletImport {\n /**\n * The name of the packlet being imported.\n */\n packletName: string;\n\n /**\n * The absolute path of the file that imports the packlet.\n */\n fromFilePath: string;\n}\n\n/**\n * Used to build a linked list of imports that represent a circular dependency.\n */\ninterface IImportListNode extends IPackletImport {\n /**\n * The previous link in the linked list.\n */\n previousNode: IImportListNode | undefined;\n}\n\nexport class DependencyAnalyzer {\n /**\n * @param packletName - the packlet to be checked next in our traversal\n * @param startingPackletName - the packlet that we started with; if the traversal reaches this packlet,\n * then a circular dependency has been detected\n * @param refFileMap - the compiler's `refFileMap` data structure describing import relationships\n * @param fileIncludeReasonsMap - the compiler's data structure describing import relationships\n * @param program - the compiler's `ts.Program` object\n * @param packletsFolderPath - the absolute path of the \"src/packlets\" folder.\n * @param visitedPacklets - the set of packlets that have already been visited in this traversal\n * @param previousNode - a linked list of import statements that brought us to this step in the traversal\n */\n private static _walkImports(\n packletName: string,\n startingPackletName: string,\n refFileMap: Map<string, IRefFile[]> | undefined,\n fileIncludeReasonsMap: Map<string, IFileIncludeReason[]> | undefined,\n program: ts.Program,\n packletsFolderPath: string,\n visitedPacklets: Set<string>,\n previousNode: IImportListNode | undefined\n ): IImportListNode | undefined {\n visitedPacklets.add(packletName);\n\n const packletEntryPoint: string = Path.join(packletsFolderPath, packletName, 'index');\n\n const tsSourceFile: ts.SourceFile | undefined =\n program.getSourceFile(packletEntryPoint + '.ts') || program.getSourceFile(packletEntryPoint + '.tsx');\n if (!tsSourceFile) {\n return undefined;\n }\n\n const referencingFilePaths: string[] = [];\n\n if (refFileMap) {\n // TypeScript version range: >= 3.6.0, <= 4.2.0\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const refFiles: IRefFile[] | undefined = refFileMap.get((tsSourceFile as any).path);\n if (refFiles) {\n for (const refFile of refFiles) {\n if (refFile.kind === RefFileKind.Import) {\n referencingFilePaths.push(refFile.file);\n }\n }\n }\n } else if (fileIncludeReasonsMap) {\n // Typescript version range: > 4.2.0\n const fileIncludeReasons: IFileIncludeReason[] | undefined = fileIncludeReasonsMap.get(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (tsSourceFile as any).path\n );\n if (fileIncludeReasons) {\n for (const fileIncludeReason of fileIncludeReasons) {\n if (fileIncludeReason.kind === FileIncludeKind.Import) {\n if (fileIncludeReason.file) {\n referencingFilePaths.push(fileIncludeReason.file);\n }\n }\n }\n }\n }\n\n for (const referencingFilePath of referencingFilePaths) {\n // Is it a reference to a packlet?\n if (Path.isUnder(referencingFilePath, packletsFolderPath)) {\n const referencingRelativePath: string = Path.relative(packletsFolderPath, referencingFilePath);\n const referencingPathParts: string[] = referencingRelativePath.split(/[\\/\\\\]+/);\n const referencingPackletName: string = referencingPathParts[0];\n\n // Did we return to where we started from?\n if (referencingPackletName === startingPackletName) {\n // Ignore the degenerate case where the starting node imports itself,\n // since @rushstack/packlets/mechanics will already report that.\n if (previousNode) {\n // Make a new linked list node to record this step of the traversal\n const importListNode: IImportListNode = {\n previousNode: previousNode,\n fromFilePath: referencingFilePath,\n packletName: packletName\n };\n\n // The traversal has returned to the packlet that we started from;\n // this means we have detected a circular dependency\n return importListNode;\n }\n }\n\n // Have we already analyzed this packlet?\n if (!visitedPacklets.has(referencingPackletName)) {\n // Make a new linked list node to record this step of the traversal\n const importListNode: IImportListNode = {\n previousNode: previousNode,\n fromFilePath: referencingFilePath,\n packletName: packletName\n };\n\n const result: IImportListNode | undefined = DependencyAnalyzer._walkImports(\n referencingPackletName,\n startingPackletName,\n refFileMap,\n fileIncludeReasonsMap,\n program,\n packletsFolderPath,\n visitedPacklets,\n importListNode\n );\n if (result) {\n return result;\n }\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * For the specified packlet, trace all modules that import it, looking for a circular dependency\n * between packlets. If found, an array is returned describing the import statements that cause\n * the problem.\n *\n * @remarks\n * For example, suppose we have files like this:\n *\n * ```\n * src/packlets/logging/index.ts\n * src/packlets/logging/Logger.ts --> imports \"../data-model\"\n * src/packlets/data-model/index.ts\n * src/packlets/data-model/DataModel.ts --> imports \"../logging\"\n * ```\n *\n * The returned array would be:\n * ```ts\n * [\n * { packletName: \"logging\", fromFilePath: \"/path/to/src/packlets/data-model/DataModel.ts\" },\n * { packletName: \"data-model\", fromFilePath: \"/path/to/src/packlets/logging/Logger.ts\" },\n * ]\n * ```\n *\n * If there is more than one circular dependency chain, only the first one that is encountered\n * will be returned.\n */\n public static checkEntryPointForCircularImport(\n packletName: string,\n packletAnalyzer: PackletAnalyzer,\n program: ts.Program\n ): IPackletImport[] | undefined {\n const programInternals: ITsProgramInternals = program;\n\n let refFileMap: Map<string, IRefFile[]> | undefined;\n let fileIncludeReasonsMap: Map<string, IFileIncludeReason[]> | undefined;\n\n if (programInternals.getRefFileMap) {\n // TypeScript version range: >= 3.6.0, <= 4.2.0\n refFileMap = programInternals.getRefFileMap();\n } else if (programInternals.getFileIncludeReasons) {\n // Typescript version range: > 4.2.0\n fileIncludeReasonsMap = programInternals.getFileIncludeReasons();\n } else {\n // If you encounter this error, please report a bug\n throw new Error(\n 'Your TypeScript compiler version is not supported; please upgrade @rushstack/eslint-plugin-packlets' +\n ' or report a GitHub issue'\n );\n }\n\n const visitedPacklets: Set<string> = new Set();\n\n const listNode: IImportListNode | undefined = DependencyAnalyzer._walkImports(\n packletName,\n packletName,\n refFileMap,\n fileIncludeReasonsMap,\n program,\n packletAnalyzer.packletsFolderPath!,\n visitedPacklets,\n undefined // previousNode\n );\n\n if (listNode) {\n // Convert the linked list to an array\n const packletImports: IPackletImport[] = [];\n for (let current: IImportListNode | undefined = listNode; current; current = current.previousNode) {\n packletImports.push({ fromFilePath: current.fromFilePath, packletName: current.packletName });\n }\n return packletImports;\n }\n\n return undefined;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PackletAnalyzer.d.ts","sourceRoot":"","sources":["../src/PackletAnalyzer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PackletAnalyzer.d.ts","sourceRoot":"","sources":["../src/PackletAnalyzer.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,mBAAmB,GAC3B,wBAAwB,GACxB,sBAAsB,GACtB,2BAA2B,GAC3B,oBAAoB,GACpB,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B,MAAM,MAAM,gBAAgB,GACxB,sBAAsB,GACtB,sBAAsB,GACtB,gCAAgC,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,mBAAmB,GAAG,gBAAgB,CAAC;IAClD,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC1C;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAsC;IAEtE;;;;OAIG;IACH,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC;;OAEG;IACH,SAAgB,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;IAElD;;;;OAIG;IACH,SAAgB,WAAW,EAAE,OAAO,CAAC;IAErC;;OAEG;IACH,SAAgB,mBAAmB,EAAE,OAAO,CAAC;IAE7C;;OAEG;IACH,SAAgB,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvD;;OAEG;IACH,SAAgB,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzD;;OAEG;IACH,SAAgB,YAAY,EAAE,OAAO,CAAC;IAEtC,OAAO;WAmGO,gBAAgB,CAC5B,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,eAAe;IAIX,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;CAmFrE"}
|
package/lib/PackletAnalyzer.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
})();
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.PackletAnalyzer = void 0;
|
|
39
|
-
const fs = __importStar(require("fs"));
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
40
|
const Path_1 = require("./Path");
|
|
41
41
|
class PackletAnalyzer {
|
|
42
42
|
constructor(inputFilePath, tsconfigFilePath) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PackletAnalyzer.js","sourceRoot":"","sources":["../src/PackletAnalyzer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as fs from 'fs';\nimport { Path } from './Path';\n\nexport type InputFileMessageIds =\n | 'file-in-packets-folder'\n | 'invalid-packlet-name'\n | 'misplaced-packlets-folder'\n | 'missing-src-folder'\n | 'missing-tsconfig'\n | 'packlet-folder-case';\n\nexport type ImportMessageIds =\n | 'bypassed-entry-point'\n | 'circular-entry-point'\n | 'packlet-importing-project-file';\n\nexport interface IAnalyzerError {\n messageId: InputFileMessageIds | ImportMessageIds;\n data?: Readonly<Record<string, unknown>>;\n}\n\nexport class PackletAnalyzer {\n private static _validPackletName: RegExp = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n\n /**\n * The input file being linted.\n *\n * Example: \"/path/to/my-project/src/file.ts\"\n */\n public readonly inputFilePath: string;\n\n /**\n * An error that occurred while analyzing the inputFilePath.\n */\n public readonly error: IAnalyzerError | undefined;\n\n /**\n * Returned to indicate that the linter can ignore this file. Possible reasons:\n * - It's outside the \"src\" folder\n * - The project doesn't define any packlets\n */\n public readonly nothingToDo: boolean;\n\n /**\n * If true, then the \"src/packlets\" folder exists.\n */\n public readonly projectUsesPacklets: boolean;\n\n /**\n * The absolute path of the \"src/packlets\" folder.\n */\n public readonly packletsFolderPath: string | undefined;\n\n /**\n * The packlet that the inputFilePath is under, if any.\n */\n public readonly inputFilePackletName: string | undefined;\n\n /**\n * Returns true if inputFilePath belongs to a packlet and is the entry point index.ts.\n */\n public readonly isEntryPoint: boolean;\n\n private constructor(inputFilePath: string, tsconfigFilePath: string | undefined) {\n this.inputFilePath = inputFilePath;\n this.error = undefined;\n this.nothingToDo = false;\n this.projectUsesPacklets = false;\n this.packletsFolderPath = undefined;\n this.inputFilePackletName = undefined;\n this.isEntryPoint = false;\n\n // Example: /path/to/my-project/src\n\n if (!tsconfigFilePath) {\n this.error = { messageId: 'missing-tsconfig' };\n return;\n }\n\n const srcFolderPath: string = Path.join(Path.dirname(tsconfigFilePath), 'src');\n\n if (!fs.existsSync(srcFolderPath)) {\n this.error = { messageId: 'missing-src-folder', data: { srcFolderPath } };\n return;\n }\n\n if (!Path.isUnder(inputFilePath, srcFolderPath)) {\n // Ignore files outside the \"src\" folder\n this.nothingToDo = true;\n return;\n }\n\n // Example: packlets/my-packlet/index.ts\n const inputFilePathRelativeToSrc: string = Path.relative(srcFolderPath, inputFilePath);\n\n // Example: [ 'packlets', 'my-packlet', 'index.ts' ]\n const pathParts: string[] = inputFilePathRelativeToSrc.split(/[\\/\\\\]+/);\n\n let underPackletsFolder: boolean = false;\n\n const expectedPackletsFolder: string = Path.join(srcFolderPath, 'packlets');\n\n for (let i: number = 0; i < pathParts.length; ++i) {\n const pathPart: string = pathParts[i];\n if (pathPart.toUpperCase() === 'PACKLETS') {\n if (pathPart !== 'packlets') {\n // Example: /path/to/my-project/src/PACKLETS\n const packletsFolderPath: string = Path.join(srcFolderPath, ...pathParts.slice(0, i + 1));\n this.error = { messageId: 'packlet-folder-case', data: { packletsFolderPath } };\n return;\n }\n\n if (i !== 0) {\n this.error = { messageId: 'misplaced-packlets-folder', data: { expectedPackletsFolder } };\n return;\n }\n\n underPackletsFolder = true;\n }\n }\n\n if (underPackletsFolder || fs.existsSync(expectedPackletsFolder)) {\n // packletsAbsolutePath\n this.projectUsesPacklets = true;\n this.packletsFolderPath = expectedPackletsFolder;\n }\n\n if (underPackletsFolder) {\n if (pathParts.length === 2) {\n // Example: src/packlets/SomeFile.ts\n this.error = { messageId: 'file-in-packets-folder' };\n return;\n }\n if (pathParts.length >= 2) {\n // Example: 'my-packlet'\n const packletName: string = pathParts[1];\n this.inputFilePackletName = packletName;\n\n if (pathParts.length === 3) {\n // Example: 'index.ts' or 'index.tsx'\n const thirdPart: string = pathParts[2];\n\n // Example: 'index'\n const thirdPartWithoutExtension: string = Path.parse(thirdPart).name;\n\n if (thirdPartWithoutExtension.toUpperCase() === 'INDEX') {\n if (!PackletAnalyzer._validPackletName.test(packletName)) {\n this.error = { messageId: 'invalid-packlet-name', data: { packletName } };\n return;\n }\n\n this.isEntryPoint = true;\n }\n }\n }\n }\n\n if (this.error === undefined && !this.projectUsesPacklets) {\n this.nothingToDo = true;\n }\n }\n\n public static analyzeInputFile(\n inputFilePath: string,\n tsconfigFilePath: string | undefined\n ): PackletAnalyzer {\n return new PackletAnalyzer(inputFilePath, tsconfigFilePath);\n }\n\n public analyzeImport(modulePath: string): IAnalyzerError | undefined {\n if (!this.packletsFolderPath) {\n // The caller should ensure this can never happen\n throw new Error('Internal error: packletsFolderPath is not defined');\n }\n\n // Example: /path/to/my-project/src/packlets/my-packlet\n const inputFileFolder: string = Path.dirname(this.inputFilePath);\n\n // Example: /path/to/my-project/src/other-packlet/index\n const importedPath: string = Path.resolve(inputFileFolder, modulePath);\n\n // Is the imported path referring to a file under the src/packlets folder?\n if (Path.isUnder(importedPath, this.packletsFolderPath)) {\n // Example: other-packlet/index\n const importedPathRelativeToPackletsFolder: string = Path.relative(\n this.packletsFolderPath,\n importedPath\n );\n // Example: [ 'other-packlet', 'index' ]\n const importedPathParts: string[] = importedPathRelativeToPackletsFolder.split(/[\\/\\\\]+/);\n if (importedPathParts.length > 0) {\n // Example: 'other-packlet'\n const importedPackletName: string = importedPathParts[0];\n\n // We are importing from a packlet. Is the input file part of the same packlet?\n if (this.inputFilePackletName && importedPackletName === this.inputFilePackletName) {\n // Yes. Then our import must NOT use the packlet entry point.\n\n // Example: 'index'\n //\n // We discard the file extension to handle a degenerate case like:\n // import { X } from \"../index.js\";\n const lastPart: string = Path.parse(importedPathParts[importedPathParts.length - 1]).name;\n let pathToCompare: string;\n if (lastPart.toUpperCase() === 'INDEX') {\n // Example:\n // importedPath = /path/to/my-project/src/other-packlet/index\n // pathToCompare = /path/to/my-project/src/other-packlet\n pathToCompare = Path.dirname(importedPath);\n } else {\n pathToCompare = importedPath;\n }\n\n // Example: /path/to/my-project/src/other-packlet\n const entryPointPath: string = Path.join(this.packletsFolderPath, importedPackletName);\n\n if (Path.isEqual(pathToCompare, entryPointPath)) {\n return {\n messageId: 'circular-entry-point'\n };\n }\n } else {\n // No. If we are not part of the same packlet, then the module path must refer\n // to the index.ts entry point.\n\n // Example: /path/to/my-project/src/other-packlet\n const entryPointPath: string = Path.join(this.packletsFolderPath, importedPackletName);\n\n if (!Path.isEqual(importedPath, entryPointPath)) {\n // Example: \"../packlets/other-packlet\"\n const entryPointModulePath: string = Path.convertToSlashes(\n Path.relative(inputFileFolder, entryPointPath)\n );\n\n return {\n messageId: 'bypassed-entry-point',\n data: { entryPointModulePath }\n };\n }\n }\n }\n } else {\n // The imported path does NOT refer to a file under the src/packlets folder\n if (this.inputFilePackletName) {\n return {\n messageId: 'packlet-importing-project-file'\n };\n }\n }\n\n return undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PackletAnalyzer.js","sourceRoot":"","sources":["../src/PackletAnalyzer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as fs from 'node:fs';\n\nimport { Path } from './Path';\n\nexport type InputFileMessageIds =\n | 'file-in-packets-folder'\n | 'invalid-packlet-name'\n | 'misplaced-packlets-folder'\n | 'missing-src-folder'\n | 'missing-tsconfig'\n | 'packlet-folder-case';\n\nexport type ImportMessageIds =\n | 'bypassed-entry-point'\n | 'circular-entry-point'\n | 'packlet-importing-project-file';\n\nexport interface IAnalyzerError {\n messageId: InputFileMessageIds | ImportMessageIds;\n data?: Readonly<Record<string, unknown>>;\n}\n\nexport class PackletAnalyzer {\n private static _validPackletName: RegExp = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n\n /**\n * The input file being linted.\n *\n * Example: \"/path/to/my-project/src/file.ts\"\n */\n public readonly inputFilePath: string;\n\n /**\n * An error that occurred while analyzing the inputFilePath.\n */\n public readonly error: IAnalyzerError | undefined;\n\n /**\n * Returned to indicate that the linter can ignore this file. Possible reasons:\n * - It's outside the \"src\" folder\n * - The project doesn't define any packlets\n */\n public readonly nothingToDo: boolean;\n\n /**\n * If true, then the \"src/packlets\" folder exists.\n */\n public readonly projectUsesPacklets: boolean;\n\n /**\n * The absolute path of the \"src/packlets\" folder.\n */\n public readonly packletsFolderPath: string | undefined;\n\n /**\n * The packlet that the inputFilePath is under, if any.\n */\n public readonly inputFilePackletName: string | undefined;\n\n /**\n * Returns true if inputFilePath belongs to a packlet and is the entry point index.ts.\n */\n public readonly isEntryPoint: boolean;\n\n private constructor(inputFilePath: string, tsconfigFilePath: string | undefined) {\n this.inputFilePath = inputFilePath;\n this.error = undefined;\n this.nothingToDo = false;\n this.projectUsesPacklets = false;\n this.packletsFolderPath = undefined;\n this.inputFilePackletName = undefined;\n this.isEntryPoint = false;\n\n // Example: /path/to/my-project/src\n\n if (!tsconfigFilePath) {\n this.error = { messageId: 'missing-tsconfig' };\n return;\n }\n\n const srcFolderPath: string = Path.join(Path.dirname(tsconfigFilePath), 'src');\n\n if (!fs.existsSync(srcFolderPath)) {\n this.error = { messageId: 'missing-src-folder', data: { srcFolderPath } };\n return;\n }\n\n if (!Path.isUnder(inputFilePath, srcFolderPath)) {\n // Ignore files outside the \"src\" folder\n this.nothingToDo = true;\n return;\n }\n\n // Example: packlets/my-packlet/index.ts\n const inputFilePathRelativeToSrc: string = Path.relative(srcFolderPath, inputFilePath);\n\n // Example: [ 'packlets', 'my-packlet', 'index.ts' ]\n const pathParts: string[] = inputFilePathRelativeToSrc.split(/[\\/\\\\]+/);\n\n let underPackletsFolder: boolean = false;\n\n const expectedPackletsFolder: string = Path.join(srcFolderPath, 'packlets');\n\n for (let i: number = 0; i < pathParts.length; ++i) {\n const pathPart: string = pathParts[i];\n if (pathPart.toUpperCase() === 'PACKLETS') {\n if (pathPart !== 'packlets') {\n // Example: /path/to/my-project/src/PACKLETS\n const packletsFolderPath: string = Path.join(srcFolderPath, ...pathParts.slice(0, i + 1));\n this.error = { messageId: 'packlet-folder-case', data: { packletsFolderPath } };\n return;\n }\n\n if (i !== 0) {\n this.error = { messageId: 'misplaced-packlets-folder', data: { expectedPackletsFolder } };\n return;\n }\n\n underPackletsFolder = true;\n }\n }\n\n if (underPackletsFolder || fs.existsSync(expectedPackletsFolder)) {\n // packletsAbsolutePath\n this.projectUsesPacklets = true;\n this.packletsFolderPath = expectedPackletsFolder;\n }\n\n if (underPackletsFolder) {\n if (pathParts.length === 2) {\n // Example: src/packlets/SomeFile.ts\n this.error = { messageId: 'file-in-packets-folder' };\n return;\n }\n if (pathParts.length >= 2) {\n // Example: 'my-packlet'\n const packletName: string = pathParts[1];\n this.inputFilePackletName = packletName;\n\n if (pathParts.length === 3) {\n // Example: 'index.ts' or 'index.tsx'\n const thirdPart: string = pathParts[2];\n\n // Example: 'index'\n const thirdPartWithoutExtension: string = Path.parse(thirdPart).name;\n\n if (thirdPartWithoutExtension.toUpperCase() === 'INDEX') {\n if (!PackletAnalyzer._validPackletName.test(packletName)) {\n this.error = { messageId: 'invalid-packlet-name', data: { packletName } };\n return;\n }\n\n this.isEntryPoint = true;\n }\n }\n }\n }\n\n if (this.error === undefined && !this.projectUsesPacklets) {\n this.nothingToDo = true;\n }\n }\n\n public static analyzeInputFile(\n inputFilePath: string,\n tsconfigFilePath: string | undefined\n ): PackletAnalyzer {\n return new PackletAnalyzer(inputFilePath, tsconfigFilePath);\n }\n\n public analyzeImport(modulePath: string): IAnalyzerError | undefined {\n if (!this.packletsFolderPath) {\n // The caller should ensure this can never happen\n throw new Error('Internal error: packletsFolderPath is not defined');\n }\n\n // Example: /path/to/my-project/src/packlets/my-packlet\n const inputFileFolder: string = Path.dirname(this.inputFilePath);\n\n // Example: /path/to/my-project/src/other-packlet/index\n const importedPath: string = Path.resolve(inputFileFolder, modulePath);\n\n // Is the imported path referring to a file under the src/packlets folder?\n if (Path.isUnder(importedPath, this.packletsFolderPath)) {\n // Example: other-packlet/index\n const importedPathRelativeToPackletsFolder: string = Path.relative(\n this.packletsFolderPath,\n importedPath\n );\n // Example: [ 'other-packlet', 'index' ]\n const importedPathParts: string[] = importedPathRelativeToPackletsFolder.split(/[\\/\\\\]+/);\n if (importedPathParts.length > 0) {\n // Example: 'other-packlet'\n const importedPackletName: string = importedPathParts[0];\n\n // We are importing from a packlet. Is the input file part of the same packlet?\n if (this.inputFilePackletName && importedPackletName === this.inputFilePackletName) {\n // Yes. Then our import must NOT use the packlet entry point.\n\n // Example: 'index'\n //\n // We discard the file extension to handle a degenerate case like:\n // import { X } from \"../index.js\";\n const lastPart: string = Path.parse(importedPathParts[importedPathParts.length - 1]).name;\n let pathToCompare: string;\n if (lastPart.toUpperCase() === 'INDEX') {\n // Example:\n // importedPath = /path/to/my-project/src/other-packlet/index\n // pathToCompare = /path/to/my-project/src/other-packlet\n pathToCompare = Path.dirname(importedPath);\n } else {\n pathToCompare = importedPath;\n }\n\n // Example: /path/to/my-project/src/other-packlet\n const entryPointPath: string = Path.join(this.packletsFolderPath, importedPackletName);\n\n if (Path.isEqual(pathToCompare, entryPointPath)) {\n return {\n messageId: 'circular-entry-point'\n };\n }\n } else {\n // No. If we are not part of the same packlet, then the module path must refer\n // to the index.ts entry point.\n\n // Example: /path/to/my-project/src/other-packlet\n const entryPointPath: string = Path.join(this.packletsFolderPath, importedPackletName);\n\n if (!Path.isEqual(importedPath, entryPointPath)) {\n // Example: \"../packlets/other-packlet\"\n const entryPointModulePath: string = Path.convertToSlashes(\n Path.relative(inputFileFolder, entryPointPath)\n );\n\n return {\n messageId: 'bypassed-entry-point',\n data: { entryPointModulePath }\n };\n }\n }\n }\n } else {\n // The imported path does NOT refer to a file under the src/packlets folder\n if (this.inputFilePackletName) {\n return {\n messageId: 'packlet-importing-project-file'\n };\n }\n }\n\n return undefined;\n }\n}\n"]}
|
package/lib/Path.d.ts
CHANGED
package/lib/Path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Path.d.ts","sourceRoot":"","sources":["../src/Path.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"Path.d.ts","sourceRoot":"","sources":["../src/Path.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;AAIzC,qBAAa,IAAI;IACf;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAc,kBAAkB,EAAE,OAAO,CAA+B;IAExE,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAMnC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAQnC,OAAO,CAAC,MAAM,CAAC,wBAAwB;WAqDzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;WAU1C,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;WAI1B,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM;WAIhC,OAAO,CAAC,GAAG,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM;WAI1C,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU;IAOnD;;;;;;;;;OASG;WACW,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO;IAK3E;;;;;;OAMG;WACW,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAI5D;;;;;OAKG;WACW,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAG1D"}
|
package/lib/Path.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
})();
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.Path = void 0;
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
41
|
const RELATIVE_PATH_REGEXP = /^[.\/\\]+$/;
|
|
42
42
|
class Path {
|
|
43
43
|
static _detectCaseSensitive() {
|
package/lib/Path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Path.js","sourceRoot":"","sources":["../src/Path.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE3D,
|
|
1
|
+
{"version":3,"file":"Path.js","sourceRoot":"","sources":["../src/Path.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\n\nexport type ParsedPath = path.ParsedPath;\n\nconst RELATIVE_PATH_REGEXP: RegExp = /^[.\\/\\\\]+$/;\n\nexport class Path {\n /**\n * Whether the filesystem is assumed to be case sensitive for Path operations.\n *\n * @remarks\n * Regardless of operating system, a given file system's paths may be case-sensitive or case-insensitive.\n * If a volume is mounted under a subfolder, then different parts of a path can even have different\n * case-sensitivity. The Node.js \"path\" API naively assumes that all Windows paths are case-insensitive,\n * and that all other OS's are case-sensitive. This is way off, for example a modern MacBook has a\n * case-insensitive filesystem by default. There isn't an easy workaround because Node.js does not expose\n * the native OS APIs that would give accurate answers.\n *\n * The TypeScript compiler does somewhat better: it performs an empirical test of its own bundle path to see\n * whether it can be read using different case. If so, it normalizes all paths to lowercase (sometimes with\n * no API for retrieving the real path). This caused our Path.isUnder() to return incorrect answers because\n * it relies on Node.js path.relative().\n *\n * To solve that problem, Path.ts performs an empirical test similar to what the TypeScript compiler does,\n * and then we adjust path.relative() to be case insensitive if appropriate.\n *\n * @see {@link https://nodejs.org/en/docs/guides/working-with-different-filesystems/}\n */\n public static usingCaseSensitive: boolean = Path._detectCaseSensitive();\n\n private static _detectCaseSensitive(): boolean {\n // Can our own file be accessed using a path with different case? If so, then the filesystem is case-insensitive.\n return !fs.existsSync(__filename.toUpperCase());\n }\n\n // Removes redundant trailing slashes from a path.\n private static _trimTrailingSlashes(inputPath: string): string {\n // Examples:\n // \"/a/b///\\\\\" --> \"/a/b\"\n // \"/\" --> \"/\"\n return inputPath.replace(/(?<=[^\\/\\\\])[\\/\\\\]+$/, '');\n }\n\n // An implementation of path.relative() that is case-insensitive.\n private static _relativeCaseInsensitive(from: string, to: string): string {\n // path.relative() apples path.normalize() and also trims any trailing slashes.\n // Since we'll be matching toNormalized against result, we need to do that for our string as well.\n const normalizedTo: string = Path._trimTrailingSlashes(path.normalize(to));\n\n // We start by converting everything to uppercase and call path.relative()\n const uppercasedFrom: string = from.toUpperCase();\n const uppercasedTo: string = normalizedTo.toUpperCase();\n\n // The result will be all uppercase because its inputs were uppercased\n const uppercasedResult: string = path.relative(uppercasedFrom, uppercasedTo);\n\n // Are there any cased characters in the result?\n if (uppercasedResult.toLowerCase() === uppercasedResult) {\n // No cased characters\n // Example: \"../..\"\n return uppercasedResult;\n }\n\n // Example:\n // from=\"/a/b/c\"\n // to=\"/a/b/d/e\"\n //\n // fromNormalized=\"/A/B/C\"\n // toNormalized=\"/A/B/D/E\"\n //\n // result=\"../D/E\"\n //\n // Scan backwards comparing uppercasedResult versus uppercasedTo, stopping at the first place where they differ.\n let resultIndex: number = uppercasedResult.length;\n let toIndex: number = normalizedTo.length;\n for (;;) {\n if (resultIndex === 0 || toIndex === 0) {\n // Stop if we reach the start of the string\n break;\n }\n\n if (uppercasedResult.charCodeAt(resultIndex - 1) !== uppercasedTo.charCodeAt(toIndex - 1)) {\n // Stop before we reach a character that is different\n break;\n }\n\n --resultIndex;\n --toIndex;\n }\n\n // Replace the matching part with the properly cased substring from the \"normalizedTo\" input\n //\n // Example:\n // \"..\" + \"/d/e\" = \"../d/e\"\n return uppercasedResult.substring(0, resultIndex) + normalizedTo.substring(toIndex);\n }\n\n public static relative(from: string, to: string): string {\n if (!Path.usingCaseSensitive) {\n return Path._relativeCaseInsensitive(from, to);\n }\n return path.relative(from, to);\n }\n\n // --------------------------------------------------------------------------------------------------------\n // The operations below don't care about case sensitivity\n\n public static dirname(p: string): string {\n return path.dirname(p);\n }\n\n public static join(...paths: string[]): string {\n return path.join(...paths);\n }\n\n public static resolve(...pathSegments: string[]): string {\n return path.resolve(...pathSegments);\n }\n\n public static parse(pathString: string): ParsedPath {\n return path.parse(pathString);\n }\n\n // --------------------------------------------------------------------------------------------------------\n // The operations below are borrowed from @rushstack/node-core-library\n\n /**\n * Returns true if \"childPath\" is located inside the \"parentFolderPath\" folder\n * or one of its child folders. Note that \"parentFolderPath\" is not considered to be\n * under itself. The \"childPath\" can refer to any type of file system object.\n *\n * @remarks\n * The indicated file/folder objects are not required to actually exist on disk.\n * For example, \"parentFolderPath\" is interpreted as a folder name even if it refers to a file.\n * If the paths are relative, they will first be resolved using path.resolve().\n */\n public static isUnder(childPath: string, parentFolderPath: string): boolean {\n const relativePath: string = Path.relative(childPath, parentFolderPath);\n return RELATIVE_PATH_REGEXP.test(relativePath);\n }\n\n /**\n * Returns true if `path1` and `path2` refer to the same underlying path.\n *\n * @remarks\n *\n * The comparison is performed using `path.relative()`.\n */\n public static isEqual(path1: string, path2: string): boolean {\n return Path.relative(path1, path2) === '';\n }\n\n /**\n * Replaces Windows-style backslashes with POSIX-style slashes.\n *\n * @remarks\n * POSIX is a registered trademark of the Institute of Electrical and Electronic Engineers, Inc.\n */\n public static convertToSlashes(inputPath: string): string {\n return inputPath.split('\\\\').join('/');\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circular-deps.d.ts","sourceRoot":"","sources":["../src/circular-deps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"circular-deps.d.ts","sourceRoot":"","sources":["../src/circular-deps.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAOnE,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAC3C,KAAK,OAAO,GAAG,EAAE,CAAC;AAElB,QAAA,MAAM,YAAY,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAyE1D,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
package/lib/circular-deps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circular-deps.js","sourceRoot":"","sources":["../src/circular-deps.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;
|
|
1
|
+
{"version":3,"file":"circular-deps.js","sourceRoot":"","sources":["../src/circular-deps.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAI3D,oDAAuD;AAEvD,uDAAoD;AACpD,6DAA+E;AAC/E,iCAA8B;AAK9B,MAAM,YAAY,GAA6C;IAC7D,cAAc,EAAE,EAAE;IAClB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,EAAE,iBAAiB,EAAE,0DAA0D,EAAE;QAC3F,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,IAAI,EAAE;YACJ,WAAW,EAAE,kDAAkD;YAC/D,WAAW,EAAE,aAAa;YAC1B,GAAG,EAAE,iEAAiE;SAC1C;KAC/B;IAED,MAAM,EAAE,CAAC,OAAkD,EAAE,EAAE;QAC7D,gEAAgE;QAChE,MAAM,aAAa,GAAW,OAAO,CAAC,WAAW,EAAE,CAAC;QAEpD,6CAA6C;QAC7C,MAAM,OAAO,GAAe,mBAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QAC3E,MAAM,gBAAgB,GAAuB,OAAO,CAAC,kBAAkB,EAAE,CAAC,cAAwB,CAAC;QAEnG,MAAM,eAAe,GAAoB,iCAAe,CAAC,gBAAgB,CACvE,aAAa,EACb,gBAAgB,CACjB,CAAC;QACF,IAAI,eAAe,CAAC,WAAW,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL,mGAAmG;YACnG,yGAAyG;YACzG,gDAAgD;YAChD,OAAO,EAAE,CAAC,IAAmB,EAAQ,EAAE;gBACrC,IAAI,eAAe,CAAC,YAAY,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;oBAC3D,MAAM,cAAc,GAClB,uCAAkB,CAAC,gCAAgC,CACjD,eAAe,CAAC,oBAAqB,EACrC,eAAe,EACf,OAAO,CACR,CAAC;oBAEJ,IAAI,cAAc,EAAE,CAAC;wBACnB,MAAM,kBAAkB,GAAW,WAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;wBAElE,MAAM,oBAAoB,GAAa,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;wBAEhF,wGAAwG;wBACxG,4EAA4E;wBAC5E,oBAAoB,CAAC,IAAI,EAAE,CAAC;wBAC5B,IAAI,oBAAoB,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,oBAAoB,EAAE,CAAC;4BACrE,IAAI,MAAM,GAAW,EAAE,CAAC;4BACxB,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;gCAC3C,MAAM,QAAQ,GAAW,WAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;gCACvF,MAAM,IAAI,IAAI,aAAa,CAAC,WAAW,sBAAsB,QAAQ,IAAI,CAAC;4BAC5E,CAAC;4BAED,OAAO,CAAC,MAAM,CAAC;gCACb,IAAI,EAAE,IAAI;gCACV,SAAS,EAAE,iBAAiB;gCAC5B,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;6BACzB,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEO,oCAAY","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type * as ts from 'typescript';\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils';\nimport { ESLintUtils } from '@typescript-eslint/utils';\n\nimport { PackletAnalyzer } from './PackletAnalyzer';\nimport { DependencyAnalyzer, type IPackletImport } from './DependencyAnalyzer';\nimport { Path } from './Path';\n\nexport type MessageIds = 'circular-import';\ntype Options = [];\n\nconst circularDeps: TSESLint.RuleModule<MessageIds, Options> = {\n defaultOptions: [],\n meta: {\n type: 'problem',\n messages: { 'circular-import': 'Packlet imports create a circular reference:\\n{{report}}' },\n schema: [\n {\n type: 'object',\n additionalProperties: false\n }\n ],\n docs: {\n description: 'Check for circular dependencies between packlets',\n recommended: 'recommended',\n url: 'https://www.npmjs.com/package/@rushstack/eslint-plugin-packlets'\n } as TSESLint.RuleMetaDataDocs\n },\n\n create: (context: TSESLint.RuleContext<MessageIds, Options>) => {\n // Example: /path/to/my-project/src/packlets/my-packlet/index.ts\n const inputFilePath: string = context.getFilename();\n\n // Example: /path/to/my-project/tsconfig.json\n const program: ts.Program = ESLintUtils.getParserServices(context).program;\n const tsconfigFilePath: string | undefined = program.getCompilerOptions().configFilePath as string;\n\n const packletAnalyzer: PackletAnalyzer = PackletAnalyzer.analyzeInputFile(\n inputFilePath,\n tsconfigFilePath\n );\n if (packletAnalyzer.nothingToDo) {\n return {};\n }\n\n return {\n // Match the first node in the source file. Ideally we should be matching \"Program > :first-child\"\n // so a warning doesn't highlight the whole file. But that's blocked behind a bug in the query selector:\n // https://github.com/estools/esquery/issues/114\n Program: (node: TSESTree.Node): void => {\n if (packletAnalyzer.isEntryPoint && !packletAnalyzer.error) {\n const packletImports: IPackletImport[] | undefined =\n DependencyAnalyzer.checkEntryPointForCircularImport(\n packletAnalyzer.inputFilePackletName!,\n packletAnalyzer,\n program\n );\n\n if (packletImports) {\n const tsconfigFileFolder: string = Path.dirname(tsconfigFilePath);\n\n const affectedPackletNames: string[] = packletImports.map((x) => x.packletName);\n\n // If 3 different packlets form a circular dependency, we don't need to report the same warning 3 times.\n // Instead, only report the warning for the alphabetically smallest packlet.\n affectedPackletNames.sort();\n if (affectedPackletNames[0] === packletAnalyzer.inputFilePackletName) {\n let report: string = '';\n for (const packletImport of packletImports) {\n const filePath: string = Path.relative(tsconfigFileFolder, packletImport.fromFilePath);\n report += `\"${packletImport.packletName}\" is referenced by ${filePath}\\n`;\n }\n\n context.report({\n node: node,\n messageId: 'circular-import',\n data: { report: report }\n });\n }\n }\n }\n }\n };\n }\n};\n\nexport { circularDeps };\n"]}
|
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAMzD,UAAU,OAAO;IACf,KAAK,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;KAAE,CAAC;IACtE,OAAO,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC1C;AAED,QAAA,MAAM,MAAM,EAAE,OAkBb,CAAC;AAEF,SAAS,MAAM,CAAC"}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;AAI3D,2CAAwC;AACxC,mDAA+C;AAC/C,qCAAkC;AAOlC,MAAM,MAAM,GAAY;IACtB,KAAK,EAAE;QACL,6CAA6C;QAC7C,SAAS,EAAE,qBAAS;QACpB,iDAAiD;QACjD,eAAe,EAAE,4BAAY;QAC7B,MAAM,EAAE,eAAM;KACf;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,mCAAmC,CAAC;YAC9C,KAAK,EAAE;gBACL,+BAA+B,EAAE,MAAM;gBACvC,mCAAmC,EAAE,MAAM;gBAC3C,4BAA4B,EAAE,KAAK;aACpC;SACF;KACF;CACF,CAAC;AAEF,iBAAS,MAAM,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { TSESLint } from '@typescript-eslint/utils';\n\nimport { mechanics } from './mechanics';\nimport { circularDeps } from './circular-deps';\nimport { readme } from './readme';\n\ninterface IPlugin {\n rules: { [ruleName: string]: TSESLint.RuleModule<string, unknown[]> };\n configs: { [ruleName: string]: unknown };\n}\n\nconst plugin: IPlugin = {\n rules: {\n // Full name: \"@rushstack/packlets/mechanics\"\n mechanics: mechanics,\n // Full name: \"@rushstack/packlets/circular-deps\"\n 'circular-deps': circularDeps,\n readme: readme\n },\n configs: {\n recommended: {\n plugins: ['@rushstack/eslint-plugin-packlets'],\n rules: {\n '@rushstack/packlets/mechanics': 'warn',\n '@rushstack/packlets/circular-deps': 'warn',\n '@rushstack/packlets/readme': 'off'\n }\n }\n }\n};\n\nexport = plugin;\n"]}
|
package/lib/mechanics.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
-
import { InputFileMessageIds, ImportMessageIds } from './PackletAnalyzer';
|
|
2
|
+
import { type InputFileMessageIds, type ImportMessageIds } from './PackletAnalyzer';
|
|
3
3
|
export type MessageIds = InputFileMessageIds | ImportMessageIds;
|
|
4
4
|
type Options = [];
|
|
5
5
|
declare const mechanics: TSESLint.RuleModule<MessageIds, Options>;
|
package/lib/mechanics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mechanics.d.ts","sourceRoot":"","sources":["../src/mechanics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAGnE,OAAO,
|
|
1
|
+
{"version":3,"file":"mechanics.d.ts","sourceRoot":"","sources":["../src/mechanics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAGnE,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,UAAU,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;AAChE,KAAK,OAAO,GAAG,EAAE,CAAC;AAElB,QAAA,MAAM,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAoHvD,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
package/lib/mechanics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mechanics.js","sourceRoot":"","sources":["../src/mechanics.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAG3D,oDAAuE;AAEvE,
|
|
1
|
+
{"version":3,"file":"mechanics.js","sourceRoot":"","sources":["../src/mechanics.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport {\n PackletAnalyzer,\n type IAnalyzerError,\n type InputFileMessageIds,\n type ImportMessageIds\n} from './PackletAnalyzer';\n\nexport type MessageIds = InputFileMessageIds | ImportMessageIds;\ntype Options = [];\n\nconst mechanics: TSESLint.RuleModule<MessageIds, Options> = {\n defaultOptions: [],\n meta: {\n type: 'problem',\n messages: {\n // InputFileMessageIds\n 'file-in-packets-folder': 'The \"packlets\" folder must not contain regular source files',\n 'invalid-packlet-name':\n 'Invalid packlet name \"{{packletName}}\".' +\n ' The name must be lowercase alphanumeric words separated by hyphens. Example: \"my-packlet\"',\n 'misplaced-packlets-folder': 'The packlets folder must be located at \"{{expectedPackletsFolder}}\"',\n 'missing-src-folder': 'Expecting to find a \"src\" folder at: {{srcFolderPath}}',\n 'missing-tsconfig':\n 'In order to use @rushstack/eslint-plugin-packlets, your ESLint config file' +\n ' must configure the TypeScript parser',\n 'packlet-folder-case': 'The packlets folder must be all lower case: {{packletsFolderPath}}',\n\n // ImportMessageIds\n 'bypassed-entry-point':\n 'The import statement does not use the packlet\\'s entry point \"{{entryPointModulePath}}\"',\n 'circular-entry-point': 'Files under a packlet folder must not import from their own index.ts file',\n 'packlet-importing-project-file':\n 'A local project file cannot be imported.' +\n \" A packlet's dependencies must be NPM packages and/or other packlets.\"\n },\n schema: [\n {\n type: 'object',\n additionalProperties: false\n }\n ],\n docs: {\n description: 'Check that file paths and imports follow the basic mechanics for the packlet formalism',\n recommended: 'recommended',\n url: 'https://www.npmjs.com/package/@rushstack/eslint-plugin-packlets'\n } as TSESLint.RuleMetaDataDocs\n },\n\n create: (context: TSESLint.RuleContext<MessageIds, Options>) => {\n // Example: /path/to/my-project/src/packlets/my-packlet/index.ts\n const inputFilePath: string = context.getFilename();\n\n // Example: /path/to/my-project/tsconfig.json\n const tsconfigFilePath: string | undefined = ESLintUtils.getParserServices(\n context\n ).program.getCompilerOptions().configFilePath as string;\n\n const packletAnalyzer: PackletAnalyzer = PackletAnalyzer.analyzeInputFile(\n inputFilePath,\n tsconfigFilePath\n );\n if (packletAnalyzer.nothingToDo) {\n return {};\n }\n\n return {\n // Match the first node in the source file. Ideally we should be matching \"Program > :first-child\"\n // so a warning doesn't highlight the whole file. But that's blocked behind a bug in the query selector:\n // https://github.com/estools/esquery/issues/114\n Program: (node: TSESTree.Node): void => {\n if (packletAnalyzer.error) {\n context.report({\n node: node,\n messageId: packletAnalyzer.error.messageId,\n data: packletAnalyzer.error.data\n });\n }\n },\n\n // ImportDeclaration matches these forms:\n // import { X } from '../../packlets/other-packlet';\n // import X from '../../packlets/other-packlet';\n // import type { X, Y } from '../../packlets/other-packlet';\n // import * as X from '../../packlets/other-packlet';\n //\n // ExportNamedDeclaration matches these forms:\n // export { X } from '../../packlets/other-packlet';\n //\n // ExportAllDeclaration matches these forms:\n // export * from '../../packlets/other-packlet';\n // export * as X from '../../packlets/other-packlet';\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'ImportDeclaration, ExportNamedDeclaration, ExportAllDeclaration': (\n node: TSESTree.ImportDeclaration | TSESTree.ExportNamedDeclaration | TSESTree.ExportAllDeclaration\n ): void => {\n if (node.source?.type === AST_NODE_TYPES.Literal) {\n if (packletAnalyzer.projectUsesPacklets) {\n // Extract the import/export module path\n // Example: \"../../packlets/other-packlet\"\n const modulePath: string = node.source.value;\n if (typeof modulePath !== 'string') {\n return;\n }\n\n if (!(modulePath.startsWith('.') || modulePath.startsWith('..'))) {\n // It's not a local import.\n\n // Examples:\n // import { X } from \"npm-package\";\n // import { X } from \"raw-loader!./webpack-file.ts\";\n return;\n }\n\n const lint: IAnalyzerError | undefined = packletAnalyzer.analyzeImport(modulePath);\n if (lint) {\n context.report({\n node: node,\n messageId: lint.messageId,\n data: lint.data\n });\n }\n }\n }\n }\n };\n }\n};\n\nexport { mechanics };\n"]}
|
package/lib/readme.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readme.d.ts","sourceRoot":"","sources":["../src/readme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"readme.d.ts","sourceRoot":"","sources":["../src/readme.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAKnE,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,kBAAkB,CAAC;AACtF,KAAK,OAAO,GAAG;IACb;QACE,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B;CACF,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA4FpD,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/lib/readme.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
})();
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.readme = void 0;
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
41
|
const utils_1 = require("@typescript-eslint/utils");
|
|
42
42
|
const PackletAnalyzer_1 = require("./PackletAnalyzer");
|
|
43
43
|
const readme = {
|
package/lib/readme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readme.js","sourceRoot":"","sources":["../src/readme.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE3D,
|
|
1
|
+
{"version":3,"file":"readme.js","sourceRoot":"","sources":["../src/readme.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\n\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils';\nimport { ESLintUtils } from '@typescript-eslint/utils';\n\nimport { PackletAnalyzer } from './PackletAnalyzer';\n\nexport type MessageIds = 'missing-readme' | 'error-reading-file' | 'readme-too-short';\ntype Options = [\n {\n minimumReadmeWords?: number;\n }\n];\n\nconst readme: TSESLint.RuleModule<MessageIds, Options> = {\n defaultOptions: [{}],\n meta: {\n type: 'problem',\n messages: {\n 'missing-readme':\n 'The ESLint configuration requires each packlet to provide a README.md file summarizing' +\n ' its purpose and usage: {{readmePath}}',\n 'readme-too-short':\n 'The ESLint configuration requires at least {{minimumReadmeWords}} words of documentation in the' +\n ' README.md file: {{readmePath}}',\n 'error-reading-file': 'Error reading input file {{readmePath}}:\\n{{errorMessage}}'\n },\n schema: [\n {\n type: 'object',\n properties: {\n minimumReadmeWords: {\n type: 'number'\n }\n },\n additionalProperties: false\n }\n ],\n\n docs: {\n description: 'Require each packlet folder to have a README.md file summarizing its purpose and usage',\n // Too strict to be recommended in the default configuration\n recommended: 'strict',\n url: 'https://www.npmjs.com/package/@rushstack/eslint-plugin-packlets'\n } as TSESLint.RuleMetaDataDocs\n },\n\n create: (context: TSESLint.RuleContext<MessageIds, Options>) => {\n const minimumReadmeWords: number = context.options[0]?.minimumReadmeWords || 10;\n\n // Example: /path/to/my-project/src/packlets/my-packlet/index.ts\n const inputFilePath: string = context.getFilename();\n\n // Example: /path/to/my-project/tsconfig.json\n const tsconfigFilePath: string | undefined = ESLintUtils.getParserServices(\n context\n ).program.getCompilerOptions().configFilePath as string;\n\n const packletAnalyzer: PackletAnalyzer = PackletAnalyzer.analyzeInputFile(\n inputFilePath,\n tsconfigFilePath\n );\n\n if (!packletAnalyzer.nothingToDo && !packletAnalyzer.error) {\n if (packletAnalyzer.isEntryPoint) {\n return {\n Program: (node: TSESTree.Node): void => {\n const readmePath: string = path.join(\n packletAnalyzer.packletsFolderPath!,\n packletAnalyzer.inputFilePackletName!,\n 'README.md'\n );\n try {\n if (!fs.existsSync(readmePath)) {\n context.report({\n node: node,\n messageId: 'missing-readme',\n data: { readmePath }\n });\n } else {\n if (minimumReadmeWords > 0) {\n const readmeContent: string = fs.readFileSync(readmePath).toString();\n const words: string[] = readmeContent.split(/[^a-z'\"]+/i).filter((x) => x.length > 0);\n if (words.length < minimumReadmeWords) {\n context.report({\n node: node,\n messageId: 'readme-too-short',\n data: { readmePath, minimumReadmeWords }\n });\n }\n }\n }\n } catch (error) {\n context.report({\n node: node,\n messageId: 'error-reading-file',\n data: { readmePath, errorMessage: (error as Error).toString() }\n });\n }\n }\n };\n }\n }\n\n return {};\n }\n};\n\nexport { readme };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rushstack/eslint-plugin-packlets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "A lightweight alternative to NPM packages for organizing source files within a single project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -18,24 +18,18 @@
|
|
|
18
18
|
"main": "lib/index.js",
|
|
19
19
|
"typings": "lib/index.d.ts",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@typescript-eslint/utils": "~8.
|
|
21
|
+
"@typescript-eslint/utils": "~8.31.0",
|
|
22
22
|
"@rushstack/tree-pattern": "0.3.4"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
25
|
+
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@rushstack/heft": "0.
|
|
29
|
-
"@
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"@types/node": "20.17.19",
|
|
34
|
-
"@typescript-eslint/parser": "~8.26.1",
|
|
35
|
-
"@typescript-eslint/typescript-estree": "~8.26.1",
|
|
36
|
-
"eslint": "~8.57.0",
|
|
37
|
-
"eslint-plugin-header": "~3.1.1",
|
|
38
|
-
"typescript": "~5.8.2"
|
|
28
|
+
"@rushstack/heft": "1.0.0",
|
|
29
|
+
"@typescript-eslint/parser": "~8.31.0",
|
|
30
|
+
"eslint": "~9.25.1",
|
|
31
|
+
"typescript": "~5.8.2",
|
|
32
|
+
"decoupled-local-node-rig": "1.0.0"
|
|
39
33
|
},
|
|
40
34
|
"scripts": {
|
|
41
35
|
"build": "heft build --clean",
|