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
2 changes: 1 addition & 1 deletion .github/workflows/publish-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2

- run: corepack enable
- run: npm install -g corepack@latest && corepack enable
- uses: actions/setup-node@v4
with:
node-version: 20
Expand Down
1 change: 1 addition & 0 deletions apps/site/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
DOCSEARCH_APP_ID=RETR9S9VHS
DOCSEARCH_API_KEY=326c1723a310dfe29004b47608709907
DOCSEARCH_INDEX_NAME=tailwindui-protocol
GITHUB_TOKEN=foo
5 changes: 2 additions & 3 deletions apps/site/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
json,
type LinksFunction,
type MetaFunction,
type LoaderFunctionArgs,
Expand Down Expand Up @@ -46,13 +45,13 @@ export const links: LinksFunction = () => [
];

export async function loader({ context: { cloudflare } }: LoaderFunctionArgs) {
return json({
return {
ENV: {
DOCSEARCH_APP_ID: cloudflare.env.DOCSEARCH_APP_ID,
DOCSEARCH_API_KEY: cloudflare.env.DOCSEARCH_API_KEY,
DOCSEARCH_INDEX_NAME: cloudflare.env.DOCSEARCH_INDEX_NAME,
},
});
};
}

const themeScript = `
Expand Down
3 changes: 1 addition & 2 deletions apps/site/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
json,
type LoaderFunctionArgs,
type MetaFunction,
} from "@remix-run/cloudflare";
Expand Down Expand Up @@ -34,7 +33,7 @@ export async function loader({
const { content, title, tableOfContents, description } =
parseMarkdoc(markdown);

return json({ content, title, tableOfContents, manifest, description });
return { content, title, tableOfContents, manifest, description };
}

export const meta: MetaFunction<typeof loader> = ({ data }) => [
Expand Down
8 changes: 0 additions & 8 deletions apps/site/types/build.d.ts

This file was deleted.

8 changes: 8 additions & 0 deletions apps/site/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import {
} from "@remix-run/dev";
import tsconfigPaths from "vite-tsconfig-paths";

declare module "@remix-run/cloudflare" {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Future {
v3_singleFetch: true;
}
}

export default defineConfig({
plugins: [
cloudflareDevProxyVitePlugin(),
Expand All @@ -13,6 +20,7 @@ export default defineConfig({
v3_fetcherPersist: true,
v3_lazyRouteDiscovery: true,
v3_relativeSplatPath: true,
v3_singleFetch: true,
v3_throwAbortReason: true,
},
}),
Expand Down
1 change: 1 addition & 0 deletions apps/site/worker-configuration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ interface Env {
DOCSEARCH_APP_ID: string;
DOCSEARCH_API_KEY: string;
DOCSEARCH_INDEX_NAME: string;
GITHUB_TOKEN: string;
}
2 changes: 1 addition & 1 deletion examples/remix-cms/app/models/Article.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Model } from "superflare";
import { User } from "./User";

export class Article extends Model {
user!: User | Promise<User>;
user!: User;
$user() {
return this.belongsTo(User);
}
Expand Down
1 change: 1 addition & 0 deletions examples/remix-cms/app/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class User extends Model {
return rest;
}
}

Model.register(User);

export interface User extends UserRow {}
7 changes: 2 additions & 5 deletions examples/remix-cms/app/routes/admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import clsx from "clsx";
import { Link, NavLink, Outlet, useLoaderData } from "@remix-run/react";
import { Toast } from "~/components/Toast";
import { json, type LoaderFunctionArgs, redirect } from "@remix-run/cloudflare";
import { type LoaderFunctionArgs, redirect } from "@remix-run/cloudflare";
import { User } from "~/models/User";

const navigation = [
Expand All @@ -33,10 +33,7 @@ export async function loader({

const user = await auth.user(User);

return json({
flash,
user,
});
return { flash, user };
}

export default function AdminLayout() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export async function loader({ params }: LoaderFunctionArgs) {
throw new Response("Not found", { status: 404 });
}

return json({
return {
article,
html: await convertToHtml(article.content ?? ""),
});
};
}

export default function NewArticle() {
Expand Down
4 changes: 2 additions & 2 deletions examples/remix-cms/app/routes/admin/articles.$slug.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EyeIcon } from "@heroicons/react/24/outline";
import { json, type LoaderFunctionArgs } from "@remix-run/cloudflare";
import { type LoaderFunctionArgs } from "@remix-run/cloudflare";
import { useLoaderData, useRevalidator } from "@remix-run/react";
import invariant from "tiny-invariant";
import { Button, SecondaryButton } from "~/components/admin/Button";
Expand All @@ -24,7 +24,7 @@ export async function loader({ params }: LoaderFunctionArgs) {

SayHelloJob.dispatch(article);

return json({ article });
return { article };
}

export default function NewArticle() {
Expand Down
3 changes: 1 addition & 2 deletions examples/remix-cms/app/routes/admin/articles.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { json } from "@remix-run/cloudflare";
import { Link, useLoaderData } from "@remix-run/react";
import { Button } from "~/components/admin/Button";
import { Page } from "~/components/admin/Page";
Expand All @@ -8,7 +7,7 @@ import { useChannel } from "~/utils/use-channel";
export async function loader() {
const articles = await Article.with("user").orderBy("createdAt", "desc");

return json({ articles });
return { articles };
}

export default function Articles() {
Expand Down
11 changes: 3 additions & 8 deletions examples/remix-cms/app/routes/admin/components/article-form.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
json,
redirect,
type SerializeFrom,
type ActionFunctionArgs,
} from "@remix-run/cloudflare";
import { redirect, type ActionFunctionArgs } from "@remix-run/cloudflare";
import { Form, useActionData } from "@remix-run/react";
import { Article } from "~/models/Article";
import invariant from "tiny-invariant";
Expand All @@ -29,7 +24,7 @@ const enum Intent {
Update = "update",
}

const badResponse = (data: ActionData) => json(data, { status: 422 });
const badResponse = (data: ActionData) => Response.json(data, { status: 422 });

export async function action({
request,
Expand Down Expand Up @@ -110,7 +105,7 @@ export function ArticleForm({
article,
id,
}: {
article?: SerializeFrom<Article>;
article?: Article;
id?: string;
}) {
const actionData = useActionData<ActionData>();
Expand Down
6 changes: 2 additions & 4 deletions examples/remix-cms/app/routes/admin/upload.$.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { json, type ActionFunctionArgs } from "@remix-run/cloudflare";
import { type ActionFunctionArgs } from "@remix-run/cloudflare";
import { parseMultipartFormData, storage } from "superflare";

export async function action({ request }: ActionFunctionArgs) {
Expand All @@ -13,7 +13,5 @@ export async function action({ request }: ActionFunctionArgs) {
}
);

return json({
url: storage().url(formData.get("file") as string),
});
return { url: storage().url(formData.get("file") as string) };
}
6 changes: 3 additions & 3 deletions examples/remix-cms/app/routes/auth/login.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { redirect, type ActionFunctionArgs } from "@remix-run/cloudflare";
import { Form, Link, useActionData } from "@remix-run/react";
import { json, redirect, type ActionFunctionArgs } from "@remix-run/cloudflare";
import { Button } from "~/components/admin/Button";
import { FormField } from "~/components/Form";
import { User } from "~/models/User";
Expand All @@ -26,11 +26,11 @@ export async function action({
return redirect("/admin");
}

return json({ error: "Invalid credentials" }, { status: 400 });
return Response.json({ error: "Invalid credentials" }, { status: 400 });
}

export default function Login() {
const actionData = useActionData<typeof action>();
const actionData = useActionData<{ error: string }>();

return (
<>
Expand Down
6 changes: 3 additions & 3 deletions examples/remix-cms/app/routes/auth/register.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Form, Link, useActionData } from "@remix-run/react";
import { json, redirect, type ActionFunctionArgs } from "@remix-run/cloudflare";
import { redirect, type ActionFunctionArgs } from "@remix-run/cloudflare";
import { Button } from "~/components/admin/Button";
import { FormField } from "~/components/Form";
import { User } from "~/models/User";
Expand All @@ -19,7 +19,7 @@ export async function action({
const name = formData.get("name") as string;

if (await User.where("email", email).count()) {
return json({ error: "Email already exists" }, { status: 400 });
return Response.json({ error: "Email already exists" }, { status: 400 });
}

const user = await User.create({
Expand All @@ -34,7 +34,7 @@ export async function action({
}

export default function Register() {
const actionData = useActionData<typeof action>();
const actionData = useActionData<{ error: string }>();

return (
<Form method="post" className="grid grid-cols-6 gap-4">
Expand Down
8 changes: 0 additions & 8 deletions examples/remix-cms/types/build.d.ts

This file was deleted.

8 changes: 8 additions & 0 deletions examples/remix-cms/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { createRoutesFromFolders } from "@remix-run/v1-route-convention";
import { superflareDevProxyVitePlugin } from "@superflare/remix/dev";
import tsconfigPaths from "vite-tsconfig-paths";

declare module "@remix-run/cloudflare" {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Future {
v3_singleFetch: true;
}
}

export default defineConfig({
plugins: [
superflareDevProxyVitePlugin<Env>(),
Expand All @@ -12,6 +19,7 @@ export default defineConfig({
v3_fetcherPersist: true,
v3_lazyRouteDiscovery: true,
v3_relativeSplatPath: true,
v3_singleFetch: true,
v3_throwAbortReason: true,
},
// Tell Remix to ignore everything in the routes directory.
Expand Down
2 changes: 1 addition & 1 deletion packages/superflare/docs/database/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ However, we cannot simply send the entire data model over the wire from the serv

Instead, modern frameworks will serialize the output sent (from "loaders" in Remix, or passed as props from server components to client components in Next.js).

Superflare makes it obvious how to serialize your models as JSON by providing the standard `toJSON()` method by on new models.
Superflare makes it obvious how to serialize your models as JSON by providing the standard `toJSON()` method on new models.

By default, this method will return all of the model's attributes, in addition to any relations that are loaded on the instance either manually or by using eager-loading.

Expand Down
17 changes: 8 additions & 9 deletions packages/superflare/docs/database/relationships.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Model } from "superflare";
import { Profile } from "./Profile";

export class User extends Model {
profile!: Profile | Promise<Profile>;
profile!: Profile;
$profile() {
return this.hasOne(Profile);
}
Expand Down Expand Up @@ -46,7 +46,7 @@ To define the inverse relationship, use the `belongsTo` method:
import { Model } from "superflare";

export class Profile extends Model {
user!: User | Promise<User>;
user!: User;
$user() {
return this.belongsTo(User);
}
Expand All @@ -71,7 +71,7 @@ To define a one-to-many relationship, use the `hasMany` method:
import { Model } from "superflare";

export class User extends Model {
posts!: Post[] | Promise<Post[]>;
posts!: Post[];
$posts() {
return this.hasMany(Post);
}
Expand All @@ -96,7 +96,7 @@ To define the inverse relationship, use the `belongsTo` method:
import { Model } from "superflare";

export class Post extends Model {
user!: User | Promise<User>;
user!: User;
$user() {
return this.belongsTo(User);
}
Expand Down Expand Up @@ -144,7 +144,7 @@ To define a many-to-many relationship, use the `belongsToMany` method:
import { Model } from "superflare";

export class Post extends Model {
tags!: Tag[] | Promise<Tag[]>;
tags!: Tag[];
$tags() {
return this.belongsToMany(Tag);
}
Expand All @@ -163,15 +163,15 @@ for (const tag of tags) {
}
```

When invoking the `$tags()` method or awaiting the `tags` property, Superflare will check an intermediate table, often referred to as a "join table," for rows which have a `postId` that matches the `id` of the `Post` model. It will return all `Tag` models which have a `id` that matches the `tagId` of the join table rows.
When invoking the `$tags()` method or awaiting the `tags` property, Superflare will check an intermediate table, often referred to as a "join table", for rows which have a `postId` that matches the `id` of the `Post` model. It will return all `Tag` models which have a `id` that matches the `tagId` of the join table rows.

To define the inverse relationship, use the `belongsToMany` method again:

```ts
import { Model } from "superflare";

export class Tag extends Model {
posts!: Post[] | Promise<Post[]>;
posts!: Post[];
$posts() {
return this.belongsToMany(Post);
}
Expand Down Expand Up @@ -202,7 +202,6 @@ If you don't eager load the related models, the related data will not be availab

```tsx
import { User } from "~/models/User";
import { json } from "@remix-run/cloudflare";

export async function loader() {
// ❌ The profile relation will not be loaded
Expand All @@ -211,7 +210,7 @@ export async function loader() {
// ✅ This will load the profile relation for the view
const user = await User.with("profile").find(1);

return json({ user });
return { user };
}

export default function UserView() {
Expand Down
2 changes: 1 addition & 1 deletion packages/superflare/docs/security/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function loader({ context: { auth } }: LoaderFunctionArgs) {
const user = await auth.user(User);

// If the user is logged in, show them the secret page
return json({ message: `You're logged in, ${user.name}!` });
return { message: `You're logged in, ${user.name}!` };
}
```

Expand Down
Loading