-
-
Notifications
You must be signed in to change notification settings - Fork 293
Expand file tree
/
Copy pathassemble.ts
More file actions
executable file
·94 lines (86 loc) · 2.95 KB
/
Copy pathassemble.ts
File metadata and controls
executable file
·94 lines (86 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#! /usr/bin/env node
import { createHash } from 'node:crypto'
import { glob, readFile, writeFile } from 'node:fs/promises'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { styleText } from 'node:util'
import { z } from 'zod'
import {
registrySourceItemSchema,
type Registry,
type RegistrySourceFile,
type RegistrySourceItem
} from './schemas.ts'
// Paths
const __dirname = fileURLToPath(new URL('.', import.meta.url))
const packageRoot = resolve(__dirname, '../../')
const docsItemsDir = resolve(__dirname, './items')
const registryItemsDir = resolve(packageRoot, 'node_modules/registry/items')
const remoteDir = resolve(__dirname, './remote')
const registryJson = resolve(packageRoot, 'registry.json')
async function loadItems() {
const [localFiles, registryFiles] = await Promise.all([
Array.fromAsync(glob(`${docsItemsDir}/*.json`)),
Array.fromAsync(glob(`${registryItemsDir}/*.json`))
])
const itemFiles = [...localFiles, ...registryFiles]
return await Promise.all(
itemFiles.map(async filePath => {
const item = await loadItem(filePath)
console.log(` ${styleText('green', '✔')} %s`, item.name)
return item
})
)
}
async function loadItem(filePath: string) {
const contents = await readFile(filePath, 'utf-8')
const item = registrySourceItemSchema.parse(JSON.parse(contents))
await hydrateItem(item)
return item
}
async function hydrateItem(item: RegistrySourceItem) {
async function hydrateFile(file: RegistrySourceFile) {
if (z.url().safeParse(file.path).success === false) {
return
}
const response = await fetch(file.path)
if (!response.ok) {
throw new Error(
`Failed to fetch file at ${file.path}: ${response.statusText}`
)
}
// This is kind of dumb, but we need to save it to a temporary file
// so that the `shadcn build` command can do this on the assembled registry.
const content = await response.text()
const tempFilePath = resolve(
remoteDir,
`${item.name}.${hash(file.path, file.target, content).slice(0, 12)}.txt`
)
await writeFile(tempFilePath, content)
file.path = tempFilePath.replace(packageRoot + '/', '')
}
return Promise.all(item.files.map(file => hydrateFile(file)))
}
function hash(...contents: string[]) {
const hash = createHash('sha256')
for (const content of contents) {
hash.update(content)
}
return hash.digest('base64url')
}
async function main() {
console.log(`${styleText('blue', 'i')} Assembling registry...`)
const items = await loadItems()
const registry: Registry = {
$schema: 'https://ui.shadcn.com/schema/registry.json',
name: 'nuqs',
homepage: 'https://nuqs.dev',
items: items.sort((a, b) => a.name.localeCompare(b.name))
}
await writeFile(registryJson, JSON.stringify(registry, null, 2), 'utf-8')
console.log(
`${styleText('green', '✔')} Registry assembled successfully (processed %d items)`,
items.length
)
}
await main()