Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.

Commit f327a40

Browse files
committed
fix: path
1 parent fc7219c commit f327a40

File tree

4 files changed

+100
-13
lines changed

4 files changed

+100
-13
lines changed

package.json

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,7 @@
99
"intentui": "dist/index.js",
1010
"shadcnClone": "dist/shadcn/index.js"
1111
},
12-
"files": [
13-
"dist",
14-
"LICENSE",
15-
"README.md",
16-
"package.json"
17-
],
12+
"files": ["dist", "LICENSE", "README.md", "package.json"],
1813
"repository": {
1914
"type": "git",
2015
"url": "git+https://github.com/intentuilabs/cli.git"
@@ -34,12 +29,7 @@
3429
"release": "export GITHUB_TOKEN=$(cat .github_token) && release-it",
3530
"typecheck": "tsc --noEmit"
3631
},
37-
"keywords": [
38-
"cli",
39-
"intentui cli",
40-
"Intent UI",
41-
"design-system"
42-
],
32+
"keywords": ["cli", "intentui cli", "Intent UI", "design-system"],
4333
"author": "Irsyad A. Panjaitan",
4434
"license": "MIT",
4535
"devDependencies": {

src/commands/add.command.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { Args, Command, Options } from "@effect/cli"
2+
import * as FileSystem from "@effect/platform/FileSystem"
3+
4+
import * as Path from "node:path"
25
import {
36
HttpClient,
47
HttpClientRequest,
@@ -8,6 +11,14 @@ import {
811
import chalk from "chalk"
912
import { Console, Effect, Schema, pipe } from "effect"
1013
import { REGISTRY_URL } from "~/consts"
14+
import { applyUserAliases } from "~/lib/apply-user-aliases"
15+
import {
16+
isLaravel,
17+
isNextWithSrc,
18+
isNextWithoutSrc,
19+
isRemix,
20+
} from "~/lib/check-current-user-project"
21+
import { walkFiles } from "~/lib/walk-files"
1122
import { Component } from "~/schema/component"
1223

1324
export const componentNames = Args.text({ name: "componentNames" }).pipe(Args.repeated)
@@ -78,13 +89,61 @@ export const addCommand = Command.make(
7889
}
7990
args.push(...componentPaths)
8091

81-
return yield* pipe(
92+
const exitCode = yield* pipe(
8293
RawCommand.make("shadcnClone", ...args).pipe(
8394
RawCommand.stdin("inherit"),
8495
RawCommand.stdout("inherit"),
8596
RawCommand.stderr("inherit"),
8697
RawCommand.exitCode,
8798
),
8899
)
100+
101+
if (exitCode === 0) {
102+
const fileSystem = yield* FileSystem.FileSystem
103+
104+
const userConfigPath = Path.resolve(process.cwd(), "components.json")
105+
const userConfigRaw = yield* fileSystem.readFileString(userConfigPath)
106+
const userConfig = JSON.parse(userConfigRaw)
107+
108+
const cwd = process.cwd()
109+
110+
const hasSrc = yield* Effect.promise(() => isNextWithSrc(cwd))
111+
const noSrc = yield* Effect.promise(() => isNextWithoutSrc(cwd))
112+
const isRemixApp = yield* Effect.promise(() => isRemix(cwd))
113+
const isLaravelApp = yield* Effect.promise(() => isLaravel(cwd))
114+
115+
function resolveAliasPath(aliasPath: string): string {
116+
const base =
117+
isLaravelApp || noSrc ? cwd : hasSrc || isRemixApp ? Path.join(cwd, "src") : cwd
118+
119+
return Path.resolve(aliasPath.replace(/^@\//, `${base}/`))
120+
}
121+
122+
const foldersToPatch = Object.values(userConfig.aliases as Record<string, string>)
123+
.filter((dir) => typeof dir === "string" && dir.startsWith("@/"))
124+
.map((aliasPath) => resolveAliasPath(aliasPath))
125+
126+
for (const folder of foldersToPatch) {
127+
const exists = yield* fileSystem.exists(folder)
128+
if (!exists) continue
129+
130+
const allFiles = yield* walkFiles(fileSystem, folder)
131+
132+
for (const file of allFiles) {
133+
const fullPath = Path.join(folder, file)
134+
if (!fullPath.endsWith(".tsx")) continue
135+
136+
const raw = yield* fileSystem.readFileString(fullPath)
137+
const updated = applyUserAliases(raw, userConfig.aliases)
138+
139+
if (updated !== raw) {
140+
yield* fileSystem.writeFile(fullPath, Buffer.from(updated))
141+
}
142+
}
143+
}
144+
145+
}
146+
147+
return exitCode
89148
}),
90149
).pipe(Command.withDescription("Adds UI components or blocks to your project."))

src/lib/apply-user-aliases.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function applyUserAliases(content: string, aliases: Record<string, string>) {
2+
return Object.entries(aliases).reduce((updated, [alias, resolved]) => {
3+
const escaped = alias.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")
4+
const regex = new RegExp(`(["'])@/${escaped}(/[^"']*)?\\1`, "g")
5+
6+
return updated.replace(regex, (_match, quote, subpath = "") => {
7+
return `${quote}${resolved}${subpath}${quote}`
8+
})
9+
}, content)
10+
}

src/lib/walk-files.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// biome-ignore lint/style/useImportType: <explanation>
2+
import * as FS from "@effect/platform/FileSystem"
3+
import * as Path from "node:path"
4+
import { Effect } from "effect"
5+
6+
export function walkFiles(
7+
fs: FS.FileSystem,
8+
dir: string,
9+
): Effect.Effect<string[], unknown> {
10+
return Effect.gen(function* () {
11+
const entries = yield* fs.readDirectory(dir)
12+
const out: string[] = []
13+
14+
for (const entry of entries) {
15+
const full = Path.join(dir, entry)
16+
const info = yield* fs.stat(full)
17+
18+
if (info.type === "Directory") {
19+
const nested = yield* walkFiles(fs, full)
20+
out.push(...nested.map((f) => Path.join(entry, f)))
21+
} else if (info.type === "File") {
22+
out.push(entry)
23+
}
24+
}
25+
26+
return out
27+
})
28+
}

0 commit comments

Comments
 (0)