From 51f2056c899ac3023cd15893b9b8642f0ea50c74 Mon Sep 17 00:00:00 2001 From: tada5hi Date: Thu, 16 Feb 2023 15:39:03 +0100 Subject: [PATCH] fix: more secure path extension replacement --- src/data-source/options/utils.ts | 29 ++++++++++++++++++++++++++--- test/unit/connection/utils.spec.ts | 12 ++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/data-source/options/utils.ts b/src/data-source/options/utils.ts index 4c97f8e4..995f1e67 100644 --- a/src/data-source/options/utils.ts +++ b/src/data-source/options/utils.ts @@ -83,10 +83,33 @@ export function changeTSToJSPath( const tsExtensions = ['ts', 'cts', 'mts']; for (let i = 0; i < tsExtensions.length; i++) { - const baseExtensionIndex = base.indexOf(tsExtensions[i]); - if (baseExtensionIndex !== -1) { - base = base.replace(tsExtensions[i], jsExtensions[i]); + const regex = new RegExp(`(\\.${tsExtensions[i]}|${tsExtensions[i]})`, 'g'); + let matchesSum : number | undefined; + const matches = base.match(regex); + if (Array.isArray(matches)) { + matchesSum = matches.length; } + + let matchesCounter = 0; + + const bracketIndex = base.lastIndexOf('{'); + base = base.replace( + regex, + (...args) => { + matchesCounter++; + + // if the file extension name comes after the last bracket index, + // we can be pretty sure that the extension name is not part of a filename + if ( + (args[2] >= bracketIndex && bracketIndex !== -1) || + (bracketIndex === -1 && matchesCounter === matchesSum) + ) { + return args[0].startsWith('.') ? `.${jsExtensions[i]}` : jsExtensions[i]; + } + + return args[0]; + }, + ); } if (baseIndex !== -1) { diff --git a/test/unit/connection/utils.spec.ts b/test/unit/connection/utils.spec.ts index 869c614f..1e94c92c 100644 --- a/test/unit/connection/utils.spec.ts +++ b/test/unit/connection/utils.spec.ts @@ -35,6 +35,18 @@ describe('src/connection/utils.ts', () => { srcPath = '/src/entities.ts'; expect(changeTSToJSPath(srcPath)).toEqual('/dist/entities.js'); + srcPath = 'src/ts.{ts}'; + expect(changeTSToJSPath(srcPath)).toEqual('dist/ts.{js}'); + + srcPath = 'src/ts.ts.{ts,cts}'; + expect(changeTSToJSPath(srcPath)).toEqual('dist/ts.ts.{js,cjs}'); + + srcPath = 'src/*.{ts,cts}'; + expect(changeTSToJSPath(srcPath)).toEqual('dist/*.{js,cjs}'); + + srcPath = 'src/ts.ts'; + expect(changeTSToJSPath(srcPath)).toEqual('dist/ts.js'); + const srcPaths = ['src/entities.ts', './src/entities.ts']; for(let i=0; i