fix: cli installation error

This commit is contained in:
zernonia 2023-09-06 12:55:50 +08:00
parent bc545c95e4
commit ec0c3cc659
12 changed files with 167 additions and 162 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.env
node_modules
.DS_Store
dist

View File

@ -292,74 +292,41 @@ Add the following to your `src/app.postcss` file. You can learn more about using
You'll want to create a `cn` helper to make it easier to conditionally add Tailwind CSS classes. Additionally, you'll want to add the custom transition that is used by various components.
```ts title="src/lib/utils.ts"
import type { Updater } from '@tanstack/vue-table'
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { cubicOut } from 'svelte/easing'
import type { TransitionConfig } from 'svelte/transition'
import { type Ref, camelize, getCurrentInstance, toHandlerKey } from 'vue'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
interface FlyAndScaleParams {
y?: number
x?: number
start?: number
duration?: number
// Vue doesn't have emits forwarding, in order to bind the emits we have to convert events into `onXXX` handlers
// issue: https://github.com/vuejs/core/issues/5917
export function useEmitAsProps<Name extends string>(
emit: (name: Name, ...args: any[]) => void,
) {
const vm = getCurrentInstance()
const events = vm?.type.emits as Name[]
const result: Record<string, any> = {}
if (!events?.length) {
console.warn(
`No emitted event found. Please check component: ${vm?.type.__name}`,
)
}
export function flyAndScale(node: Element,
params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }): TransitionConfig {
const style = getComputedStyle(node)
const transform = style.transform === 'none' ? '' : style.transform
const scaleConversion = (
valueA: number,
scaleA: [number, number],
scaleB: [number, number]
) => {
const [minA, maxA] = scaleA
const [minB, maxB] = scaleB
const percentage = (valueA - minA) / (maxA - minA)
const valueB = percentage * (maxB - minB) + minB
return valueB
}
const styleToString = (
style: Record<string, number | string | undefined>
): string => {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined)
return str
return `${str + key}:${style[key]};`
}, '')
}
return {
duration: params.duration ?? 200,
delay: 0,
css: (t) => {
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0])
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0])
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1])
return styleToString({
transform:
`${transform
}translate3d(${
x
}px, ${
y
}px, 0) scale(${
scale
})`,
opacity: t
events?.forEach((ev) => {
result[toHandlerKey(camelize(ev))] = (...arg: any) => emit(ev, ...arg)
})
},
easing: cubicOut
return result
}
export function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref) {
ref.value
= typeof updaterOrValue === 'function'
? updaterOrValue(ref.value)
: updaterOrValue
}
```

View File

@ -1,13 +1,7 @@
import type { Updater } from '@tanstack/vue-table'
import type { ClassValue } from 'clsx'
import { clsx } from 'clsx'
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
import type { FunctionalComponent, Ref } from 'vue'
import { camelize, defineComponent, getCurrentInstance, h, toHandlerKey } from 'vue'
export type ParseEmits<T extends Record<string, any>> = {
[K in keyof T]: (...args: T[K]) => void;
}
import { type Ref, camelize, getCurrentInstance, toHandlerKey } from 'vue'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
@ -34,15 +28,19 @@ export function useEmitAsProps<Name extends string>(
return result
}
export function convertToComponent(component: FunctionalComponent) {
return defineComponent({
setup() { return () => h(component) },
})
}
export function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref) {
ref.value
= typeof updaterOrValue === 'function'
? updaterOrValue(ref.value)
: updaterOrValue
}
// export type ParseEmits<T extends Record<string, any>> = {
// [K in keyof T]: (...args: T[K]) => void;
// }
// export function convertToComponent(component: FunctionalComponent) {
// return defineComponent({
// setup() { return () => h(component) },
// })
// }

View File

@ -72,6 +72,7 @@
"@types/lodash.template": "^4.5.1",
"@types/prompts": "^2.4.4",
"@vitest/ui": "^0.34.3",
"magic-string": "^0.30.3",
"rimraf": "^5.0.1",
"tsup": "^7.2.0",
"type-fest": "^4.3.0",

View File

@ -7,6 +7,7 @@ import { execa } from 'execa'
import ora from 'ora'
import prompts from 'prompts'
import * as z from 'zod'
import { transformImport } from '../utils/transformers/transform-import'
import { getConfig } from '@/src/utils/get-config'
import { getPackageManager } from '@/src/utils/get-package-manager'
import { handleError } from '@/src/utils/handle-error'
@ -18,7 +19,6 @@ import {
getRegistryIndex,
resolveTree,
} from '@/src/utils/registry'
import { transform } from '@/src/utils/transformers'
const addOptionsSchema = z.object({
components: z.array(z.string()).optional(),
@ -107,6 +107,7 @@ export const add = new Command()
}
const spinner = ora('Installing components...').start()
const skippedDeps = new Set<string>()
for (const item of payload) {
spinner.text = `Installing ${item.name}...`
const targetDir = await getItemTargetPath(
@ -122,41 +123,49 @@ export const add = new Command()
await fs.mkdir(targetDir, { recursive: true })
const existingComponent = item.files.filter(file =>
existsSync(path.resolve(targetDir, file.name)),
existsSync(path.resolve(targetDir, item.name, file.name)),
)
if (existingComponent.length && !options.overwrite) {
if (selectedComponents.includes(item.name)) {
logger.warn(
`Component ${item.name} already exists. Use ${chalk.green(
`\nComponent ${
item.name
} already exists. Use ${chalk.green(
'--overwrite',
)} to overwrite.`,
)
process.exit(1)
spinner.stop()
process.exitCode = 1
return
}
continue
}
for (const file of item.files) {
const filePath = path.resolve(targetDir, file.name)
const componentDir = path.resolve(targetDir, item.name)
const filePath = path.resolve(
targetDir,
item.name,
file.name,
)
// Run transformers.
const content = await transform({
filename: file.name,
raw: file.content,
config,
baseColor,
})
const content = transformImport(file.content, config)
// if (!config.tsx)
// filePath = filePath.replace(/\.tsx$/, '.jsx')
if (!existsSync(componentDir))
await fs.mkdir(componentDir, { recursive: true })
await fs.writeFile(filePath, content)
}
// Install dependencies.
if (item.dependencies?.length) {
item.dependencies.forEach(dep =>
skippedDeps.add(dep),
)
const packageManager = await getPackageManager(cwd)
await execa(
packageManager,

View File

@ -112,8 +112,8 @@ export async function promptForConfig(
name: 'framework',
message: `Which ${highlight('framework')} are you using?`,
choices: [
{ title: 'Nuxt', value: 'nuxt' },
{ title: 'Vite + Vue', value: 'vue' },
{ title: 'Nuxt', value: 'nuxt' },
],
},
{
@ -140,7 +140,7 @@ export async function promptForConfig(
type: 'text',
name: 'tailwindCss',
message: `Where is your ${highlight('Tailwind CSS')} file?`,
initial: (prev, values) => defaultConfig?.tailwind.css ?? values.framework === 'nuxt' ? DEFAULT_TAILWIND_CSS_NUXT : DEFAULT_TAILWIND_CSS,
initial: (prev, values) => defaultConfig?.tailwind.css ?? (values.framework === 'nuxt' ? DEFAULT_TAILWIND_CSS_NUXT : DEFAULT_TAILWIND_CSS),
},
{
type: 'toggle',

View File

@ -6,8 +6,8 @@ import { resolveImport } from '@/src/utils/resolve-import'
export const DEFAULT_STYLE = 'default'
export const DEFAULT_COMPONENTS = '@/components'
export const DEFAULT_UTILS = '@/utils'
export const DEFAULT_TAILWIND_CSS = 'src/style.css'
export const DEFAULT_UTILS = '@/lib/utils'
export const DEFAULT_TAILWIND_CSS = 'src/assets/index.css'
export const DEFAULT_TAILWIND_CSS_NUXT = 'assets/style/tailwind.css'
export const DEFAULT_TAILWIND_CONFIG = 'tailwind.config.js'
export const DEFAULT_TAILWIND_BASE_COLOR = 'slate'
@ -61,8 +61,17 @@ export async function getConfig(cwd: string) {
}
export async function resolveConfigPaths(cwd: string, config: RawConfig) {
const TSCONFIG_PATH = config.framework === 'nuxt' ? '.nuxt/tsconfig.json' : './tsconfig.json'
// In new Vue project, tsconfig has references to tsconfig.app.json, which is causing the path not resolving correctly
const FALLBACK_TSCONFIG_PATH = './tsconfig.app.json'
// Read tsconfig.json.
const tsConfig = await loadConfig(cwd)
const tsconfigPath = path.resolve(cwd, TSCONFIG_PATH)
let tsConfig = loadConfig(tsconfigPath)
// If no paths were found, we load the fallback tsconfig
if ('paths' in tsConfig && Object.keys(tsConfig.paths).length === 0)
tsConfig = loadConfig(path.resolve(cwd, FALLBACK_TSCONFIG_PATH))
if (tsConfig.resultType === 'failed') {
throw new Error(

View File

@ -144,7 +144,6 @@ async function fetchRegistry(paths: string[]) {
return await response.json()
}),
)
return results
}
catch (error) {

View File

@ -1,10 +1,29 @@
export const UTILS = `import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export const UTILS = `import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
`
export function useEmitAsProps<Name extends string>(
emit: (name: Name, ...args: any[]) => void,
) {
const vm = getCurrentInstance()
const events = vm?.type.emits as Name[]
const result: Record<string, any> = {}
if (!events?.length) {
console.warn(
'No emitted event found. Please check component: \${vm?.type.__name}',
)
}
events?.forEach((ev) => {
result[toHandlerKey(camelize(ev))] = (...arg: any) => emit(ev, ...arg)
})
return result
}`
export const UTILS_JS = `import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
@ -12,6 +31,23 @@ import { twMerge } from "tailwind-merge"
export function cn(...inputs) {
return twMerge(clsx(inputs))
}
export function useEmitAsProps(emit) {
const vm = getCurrentInstance()
const events = vm?.type.emits
const result = {}
if (!events?.length) {
console.warn(
'No emitted event found. Please check component: \${vm?.type.__name}',
)
}
events?.forEach((ev) => {
result[toHandlerKey(camelize(ev))] = (...arg) => emit(ev, ...arg)
})
return result
}
`
export const TAILWIND_CONFIG = `/** @type {import('tailwindcss').Config} */

View File

@ -6,7 +6,6 @@ import type * as z from 'zod'
import type { Config } from '@/src/utils/get-config'
import type { registryBaseColorSchema } from '@/src/utils/registry/schema'
import { transformCssVars } from '@/src/utils/transformers/transform-css-vars'
import { transformImport } from '@/src/utils/transformers/transform-import'
export interface TransformOpts {
filename: string
@ -22,7 +21,6 @@ export type Transformer<Output = SourceFile> = (
) => Promise<Output>
const transformers: Transformer[] = [
transformImport,
transformCssVars,
]

View File

@ -1,32 +1,49 @@
import type { Transformer } from '@/src/utils/transformers'
import MagicString from 'magic-string'
import type { z } from 'zod'
import type { Config } from '../get-config'
import type { registryBaseColorSchema } from '../registry/schema'
export const transformImport: Transformer = async ({ sourceFile, config }) => {
const importDeclarations = sourceFile.getImportDeclarations()
for (const importDeclaration of importDeclarations) {
const moduleSpecifier = importDeclaration.getModuleSpecifierValue()
// Replace @/registry/[style] with the components alias.
if (moduleSpecifier.startsWith('@/registry/')) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(
/^@\/registry\/[^/]+/,
config.aliases.components,
),
)
export interface TransformOpts {
filename: string
raw: string
config: Config
baseColor?: z.infer<typeof registryBaseColorSchema>
}
// Replace `import { cn } from "@/lib/utils"`
if (moduleSpecifier === '@/lib/utils') {
const namedImports = importDeclaration.getNamedImports()
const cnImport = namedImports.find(i => i.getName() === 'cn')
if (cnImport) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(/^@\/lib\/utils/, config.aliases.utils),
)
}
}
export function transformImport(content: string, config: Config) {
const s = new MagicString(content)
s.replaceAll(/@\/registry\/[^/]+/g, config.aliases.components)
s.replaceAll(/\$lib\/utils/g, config.aliases.utils)
return s.toString()
}
return sourceFile
}
// export const transformImport: Transformer = async ({ sourceFile, config }) => {
// const importDeclarations = sourceFile.getImportDeclarations()
// for (const importDeclaration of importDeclarations) {
// const moduleSpecifier = importDeclaration.getModuleSpecifierValue()
// // Replace @/registry/[style] with the components alias.
// if (moduleSpecifier.startsWith('@/registry/')) {
// importDeclaration.setModuleSpecifier(
// moduleSpecifier.replace(
// /^@\/registry\/[^/]+/,
// config.aliases.components,
// ),
// )
// }
// // Replace `import { cn } from "@/lib/utils"`
// if (moduleSpecifier === '@/lib/utils') {
// const namedImports = importDeclaration.getNamedImports()
// const cnImport = namedImports.find(i => i.getName() === 'cn')
// if (cnImport) {
// importDeclaration.setModuleSpecifier(
// moduleSpecifier.replace(/^@\/lib\/utils/, config.aliases.utils),
// )
// }
// }
// }
// return sourceFile
// }

View File

@ -144,9 +144,6 @@ importers:
vite:
specifier: ^4.3.9
version: 4.3.9(@types/node@20.5.7)
vite-tsconfig-paths:
specifier: ^4.2.0
version: 4.2.0(typescript@5.0.2)(vite@4.3.9)
vue-tsc:
specifier: ^1.4.2
version: 1.4.2(typescript@5.0.2)
@ -229,6 +226,9 @@ importers:
'@vitest/ui':
specifier: ^0.34.3
version: 0.34.3(vitest@0.34.3)
magic-string:
specifier: ^0.30.3
version: 0.30.3
rimraf:
specifier: ^5.0.1
version: 5.0.1
@ -7224,19 +7224,6 @@ packages:
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
/tsconfck@2.1.2(typescript@5.0.2):
resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==}
engines: {node: ^14.13.1 || ^16 || >=18}
hasBin: true
peerDependencies:
typescript: ^4.3.5 || ^5.0.0
peerDependenciesMeta:
typescript:
optional: true
dependencies:
typescript: 5.0.2
dev: true
/tsconfck@2.1.2(typescript@5.2.2):
resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==}
engines: {node: ^14.13.1 || ^16 || >=18}
@ -7586,23 +7573,6 @@ packages:
- terser
dev: true
/vite-tsconfig-paths@4.2.0(typescript@5.0.2)(vite@4.3.9):
resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==}
peerDependencies:
vite: '*'
peerDependenciesMeta:
vite:
optional: true
dependencies:
debug: 4.3.4
globrex: 0.1.2
tsconfck: 2.1.2(typescript@5.0.2)
vite: 4.3.9(@types/node@20.5.7)
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/vite-tsconfig-paths@4.2.0(typescript@5.2.2):
resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==}
peerDependencies: