vasp-cli 0.1.2 → 0.1.3
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/dist/vasp +23 -18
- package/package.json +3 -5
- package/templates/shared/.env.example.hbs +14 -0
- package/templates/shared/.gitignore.hbs +8 -0
- package/templates/shared/auth/client/Login.vue.hbs +46 -0
- package/templates/shared/auth/client/Register.vue.hbs +42 -0
- package/templates/shared/auth/server/index.hbs +51 -0
- package/templates/shared/auth/server/middleware.hbs +33 -0
- package/templates/shared/auth/server/providers/github.hbs +48 -0
- package/templates/shared/auth/server/providers/google.hbs +53 -0
- package/templates/shared/auth/server/providers/usernameAndPassword.hbs +69 -0
- package/templates/shared/bunfig.toml.hbs +2 -0
- package/templates/shared/drizzle/schema.hbs +37 -0
- package/templates/shared/jobs/_job.hbs +24 -0
- package/templates/shared/jobs/boss.hbs +15 -0
- package/templates/shared/package.json.hbs +32 -0
- package/templates/shared/server/db/client.hbs +12 -0
- package/templates/shared/server/index.hbs +52 -0
- package/templates/shared/server/routes/actions/_action.hbs +20 -0
- package/templates/shared/server/routes/crud/_crud.hbs +42 -0
- package/templates/shared/server/routes/jobs/_schedule.hbs +12 -0
- package/templates/shared/server/routes/queries/_query.hbs +20 -0
- package/templates/shared/server/routes/realtime/_channel.hbs +30 -0
- package/templates/shared/server/routes/realtime/index.hbs +9 -0
- package/templates/shared/tsconfig.json.hbs +21 -0
- package/templates/spa/js/index.html.hbs +12 -0
- package/templates/spa/js/src/App.vue.hbs +3 -0
- package/templates/spa/js/src/main.js.hbs +9 -0
- package/templates/spa/js/src/router/index.js.hbs +41 -0
- package/templates/spa/js/src/vasp/auth.js.hbs +45 -0
- package/templates/spa/js/src/vasp/client/actions.js.hbs +15 -0
- package/templates/spa/js/src/vasp/client/crud.js.hbs +30 -0
- package/templates/spa/js/src/vasp/client/index.js.hbs +16 -0
- package/templates/spa/js/src/vasp/client/queries.js.hbs +15 -0
- package/templates/spa/js/src/vasp/client/realtime.js.hbs +51 -0
- package/templates/spa/js/src/vasp/plugin.js.hbs +11 -0
- package/templates/spa/js/vite.config.js.hbs +26 -0
- package/templates/spa/ts/index.html.hbs +12 -0
- package/templates/spa/ts/src/App.vue.hbs +3 -0
- package/templates/spa/ts/src/main.ts.hbs +9 -0
- package/templates/spa/ts/src/router/index.ts.hbs +41 -0
- package/templates/spa/ts/src/vasp/auth.ts.hbs +53 -0
- package/templates/spa/ts/src/vasp/client/actions.ts.hbs +19 -0
- package/templates/spa/ts/src/vasp/client/crud.ts.hbs +37 -0
- package/templates/spa/ts/src/vasp/client/index.ts.hbs +17 -0
- package/templates/spa/ts/src/vasp/client/queries.ts.hbs +19 -0
- package/templates/spa/ts/src/vasp/client/realtime.ts.hbs +56 -0
- package/templates/spa/ts/src/vasp/client/types.ts.hbs +33 -0
- package/templates/spa/ts/src/vasp/plugin.ts.hbs +12 -0
- package/templates/spa/ts/vite.config.ts.hbs +26 -0
- package/templates/ssr/js/_page.vue.hbs +10 -0
- package/templates/ssr/js/app.vue.hbs +3 -0
- package/templates/ssr/js/composables/useAuth.js.hbs +52 -0
- package/templates/ssr/js/composables/useVasp.js.hbs +6 -0
- package/templates/ssr/js/middleware/auth.js.hbs +8 -0
- package/templates/ssr/js/nuxt.config.js.hbs +15 -0
- package/templates/ssr/js/plugins/vasp.client.js.hbs +17 -0
- package/templates/ssr/js/plugins/vasp.server.js.hbs +33 -0
- package/templates/ssr/ts/_page.vue.hbs +10 -0
- package/templates/ssr/ts/app.vue.hbs +3 -0
- package/templates/ssr/ts/composables/useAuth.ts.hbs +56 -0
- package/templates/ssr/ts/composables/useVasp.ts.hbs +10 -0
- package/templates/ssr/ts/middleware/auth.ts.hbs +8 -0
- package/templates/ssr/ts/nuxt.config.ts.hbs +19 -0
- package/templates/ssr/ts/plugins/vasp.client.ts.hbs +17 -0
- package/templates/ssr/ts/plugins/vasp.server.ts.hbs +33 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Auto-generated by Vasp — entity types inferred from Drizzle schema
|
|
2
|
+
import type {
|
|
3
|
+
{{#each cruds}}
|
|
4
|
+
{{pascalCase entity}},
|
|
5
|
+
New{{pascalCase entity}},
|
|
6
|
+
{{/each}}
|
|
7
|
+
{{#if hasAuth}}
|
|
8
|
+
User,
|
|
9
|
+
{{/if}}
|
|
10
|
+
} from '../../../../../../drizzle/schema.js'
|
|
11
|
+
|
|
12
|
+
{{#each queries}}
|
|
13
|
+
// Arguments and return type for '{{name}}' — customize as needed
|
|
14
|
+
export type {{pascalCase name}}Args = Record<string, unknown>
|
|
15
|
+
export type {{pascalCase name}}Return = unknown
|
|
16
|
+
|
|
17
|
+
{{/each}}
|
|
18
|
+
{{#each actions}}
|
|
19
|
+
// Arguments and return type for '{{name}}' — customize as needed
|
|
20
|
+
export type {{pascalCase name}}Args = Record<string, unknown>
|
|
21
|
+
export type {{pascalCase name}}Return = unknown
|
|
22
|
+
|
|
23
|
+
{{/each}}
|
|
24
|
+
// Re-export entity types for convenience
|
|
25
|
+
export type {
|
|
26
|
+
{{#each cruds}}
|
|
27
|
+
{{pascalCase entity}},
|
|
28
|
+
New{{pascalCase entity}},
|
|
29
|
+
{{/each}}
|
|
30
|
+
{{#if hasAuth}}
|
|
31
|
+
User,
|
|
32
|
+
{{/if}}
|
|
33
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { App } from 'vue'
|
|
2
|
+
import { createVaspClient } from '@vasp-framework/runtime'
|
|
3
|
+
|
|
4
|
+
export const vaspPlugin = {
|
|
5
|
+
install(app: App) {
|
|
6
|
+
const client = createVaspClient({
|
|
7
|
+
baseURL: import.meta.env.VITE_API_URL || '/api',
|
|
8
|
+
})
|
|
9
|
+
app.provide('$vasp', client)
|
|
10
|
+
app.config.globalProperties.$vasp = client
|
|
11
|
+
},
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import vue from '@vitejs/plugin-vue'
|
|
3
|
+
import { fileURLToPath, URL } from 'node:url'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [vue()],
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: {
|
|
9
|
+
'@src': fileURLToPath(new URL('./src', import.meta.url)),
|
|
10
|
+
'@vasp-framework/client': fileURLToPath(new URL('./src/vasp/client', import.meta.url)),
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
server: {
|
|
14
|
+
port: {{frontendPort}},
|
|
15
|
+
proxy: {
|
|
16
|
+
'/api': {
|
|
17
|
+
target: 'http://localhost:{{backendPort}}',
|
|
18
|
+
changeOrigin: true,
|
|
19
|
+
},
|
|
20
|
+
'/ws': {
|
|
21
|
+
target: 'ws://localhost:{{backendPort}}',
|
|
22
|
+
ws: true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// SSR-aware auth composable — uses cookies (httpOnly) and Nuxt's useRequestHeaders for server-side access
|
|
3
|
+
import { $fetch } from 'ofetch'
|
|
4
|
+
|
|
5
|
+
const _user = ref(null)
|
|
6
|
+
let _checked = false
|
|
7
|
+
|
|
8
|
+
export function useAuth() {
|
|
9
|
+
const config = useRuntimeConfig()
|
|
10
|
+
const baseURL = config.public.apiBase
|
|
11
|
+
|
|
12
|
+
// On server, forward cookies from the incoming request
|
|
13
|
+
const headers = import.meta.server ? useRequestHeaders(['cookie']) : {}
|
|
14
|
+
|
|
15
|
+
async function checkAuth() {
|
|
16
|
+
if (_checked) return
|
|
17
|
+
_checked = true
|
|
18
|
+
try {
|
|
19
|
+
_user.value = await $fetch(`${baseURL}/auth/me`, { headers, credentials: 'include' })
|
|
20
|
+
} catch {
|
|
21
|
+
_user.value = null
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function login(username, password) {
|
|
26
|
+
_user.value = await $fetch(`${baseURL}/auth/login`, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
body: { username, password },
|
|
29
|
+
credentials: 'include',
|
|
30
|
+
})
|
|
31
|
+
_checked = true
|
|
32
|
+
return _user.value
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function register(username, password, email) {
|
|
36
|
+
_user.value = await $fetch(`${baseURL}/auth/register`, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
body: { username, password, email },
|
|
39
|
+
credentials: 'include',
|
|
40
|
+
})
|
|
41
|
+
_checked = true
|
|
42
|
+
return _user.value
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function logout() {
|
|
46
|
+
await $fetch(`${baseURL}/auth/logout`, { method: 'POST', credentials: 'include' })
|
|
47
|
+
_user.value = null
|
|
48
|
+
_checked = false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { user: _user, checkAuth, login, register, logout }
|
|
52
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
export default defineNuxtRouteMiddleware((to) => {
|
|
3
|
+
const { user } = useAuth()
|
|
4
|
+
const publicPaths = ['/login', '/register']
|
|
5
|
+
if (!user.value && !publicPaths.includes(to.path)) {
|
|
6
|
+
return navigateTo('/login')
|
|
7
|
+
}
|
|
8
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
3
|
+
export default defineNuxtConfig({
|
|
4
|
+
compatibilityDate: '2024-11-01',
|
|
5
|
+
devtools: { enabled: true },
|
|
6
|
+
alias: {
|
|
7
|
+
'@src': '~/src',
|
|
8
|
+
},
|
|
9
|
+
runtimeConfig: {
|
|
10
|
+
backendUrl: process.env.BACKEND_URL || 'http://localhost:{{backendPort}}',
|
|
11
|
+
public: {
|
|
12
|
+
apiBase: process.env.API_BASE || 'http://localhost:{{backendPort}}/api',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// Runs only on the client after hydration — routes calls to the Elysia backend via ofetch
|
|
3
|
+
import { $fetch } from 'ofetch'
|
|
4
|
+
|
|
5
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
6
|
+
const config = useRuntimeConfig()
|
|
7
|
+
const baseURL = config.public.apiBase
|
|
8
|
+
|
|
9
|
+
nuxtApp.provide('vasp', {
|
|
10
|
+
async query(name, args) {
|
|
11
|
+
return $fetch(`/queries/${name}`, { baseURL, method: 'GET', query: args })
|
|
12
|
+
},
|
|
13
|
+
async action(name, args) {
|
|
14
|
+
return $fetch(`/actions/${name}`, { baseURL, method: 'POST', body: args })
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// Runs only on the server during SSR render — calls query/action functions directly (zero HTTP overhead)
|
|
3
|
+
{{#each queries}}
|
|
4
|
+
import { {{importName fn}} } from '{{fn.source}}'
|
|
5
|
+
{{/each}}
|
|
6
|
+
{{#each actions}}
|
|
7
|
+
import { {{importName fn}} } from '{{fn.source}}'
|
|
8
|
+
{{/each}}
|
|
9
|
+
|
|
10
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
11
|
+
const queryFns = {
|
|
12
|
+
{{#each queries}}
|
|
13
|
+
{{camelCase name}}: {{importName fn}},
|
|
14
|
+
{{/each}}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const actionFns = {
|
|
18
|
+
{{#each actions}}
|
|
19
|
+
{{camelCase name}}: {{importName fn}},
|
|
20
|
+
{{/each}}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
nuxtApp.provide('vasp', {
|
|
24
|
+
async query(name, args) {
|
|
25
|
+
if (!queryFns[name]) throw new Error(`[Vasp] Unknown query: ${name}`)
|
|
26
|
+
return queryFns[name](args)
|
|
27
|
+
},
|
|
28
|
+
async action(name, args) {
|
|
29
|
+
if (!actionFns[name]) throw new Error(`[Vasp] Unknown action: ${name}`)
|
|
30
|
+
return actionFns[name](args)
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
})
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// SSR-aware auth composable — uses cookies (httpOnly) and Nuxt's useRequestHeaders for server-side access
|
|
3
|
+
import { $fetch } from 'ofetch'
|
|
4
|
+
|
|
5
|
+
interface AuthUser {
|
|
6
|
+
id: number
|
|
7
|
+
username: string
|
|
8
|
+
email?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const _user = ref<AuthUser | null>(null)
|
|
12
|
+
let _checked = false
|
|
13
|
+
|
|
14
|
+
export function useAuth() {
|
|
15
|
+
const config = useRuntimeConfig()
|
|
16
|
+
const baseURL = config.public.apiBase as string
|
|
17
|
+
const headers = import.meta.server ? useRequestHeaders(['cookie']) : {}
|
|
18
|
+
|
|
19
|
+
async function checkAuth(): Promise<void> {
|
|
20
|
+
if (_checked) return
|
|
21
|
+
_checked = true
|
|
22
|
+
try {
|
|
23
|
+
_user.value = await $fetch<AuthUser>(`${baseURL}/auth/me`, { headers, credentials: 'include' })
|
|
24
|
+
} catch {
|
|
25
|
+
_user.value = null
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function login(username: string, password: string): Promise<AuthUser> {
|
|
30
|
+
_user.value = await $fetch<AuthUser>(`${baseURL}/auth/login`, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
body: { username, password },
|
|
33
|
+
credentials: 'include',
|
|
34
|
+
})
|
|
35
|
+
_checked = true
|
|
36
|
+
return _user.value!
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function register(username: string, password: string, email?: string): Promise<AuthUser> {
|
|
40
|
+
_user.value = await $fetch<AuthUser>(`${baseURL}/auth/register`, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
body: { username, password, email },
|
|
43
|
+
credentials: 'include',
|
|
44
|
+
})
|
|
45
|
+
_checked = true
|
|
46
|
+
return _user.value!
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function logout(): Promise<void> {
|
|
50
|
+
await $fetch(`${baseURL}/auth/logout`, { method: 'POST', credentials: 'include' })
|
|
51
|
+
_user.value = null
|
|
52
|
+
_checked = false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { user: _user, checkAuth, login, register, logout }
|
|
56
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
interface VaspClient {
|
|
3
|
+
query<T = unknown>(name: string, args?: unknown): Promise<T>
|
|
4
|
+
action<T = unknown>(name: string, args?: unknown): Promise<T>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const useVasp = (): { $vasp: VaspClient } => {
|
|
8
|
+
const { $vasp } = useNuxtApp()
|
|
9
|
+
return { $vasp: $vasp as VaspClient }
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
export default defineNuxtRouteMiddleware((to) => {
|
|
3
|
+
const { user } = useAuth()
|
|
4
|
+
const publicPaths = ['/login', '/register']
|
|
5
|
+
if (!user.value && !publicPaths.includes(to.path)) {
|
|
6
|
+
return navigateTo('/login')
|
|
7
|
+
}
|
|
8
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
3
|
+
export default defineNuxtConfig({
|
|
4
|
+
compatibilityDate: '2024-11-01',
|
|
5
|
+
devtools: { enabled: true },
|
|
6
|
+
typescript: {
|
|
7
|
+
strict: true,
|
|
8
|
+
typeCheck: true,
|
|
9
|
+
},
|
|
10
|
+
alias: {
|
|
11
|
+
'@src': '~/src',
|
|
12
|
+
},
|
|
13
|
+
runtimeConfig: {
|
|
14
|
+
backendUrl: process.env.BACKEND_URL || 'http://localhost:{{backendPort}}',
|
|
15
|
+
public: {
|
|
16
|
+
apiBase: process.env.API_BASE || 'http://localhost:{{backendPort}}/api',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// Runs only on the client after hydration — routes calls to the Elysia backend via ofetch
|
|
3
|
+
import { $fetch } from 'ofetch'
|
|
4
|
+
|
|
5
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
6
|
+
const config = useRuntimeConfig()
|
|
7
|
+
const baseURL = config.public.apiBase as string
|
|
8
|
+
|
|
9
|
+
nuxtApp.provide('vasp', {
|
|
10
|
+
async query<T = unknown>(name: string, args?: unknown): Promise<T> {
|
|
11
|
+
return $fetch<T>(`/queries/${name}`, { baseURL, method: 'GET', query: args as Record<string, unknown> })
|
|
12
|
+
},
|
|
13
|
+
async action<T = unknown>(name: string, args?: unknown): Promise<T> {
|
|
14
|
+
return $fetch<T>(`/actions/${name}`, { baseURL, method: 'POST', body: args })
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Auto-generated by Vasp — do not edit directly
|
|
2
|
+
// Runs only on the server during SSR render — calls query/action functions directly (zero HTTP overhead)
|
|
3
|
+
{{#each queries}}
|
|
4
|
+
import { {{importName fn}} } from '{{fn.source}}'
|
|
5
|
+
{{/each}}
|
|
6
|
+
{{#each actions}}
|
|
7
|
+
import { {{importName fn}} } from '{{fn.source}}'
|
|
8
|
+
{{/each}}
|
|
9
|
+
|
|
10
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
11
|
+
const queryFns: Record<string, (args?: unknown) => Promise<unknown>> = {
|
|
12
|
+
{{#each queries}}
|
|
13
|
+
{{camelCase name}}: {{importName fn}} as (args?: unknown) => Promise<unknown>,
|
|
14
|
+
{{/each}}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const actionFns: Record<string, (args?: unknown) => Promise<unknown>> = {
|
|
18
|
+
{{#each actions}}
|
|
19
|
+
{{camelCase name}}: {{importName fn}} as (args?: unknown) => Promise<unknown>,
|
|
20
|
+
{{/each}}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
nuxtApp.provide('vasp', {
|
|
24
|
+
async query<T = unknown>(name: string, args?: unknown): Promise<T> {
|
|
25
|
+
if (!queryFns[name]) throw new Error(`[Vasp] Unknown query: ${name}`)
|
|
26
|
+
return queryFns[name](args) as Promise<T>
|
|
27
|
+
},
|
|
28
|
+
async action<T = unknown>(name: string, args?: unknown): Promise<T> {
|
|
29
|
+
if (!actionFns[name]) throw new Error(`[Vasp] Unknown action: ${name}`)
|
|
30
|
+
return actionFns[name](args) as Promise<T>
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
})
|