Home / File/ search.ts — ui Source File

search.ts — ui Source File

Architecture documentation for search.ts, a typescript file in the ui codebase. 13 imports, 0 dependents.

File typescript FrameworkTooling CLICore 13 imports 1 functions

Entity Profile

Dependency Diagram

graph LR
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc["search.ts"]
  d05ec4ea_7a68_3a36_bfa4_9ba7f8409ee5["path"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> d05ec4ea_7a68_3a36_bfa4_9ba7f8409ee5
  1f2f79fc_356c_e956_002d_737290df27fd["config"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> 1f2f79fc_356c_e956_002d_737290df27fd
  ff842930_3a95_1c03_7d51_b342f47a7971["context"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> ff842930_3a95_1c03_7d51_b342f47a7971
  ca3bad94_bf9d_90f4_f711_b0bd7a5c4cd0["search"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> ca3bad94_bf9d_90f4_f711_b0bd7a5c4cd0
  57e5010f_701c_22f8_5921_3e11fc3c65aa["validator"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> 57e5010f_701c_22f8_5921_3e11fc3c65aa
  a3b2545e_3d8c_699d_ef11_6ab18db14666["schema"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> a3b2545e_3d8c_699d_ef11_6ab18db14666
  b900020d_484b_aaae_1b3f_6d4201875bd9["env-loader"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> b900020d_484b_aaae_1b3f_6d4201875bd9
  b2895591_2a74_d518_deda_2f26be766dcb["get-config"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> b2895591_2a74_d518_deda_2f26be766dcb
  6be7d8a9_c93c_8743_3ef7_968efff25479["handle-error"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> 6be7d8a9_c93c_8743_3ef7_968efff25479
  a54774e0_4fdd_ca8d_dfff_060d01ad3f57["registries"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> a54774e0_4fdd_ca8d_dfff_060d01ad3f57
  7d629454_eee6_73fe_2526_919af8d00ef9["commander"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> 7d629454_eee6_73fe_2526_919af8d00ef9
  f9f5e551_eb59_1a6b_8bf2_b97e73eb13de["fs-extra"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> f9f5e551_eb59_1a6b_8bf2_b97e73eb13de
  6802ce19_522d_e5fb_e458_8826d9f6952e["zod"]
  4e5f7e35_b0ab_caaf_1279_d9bb981befcc --> 6802ce19_522d_e5fb_e458_8826d9f6952e
  style 4e5f7e35_b0ab_caaf_1279_d9bb981befcc fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

import path from "path"
import { configWithDefaults } from "@/src/registry/config"
import { clearRegistryContext } from "@/src/registry/context"
import { searchRegistries } from "@/src/registry/search"
import { validateRegistryConfigForItems } from "@/src/registry/validator"
import { rawConfigSchema } from "@/src/schema"
import { loadEnvFiles } from "@/src/utils/env-loader"
import { createConfig, getConfig } from "@/src/utils/get-config"
import { handleError } from "@/src/utils/handle-error"
import { ensureRegistriesInConfig } from "@/src/utils/registries"
import { Command } from "commander"
import fsExtra from "fs-extra"
import { z } from "zod"

const searchOptionsSchema = z.object({
  cwd: z.string(),
  query: z.string().optional(),
  limit: z.number().optional(),
  offset: z.number().optional(),
})

// TODO: We're duplicating logic for shadowConfig here.
// Revisit and properly abstract this.

export const search = new Command()
  .name("search")
  .alias("list")
  .description("search items from registries")
  .argument(
    "<registries...>",
    "the registry names or urls to search items from. Names must be prefixed with @."
  )
  .option(
    "-c, --cwd <cwd>",
    "the working directory. defaults to the current directory.",
    process.cwd()
  )
  .option("-q, --query <query>", "query string")
  .option(
    "-l, --limit <number>",
    "maximum number of items to display per registry",
    "100"
  )
  .option("-o, --offset <number>", "number of items to skip", "0")
  .action(async (registries: string[], opts) => {
    try {
      const options = searchOptionsSchema.parse({
        cwd: path.resolve(opts.cwd),
        query: opts.query,
        limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
        offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
      })

      await loadEnvFiles(options.cwd)

      // Start with a shadow config to support partial components.json.
      // Use createConfig to get proper default paths
      const defaultConfig = createConfig({
        style: "new-york",
        resolvedPaths: {
          cwd: options.cwd,
        },
      })
      let shadowConfig = configWithDefaults(defaultConfig)

      // Check if there's a components.json file (partial or complete).
      const componentsJsonPath = path.resolve(options.cwd, "components.json")
      if (fsExtra.existsSync(componentsJsonPath)) {
        const existingConfig = await fsExtra.readJson(componentsJsonPath)
        const partialConfig = rawConfigSchema.partial().parse(existingConfig)
        shadowConfig = configWithDefaults({
          ...defaultConfig,
          ...partialConfig,
        })
      }

      // Try to get the full config, but fall back to shadow config if it fails.
      let config = shadowConfig
      try {
        const fullConfig = await getConfig(options.cwd)
        if (fullConfig) {
          config = configWithDefaults(fullConfig)
        }
      } catch {
        // Use shadow config if getConfig fails (partial components.json).
      }

      const { config: updatedConfig, newRegistries } =
        await ensureRegistriesInConfig(
          registries.map((registry) => `${registry}/registry`),
          config,
          {
            silent: true,
            writeFile: false,
          }
        )
      if (newRegistries.length > 0) {
        config.registries = updatedConfig.registries
      }

      // Validate registries early for better error messages.
      validateRegistryConfigForItems(registries, config)

      // Use searchRegistries for both search and non-search cases
      const results = await searchRegistries(registries as `@${string}`[], {
        query: options.query,
        limit: options.limit,
        offset: options.offset,
        config,
      })

      console.log(JSON.stringify(results, null, 2))
      process.exit(0)
    } catch (error) {
      handleError(error)
    } finally {
      clearRegistryContext()
    }
  })

Subdomains

Functions

Dependencies

  • commander
  • config
  • context
  • env-loader
  • fs-extra
  • get-config
  • handle-error
  • path
  • registries
  • schema
  • search
  • validator
  • zod

Frequently Asked Questions

What does search.ts do?
search.ts is a source file in the ui codebase, written in typescript. It belongs to the FrameworkTooling domain, CLICore subdomain.
What functions are defined in search.ts?
search.ts defines 1 function(s): search.
What does search.ts depend on?
search.ts imports 13 module(s): commander, config, context, env-loader, fs-extra, get-config, handle-error, path, and 5 more.
Where is search.ts in the architecture?
search.ts is located at packages/shadcn/src/commands/search.ts (domain: FrameworkTooling, subdomain: CLICore, directory: packages/shadcn/src/commands).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free