@techstream/quark-create-app 1.5.3 → 1.6.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/package.json +4 -2
- package/src/index.js +52 -9
- package/templates/base-project/.github/dependabot.yml +12 -0
- package/templates/base-project/.github/workflows/ci.yml +97 -0
- package/templates/base-project/.github/workflows/dependabot-auto-merge.yml +22 -0
- package/templates/base-project/.github/workflows/release.yml +38 -0
- package/templates/base-project/apps/web/biome.json +7 -0
- package/templates/base-project/apps/web/jsconfig.json +5 -5
- package/templates/base-project/apps/web/next.config.js +86 -1
- package/templates/base-project/apps/web/package.json +4 -4
- package/templates/base-project/apps/web/src/app/api/auth/register/route.js +6 -7
- package/templates/base-project/apps/web/src/app/layout.js +3 -4
- package/templates/base-project/apps/web/src/app/manifest.js +12 -0
- package/templates/base-project/apps/web/src/app/robots.js +21 -0
- package/templates/base-project/apps/web/src/app/sitemap.js +20 -0
- package/templates/base-project/apps/web/src/lib/seo/indexing.js +23 -0
- package/templates/base-project/apps/web/src/lib/seo/site-metadata.js +33 -0
- package/templates/base-project/apps/web/src/proxy.js +1 -2
- package/templates/base-project/apps/worker/package.json +4 -4
- package/templates/base-project/apps/worker/src/index.js +26 -12
- package/templates/base-project/apps/worker/src/index.test.js +296 -15
- package/templates/base-project/biome.json +44 -0
- package/templates/base-project/docker-compose.yml +7 -4
- package/templates/base-project/package.json +1 -1
- package/templates/base-project/packages/db/package.json +1 -1
- package/templates/base-project/packages/db/prisma/schema.prisma +1 -17
- package/templates/base-project/packages/db/prisma.config.ts +3 -2
- package/templates/base-project/packages/db/scripts/seed.js +117 -30
- package/templates/base-project/packages/db/src/queries.js +52 -118
- package/templates/base-project/packages/db/src/queries.test.js +0 -29
- package/templates/base-project/packages/db/src/schemas.js +0 -12
- package/templates/base-project/pnpm-workspace.yaml +4 -0
- package/templates/base-project/turbo.json +5 -3
- package/templates/config/package.json +2 -0
- package/templates/config/src/environment.js +270 -0
- package/templates/config/src/index.js +10 -18
- package/templates/config/src/load-config.js +135 -0
- package/templates/config/src/validate-env.js +60 -2
- package/templates/jobs/package.json +2 -2
- package/templates/jobs/src/definitions.test.js +34 -0
- package/templates/jobs/src/index.js +1 -1
- package/templates/ui/package.json +4 -4
- package/templates/ui/src/button.test.js +23 -0
- package/templates/ui/src/index.js +1 -3
- package/templates/base-project/apps/web/src/app/api/posts/[id]/route.js +0 -65
- package/templates/base-project/apps/web/src/app/api/posts/route.js +0 -95
- package/templates/ui/src/card.js +0 -14
- package/templates/ui/src/input.js +0 -11
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createQueryBuilder,
|
|
3
|
-
validateBody,
|
|
4
|
-
withCsrfProtection,
|
|
5
|
-
} from "@techstream/quark-core";
|
|
6
|
-
import { post, postCreateSchema } from "@techstream/quark-db";
|
|
7
|
-
import { NextResponse } from "next/server";
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
import { requireAuth } from "@/lib/auth-middleware";
|
|
10
|
-
import { handleError } from "../error-handler";
|
|
11
|
-
|
|
12
|
-
const paginationSchema = z.object({
|
|
13
|
-
page: z.coerce.number().int().min(1).default(1),
|
|
14
|
-
limit: z.coerce.number().int().min(1).max(100).default(10),
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const querySchema = paginationSchema.extend({
|
|
18
|
-
search: z.string().optional(),
|
|
19
|
-
status: z.enum(["draft", "published"]).optional(),
|
|
20
|
-
authorId: z.string().optional(),
|
|
21
|
-
sort: z.enum(["createdAt", "updatedAt", "title"]).optional(),
|
|
22
|
-
order: z.enum(["asc", "desc"]).default("desc"),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export async function GET(request) {
|
|
26
|
-
try {
|
|
27
|
-
const { searchParams } = new URL(request.url);
|
|
28
|
-
const { page, limit, search, status, authorId, sort, order } =
|
|
29
|
-
querySchema.parse({
|
|
30
|
-
page: searchParams.get("page") ?? undefined,
|
|
31
|
-
limit: searchParams.get("limit") ?? undefined,
|
|
32
|
-
search: searchParams.get("search") ?? undefined,
|
|
33
|
-
status: searchParams.get("status") ?? undefined,
|
|
34
|
-
authorId: searchParams.get("authorId") ?? undefined,
|
|
35
|
-
sort: searchParams.get("sort") ?? undefined,
|
|
36
|
-
order: searchParams.get("order") ?? undefined,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const skip = (page - 1) * limit;
|
|
40
|
-
|
|
41
|
-
// Build query with filters, search, and sort
|
|
42
|
-
const qb = createQueryBuilder({
|
|
43
|
-
filterableFields: ["published", "authorId"],
|
|
44
|
-
searchFields: ["title", "content"],
|
|
45
|
-
sortableFields: ["createdAt", "updatedAt", "title"],
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// Apply filters
|
|
49
|
-
if (status === "published") {
|
|
50
|
-
qb.filter("published", "eq", true);
|
|
51
|
-
} else if (status === "draft") {
|
|
52
|
-
qb.filter("published", "eq", false);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (authorId) {
|
|
56
|
-
qb.filter("authorId", "eq", authorId);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Apply search
|
|
60
|
-
if (search) {
|
|
61
|
-
qb.search(search);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Apply sort
|
|
65
|
-
if (sort) {
|
|
66
|
-
qb.sort(sort, order);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const posts = await post.findAll({
|
|
70
|
-
skip,
|
|
71
|
-
take: limit,
|
|
72
|
-
where: qb.toWhere(),
|
|
73
|
-
orderBy: qb.toOrderBy(),
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
return NextResponse.json(posts);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
return handleError(error);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const POST = withCsrfProtection(async (request) => {
|
|
83
|
-
try {
|
|
84
|
-
const session = await requireAuth();
|
|
85
|
-
const data = await validateBody(request, postCreateSchema);
|
|
86
|
-
|
|
87
|
-
const newPost = await post.create({
|
|
88
|
-
...data,
|
|
89
|
-
authorId: session.user.id,
|
|
90
|
-
});
|
|
91
|
-
return NextResponse.json(newPost, { status: 201 });
|
|
92
|
-
} catch (error) {
|
|
93
|
-
return handleError(error);
|
|
94
|
-
}
|
|
95
|
-
});
|
package/templates/ui/src/card.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
export const Card = ({ className, children, ...props }) => {
|
|
4
|
-
const baseStyles = "bg-white rounded-lg shadow-md p-4";
|
|
5
|
-
|
|
6
|
-
return React.createElement(
|
|
7
|
-
"div",
|
|
8
|
-
{
|
|
9
|
-
className: `${baseStyles} ${className || ""}`,
|
|
10
|
-
...props,
|
|
11
|
-
},
|
|
12
|
-
children,
|
|
13
|
-
);
|
|
14
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
export const Input = ({ className, ...props }) => {
|
|
4
|
-
const baseStyles =
|
|
5
|
-
"px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500";
|
|
6
|
-
|
|
7
|
-
return React.createElement("input", {
|
|
8
|
-
className: `${baseStyles} ${className || ""}`,
|
|
9
|
-
...props,
|
|
10
|
-
});
|
|
11
|
-
};
|