Skip to content

Commit 46542a9

Browse files
authored
Merge pull request #113 from eryue0220/fix/issue-54
feat: support project alias from config
2 parents afcf50e + 983fe94 commit 46542a9

File tree

6 files changed

+293
-7
lines changed

6 files changed

+293
-7
lines changed

examples/vite-example/tsconfig.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
"isolatedModules": true,
1010
"resolveJsonModule": true,
1111
"moduleResolution": "bundler",
12-
"useDefineForClassFields": true
12+
"useDefineForClassFields": true,
13+
"paths": {
14+
"@/*": ["./src/*"]
15+
}
1316
},
1417
"include": ["src"],
1518
"exclude": ["node_modules"]

src/core/options.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { StylexOptions, UnpluginStylexOptions } from '@/types'
2-
import { isDevelopment } from './constants'
2+
import { getAliases, isDevelopment } from '@/utils'
33

4-
export function getOptions(options: UnpluginStylexOptions): Required<UnpluginStylexOptions> {
4+
export function getOptions(options: UnpluginStylexOptions & { framework: string }): Required<UnpluginStylexOptions> {
5+
const projectAliases = getAliases(options.framework)
56
const stylex = options.stylex || ({} as StylexOptions)
67
const isDev = options.dev || isDevelopment
78

@@ -14,7 +15,7 @@ export function getOptions(options: UnpluginStylexOptions): Required<UnpluginSty
1415
filename: stylex.filename || 'stylex.css',
1516
stylexImports: stylex.stylexImports || ['@stylexjs/stylex'],
1617
runtimeInjection: stylex.runtimeInjection ?? isDev,
17-
aliases: stylex.aliases,
18+
aliases: stylex.aliases ?? projectAliases ?? {},
1819
useCSSLayers: stylex.useCSSLayers || false,
1920
unstable_moduleResolution: stylex.unstable_moduleResolution || { type: 'commonJS', rootDir: process.cwd() },
2021
babelConfig: {

src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ import type { UnpluginFactory, UnpluginInstance } from 'unplugin'
1212
import type { BuildOptions } from 'vite'
1313

1414
import { buildStylexRules } from './core/build'
15-
import { PLUGIN_NAME } from './core/constants'
1615
import { getOptions } from './core/options'
1716
import { transformer } from './core/transformer'
1817
import type { UnpluginStylexOptions } from './types'
18+
import { PLUGIN_NAME } from './utils'
1919

2020
/**
2121
* The main unplugin factory.
2222
*/
23-
export const unpluginFactory: UnpluginFactory<UnpluginStylexOptions | undefined> = (rawOptions = {}) => {
24-
const options = getOptions(rawOptions)
23+
export const unpluginFactory: UnpluginFactory<UnpluginStylexOptions | undefined> = (rawOptions, meta) => {
24+
const options = getOptions({ ...(rawOptions || {}), framework: meta.framework })
2525
const stylexRules = {}
2626
let viteConfig: { build: BuildOptions | undefined; base: string | undefined } | null = null
2727

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export const PLUGIN_NAME = 'unplugin-stylex'
22

33
export const isDevelopment = process.env.NODE_ENV !== 'production' || process.env.BABEL_ENV !== 'production'
4+
5+
export const EXTENSIONS = ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts']

src/utils/get-aliases.ts

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import { EXTENSIONS } from './constants'
4+
5+
function makePathAbsolute(value: string) {
6+
return path.isAbsolute(value as string) ? value : path.resolve(process.cwd(), value as string)
7+
}
8+
9+
function isTSProject() {
10+
const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json')
11+
return fs.existsSync(tsConfigPath)
12+
}
13+
14+
function getAliasesFromTSConfig() {
15+
if (!isTSProject()) {
16+
return undefined
17+
}
18+
19+
try {
20+
const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json')
21+
const tsConfigContent = fs.readFileSync(tsConfigPath, 'utf8')
22+
const tsConfig = JSON.parse(tsConfigContent)
23+
const paths = tsConfig?.compilerOptions?.paths || {}
24+
25+
const aliases = Object.entries(paths).reduce(
26+
(acc, [key, value]) => {
27+
acc[key] = Array.isArray(value) ? value.map(makePathAbsolute) : makePathAbsolute(value as string)
28+
return acc
29+
},
30+
{} as Record<string, string | string[]>,
31+
)
32+
33+
return Object.keys(aliases).length > 0 ? aliases : undefined
34+
} catch (error) {
35+
// If file doesn't exist or is invalid JSON, return null
36+
return undefined
37+
}
38+
}
39+
40+
function getAliasesFromViteConfig() {
41+
const configFiles = EXTENSIONS.map((ext) => `vite.config${ext}`)
42+
const configPath = configFiles.find((file) => fs.existsSync(path.resolve(process.cwd(), file)))
43+
44+
if (!configPath) {
45+
return {}
46+
}
47+
48+
try {
49+
// Import the config file
50+
const configModule = require(path.resolve(process.cwd(), configPath))
51+
const config = typeof configModule === 'function' ? configModule() : configModule.default || configModule
52+
const aliases = config?.resolve?.alias || {}
53+
54+
// Convert aliases to absolute paths
55+
return Object.entries(aliases).reduce(
56+
(acc, [key, value]) => {
57+
acc[key] = makePathAbsolute(value as string)
58+
return acc
59+
},
60+
{} as Record<string, string>,
61+
)
62+
} catch (error) {
63+
// If file can't be read or parsed, return empty object
64+
return {}
65+
}
66+
}
67+
68+
function getAliasesFromWebpackConfig() {
69+
const configFiles = EXTENSIONS.map((ext) => `webpack.config${ext}`)
70+
const configPath = configFiles.find((file) => fs.existsSync(path.resolve(process.cwd(), file)))
71+
72+
if (!configPath) {
73+
return {}
74+
}
75+
76+
try {
77+
const configContent = fs.readFileSync(path.resolve(process.cwd(), configPath), 'utf8')
78+
const config = JSON.parse(configContent)
79+
const aliases = config?.resolve?.alias || {}
80+
81+
// Convert aliases to absolute paths
82+
return Object.entries(aliases).reduce(
83+
(acc, [key, value]) => {
84+
acc[key] = makePathAbsolute(value as string)
85+
return acc
86+
},
87+
{} as Record<string, string>,
88+
)
89+
} catch (error) {
90+
// If file can't be read or parsed, return empty object
91+
return {}
92+
}
93+
}
94+
95+
function getAliasesFromRollupConfig() {
96+
const configFiles = EXTENSIONS.map((ext) => `rollup.config${ext}`)
97+
const configPath = configFiles.find((file) => fs.existsSync(path.resolve(process.cwd(), file)))
98+
99+
if (!configPath) {
100+
return {}
101+
}
102+
103+
try {
104+
const configModule = require(path.resolve(process.cwd(), configPath))
105+
const config = typeof configModule === 'function' ? configModule() : configModule.default || configModule
106+
107+
// Look for @rollup/plugin-alias configuration
108+
const aliasPlugin = config?.plugins?.find((plugin) => {
109+
if (typeof plugin === 'object' && plugin !== null) {
110+
return plugin.name === '@rollup/plugin-alias'
111+
}
112+
return false
113+
})
114+
115+
if (!aliasPlugin) {
116+
return {}
117+
}
118+
119+
const aliases = aliasPlugin?.options?.entries || {}
120+
121+
// Convert aliases to absolute paths
122+
return Object.entries(aliases).reduce(
123+
(acc, [key, value]) => {
124+
acc[key] = makePathAbsolute(value as string)
125+
return acc
126+
},
127+
{} as Record<string, string>,
128+
)
129+
} catch (error) {
130+
// If file can't be read or parsed, return empty object
131+
return {}
132+
}
133+
}
134+
135+
function getAliasesFromRolldownConfig() {
136+
const configFiles = EXTENSIONS.map((ext) => `vite.config${ext}`)
137+
const configPath = configFiles.find((file) => fs.existsSync(path.resolve(process.cwd(), file)))
138+
139+
if (!configPath) {
140+
return {}
141+
}
142+
143+
try {
144+
const configModule = require(path.resolve(process.cwd(), configPath))
145+
const config = typeof configModule === 'function' ? configModule() : configModule.default || configModule
146+
const aliases = config?.resolve?.alias || {}
147+
148+
// Convert aliases to absolute paths
149+
return Object.entries(aliases).reduce(
150+
(acc, [key, value]) => {
151+
acc[key] = makePathAbsolute(value as string)
152+
return acc
153+
},
154+
{} as Record<string, string>,
155+
)
156+
} catch (error) {
157+
// If file can't be read or parsed, return empty object
158+
return {}
159+
}
160+
}
161+
162+
function getAliasesFromEsbuildConfig() {
163+
return {}
164+
}
165+
166+
function getAliasesFromRspackConfig() {
167+
const configFiles = EXTENSIONS.map((ext) => `rspack.config${ext}`)
168+
const configPath = configFiles.find((file) => fs.existsSync(path.resolve(process.cwd(), file)))
169+
170+
if (!configPath) {
171+
return {}
172+
}
173+
174+
try {
175+
const configContent = fs.readFileSync(path.resolve(process.cwd(), configPath), 'utf8')
176+
const config = JSON.parse(configContent)
177+
const aliases = config?.resolve?.alias || {}
178+
179+
// Convert aliases to absolute paths
180+
return Object.entries(aliases).reduce(
181+
(acc, [key, value]) => {
182+
acc[key] = makePathAbsolute(value as string)
183+
return acc
184+
},
185+
{} as Record<string, string>,
186+
)
187+
} catch (error) {
188+
// If file can't be read or parsed, return empty object
189+
return {}
190+
}
191+
}
192+
193+
function getAliasesFromFarmConfig() {
194+
const configFiles = EXTENSIONS.map((ext) => `farm.config${ext}`)
195+
const configPath = configFiles.find((file) => fs.existsSync(path.resolve(process.cwd(), file)))
196+
197+
if (!configPath) {
198+
return {}
199+
}
200+
201+
try {
202+
const configModule = require(path.resolve(process.cwd(), configPath))
203+
const config = typeof configModule === 'function' ? configModule() : configModule.default || configModule
204+
const aliases = config?.resolve?.alias || {}
205+
206+
// Convert aliases to absolute paths
207+
return Object.entries(aliases).reduce(
208+
(acc, [key, value]) => {
209+
acc[key] = makePathAbsolute(value as string)
210+
return acc
211+
},
212+
{} as Record<string, string>,
213+
)
214+
} catch (error) {
215+
// If file can't be read or parsed, return empty object
216+
return {}
217+
}
218+
}
219+
220+
export function getAliases(framework: string) {
221+
const tsAliases = getAliasesFromTSConfig()
222+
223+
if (framework === 'vite') {
224+
const viteAliases = getAliasesFromViteConfig()
225+
return {
226+
...tsAliases,
227+
...viteAliases,
228+
}
229+
}
230+
231+
if (framework === 'webpack') {
232+
const webpackAliases = getAliasesFromWebpackConfig()
233+
return {
234+
...tsAliases,
235+
...webpackAliases,
236+
}
237+
}
238+
239+
if (framework === 'rollup') {
240+
const rollupAliases = getAliasesFromRollupConfig()
241+
return {
242+
...tsAliases,
243+
...rollupAliases,
244+
}
245+
}
246+
247+
if (framework === 'rolldown') {
248+
const rolldownAliases = getAliasesFromRolldownConfig()
249+
return {
250+
...tsAliases,
251+
...rolldownAliases,
252+
}
253+
}
254+
255+
if (framework === 'esbuild') {
256+
const esbuildAliases = getAliasesFromEsbuildConfig()
257+
return {
258+
...tsAliases,
259+
...esbuildAliases,
260+
}
261+
}
262+
263+
if (framework === 'rspack') {
264+
const rspackAliases = getAliasesFromRspackConfig()
265+
return {
266+
...tsAliases,
267+
...rspackAliases,
268+
}
269+
}
270+
271+
if (framework === 'farm') {
272+
const farmAliases = getAliasesFromFarmConfig()
273+
return {
274+
...tsAliases,
275+
...farmAliases,
276+
}
277+
}
278+
}

src/utils/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './constants'
2+
export * from './get-aliases'

0 commit comments

Comments
 (0)