Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nuxt): add nuxt template settings #875

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/create/README.md
Expand Up @@ -42,7 +42,7 @@ Navigate into `packages/create`:
$ cd packages/create
```

Build `@edgedb/generate`
Build `@edgedb/create`

```bash
$ yarn build
Expand Down
1 change: 1 addition & 0 deletions packages/create/src/recipes/_base/index.ts
Expand Up @@ -27,6 +27,7 @@ const recipe: BaseRecipe = {
message: "What web framework should be used?",
options: [
{ value: "next", label: "Next.js" },
{ value: "nuxt", label: "Nuxt" },
{ value: "remix", label: "Remix" },
{ value: "express", label: "Express" },
{ value: "sveltekit", label: "SvelteKit" },
Expand Down
2 changes: 2 additions & 0 deletions packages/create/src/recipes/index.ts
Expand Up @@ -6,6 +6,7 @@ import express from "./express/index.js";
import nextjs from "./nextjs/index.js";
import remix from "./remix/index.js";
import sveltekit from "./sveltekit/index.js";
import nuxt from "./nuxt/index.js";

import { type Recipe } from "./types.js";

Expand All @@ -17,6 +18,7 @@ export const recipes: Recipe<any>[] = [
nextjs,
remix,
sveltekit,
nuxt,
// init
_edgedbInit,
_install,
Expand Down
2 changes: 1 addition & 1 deletion packages/create/src/recipes/nextjs/index.ts
Expand Up @@ -3,7 +3,7 @@ import * as p from "@clack/prompts";
import debug from "debug";
import { updatePackage } from "write-package";

import { BaseOptions, Recipe } from "../types.js";
import type { BaseOptions, Recipe } from "../types.js";
import { copyTemplateFiles } from "../../utils.js";

const logger = debug("@edgedb/create:recipe:nextjs");
Expand Down
50 changes: 50 additions & 0 deletions packages/create/src/recipes/nuxt/index.ts
@@ -0,0 +1,50 @@
import path from "node:path";
import debug from "debug";
import { updatePackage } from "write-package";

import type { BaseOptions, Recipe } from "../types.js";
import { copyTemplateFiles } from "../../utils.js";

const logger = debug("@edgedb/create:recipe:nuxt");

// interface NuxtOptions {}

const recipe: Recipe = {
skip(opts: BaseOptions) {
return opts.framework !== "nuxt";
},
async apply(
{ projectDir }: BaseOptions,
) {
logger("Running nuxt recipe");

const dirname = path.dirname(new URL(import.meta.url).pathname);

await copyTemplateFiles(
path.resolve(dirname, 'template'),
projectDir
);

await updatePackage(projectDir, {
type: 'module',
scripts: {
dev: "nuxi dev",
build: "nuxi build",
start: "nuxi start",
generate: "nuxi generate"
},
dependencies: {
"@iconify-json/heroicons": "1.1.19",
"@nuxt/ui": "^2.13.0",
"nuxt-edgedb-module": "^0.0.42"
},
devDependencies: {
"@edgedb/generate": "0.4.1",
"@nuxt/devtools": "latest",
"nuxt": "latest"
},
});
},
};

export default recipe;
59 changes: 59 additions & 0 deletions packages/create/src/recipes/nuxt/template/app.vue
@@ -0,0 +1,59 @@
<script setup lang="ts">
const { isLoggedIn } = useEdgeDbIdentity()

const links = computed(() => {
const links = [
{
label: 'Home',
icon: 'i-heroicons-home',
to: '/',
},
]

if (isLoggedIn.value) {
links.push(
{
label: 'New blogpost',
icon: 'i-heroicons-newspaper-20-solid',
to: '/new',
},
{
label: 'Logout',
icon: 'i-heroicons-newspaper-20-solid',
to: '/auth/logout',
},
)
}
else {
links.push(
{
label: 'Register',
icon: 'i-heroicons-key-20-solid',
to: '/auth/signup',
},
{
label: 'Login',
icon: 'i-heroicons-lock-open-20-solid',
to: '/auth/login',
},
{
label: 'Forgot my password',
icon: 'i-heroicons-sparkles-20-solid',
to: '/auth/forgot-password',
},
)
}

return links
})
</script>

<template>
<UContainer class="p-8 flex flex-col gap-4">
<UVerticalNavigation :links="links" />

<div>
<NuxtPage />
</div>
</UContainer>
</template>
Empty file.
@@ -0,0 +1,14 @@
<template>
<EdgeDbAuthProviders v-slot="{ oAuthProviders: providers }">
<EdgeDbOAuthButton
v-for="provider of providers"
:key="provider.name"
v-slot="{ redirect }"
:provider="provider.name"
>
<UButton @click="() => redirect()">
{{ provider.display_name }}
</UButton>
</EdgeDbOAuthButton>
</EdgeDbAuthProviders>
</template>
38 changes: 38 additions & 0 deletions packages/create/src/recipes/nuxt/template/dbschema/default.esdl
@@ -0,0 +1,38 @@
using extension auth;

module default {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I think we should have these recipes be starting point for any kind of app, not really an example app, if that makes sense. I'd expect that the schema here is empty, and that we add the auth extension here conditionally based on options set by the user.

To that end, if you want to design a small single page that just scaffolds some very basic layout and styles, definitely do that. Probably something closer to https://github.com/nuxt/starter/tree/v3 .

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, sounds great.

I started doing the "most minimal" Nuxt starter, but for Nuxt it just looks like adding nuxt-edgedb-module to their modules array.

The rest of it is just described in nuxt-edgedb-module.

Should I push that instead?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay in getting back to you here.

I'm not sure I understand the question but what I expect to see in these recipes is a totally empty default.esdl file, not even including the using extension auth; expression even. No migrations, no query builder code generator output, etc. These recipes should represent how you'd start day 0 on a new project, not as an example project, if that makes sense. The UI/app itself should also be minimal so that developers can quickly check that everything is working right, but nothing else.

Does that make sense?

global current_user := (
assert_single((
select User { id, name }
filter .identity = global ext::auth::ClientTokenIdentity
))
);

type User {
required name: str;
required identity: ext::auth::Identity;
multi link posts -> BlogPost {
on source delete delete target;
}
}

type BlogPost {
property content: str {
default := 'My super blog post.';
};
property description: str {
default := 'My blog post description.';
};
property title: str {
default := 'My blog super blog post title.';
};
required author: User {
default := global current_user;
};
access policy author_has_full_access
allow all
using (.author ?= global current_user);
access policy others_read_only
allow select;
}
}