Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,697 changes: 7,694 additions & 3 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nuxtus/generator",
"version": "1.9.4",
"version": "1.9.5",
"description": "Package responsible for generating a Nuxt page from Directus collection.",
"main": "dist/generator.es.js",
"module": "dist/generator.es.js",
Expand Down Expand Up @@ -55,7 +55,7 @@
"vitest": "4.1.0"
},
"dependencies": {
"@directus/sdk": "^21.0.0",
"@directus/sdk": "^21.2.0",
"camelcase": "^9.0.0",
"chalk": "^5.0.1",
"nanoid": "^5.0.5",
Expand Down
53 changes: 45 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
AuthenticationClient,
DirectusClient,
RestClient,
StaticTokenClient,
authentication,
createDirectus,
readCollections,
Expand All @@ -18,8 +19,8 @@ import { nanoid } from "nanoid"
export type Schema = {} // TODO: Not sure we actually will every use the Schema

export type Directus = DirectusClient<Schema> &
AuthenticationClient<Schema> &
RestClient<Schema>
RestClient<Schema> &
(AuthenticationClient<Schema> | StaticTokenClient<Schema>)

export default class Generator {
chalk = Chalk
Expand Down Expand Up @@ -53,11 +54,18 @@ export default class Generator {
)
.with(rest())
.with(authentication())

this.login()
}

public async login(): Promise<void> {
const staticTokenValue = process.env.NUXTUS_DIRECTUS_STATIC_TOKEN
if (staticTokenValue) {
this.directus = createDirectus(
process.env.DIRECTUS_URL || "http://localhost:8055"
)
.with(rest())
.with(staticToken(staticTokenValue))
return
}
await login(this.directus, this.chalk)
}

Expand All @@ -78,15 +86,44 @@ export default class Generator {
}

public async getCollections(): Promise<unknown> {
// TODO: THis return type is not unknown!
await this.login() // Need to be logged in as admin to get all collections
return this.directus.request(readCollections())
await this.login()
const result: any = await this.directus.request(readCollections())
return Array.isArray(result) ? result : (result.data || result)
}

public async generateStaticToken(): Promise<string> {
await this.login()
const token = nanoid()
this.directus.setToken(token)
const accessToken = await this.directus.getToken()
const meResp = await fetch(
process.env.DIRECTUS_URL + "/users/me",
{ headers: { Authorization: "Bearer " + accessToken } }
)
const meData = await meResp.json()
const userId = meData.data.id
const resp = await fetch(
process.env.DIRECTUS_URL + "/users/" + userId,
{
method: "PATCH",
headers: {
Authorization: "Bearer " + accessToken,
"Content-Type": "application/json",
},
body: JSON.stringify({ token }),
}
)
if (!resp.ok) {
const err: any = await resp.json()
throw new Error(
"Failed to register static token: " +
(err.errors?.[0]?.message || resp.statusText)
)
}
this.directus = createDirectus(
process.env.DIRECTUS_URL || "http://localhost:8055"
)
.with(rest())
.with(staticToken(token))
return token
}
}
4 changes: 2 additions & 2 deletions src/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function createPage(
localChalk: typeof chalk | undefined = undefined
): void {
let templateFolder = path.join(__dirname, "templates")
if (!fs.existsSync(templateFolder)) {
if (!fs.existsSync(templateFolder)) {
templateFolder = path.join(
process.cwd(),
"node_modules",
Expand All @@ -72,7 +72,7 @@ export function createPage(
"dist",
"templates"
)
}
}

const env: nunjucks.Environment = nunjucks.configure(templateFolder, {
tags: {
Expand Down
32 changes: 19 additions & 13 deletions src/templates/index.njk.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@ import type { components } from "../../interfaces/nuxtus"
type {$ collection | camelcase $} = components["schemas"]["Items{$ collection | camelcase $}"]
const { $directus, $readItems, $checkError } = useNuxtApp()

const query: Query<components, {$ collection | camelcase $}> = {
// Add your filters and query customisations here
}
const query: Query<components, {$ collection | camelcase $}> = {}

const { data, error } = useAsyncData <{$ collection | camelcase $}[] | null> ('{$ collection $}', () => {
const { data, error } = useAsyncData<{$ collection | camelcase $}[] | null>('{$ collection $}-list', () => {
return $directus.request($readItems('{$ collection $}', query))
})
$checkError(error)
</script>

<template>
<ul v-if="data === null || data.length > 0">
<li v-for="{$ collection | lower $} in data" :key=" {$ collection | lower $}.id ">
<NuxtLink :to=" `/{$ collection $}/${{$ collection | lower $}.id}`">
{{ {$ collection | lower $}.id }}
</NuxtLink>
</li>
</ul>
<p v-else>No {$ collection $} found.</p>
</template>
<div class="max-w-3xl mx-auto px-4 py-8">
<h1 class="text-3xl font-bold mb-8">{$ collection | camelcase $}</h1>
<div v-if="data && data.length > 0" class="space-y-8">
<article v-for="item in data" :key="item.id" class="border-b border-gray-200 pb-8">
<NuxtLink :to="`/{$ collection $}/${item.id}`" class="group">
<h2 class="text-xl font-semibold group-hover:text-blue-600 transition-colors">
<template v-if="item.title">{{ item.title }}</template>
<template v-else-if="item.name">{{ item.name }}</template>
<template v-else>{{ item.id }}</template>
</h2>
</NuxtLink>
</article>
</div>
<p v-else-if="data && data.length === 0" class="text-gray-500">No {$ collection $} found.</p>
<p v-else>Loading...</p>
</div>
</template>
29 changes: 20 additions & 9 deletions src/templates/individual.njk.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,30 @@ type {$ collection | camelcase $} = components["schemas"]["Items{$ collection |
const route = useRoute()
const { $directus, $readItem, $checkError } = useNuxtApp()

const query: Query<components, {$ collection | camelcase $}> = {
// Add your filters and query customisations here
}
const query: Query<components, {$ collection | camelcase $}> = {}

const { data: {$ collection $}, error } = useAsyncData <{$ collection | camelcase $} | null> ('{$ collection $}', () => {
return $directus.request($readItem('{$ collection $}', route.params.id, query))
const { data, error } = useAsyncData<{$ collection | camelcase $} | null>('{$ collection $}-detail', () => {
return $directus.request($readItem('{$ collection $}', route.params.id as string, query))
})
$checkError(error)
</script>

<template>
<div>
<h1>{$ collection | camelcase $}</h1>
<div>{{ {$ collection $} }}</div>
<div class="max-w-3xl mx-auto px-4 py-8">
<NuxtLink :to="`/{$ collection $}`" class="text-blue-600 hover:underline text-sm">&larr; Back to {$ collection $}</NuxtLink>

<template v-if="data">
<h1 class="text-3xl font-bold mt-4 mb-2">
<template v-if="data.title">{{ data.title }}</template>
<template v-else-if="data.name">{{ data.name }}</template>
<template v-else>{{ data.id }}</template>
</h1>
</template>

<template v-else-if="!error">
<h1 class="text-3xl font-bold mt-4">Not found</h1>
<p class="text-gray-500 mt-2">This item could not be found.</p>
<NuxtLink :to="`/{$ collection $}`" class="text-blue-600 hover:underline text-sm mt-4 inline-block">&larr; Back to {$ collection $}</NuxtLink>
</template>
</div>
</template>
</template>
24 changes: 15 additions & 9 deletions src/templates/singleton.njk.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@
import type { Query } from "@directus/sdk"
import type { components } from "../../interfaces/nuxtus"
type {$ collection | camelcase $} = components["schemas"]["Items{$ collection | camelcase $}"]
const { $directus, $readSingleton, $checkError } = useNuxtApp()
const { $directus, $readItems, $checkError } = useNuxtApp()

const query: Query<components, {$ collection | camelcase $}> = {
// Add your filters and query customisations here
}
const query: Query<components, {$ collection | camelcase $}> = {}

const { data: {$ collection $}, error } = useAsyncData <{$ collection | camelcase $} | null> ('{$ collection $}', () => {
return $directus.request($readSingleton('{$ collection $}', query))
const { data: {$ collection $}, error } = useAsyncData<{$ collection | camelcase $} | null>('{$ collection $}-singleton', () => {
return $directus.request($readItems('{$ collection $}', query))
})
$checkError(error)
</script>

<template>
<h1>{$ collection | camelcase $}</h1>
{{ {$ collection $} }}
</template>
<div class="max-w-3xl mx-auto px-4 py-8">
<template v-if="{$ collection $}">
<h1 class="text-3xl font-bold mb-4">
<template v-if="${$ collection $}.title">{{ {$ collection $}.title }}</template>
<template v-else-if="${$ collection $}.name">{{ {$ collection $}.name }}</template>
<template v-else>{$ collection | camelcase $}</template>
</h1>
</template>
<p v-else>Loading...</p>
</div>
</template>