solid-vue-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/addons/auth.js ADDED
@@ -0,0 +1,87 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { execSync } from 'node:child_process'
4
+ import chalk from 'chalk'
5
+
6
+ export default function installAuth(cwd) {
7
+ console.log(chalk.blue.bold('\n🚀 Installing basic session auth (h3 useSession + bcryptjs)...'))
8
+
9
+ try {
10
+ execSync('npm install bcryptjs', { stdio: 'inherit', cwd })
11
+ } catch (err) {
12
+ console.error(chalk.red.bold('\n❌ Failed to install bcryptjs:'))
13
+ console.error(chalk.red(err.message))
14
+ return
15
+ }
16
+
17
+ const isTs = fs.existsSync(path.join(cwd, 'tsconfig.json'))
18
+ const ext = isTs ? 'ts' : 'js'
19
+
20
+ const authDir = path.join(cwd, 'src', 'server', 'api', 'auth')
21
+ if (!fs.existsSync(authDir)) fs.mkdirSync(authDir, { recursive: true })
22
+
23
+ fs.writeFileSync(path.join(authDir, `register.${ext}`), `import { useSession, readBody } from 'solid-vue/server'
24
+ import bcrypt from 'bcryptjs'
25
+
26
+ // TODO: Ganti ku query database Aa sabenerna
27
+ async function createUser(email, passwordHash) {
28
+ throw new Error('createUser() acan diimplementasikeun — sambungkeun ka database Aa')
29
+ }
30
+
31
+ export default async function (event) {
32
+ const { email, password } = await readBody(event)
33
+ const passwordHash = await bcrypt.hash(password, 10)
34
+ const user = await createUser(email, passwordHash)
35
+
36
+ const session = await useSession(event, {
37
+ password: process.env.SESSION_SECRET, // minimal 32 karakter acak
38
+ })
39
+ await session.update({ userId: user.id })
40
+
41
+ return { status: 'ok' }
42
+ }
43
+ `)
44
+
45
+ fs.writeFileSync(path.join(authDir, `login.${ext}`), `import { useSession, readBody } from 'solid-vue/server'
46
+ import bcrypt from 'bcryptjs'
47
+
48
+ // TODO: Ganti ku query database Aa sabenerna
49
+ async function findUserByEmail(email) {
50
+ throw new Error('findUserByEmail() acan diimplementasikeun — sambungkeun ka database Aa')
51
+ }
52
+
53
+ export default async function (event) {
54
+ const { email, password } = await readBody(event)
55
+ const user = await findUserByEmail(email)
56
+
57
+ if (!user || !(await bcrypt.compare(password, user.passwordHash))) {
58
+ event.node.res.statusCode = 401
59
+ return { status: 'error', message: 'Email atawa password salah' }
60
+ }
61
+
62
+ const session = await useSession(event, {
63
+ password: process.env.SESSION_SECRET,
64
+ })
65
+ await session.update({ userId: user.id })
66
+
67
+ return { status: 'ok' }
68
+ }
69
+ `)
70
+
71
+ fs.writeFileSync(path.join(authDir, `logout.${ext}`), `import { useSession } from 'solid-vue/server'
72
+
73
+ export default async function (event) {
74
+ const session = await useSession(event, {
75
+ password: process.env.SESSION_SECRET,
76
+ })
77
+ await session.clear()
78
+
79
+ return { status: 'ok' }
80
+ }
81
+ `)
82
+
83
+ console.log(chalk.green.bold('\n✅ Basic auth scaffolding installed!'))
84
+ console.log(chalk.yellow('⚠️ Butuh ditambihan manual sateuacan dipaké:'))
85
+ console.log(chalk.white(' 1. Set SESSION_SECRET di .env (minimal 32 karakter acak)'))
86
+ console.log(chalk.white(' 2. Implementasikeun createUser() & findUserByEmail() luyu database Aa'))
87
+ }
package/addons/i18n.js ADDED
@@ -0,0 +1,31 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { execSync } from 'node:child_process'
4
+ import chalk from 'chalk'
5
+
6
+ export default function installI18n(cwd) {
7
+ console.log(chalk.blue.bold('\n🚀 Installing vue-i18n...'))
8
+
9
+ try {
10
+ execSync('npm install vue-i18n', { stdio: 'inherit', cwd })
11
+ } catch (err) {
12
+ console.error(chalk.red.bold('\n❌ Failed to install vue-i18n:'))
13
+ console.error(chalk.red(err.message))
14
+ return
15
+ }
16
+
17
+ const localesDir = path.join(cwd, 'src', 'locales')
18
+ if (!fs.existsSync(localesDir)) {
19
+ fs.mkdirSync(localesDir, { recursive: true })
20
+ fs.writeFileSync(path.join(localesDir, 'id.json'), JSON.stringify({ hello: 'Halo!' }, null, 2))
21
+ fs.writeFileSync(path.join(localesDir, 'en.json'), JSON.stringify({ hello: 'Hello!' }, null, 2))
22
+ }
23
+
24
+ console.log(chalk.green.bold('\n✅ vue-i18n installed successfully!'))
25
+ console.log(chalk.white('💡 Setup di main entry:'))
26
+ console.log(chalk.cyan(' import { createI18n } from "vue-i18n"'))
27
+ console.log(chalk.cyan(' import id from "./locales/id.json"'))
28
+ console.log(chalk.cyan(' import en from "./locales/en.json"'))
29
+ console.log(chalk.cyan(' const i18n = createI18n({ legacy: false, locale: "id", messages: { id, en } })'))
30
+ console.log(chalk.cyan(' app.use(i18n)'))
31
+ }
@@ -0,0 +1,25 @@
1
+ import tailwind from './tailwind.js'
2
+ import lucide from './lucide.js'
3
+ import tabler from './tabler.js'
4
+ import vueuse from './vueuse.js'
5
+ import vitest from './vitest.js'
6
+ import veeValidate from './vee-validate.js'
7
+ import unhead from './unhead.js'
8
+ import ofetch from './ofetch.js'
9
+ import i18n from './i18n.js'
10
+ import lint from './lint.js'
11
+ import auth from './auth.js'
12
+
13
+ export const addons = {
14
+ tailwind,
15
+ lucide,
16
+ tabler,
17
+ vueuse,
18
+ vitest,
19
+ 'vee-validate': veeValidate,
20
+ unhead,
21
+ ofetch,
22
+ i18n,
23
+ lint,
24
+ auth,
25
+ }
package/addons/lint.js ADDED
@@ -0,0 +1,38 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { execSync } from 'node:child_process'
4
+ import chalk from 'chalk'
5
+
6
+ export default function installLint(cwd) {
7
+ console.log(chalk.blue.bold('\n🚀 Installing ESLint + Prettier...'))
8
+
9
+ try {
10
+ execSync('npm install -D eslint eslint-plugin-vue @vue/eslint-config-prettier prettier', { stdio: 'inherit', cwd })
11
+ } catch (err) {
12
+ console.error(chalk.red.bold('\n❌ Failed to install lint packages:'))
13
+ console.error(chalk.red(err.message))
14
+ return
15
+ }
16
+
17
+ const eslintConfigPath = path.join(cwd, 'eslint.config.js')
18
+ if (!fs.existsSync(eslintConfigPath)) {
19
+ fs.writeFileSync(eslintConfigPath, `import pluginVue from 'eslint-plugin-vue'
20
+ import prettierConfig from '@vue/eslint-config-prettier'
21
+
22
+ export default [
23
+ ...pluginVue.configs['flat/recommended'],
24
+ prettierConfig,
25
+ ]
26
+ `)
27
+ }
28
+
29
+ const prettierConfigPath = path.join(cwd, '.prettierrc.json')
30
+ if (!fs.existsSync(prettierConfigPath)) {
31
+ fs.writeFileSync(prettierConfigPath, JSON.stringify({ semi: false, singleQuote: true, printWidth: 100 }, null, 2))
32
+ }
33
+
34
+ console.log(chalk.green.bold('\n✅ ESLint + Prettier installed successfully!'))
35
+ console.log(chalk.white('💡 Run:'))
36
+ console.log(chalk.cyan(' npx eslint . --fix'))
37
+ console.log(chalk.cyan(' npx prettier --write .'))
38
+ }
@@ -0,0 +1,19 @@
1
+ import { execSync } from 'node:child_process'
2
+ import chalk from 'chalk'
3
+
4
+ export default function installLucide(cwd) {
5
+ console.log(chalk.blue.bold('\n🚀 Installing Lucide Icons...'))
6
+
7
+ try {
8
+ execSync('npm install @lucide/vue', { stdio: 'inherit', cwd })
9
+ } catch (err) {
10
+ console.error(chalk.red.bold('\n❌ Failed to install Lucide Icons:'))
11
+ console.error(chalk.red(err.message))
12
+ return
13
+ }
14
+
15
+ console.log(chalk.green.bold('\n✅ Lucide Icons installed successfully!'))
16
+ console.log(chalk.white('💡 Usage in a .vue file:'))
17
+ console.log(chalk.cyan(' import { Home, User, Settings } from "@lucide/vue"'))
18
+ console.log(chalk.cyan(' <Home class="text-blue-500 w-6 h-6" />'))
19
+ }
@@ -0,0 +1,19 @@
1
+ import { execSync } from 'node:child_process'
2
+ import chalk from 'chalk'
3
+
4
+ export default function installOfetch(cwd) {
5
+ console.log(chalk.blue.bold('\n🚀 Installing ofetch...'))
6
+
7
+ try {
8
+ execSync('npm install ofetch', { stdio: 'inherit', cwd })
9
+ } catch (err) {
10
+ console.error(chalk.red.bold('\n❌ Failed to install ofetch:'))
11
+ console.error(chalk.red(err.message))
12
+ return
13
+ }
14
+
15
+ console.log(chalk.green.bold('\n✅ ofetch installed successfully!'))
16
+ console.log(chalk.white('💡 Usage:'))
17
+ console.log(chalk.cyan(' import { ofetch } from "ofetch"'))
18
+ console.log(chalk.cyan(' const data = await ofetch("/api/hello")'))
19
+ }
@@ -0,0 +1,19 @@
1
+ import { execSync } from 'node:child_process'
2
+ import chalk from 'chalk'
3
+
4
+ export default function installTabler(cwd) {
5
+ console.log(chalk.blue.bold('\n🚀 Installing Tabler Icons...'))
6
+
7
+ try {
8
+ execSync('npm install @tabler/icons-vue', { stdio: 'inherit', cwd })
9
+ } catch (err) {
10
+ console.error(chalk.red.bold('\n❌ Failed to install Tabler Icons:'))
11
+ console.error(chalk.red(err.message))
12
+ return
13
+ }
14
+
15
+ console.log(chalk.green.bold('\n✅ Tabler Icons installed successfully!'))
16
+ console.log(chalk.white('💡 Usage in a .vue file:'))
17
+ console.log(chalk.cyan(' import { IconHome, IconUser } from "@tabler/icons-vue"'))
18
+ console.log(chalk.cyan(' <IconHome stroke="2" />'))
19
+ }
@@ -0,0 +1,41 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { execSync } from 'node:child_process'
4
+ import chalk from 'chalk'
5
+
6
+ export default function installTailwind(cwd) {
7
+ console.log(chalk.blue.bold('\n🚀 Installing Tailwind CSS (v4) in the Solid-Vue project...'))
8
+
9
+ try {
10
+ execSync('npm install -D tailwindcss @tailwindcss/postcss postcss', { stdio: 'inherit', cwd })
11
+ } catch (err) {
12
+ console.error(chalk.red.bold('\n❌ Failed to install Tailwind CSS packages:'))
13
+ console.error(chalk.red(err.message))
14
+ return
15
+ }
16
+
17
+ const postcssConfigPath = path.join(cwd, 'postcss.config.js')
18
+ fs.writeFileSync(postcssConfigPath, `export default {
19
+ plugins: {
20
+ '@tailwindcss/postcss': {},
21
+ },
22
+ }
23
+ `)
24
+
25
+ const cssDir = path.join(cwd, 'src', 'styles')
26
+ const cssFile = path.join(cssDir, 'global.css')
27
+ const tailwindImport = `@import "tailwindcss";\n\n`
28
+
29
+ if (!fs.existsSync(cssDir)) fs.mkdirSync(cssDir, { recursive: true })
30
+
31
+ if (fs.existsSync(cssFile)) {
32
+ const currentCss = fs.readFileSync(cssFile, 'utf-8')
33
+ if (!currentCss.includes('@import "tailwindcss"')) {
34
+ fs.writeFileSync(cssFile, tailwindImport + currentCss)
35
+ }
36
+ } else {
37
+ fs.writeFileSync(cssFile, tailwindImport)
38
+ }
39
+
40
+ console.log(chalk.green.bold('\n✅ Tailwind CSS v4 has been installed successfully! Let\'s get started! ☕'))
41
+ }
@@ -0,0 +1,22 @@
1
+ import { execSync } from 'node:child_process'
2
+ import chalk from 'chalk'
3
+
4
+ export default function installUnhead(cwd) {
5
+ console.log(chalk.blue.bold('\n🚀 Installing @unhead/vue...'))
6
+
7
+ try {
8
+ execSync('npm install @unhead/vue', { stdio: 'inherit', cwd })
9
+ } catch (err) {
10
+ console.error(chalk.red.bold('\n❌ Failed to install @unhead/vue:'))
11
+ console.error(chalk.red(err.message))
12
+ return
13
+ }
14
+
15
+ console.log(chalk.green.bold('\n✅ @unhead/vue installed successfully!'))
16
+ console.log(chalk.white('💡 Setup di main entry:'))
17
+ console.log(chalk.cyan(' import { createHead } from "@unhead/vue/client"'))
18
+ console.log(chalk.cyan(' app.use(createHead())'))
19
+ console.log(chalk.white('💡 Usage di .vue file:'))
20
+ console.log(chalk.cyan(' import { useHead } from "@unhead/vue"'))
21
+ console.log(chalk.cyan(' useHead({ title: "Judul Halaman" })'))
22
+ }
@@ -0,0 +1,20 @@
1
+ import { execSync } from 'node:child_process'
2
+ import chalk from 'chalk'
3
+
4
+ export default function installVeeValidate(cwd) {
5
+ console.log(chalk.blue.bold('\n🚀 Installing VeeValidate + Zod...'))
6
+
7
+ try {
8
+ execSync('npm install vee-validate zod @vee-validate/zod', { stdio: 'inherit', cwd })
9
+ } catch (err) {
10
+ console.error(chalk.red.bold('\n❌ Failed to install validation packages:'))
11
+ console.error(chalk.red(err.message))
12
+ return
13
+ }
14
+
15
+ console.log(chalk.green.bold('\n✅ VeeValidate + Zod installed successfully!'))
16
+ console.log(chalk.white('💡 Usage in a .vue file:'))
17
+ console.log(chalk.cyan(' import { useForm } from "vee-validate"'))
18
+ console.log(chalk.cyan(' import { toTypedSchema } from "@vee-validate/zod"'))
19
+ console.log(chalk.cyan(' import { z } from "zod"'))
20
+ }
@@ -0,0 +1,51 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { execSync } from 'node:child_process'
4
+ import chalk from 'chalk'
5
+
6
+ export default function installVitest(cwd) {
7
+ console.log(chalk.blue.bold('\n🚀 Installing Vitest...'))
8
+
9
+ try {
10
+ execSync('npm install -D vitest @vue/test-utils jsdom', { stdio: 'inherit', cwd })
11
+ } catch (err) {
12
+ console.error(chalk.red.bold('\n❌ Failed to install Vitest:'))
13
+ console.error(chalk.red(err.message))
14
+ return
15
+ }
16
+
17
+ const isTs = fs.existsSync(path.join(cwd, 'tsconfig.json'))
18
+ const ext = isTs ? 'ts' : 'js'
19
+
20
+ const vitestConfigPath = path.join(cwd, `vitest.config.${ext}`)
21
+ if (!fs.existsSync(vitestConfigPath)) {
22
+ fs.writeFileSync(vitestConfigPath, `import { defineConfig } from 'vitest/config'
23
+ import vue from '@vitejs/plugin-vue'
24
+
25
+ export default defineConfig({
26
+ plugins: [vue()],
27
+ test: {
28
+ environment: 'jsdom',
29
+ globals: true,
30
+ },
31
+ })
32
+ `)
33
+ }
34
+
35
+ const testDir = path.join(cwd, 'src', '__tests__')
36
+ if (!fs.existsSync(testDir)) {
37
+ fs.mkdirSync(testDir, { recursive: true })
38
+ fs.writeFileSync(path.join(testDir, `example.test.${ext}`), `import { describe, it, expect } from 'vitest'
39
+
40
+ describe('example', () => {
41
+ it('works', () => {
42
+ expect(1 + 1).toBe(2)
43
+ })
44
+ })
45
+ `)
46
+ }
47
+
48
+ console.log(chalk.green.bold('\n✅ Vitest installed successfully!'))
49
+ console.log(chalk.white('💡 Run:'))
50
+ console.log(chalk.cyan(' npx vitest'))
51
+ }
@@ -0,0 +1,18 @@
1
+ import { execSync } from 'node:child_process'
2
+ import chalk from 'chalk'
3
+
4
+ export default function installVueUse(cwd) {
5
+ console.log(chalk.blue.bold('\n🚀 Installing VueUse...'))
6
+
7
+ try {
8
+ execSync('npm install @vueuse/core', { stdio: 'inherit', cwd })
9
+ } catch (err) {
10
+ console.error(chalk.red.bold('\n❌ Failed to install VueUse:'))
11
+ console.error(chalk.red(err.message))
12
+ return
13
+ }
14
+
15
+ console.log(chalk.green.bold('\n✅ VueUse installed successfully!'))
16
+ console.log(chalk.white('💡 Usage in a .vue file:'))
17
+ console.log(chalk.cyan(' import { useLocalStorage, useDebounce } from "@vueuse/core"'))
18
+ }
package/bin/cli.js ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import chalk from 'chalk'
3
+ import { addons } from '../addons/index.js'
4
+
5
+ function addAddon(addonName) {
6
+ const handler = addons[addonName]
7
+
8
+ if (!handler) {
9
+ console.log(chalk.red(`\n❌ Add-on '${addonName}' is not supported yet by Solid-Vue.`))
10
+ console.log(chalk.gray(` Available add-ons: ${Object.keys(addons).join(', ')}`))
11
+ process.exit(1)
12
+ }
13
+
14
+ handler(process.cwd())
15
+ }
16
+
17
+ const args = process.argv.slice(2)
18
+ const command = args[0]
19
+
20
+ if (command === 'add') {
21
+ const addonName = args[1]
22
+ if (!addonName) {
23
+ console.log(chalk.yellow('\n⚠️ Please specify the addon name. Example: npx solid-vue add tailwind'))
24
+ process.exit(1)
25
+ }
26
+ addAddon(addonName)
27
+ } else {
28
+ console.log(chalk.red(`\n❌ Command '${command}' is not recognized. Supported commands are: 'add <addon-name>'.`))
29
+ process.exit(1)
30
+ }
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "solid-vue-cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "files": ["bin", "addons"],
6
+ "bin": {
7
+ "solid-vue": "./bin/cli.js"
8
+ },
9
+ "dependencies": {
10
+ "chalk": "^6.0.0"
11
+ }
12
+ }