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

Commit da8b162

Browse files
committed
fix: resolve diff command awaiting
1 parent 2088a37 commit da8b162

1 file changed

Lines changed: 90 additions & 3 deletions

File tree

src/commands/diff.command.ts

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,96 @@
11
import { Command } from "@effect/cli"
22
import { Console, Effect } from "effect"
3-
import { componentNames, componentType } from "./add.command"
3+
import {
4+
HttpClient,
5+
HttpClientRequest,
6+
HttpClientResponse,
7+
} from "@effect/platform"
8+
import * as FS from "node:fs/promises"
9+
import * as Path from "node:path"
410

5-
export const diffCommand = Command.make("diff", { componentNames, componentType }, (config) =>
11+
const REMOTE_BASE =
12+
"https://raw.githubusercontent.com/irsyadadl/intentui/2.x/components/ui"
13+
14+
function simpleDiff(local: string, remote: string): string {
15+
const l = local.split(/\r?\n/)
16+
const r = remote.split(/\r?\n/)
17+
const max = Math.max(l.length, r.length)
18+
let out = ""
19+
for (let i = 0; i < max; i++) {
20+
const a = l[i]
21+
const b = r[i]
22+
if (a !== b) {
23+
if (a !== undefined) out += `- ${a}\n`
24+
if (b !== undefined) out += `+ ${b}\n`
25+
}
26+
}
27+
return out
28+
}
29+
30+
async function listFiles(dir: string): Promise<string[]> {
31+
const entries = await FS.readdir(dir, { withFileTypes: true })
32+
const files: string[] = []
33+
for (const entry of entries) {
34+
const res = Path.join(dir, entry.name)
35+
if (entry.isDirectory()) {
36+
files.push(...(await listFiles(res)))
37+
} else {
38+
files.push(res)
39+
}
40+
}
41+
return files
42+
}
43+
44+
export const diffCommand = Command.make("diff", {}, () =>
645
Effect.gen(function* () {
7-
yield* Console.log("Coming soon...")
46+
const client = yield* HttpClient.HttpClient
47+
const cwd = process.cwd()
48+
let config
49+
try {
50+
const jsonStr = yield* Effect.tryPromise(() => FS.readFile("components.json", "utf8"))
51+
config = JSON.parse(jsonStr)
52+
} catch {
53+
yield* Console.error("components.json not found or invalid")
54+
return
55+
}
56+
57+
const alias: string = config.aliases?.ui ?? "components/ui"
58+
const uiPath = Path.isAbsolute(alias.replace(/^@\//, ""))
59+
? alias.replace(/^@\//, "")
60+
: Path.join(cwd, alias.replace(/^@\//, ""))
61+
62+
const filesResult = yield* Effect.tryPromise(() => listFiles(uiPath)).pipe(
63+
Effect.catchAll(() => Effect.succeed([] as string[])),
64+
)
65+
if (filesResult.length === 0) {
66+
yield* Console.error(`Unable to read local components at ${uiPath}`)
67+
return
68+
}
69+
const files = filesResult
70+
71+
const diffs: Array<{ file: string; diff: string }> = []
72+
for (const file of files) {
73+
const relative = Path.relative(uiPath, file).replace(/\\/g, "/")
74+
const remoteUrl = `${REMOTE_BASE}/${relative}`
75+
const localContent = yield* Effect.tryPromise(() => FS.readFile(file, "utf8"))
76+
const remoteContent = yield* HttpClientRequest.get(remoteUrl).pipe(
77+
client.execute,
78+
Effect.flatMap(HttpClientResponse.text),
79+
Effect.catchAll(() => Effect.succeed("")),
80+
)
81+
if (localContent !== remoteContent) {
82+
diffs.push({ file: relative, diff: simpleDiff(localContent, remoteContent) })
83+
}
84+
}
85+
86+
if (diffs.length === 0) {
87+
yield* Console.log("All components are up to date.")
88+
} else {
89+
for (const d of diffs) {
90+
yield* Console.log(`--- ${d.file} ---`)
91+
yield* Console.log(d.diff)
92+
}
93+
yield* Console.log("Some components differ from the registry. Run 'intentui add <component>' to sync.")
94+
}
895
}),
996
).pipe(Command.withDescription("Compares your local components with the registry versions."))

0 commit comments

Comments
 (0)