configorama 0.6.4 → 0.6.6
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/README.md +211 -12
- package/cli.js +10 -3
- package/index.d.ts +45 -0
- package/package.json +12 -3
- package/src/index.js +9 -5
- package/src/main.js +387 -96
- package/src/parsers/esm.js +69 -0
- package/src/parsers/index.js +3 -1
- package/src/parsers/ini.js +51 -0
- package/src/parsers/ini.test.js +133 -0
- package/src/parsers/json5.js +1 -0
- package/src/parsers/typescript.js +154 -0
- package/src/parsers/yaml.test.js +1 -1
- package/src/resolvers/valueFromCron.js +252 -0
- package/src/resolvers/valueFromCron.test.js +132 -0
- package/src/resolvers/valueFromEval.js +37 -0
- package/src/resolvers/valueFromEval.test.js +44 -0
- package/src/resolvers/valueFromGit.js +6 -4
- package/src/types.d.ts +112 -0
- package/src/utils/cleanVariable.js +67 -3
- package/src/utils/createEditorLink.js +23 -0
- package/src/utils/find-nested-variables.js +10 -1
- package/src/utils/logs.js +2 -1
- package/src/utils/parse.js +40 -0
- package/src/utils/resolveAlias.js +152 -0
- package/src/utils/resolveAlias.test.js +98 -0
- package/src/utils/resolveAliasOld.js +65 -0
- package/src/utils/textUtils.js +2 -2
|
@@ -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
|
package/src/utils/textUtils.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
29
|
+
getTextAfterOccurrence,
|
|
30
30
|
findNestedVariable
|
|
31
31
|
}
|