configorama 0.6.4 → 0.6.5

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.
@@ -0,0 +1,152 @@
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const findUp = require('find-up')
4
+
5
+ const DEBUG = false
6
+ const DEBUG_LOG = (message) => {
7
+ if (DEBUG) {
8
+ DEBUG_LOG(message)
9
+ }
10
+ }
11
+
12
+ // Maximum number of parent directories to search through
13
+ const MAX_PARENT_DIRS = 5
14
+
15
+ /**
16
+ * Finds the nearest config file (tsconfig.json or jsconfig.json) in the directory tree
17
+ * @param {string} configDir - The directory to start searching from
18
+ * @returns {string|null} - Path to the config file or null if not found
19
+ */
20
+ function findConfigFile(configDir) {
21
+ // Try tsconfig.json first
22
+ const tsconfigPath = findUp.sync('tsconfig.json', {
23
+ cwd: configDir,
24
+ stopAt: path.resolve(configDir, Array(MAX_PARENT_DIRS).fill('..').join('/'))
25
+ })
26
+ if (tsconfigPath) {
27
+ return tsconfigPath
28
+ }
29
+
30
+ // Fall back to jsconfig.json
31
+ const jsconfigPath = findUp.sync('jsconfig.json', {
32
+ cwd: configDir,
33
+ stopAt: path.resolve(configDir, Array(MAX_PARENT_DIRS).fill('..').join('/'))
34
+ })
35
+ if (jsconfigPath) {
36
+ return jsconfigPath
37
+ }
38
+
39
+ return null
40
+ }
41
+
42
+ /**
43
+ * Resolves path aliases using TypeScript/JavaScript path mappings from config files
44
+ * @param {string} filePath - The potentially aliased file path
45
+ * @param {string} configDir - The base directory to search for config files
46
+ * @returns {string} - The resolved file path
47
+ */
48
+ function resolveAlias(filePath, configDir) {
49
+ try {
50
+ // Find and load config file
51
+ const configPath = findConfigFile(configDir)
52
+ if (!configPath) {
53
+ // console.warn(
54
+ // `Warning: No tsconfig.json or jsconfig.json found in directory tree starting from ${configDir}`
55
+ // )
56
+ return filePath
57
+ }
58
+
59
+ // Read and parse config file
60
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'))
61
+ const { paths = {}, baseUrl = '.' } = config.compilerOptions || {}
62
+
63
+ // Extract the alias prefix and path
64
+ // Match any non-slash characters at the start of the path
65
+ const match = filePath.match(/^([^/]+)(\/.*)?$/)
66
+ if (!match) {
67
+ return filePath
68
+ }
69
+
70
+ const [, aliasPrefix, restPath = ''] = match
71
+
72
+ // Try exact match first (e.g. settings)
73
+ const exactKey = aliasPrefix
74
+ if (paths[exactKey]) {
75
+ const mappedPath = paths[exactKey][0]
76
+ const resolvedPath = path.resolve(path.dirname(configPath), baseUrl, mappedPath)
77
+ DEBUG_LOG(`Resolving exact alias ${filePath} to ${resolvedPath}`)
78
+ return resolvedPath
79
+ }
80
+
81
+ // Try wildcard match (e.g. alias/*)
82
+ const wildcardKey = `${aliasPrefix}/*`
83
+ if (paths[wildcardKey]) {
84
+ const mappedPath = paths[wildcardKey][0]
85
+ const basePath = path.resolve(path.dirname(configPath), baseUrl, mappedPath.replace('*', ''))
86
+ const relativeRest = restPath.replace(/^\//, '')
87
+ const resolvedPath = path.join(basePath, relativeRest)
88
+ DEBUG_LOG(`Resolving wildcard alias ${filePath} to ${resolvedPath}`)
89
+ return resolvedPath
90
+ }
91
+
92
+ // Try nested alias resolution
93
+ const nestedMatch = filePath.match(/^([^/]+\/[^/]+)(\/.*)?$/)
94
+ if (nestedMatch) {
95
+ const [, nestedPrefix, nestedRest = ''] = nestedMatch
96
+ const nestedKey = `${nestedPrefix}/*`
97
+ if (paths[nestedKey]) {
98
+ const mappedPath = paths[nestedKey][0]
99
+ const basePath = path.resolve(path.dirname(configPath), baseUrl, mappedPath.replace('*', ''))
100
+ const relativeRest = nestedRest.replace(/^\//, '')
101
+ const resolvedPath = path.join(basePath, relativeRest)
102
+ DEBUG_LOG(`Resolving nested alias ${filePath} to ${resolvedPath}`)
103
+ return resolvedPath
104
+ }
105
+ }
106
+
107
+ // Fall back to original path if no alias matched
108
+ // console.warn(`Warning: No alias mapping found for ${filePath}`)
109
+ return filePath
110
+
111
+ } catch (error) {
112
+ // If alias resolution fails, fall back to original path
113
+ console.warn(`Warning: Failed to resolve alias for "${filePath}":`, error.message)
114
+ return filePath
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Gets all configured aliases from tsconfig.json or jsconfig.json
120
+ * @param {string} configDir - The base directory to search for config files
121
+ * @returns {Object} - Object containing alias names and their resolved paths
122
+ */
123
+ function getAliases(configDir) {
124
+ try {
125
+ const configPath = findConfigFile(configDir)
126
+ if (!configPath) {
127
+ // console.warn(`Warning: No tsconfig.json or jsconfig.json found in directory tree starting from ${configDir}`)
128
+ return { names: [], lookup: [] }
129
+ }
130
+
131
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'))
132
+ const { paths = {}, baseUrl = '.' } = config.compilerOptions || {}
133
+
134
+ const names = Object.keys(paths).map(key => key.replace('/*', ''))
135
+ const lookup = Object.entries(paths).map(([key, [value]]) => {
136
+ const name = key.replace('/*', '')
137
+ const absPath = path.resolve(path.dirname(configPath), baseUrl, value.replace('/*', ''))
138
+ const relPath = path.relative(configDir, absPath)
139
+ return { name, absPath, relPath }
140
+ })
141
+
142
+ return { names, lookup }
143
+ } catch (error) {
144
+ console.warn(`Warning: Failed to get aliases:`, error.message)
145
+ return { names: [], lookup: [] }
146
+ }
147
+ }
148
+
149
+ module.exports = {
150
+ resolveAlias,
151
+ getAliases
152
+ }
@@ -0,0 +1,98 @@
1
+ const { test } = require('uvu')
2
+ const assert = require('uvu/assert')
3
+ const path = require('path')
4
+ const fs = require('fs')
5
+ const findUp = require('find-up')
6
+ const { resolveAlias, getAliases } = require('./resolveAlias')
7
+
8
+ // Mock config content
9
+ const mockConfig = {
10
+ compilerOptions: {
11
+ baseUrl: '.',
12
+ paths: {
13
+ '@components': ['src/components'],
14
+ '@utils/*': ['src/utils/*'],
15
+ '@shared/*': ['src/shared/*'],
16
+ '@nested/foo/*': ['src/nested/foo/*'],
17
+ '~zaz/*': ['src/zaz/*']
18
+ }
19
+ }
20
+ }
21
+
22
+ // Store original implementations
23
+ const originalReadFileSync = fs.readFileSync
24
+ const originalFindUpSync = findUp.sync
25
+
26
+ // Mock implementations
27
+ const mockFindUpSync = (filename) => {
28
+ if (filename === 'tsconfig.json') {
29
+ return '/project/tsconfig.json'
30
+ }
31
+ return null
32
+ }
33
+
34
+ const mockReadFileSync = () => JSON.stringify(mockConfig)
35
+
36
+ test.before.each(() => {
37
+ // Reset mocks before each test
38
+ findUp.sync = mockFindUpSync
39
+ fs.readFileSync = mockReadFileSync
40
+ })
41
+
42
+ test.after(() => {
43
+ // Restore original implementations
44
+ fs.readFileSync = originalReadFileSync
45
+ findUp.sync = originalFindUpSync
46
+ })
47
+
48
+ test('resolveAlias - exact match', () => {
49
+ const result = resolveAlias('@components', '/project')
50
+ assert.is(result, path.resolve('/project', 'src/components'))
51
+ })
52
+
53
+ test('resolveAlias - wildcard match', () => {
54
+ const result = resolveAlias('@utils/helpers', '/project')
55
+ assert.is(result, path.resolve('/project', 'src/utils/helpers'))
56
+ })
57
+
58
+ test('resolveAlias - nested alias', () => {
59
+ const result = resolveAlias('@nested/foo/bar', '/project')
60
+ assert.is(result, path.resolve('/project', 'src/nested/foo/bar'))
61
+ })
62
+
63
+ test('resolveAlias - special character alias', () => {
64
+ const result = resolveAlias('~zaz/helpers', '/project')
65
+ assert.is(result, path.resolve('/project', 'src/zaz/helpers'))
66
+ })
67
+
68
+ test('resolveAlias - no config file found', () => {
69
+ findUp.sync = () => null
70
+ const result = resolveAlias('@components', '/project')
71
+ assert.is(result, '@components')
72
+ })
73
+
74
+ test('resolveAlias - no matching alias', () => {
75
+ const result = resolveAlias('unknown/path', '/project')
76
+ assert.is(result, 'unknown/path')
77
+ })
78
+
79
+ test('getAliases - returns correct alias information', () => {
80
+ const result = getAliases('/project')
81
+ assert.is(result.names.length, 5)
82
+ assert.is(result.lookup.length, 5)
83
+
84
+ // Check if all expected aliases are present
85
+ const expectedNames = ['@components', '@utils', '@shared', '@nested/foo', '~zaz']
86
+ expectedNames.forEach(name => {
87
+ assert.ok(result.names.includes(name))
88
+ })
89
+ })
90
+
91
+ test('getAliases - no config file found', () => {
92
+ findUp.sync = () => null
93
+ const result = getAliases('/project')
94
+ assert.is(result.names.length, 0)
95
+ assert.is(result.lookup.length, 0)
96
+ })
97
+
98
+ test.run()
@@ -0,0 +1,65 @@
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+
4
+ function resolveAlias(filePath, configDir) {
5
+ try {
6
+ // If no alias prefix, return original path
7
+ if (!filePath.startsWith('@')) {
8
+ return filePath
9
+ }
10
+
11
+ // Find tsconfig.json
12
+ const tsconfigPath = path.join(configDir, 'tsconfig.json')
13
+ if (!fs.existsSync(tsconfigPath)) {
14
+ console.warn(`Warning: No tsconfig.json found in ${configDir}`)
15
+ return filePath
16
+ }
17
+
18
+ // Read and parse tsconfig.json
19
+ const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'))
20
+ const aliasMappings = tsconfig.compilerOptions?.paths || {}
21
+
22
+ // Extract the alias prefix and path
23
+ const match = filePath.match(/^(@[^/]+)(\/.*)$/)
24
+ if (!match) {
25
+ return filePath
26
+ }
27
+
28
+ const [, aliasPrefix, restPath] = match
29
+ const aliasKey = `${aliasPrefix}/*`
30
+
31
+ // Check if we have a mapping for this alias
32
+ if (aliasMappings[aliasKey]) {
33
+ // Get the mapped path and normalize it
34
+ const mappedPath = aliasMappings[aliasKey][0]
35
+ const basePath = path.resolve(configDir, mappedPath.replace('*', ''))
36
+ const relativeRest = restPath.replace(/^\//, '')
37
+ const resolvedPath = path.join(basePath, relativeRest)
38
+
39
+ // Log the resolution for debugging
40
+ console.log(`Resolving ${filePath} to ${resolvedPath}`)
41
+
42
+ return resolvedPath
43
+ }
44
+
45
+ // Try exact match without wildcard
46
+ const exactKey = aliasPrefix
47
+ if (aliasMappings[exactKey]) {
48
+ const mappedPath = aliasMappings[exactKey][0]
49
+ const resolvedPath = path.resolve(configDir, mappedPath)
50
+
51
+ console.log(`Resolving ${filePath} to ${resolvedPath}`)
52
+ return resolvedPath
53
+ }
54
+
55
+ // Fall back to original path if no alias matched
56
+ return filePath
57
+
58
+ } catch (error) {
59
+ // If alias resolution fails, fall back to original path
60
+ console.warn(`Warning: Failed to resolve alias for "${filePath}":`, error.message)
61
+ return filePath
62
+ }
63
+ }
64
+
65
+ module.exports = resolveAlias
@@ -4,7 +4,7 @@
4
4
  * @param {string} search - String to search for
5
5
  * @returns {string} Text after search string or empty string if not found
6
6
  */
7
- function getTextAfterOccurance(str, search) {
7
+ function getTextAfterOccurrence(str, search) {
8
8
  const index = str.indexOf(search)
9
9
  if (index === -1) return ''
10
10
  return str.substring(index)
@@ -26,6 +26,6 @@ function findNestedVariable(split, originalSource) {
26
26
  }
27
27
 
28
28
  module.exports = {
29
- getTextAfterOccurance,
29
+ getTextAfterOccurrence,
30
30
  findNestedVariable
31
31
  }