From 5b261a67a86dbe3728cf0673d13c57dd16a93e35 Mon Sep 17 00:00:00 2001 From: Hunter Johnston Date: Mon, 21 Oct 2024 21:02:09 -0400 Subject: [PATCH] more stuff --- packages/cli/package.json | 1 + packages/cli/src/commands/add.ts | 44 +++++++++++++---- packages/cli/src/commands/update.ts | 9 ++-- packages/cli/src/utils/get-config.ts | 2 + packages/cli/src/utils/registry/index.ts | 57 ++++++++++++++++++++--- packages/cli/src/utils/registry/schema.ts | 11 +++-- playgrounds/playground-ts/package.json | 1 + pnpm-lock.yaml | 27 +++++++++++ 8 files changed, 130 insertions(+), 22 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 4187e2411..91c82de5a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -43,6 +43,7 @@ "@clack/core": "^0.3.4", "chalk": "5.2.0", "commander": "^10.0.1", + "deepmerge": "^4.3.1", "execa": "^7.2.0", "is-unicode-supported": "^2.0.0", "node-fetch-native": "^1.6.4" diff --git a/packages/cli/src/commands/add.ts b/packages/cli/src/commands/add.ts index 1de9b69c2..7b3659c08 100644 --- a/packages/cli/src/commands/add.ts +++ b/packages/cli/src/commands/add.ts @@ -13,10 +13,9 @@ import { intro, prettifyList } from "../utils/prompt-helpers.js"; import * as p from "../utils/prompts.js"; import { fetchTree, - getItemTargetPath, // getRegistryBaseColor, getRegistryIndex, - registryResolveItemsTree, + getRegistryItemFileTargetPath, resolveTree, } from "../utils/registry/index.js"; import { transformImports } from "../utils/transformers.js"; @@ -119,13 +118,39 @@ async function runAdd(cwd: string, config: Config, options: AddOptions) { // adds `registryDependency` to `selectedComponents` so that they can be individually overwritten for (const name of selectedComponents) { - const regDeps = registryDepMap.get(name); - regDeps?.forEach((dep) => selectedComponents.add(dep)); + if (registryDepMap.has(name)) { + const regDeps = registryDepMap.get(name); + regDeps?.forEach((dep) => selectedComponents.add(dep)); + } else { + const tree = await resolveTree({ + index: registryIndex, + names: [name], + includeRegDeps: true, + config, + }); + for (const item of tree) { + console.log( + "item name:", + item.name, + "registryDependencies:", + item.registryDependencies + ); + registryDepMap.set(item.name, item.registryDependencies); + for (const regDep of item.registryDependencies) { + const regDeps = registryDepMap.get(regDep); + regDeps?.forEach((dep) => selectedComponents.add(dep)); + } + } + } } - const res = await registryResolveItemsTree(Array.from(selectedComponents), config); + const tree = await resolveTree({ + index: registryIndex, + names: Array.from(selectedComponents), + includeRegDeps: false, + config, + }); - const tree = await resolveTree(registryIndex, Array.from(selectedComponents), false); const payload = await fetchTree(config, tree); // const baseColor = await getRegistryBaseColor(config.tailwind.baseColor); @@ -139,8 +164,11 @@ async function runAdd(cwd: string, config: Config, options: AddOptions) { const targetPath = options.path ? path.resolve(cwd, options.path) : undefined; for (const item of payload) { if (selectedComponents.has(item.name) === false) continue; + for (const regDep of item.registryDependencies) { + selectedComponents.add(regDep); + } - const targetDir = getItemTargetPath(config, item, targetPath); + const targetDir = getRegistryItemFileTargetPath(config, item, targetPath); if (targetDir === null) continue; const componentExists = item.files.some((file) => { @@ -190,7 +218,7 @@ async function runAdd(cwd: string, config: Config, options: AddOptions) { const dependencies = new Set(); const tasks: p.Task[] = []; for (const item of payload) { - const targetDir = getItemTargetPath(config, item, targetPath); + const targetDir = getRegistryItemFileTargetPath(config, item, targetPath); if (targetDir === null) continue; if (!existsSync(targetDir)) { diff --git a/packages/cli/src/commands/update.ts b/packages/cli/src/commands/update.ts index a09f01e2f..a05c70664 100644 --- a/packages/cli/src/commands/update.ts +++ b/packages/cli/src/commands/update.ts @@ -170,10 +170,11 @@ async function runUpdate(cwd: string, config: Config, options: UpdateOptions) { await fs.writeFile(utilsPath, config.typescript ? UTILS : UTILS_JS); } - const tree = await resolveTree( - registryIndex, - selectedComponents.map((com) => com.name) - ); + const tree = await resolveTree({ + index: registryIndex, + names: selectedComponents.map((com) => com.name), + config, + }); const payload = (await fetchTree(config, tree)).sort((a, b) => a.name.localeCompare(b.name)); const componentsToRemove: Record = {}; diff --git a/packages/cli/src/utils/get-config.ts b/packages/cli/src/utils/get-config.ts index 88442508a..7e9e52cfd 100644 --- a/packages/cli/src/utils/get-config.ts +++ b/packages/cli/src/utils/get-config.ts @@ -50,6 +50,7 @@ export const configSchema = v.object({ ...rawConfigSchema.entries, ...v.object({ resolvedPaths: v.object({ + cwd: v.string(), tailwindConfig: v.string(), tailwindCss: v.string(), utils: v.string(), @@ -105,6 +106,7 @@ export async function resolveConfigPaths(cwd: string, config: RawConfig) { return v.parse(configSchema, { ...config, resolvedPaths: { + cwd, tailwindConfig: path.resolve(cwd, config.tailwind.config), tailwindCss: path.resolve(cwd, config.tailwind.css), utils: utilsPath, diff --git a/packages/cli/src/utils/registry/index.ts b/packages/cli/src/utils/registry/index.ts index ef66ecd06..d112e02fa 100644 --- a/packages/cli/src/utils/registry/index.ts +++ b/packages/cli/src/utils/registry/index.ts @@ -1,3 +1,4 @@ +import deepmerge from "deepmerge"; import { fetch } from "node-fetch-native"; import { createProxy } from "node-fetch-native/proxy"; import path from "node:path"; @@ -80,20 +81,40 @@ export async function getRegistryBaseColor(baseColor: string) { type RegistryIndex = v.InferOutput; -export async function resolveTree(index: RegistryIndex, names: string[], includeRegDeps = true) { +type ResolveTreeProps = { + index: RegistryIndex; + names: string[]; + includeRegDeps?: boolean; + config: Config; +}; + +export async function resolveTree({ + index, + names, + includeRegDeps = true, + config, +}: ResolveTreeProps) { const tree: RegistryIndex = []; for (const name of names) { - const entry = index.find((entry) => entry.name === name); + let entry = index.find((entry) => entry.name === name); if (!entry) { - continue; + // attempt to find entry elsewhere in the registry + const trueStyle = config.typescript ? config.style : `${config.style}-js`; + const [item] = await fetchRegistry([`styles/${trueStyle}/${name}.json`]); + if (item) entry = item; + if (!entry) continue; } tree.push(entry); if (includeRegDeps && entry.registryDependencies) { - const dependencies = await resolveTree(index, entry.registryDependencies); + const dependencies = await resolveTree({ + index, + names: entry.registryDependencies, + config, + }); tree.push(...dependencies); } } @@ -145,7 +166,9 @@ async function fetchRegistry(paths: string[]) { const response = await fetch(url, { ...proxy, }); - return await response.json(); + + const json = await response.json(); + return json; }) ); @@ -172,6 +195,7 @@ export async function registryResolveItemsTree(names: string[], config: Config) const itemRegistryDependencies = await resolveRegistryDependencies(name, config); registryDependencies.push(...itemRegistryDependencies); } + console.log("REGISTRY DEPENDENCIES", registryDependencies); const uniqueRegistryDeps = Array.from(new Set(registryDependencies)); const result = await fetchRegistry(uniqueRegistryDeps); @@ -180,8 +204,8 @@ export async function registryResolveItemsTree(names: string[], config: Config) if (!payload) return null; return v.parse(schemas.registryResolvedItemsTreeSchema, { - dependencies: payload.map((item) => item.dependencies ?? []), - files: payload.map((item) => item.files ?? []), + dependencies: deepmerge.all(payload.map((item) => item.dependencies ?? [])), + files: deepmerge.all(payload.map((item) => item.files ?? [])), }); } catch (e) { if (e instanceof CLIError) throw e; @@ -230,3 +254,22 @@ function isUrl(path: string) { return false; } } + +export function getRegistryItemFileTargetPath( + config: Config, + file: schemas.RegistryItem, + override?: string +) { + if (override) return override; + + if (file.type === "registry:ui") return config.resolvedPaths.ui; + if (file.type === "registry:lib") return config.resolvedPaths.lib; + if (file.type === "registry:block" || file.type === "registry:component") { + return config.resolvedPaths.components; + } + if (file.type === "registry:hook") return config.resolvedPaths.hooks; + // TODO - we put this in components for now but will move to the appropriate route location + // depending on if using SvelteKit or whatever + if (file.type === "registry:page") return config.resolvedPaths.components; + return config.resolvedPaths.components; +} diff --git a/packages/cli/src/utils/registry/schema.ts b/packages/cli/src/utils/registry/schema.ts index 13c472d28..c46971d1e 100644 --- a/packages/cli/src/utils/registry/schema.ts +++ b/packages/cli/src/utils/registry/schema.ts @@ -6,6 +6,8 @@ const registryItemTypeSchema = v.picklist([ "registry:example", "registry:block", "registry:hook", + "registry:page", + "registry:lib", ]); export const registryItemTailwindSchema = v.object({ @@ -21,9 +23,10 @@ export const registryItemTailwindSchema = v.object({ export const registryItemFileSchema = v.object({ content: v.fallback(v.string(), ""), type: registryItemTypeSchema, - target: v.fallback(v.string(), ""), }); +export type RegistryItemFile = v.InferOutput; + export type RegistryItemTailwind = v.InferOutput; export const registryItemCssVarsSchema = v.object({ @@ -33,14 +36,16 @@ export const registryItemCssVarsSchema = v.object({ export const registryItemSchema = v.object({ name: v.string(), - dependencies: v.array(v.string()), - registryDependencies: v.array(v.string()), + dependencies: v.fallback(v.array(v.string()), []), + registryDependencies: v.fallback(v.array(v.string()), []), files: v.array(registryItemFileSchema), type: registryItemTypeSchema, tailwind: v.optional(registryItemTailwindSchema), cssVars: v.optional(registryItemCssVarsSchema), }); +export type RegistryItem = v.InferOutput; + export const registryResolvedItemsTreeSchema = v.pick(registryItemSchema, [ "dependencies", "files", diff --git a/playgrounds/playground-ts/package.json b/playgrounds/playground-ts/package.json index a528a5a16..270fba6a4 100644 --- a/playgrounds/playground-ts/package.json +++ b/playgrounds/playground-ts/package.json @@ -23,6 +23,7 @@ "vite": "^5.0.3" }, "dependencies": { + "bits-ui": "1.0.0-next.21", "clsx": "^2.1.1", "lucide-svelte": "^0.453.0", "shadcn-svelte": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e896ec8c9..ee4b94d17 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,9 @@ importers: commander: specifier: ^10.0.1 version: 10.0.1 + deepmerge: + specifier: ^4.3.1 + version: 4.3.1 execa: specifier: ^7.2.0 version: 7.2.0 @@ -181,6 +184,9 @@ importers: playgrounds/playground-ts: dependencies: + bits-ui: + specifier: 1.0.0-next.21 + version: 1.0.0-next.21(svelte@5.0.4) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -8935,6 +8941,16 @@ snapshots: svelte: 5.0.3 svelte-toolbelt: 0.4.4(svelte@5.0.3) + bits-ui@1.0.0-next.21(svelte@5.0.4): + dependencies: + '@floating-ui/core': 1.6.4 + '@floating-ui/dom': 1.6.7 + '@internationalized/date': 3.5.6 + esm-env: 1.0.0 + runed: 0.15.2(svelte@5.0.4) + svelte: 5.0.4 + svelte-toolbelt: 0.4.4(svelte@5.0.4) + blake3-wasm@2.1.5: {} boolbase@1.0.0: {} @@ -12182,6 +12198,11 @@ snapshots: esm-env: 1.0.0 svelte: 5.0.3 + runed@0.15.2(svelte@5.0.4): + dependencies: + esm-env: 1.0.0 + svelte: 5.0.4 + rw@1.3.3: {} rxjs@7.8.1: @@ -12630,6 +12651,12 @@ snapshots: style-to-object: 1.0.8 svelte: 5.0.3 + svelte-toolbelt@0.4.4(svelte@5.0.4): + dependencies: + clsx: 2.1.1 + style-to-object: 1.0.8 + svelte: 5.0.4 + svelte@4.2.12: dependencies: '@ampproject/remapping': 2.3.0