mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-18 05:11:32 +00:00
Compare commits
3 Commits
shadcn@3.2
...
shadcn@3.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
275e3a2d59 | ||
|
|
e5402f9a20 | ||
|
|
04668da018 |
@@ -87,7 +87,7 @@
|
||||
"recharts": "2.15.1",
|
||||
"rehype-pretty-code": "^0.14.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"shadcn": "3.2.0",
|
||||
"shadcn": "3.2.1",
|
||||
"shiki": "^1.10.1",
|
||||
"sonner": "^2.0.0",
|
||||
"tailwind-merge": "^3.0.1",
|
||||
|
||||
@@ -14,5 +14,6 @@
|
||||
"@heseui": "https://www.heseui.com/r/{name}.json",
|
||||
"@paceui-ui": "https://ui.paceui.com/r/{name}.json",
|
||||
"@basecn": "https://basecn.dev/r/{name}.json",
|
||||
"@ncdai": "https://chanhdai.com/r/{name}.json"
|
||||
"@ncdai": "https://chanhdai.com/r/{name}.json",
|
||||
"@8bitcn": "https://8bitcn.com/r/{name}.json"
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
"react-resizable-panels": "^2.0.22",
|
||||
"react-wrap-balancer": "^0.4.1",
|
||||
"recharts": "2.12.7",
|
||||
"shadcn": "3.2.0",
|
||||
"shadcn": "3.2.1",
|
||||
"sharp": "^0.32.6",
|
||||
"sonner": "^1.2.3",
|
||||
"swr": "2.2.6-beta.3",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @shadcn/ui
|
||||
|
||||
## 3.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#8147](https://github.com/shadcn-ui/ui/pull/8147) [`e5402f9a20f070e92e7384c1ae08e6bfb79cd7a9`](https://github.com/shadcn-ui/ui/commit/e5402f9a20f070e92e7384c1ae08e6bfb79cd7a9) Thanks [@shadcn](https://github.com/shadcn)! - fix recursive namespacing
|
||||
|
||||
## 3.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "shadcn",
|
||||
"version": "3.2.0",
|
||||
"version": "3.2.1",
|
||||
"description": "Add components to your apps.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
469
packages/shadcn/src/registry/namespaces.test.ts
Normal file
469
packages/shadcn/src/registry/namespaces.test.ts
Normal file
@@ -0,0 +1,469 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest"
|
||||
|
||||
import { Config } from "../utils/get-config"
|
||||
import { BUILTIN_REGISTRIES } from "./constants"
|
||||
import { RegistryNotConfiguredError } from "./errors"
|
||||
import { resolveRegistryNamespaces } from "./namespaces"
|
||||
import * as resolver from "./resolver"
|
||||
|
||||
// Mock the resolver module.
|
||||
vi.mock("./resolver", () => ({
|
||||
fetchRegistryItems: vi.fn(),
|
||||
}))
|
||||
|
||||
// Test utility function to check namespace configuration.
|
||||
function checkNamespaceConfiguration(
|
||||
namespaces: string[],
|
||||
config: Config
|
||||
): { configured: string[]; missing: string[] } {
|
||||
const configured: string[] = []
|
||||
const missing: string[] = []
|
||||
|
||||
for (const namespace of namespaces) {
|
||||
if (BUILTIN_REGISTRIES[namespace] || config.registries?.[namespace]) {
|
||||
configured.push(namespace)
|
||||
} else {
|
||||
missing.push(namespace)
|
||||
}
|
||||
}
|
||||
|
||||
return { configured, missing }
|
||||
}
|
||||
|
||||
describe("resolveRegistryNamespaces", () => {
|
||||
const mockConfig: Config = {
|
||||
style: "default",
|
||||
tailwind: {
|
||||
config: "tailwind.config.js",
|
||||
css: "app/globals.css",
|
||||
baseColor: "slate",
|
||||
cssVariables: true,
|
||||
},
|
||||
rsc: true,
|
||||
tsx: true,
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
utils: "@/lib/utils",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
hooks: "@/hooks",
|
||||
},
|
||||
resolvedPaths: {
|
||||
cwd: "/test",
|
||||
tailwindConfig: "/test/tailwind.config.js",
|
||||
tailwindCss: "/test/app/globals.css",
|
||||
utils: "/test/lib/utils",
|
||||
components: "/test/components",
|
||||
ui: "/test/components/ui",
|
||||
lib: "/test/lib",
|
||||
hooks: "/test/hooks",
|
||||
},
|
||||
registries: {
|
||||
...BUILTIN_REGISTRIES,
|
||||
"@foo": "https://foo.com/registry/{name}",
|
||||
"@bar": "https://bar.com/registry/{name}",
|
||||
},
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it("should discover namespaces from direct components", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems.mockResolvedValue([
|
||||
{ name: "button", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@foo/button", "@bar/card"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toEqual(["@foo", "@bar"])
|
||||
})
|
||||
|
||||
it("should skip built-in registries", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems.mockResolvedValue([
|
||||
{ name: "button", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@shadcn/button", "@foo/card"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toEqual(["@foo"])
|
||||
})
|
||||
|
||||
it("should discover namespaces from registry dependencies", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "dialog",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@bar/button", "@baz/modal"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "button", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "modal", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@foo/dialog"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toContain("@foo")
|
||||
expect(namespaces).toContain("@bar")
|
||||
expect(namespaces).toContain("@baz")
|
||||
})
|
||||
|
||||
it("should handle circular dependencies", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "comp-a",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@bar/comp-b"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "comp-b",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@foo/comp-a"],
|
||||
},
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@foo/comp-a"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toEqual(["@foo", "@bar"])
|
||||
// Should only fetch each component once despite circular reference.
|
||||
expect(mockFetchRegistryItems).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it("should handle RegistryNotConfiguredError gracefully", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems.mockRejectedValue(
|
||||
new RegistryNotConfiguredError("@unknown")
|
||||
)
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@unknown/button"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toEqual(["@unknown"])
|
||||
})
|
||||
|
||||
it("should continue processing on other errors", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockRejectedValueOnce(new Error("Network error"))
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "card", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@foo/button", "@bar/card"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
// Should still discover both @foo and @bar.
|
||||
// @foo from the initial parse, @bar from successful fetch.
|
||||
expect(namespaces).toContain("@foo")
|
||||
expect(namespaces).toContain("@bar")
|
||||
expect(namespaces).toHaveLength(2)
|
||||
})
|
||||
|
||||
it("should handle deeply nested dependencies", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "level-1",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@level2/component"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "component",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@level3/deep"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "deep",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
},
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@level1/level-1"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toEqual(["@level1", "@level2", "@level3"])
|
||||
})
|
||||
|
||||
it("should return unique namespaces", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "comp-a",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@foo/shared", "@bar/shared"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "shared", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "shared", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["@foo/comp-a", "@foo/comp-b", "@bar/comp-c"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
// Should not have duplicate @foo.
|
||||
expect(namespaces).toEqual(["@foo", "@bar"])
|
||||
})
|
||||
|
||||
it("should handle components without namespace", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems.mockResolvedValue([
|
||||
{ name: "button", type: "registry:ui", files: [], dependencies: [] },
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["button", "@foo/card"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toEqual(["@foo"])
|
||||
})
|
||||
|
||||
it("should handle empty input", async () => {
|
||||
const namespaces = await resolveRegistryNamespaces([], mockConfig)
|
||||
|
||||
expect(namespaces).toEqual([])
|
||||
expect(resolver.fetchRegistryItems).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should discover namespaces from components without namespaces but with registryDependencies", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "my-component",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@foo/dep1", "@bar/dep2"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "dep1",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "dep2",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
},
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["button"], // Component without namespace
|
||||
mockConfig
|
||||
)
|
||||
|
||||
// Should discover namespaces from registryDependencies even though "button" has no namespace.
|
||||
expect(namespaces).toEqual(["@foo", "@bar"])
|
||||
})
|
||||
|
||||
it("should discover namespaces from URL components with registryDependencies", async () => {
|
||||
const mockFetchRegistryItems = vi.mocked(resolver.fetchRegistryItems)
|
||||
mockFetchRegistryItems
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "to-8bitcn",
|
||||
type: "registry:item",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
registryDependencies: ["@8bitcn/button"],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "branch",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
},
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
{
|
||||
name: "button",
|
||||
type: "registry:ui",
|
||||
files: [],
|
||||
dependencies: [],
|
||||
},
|
||||
])
|
||||
|
||||
const namespaces = await resolveRegistryNamespaces(
|
||||
["https://api.npoint.io/2e006917dca7f7367495", "@ai-elements/branch"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(namespaces).toContain("@8bitcn")
|
||||
expect(namespaces).toContain("@ai-elements")
|
||||
|
||||
// Verify fetchRegistryItems was called with the correct arguments.
|
||||
expect(mockFetchRegistryItems).toHaveBeenCalledWith(
|
||||
["https://api.npoint.io/2e006917dca7f7367495"],
|
||||
mockConfig,
|
||||
{ useCache: true }
|
||||
)
|
||||
expect(mockFetchRegistryItems).toHaveBeenCalledWith(
|
||||
["@ai-elements/branch"],
|
||||
mockConfig,
|
||||
{ useCache: true }
|
||||
)
|
||||
expect(mockFetchRegistryItems).toHaveBeenCalledWith(
|
||||
["@8bitcn/button"],
|
||||
mockConfig,
|
||||
{ useCache: true }
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("checkNamespaceConfiguration", () => {
|
||||
const mockConfig: Config = {
|
||||
style: "default",
|
||||
tailwind: {
|
||||
config: "tailwind.config.js",
|
||||
css: "app/globals.css",
|
||||
baseColor: "slate",
|
||||
cssVariables: true,
|
||||
},
|
||||
rsc: true,
|
||||
tsx: true,
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
utils: "@/lib/utils",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
hooks: "@/hooks",
|
||||
},
|
||||
resolvedPaths: {
|
||||
cwd: "/test",
|
||||
tailwindConfig: "/test/tailwind.config.js",
|
||||
tailwindCss: "/test/app/globals.css",
|
||||
utils: "/test/lib/utils",
|
||||
components: "/test/components",
|
||||
ui: "/test/components/ui",
|
||||
lib: "/test/lib",
|
||||
hooks: "/test/hooks",
|
||||
},
|
||||
registries: {
|
||||
...BUILTIN_REGISTRIES,
|
||||
"@foo": "https://foo.com/registry/{name}",
|
||||
"@bar": "https://bar.com/registry/{name}",
|
||||
},
|
||||
}
|
||||
|
||||
it("should identify configured namespaces", () => {
|
||||
const result = checkNamespaceConfiguration(["@foo", "@bar"], mockConfig)
|
||||
|
||||
expect(result.configured).toEqual(["@foo", "@bar"])
|
||||
expect(result.missing).toEqual([])
|
||||
})
|
||||
|
||||
it("should identify missing namespaces", () => {
|
||||
const result = checkNamespaceConfiguration(
|
||||
["@foo", "@unknown", "@missing"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(result.configured).toEqual(["@foo"])
|
||||
expect(result.missing).toEqual(["@unknown", "@missing"])
|
||||
})
|
||||
|
||||
it("should handle built-in registries as configured", () => {
|
||||
const result = checkNamespaceConfiguration(["@shadcn", "@foo"], mockConfig)
|
||||
|
||||
expect(result.configured).toEqual(["@shadcn", "@foo"])
|
||||
expect(result.missing).toEqual([])
|
||||
})
|
||||
|
||||
it("should handle empty input", () => {
|
||||
const result = checkNamespaceConfiguration([], mockConfig)
|
||||
|
||||
expect(result.configured).toEqual([])
|
||||
expect(result.missing).toEqual([])
|
||||
})
|
||||
|
||||
it("should handle config without registries", () => {
|
||||
const configWithoutRegistries: Config = {
|
||||
...mockConfig,
|
||||
registries: undefined,
|
||||
}
|
||||
|
||||
const result = checkNamespaceConfiguration(
|
||||
["@foo", "@bar"],
|
||||
configWithoutRegistries
|
||||
)
|
||||
|
||||
expect(result.configured).toEqual([])
|
||||
expect(result.missing).toEqual(["@foo", "@bar"])
|
||||
})
|
||||
|
||||
it("should handle mixed configured and missing namespaces", () => {
|
||||
const result = checkNamespaceConfiguration(
|
||||
["@shadcn", "@foo", "@unknown", "@bar", "@missing"],
|
||||
mockConfig
|
||||
)
|
||||
|
||||
expect(result.configured).toContain("@shadcn")
|
||||
expect(result.configured).toContain("@foo")
|
||||
expect(result.configured).toContain("@bar")
|
||||
expect(result.missing).toContain("@unknown")
|
||||
expect(result.missing).toContain("@missing")
|
||||
})
|
||||
})
|
||||
63
packages/shadcn/src/registry/namespaces.ts
Normal file
63
packages/shadcn/src/registry/namespaces.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { BUILTIN_REGISTRIES } from "@/src/registry/constants"
|
||||
import { RegistryNotConfiguredError } from "@/src/registry/errors"
|
||||
import { parseRegistryAndItemFromString } from "@/src/registry/parser"
|
||||
import { fetchRegistryItems } from "@/src/registry/resolver"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
|
||||
// Recursively discovers all registry namespaces including nested ones.
|
||||
export async function resolveRegistryNamespaces(
|
||||
components: string[],
|
||||
config: Config
|
||||
) {
|
||||
const discoveredNamespaces = new Set<string>()
|
||||
const visitedItems = new Set<string>()
|
||||
const itemsToProcess = [...components]
|
||||
|
||||
while (itemsToProcess.length > 0) {
|
||||
const currentItem = itemsToProcess.shift()!
|
||||
|
||||
if (visitedItems.has(currentItem)) {
|
||||
continue
|
||||
}
|
||||
visitedItems.add(currentItem)
|
||||
|
||||
const { registry } = parseRegistryAndItemFromString(currentItem)
|
||||
if (registry && !BUILTIN_REGISTRIES[registry]) {
|
||||
discoveredNamespaces.add(registry)
|
||||
}
|
||||
|
||||
try {
|
||||
const [item] = await fetchRegistryItems([currentItem], config, {
|
||||
useCache: true,
|
||||
})
|
||||
|
||||
if (item?.registryDependencies) {
|
||||
for (const dep of item.registryDependencies) {
|
||||
const { registry: depRegistry } = parseRegistryAndItemFromString(dep)
|
||||
if (depRegistry && !BUILTIN_REGISTRIES[depRegistry]) {
|
||||
discoveredNamespaces.add(depRegistry)
|
||||
}
|
||||
|
||||
if (!visitedItems.has(dep)) {
|
||||
itemsToProcess.push(dep)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// If a registry is not configured, we still track it.
|
||||
if (error instanceof RegistryNotConfiguredError) {
|
||||
const { registry } = parseRegistryAndItemFromString(currentItem)
|
||||
if (registry && !BUILTIN_REGISTRIES[registry]) {
|
||||
discoveredNamespaces.add(registry)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// For other errors (network, parsing, etc.), we skip this item
|
||||
// but continue processing others to discover as many namespaces as possible.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(discoveredNamespaces)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "path"
|
||||
import { fetchRegistries } from "@/src/registry/api"
|
||||
import { BUILTIN_REGISTRIES } from "@/src/registry/constants"
|
||||
import { parseRegistryAndItemFromString } from "@/src/registry/parser"
|
||||
import { resolveRegistryNamespaces } from "@/src/registry/namespaces"
|
||||
import { rawConfigSchema } from "@/src/registry/schema"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { spinner } from "@/src/utils/spinner"
|
||||
@@ -21,16 +21,10 @@ export async function ensureRegistriesInConfig(
|
||||
...options,
|
||||
}
|
||||
|
||||
const registryNames = new Set<string>()
|
||||
// Use resolveRegistryNamespaces to discover all namespaces including dependencies.
|
||||
const registryNames = await resolveRegistryNamespaces(components, config)
|
||||
|
||||
for (const component of components) {
|
||||
const { registry } = parseRegistryAndItemFromString(component)
|
||||
if (registry) {
|
||||
registryNames.add(registry)
|
||||
}
|
||||
}
|
||||
|
||||
const missingRegistries = Array.from(registryNames).filter(
|
||||
const missingRegistries = registryNames.filter(
|
||||
(registry) =>
|
||||
!config.registries?.[registry] &&
|
||||
!Object.keys(BUILTIN_REGISTRIES).includes(registry)
|
||||
|
||||
@@ -18,12 +18,8 @@ export async function createRegistryServer(
|
||||
// Handle registries.json endpoint (don't strip .json for this one)
|
||||
if (urlRaw?.endsWith("/registries.json")) {
|
||||
response.writeHead(200, { "Content-Type": "application/json" })
|
||||
response.end(
|
||||
JSON.stringify({
|
||||
"@one": `http://localhost:${port}${path}/{name}`,
|
||||
"@two": `http://localhost:5555/registry/{name}`,
|
||||
})
|
||||
)
|
||||
// Return empty registry index for tests - we want to test manual configuration.
|
||||
response.end(JSON.stringify({}))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@@ -325,7 +325,7 @@ importers:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
shadcn:
|
||||
specifier: 3.2.0
|
||||
specifier: 3.2.1
|
||||
version: link:../../packages/shadcn
|
||||
shiki:
|
||||
specifier: ^1.10.1
|
||||
@@ -605,7 +605,7 @@ importers:
|
||||
specifier: 2.12.7
|
||||
version: 2.12.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
shadcn:
|
||||
specifier: 3.2.0
|
||||
specifier: 3.2.1
|
||||
version: link:../../packages/shadcn
|
||||
sharp:
|
||||
specifier: ^0.32.6
|
||||
|
||||
Reference in New Issue
Block a user