Skip to content

Commit

Permalink
feat(courses-list): add trpc
Browse files Browse the repository at this point in the history
  • Loading branch information
arturvoloshyn committed Mar 20, 2024
1 parent 9de59dc commit c74ff1d
Show file tree
Hide file tree
Showing 55 changed files with 477 additions and 670 deletions.
553 changes: 74 additions & 479 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"name": "core",
"version": "1.0.0",
"workspaces": ["./packages/*"],
"workspaces": [
"./packages/*"
],
"private": true,
"scripts": {
"postinstall": "patch-package",
Expand All @@ -13,7 +15,7 @@
"test": "jest",
"prettier": "prettier -w .",
"test:e2e": "npx prisma migrate reset --force && playwright test",
"upload-content-schema": "ts-node --project tsconfig.script.json ./scripts/upload-content-schema packages/content-schema/schemas/ ./src/shared/api/content/schemas",
"upload-content-schema": "ts-node --project tsconfig.script.json ./scripts/upload-content-schema packages/content-schema/schemas/ ./src/shared/api/content/_schemas",
"dev:content-schema": "npm run dev --workspace=@core/content-schema"
},
"prisma": {
Expand All @@ -32,7 +34,11 @@
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@sentry/nextjs": "^7.84.0",
"@tanstack/react-query": "^5.17.9",
"@tanstack/react-query": "^5.28.4",
"@trpc/client": "^11.0.0-next-beta.318",
"@trpc/next": "^11.0.0-next-beta.318",
"@trpc/react-query": "^11.0.0-next-beta.318",
"@trpc/server": "^11.0.0-next-beta.318",
"ajv": "^8.12.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/content-schema/scripts/generate-schema-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ async function convertSchemaToType(file: string): Promise<void> {
const ts: string = await compileFromFile(file);
fs.writeFileSync(
path.join(path.dirname(file), path.basename(file, ".json") + ".d.ts"),
ts
ts,
);
console.log(`Converted: ${file}`);
} catch (error) {
Expand Down
20 changes: 10 additions & 10 deletions packages/content-schema/scripts/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ const checkIds = (obj: any, context: string, path = "") => {
if (obj.id) {
if (ids.has(obj.id)) {
console.error(
`Duplicate ID found: ${obj.id} in ${context} path: ${path}`
`Duplicate ID found: ${obj.id} in ${context} path: ${path}`,
);
} else {
ids.add(obj.id);
}
}
Object.entries(obj).forEach(([key, value]) =>
checkIds(value, `${path}.${key}`, context)
checkIds(value, `${path}.${key}`, context),
);
}
};
Expand All @@ -51,23 +51,23 @@ const checkIds = (obj: any, context: string, path = "") => {
const lessonSchema = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "../schemas/lesson.schema.json"), {
encoding: "utf8",
})
}),
);
const courseSchema = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "../schemas/course.schema.json"), {
encoding: "utf8",
})
}),
);
const manifestSchema = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "../schemas/manifest.schema.json"), {
encoding: "utf8",
})
}),
);

async function validateLesson(file: string) {
const lesson = await contentParser.parse<Lesson>(
fs.readFileSync(file, "utf8"),
lessonSchema
lessonSchema,
);

checkIds(lesson, file);
Expand All @@ -77,7 +77,7 @@ async function validateLesson(file: string) {
async function validateCourse(file: string) {
const course = await contentParser.parse<Course>(
fs.readFileSync(file, "utf8"),
courseSchema
courseSchema,
);
checkIds(course, file);
return course;
Expand All @@ -86,7 +86,7 @@ async function validateCourse(file: string) {
async function validateManifest(file: string) {
const manifest = await contentParser.parse<Manifest>(
fs.readFileSync(file, "utf8"),
manifestSchema
manifestSchema,
);
return manifest;
}
Expand All @@ -98,12 +98,12 @@ async function scanDirectory(directoryPath: string) {

for (const coursePath of manifest.courses) {
const course = await validateCourse(
`${directoryPath}/courses/${coursePath}/course.yaml`
`${directoryPath}/courses/${coursePath}/course.yaml`,
);

for (const lessonPath of course.lessons) {
await validateLesson(
`${directoryPath}/courses/${coursePath}/lessons/${lessonPath}/lesson.yaml`
`${directoryPath}/courses/${coursePath}/lessons/${lessonPath}/lesson.yaml`,
);
}
}
Expand Down
12 changes: 6 additions & 6 deletions packages/content-schema/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
/* Visit https://aka.ms/tsconfig to read more about this file */

/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,

/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"module": "commonjs" /* Specify what module code is generated. */,

/* Interop Constraints */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,

/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
"strict": true /* Enable all strict type-checking options. */,

/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
2 changes: 1 addition & 1 deletion src/app/(auth)/auth/new-user/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getAppSessionServer } from "@/entities/user/session.server";
import { getAppSessionServer } from "@/kernel/lib/next-auth/server";
import { UpdateProfileForm } from "@/features/update-profile/update-profile-form";
import { Separator } from "@/shared/ui/separator";
import { redirect } from "next/navigation";
Expand Down
2 changes: 1 addition & 1 deletion src/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppHeader } from "@/widgets/app-header/app-header";
import { AppHeader } from "../_widgets/app-header/app-header";

export default async function Layout({
children,
Expand Down
2 changes: 1 addition & 1 deletion src/app/(private)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AuthorizedGuard from "@/features/auth/authorized-guard";
import { AppHeader } from "@/widgets/app-header/app-header";
import { AppHeader } from "../_widgets/app-header/app-header";

export default async function Layout({
children,
Expand Down
2 changes: 1 addition & 1 deletion src/app/(public)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppHeader } from "@/widgets/app-header/app-header";
import { AppHeader } from "../_widgets/app-header/app-header";

export default async function Layout({
children,
Expand Down
27 changes: 22 additions & 5 deletions src/app/_providers/app-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
"use client";

import { AppSessionProvider } from "@/entities/user/session";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import React, { useState } from "react";
import { ThemeProvider } from "@/features/theme/theme-provider";
import { queryClient } from "@/shared/api/query-client";
import { AppSessionProvider } from "@/kernel/lib/next-auth/client";
import { ComposeChildren } from "@/shared/lib/react";
import { QueryClientProvider } from "@tanstack/react-query";
import React from "react";
import { sharedApi } from "@/kernel/lib/trpc/client";
import { TRPCUntypedClient, httpBatchLink } from "@trpc/client";
import { publicConfig } from "@/shared/config/public";
import { AnyRouter } from "@trpc/server";

export function AppProvider({ children }: { children: React.ReactNode }) {
const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState<TRPCUntypedClient<AnyRouter>>(() =>
sharedApi.createClient({
links: [
httpBatchLink({
url: `${publicConfig.PUBLIC_URL}/api/trpc`,
}),
],
}),
);

return (
<ComposeChildren>
<sharedApi.Provider client={trpcClient} queryClient={queryClient}>
<></>
</sharedApi.Provider>
<QueryClientProvider client={queryClient} />
<ThemeProvider />
<AppSessionProvider />
<QueryClientProvider client={queryClient} />
{children}
</ComposeChildren>
);
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import {
import { LogOut, User } from "lucide-react";
import { Button } from "@/shared/ui/button";
import Link from "next/link";
import { useAppSession } from "@/entities/user/session";
import { Skeleton } from "@/shared/ui/skeleton";
import { useSignOut } from "@/features/auth/use-sign-out";
import { SignInButton } from "@/features/auth/sign-in-button";
import { ProfileAvatar, getProfileDisplayName } from "@/entities/user/profile";
import { useAppSession } from "@/kernel/lib/next-auth/client";

export function Profile() {
const session = useAppSession();
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { nextAuthConfig } from "@/entities/user/next-auth-config";
import { nextAuthConfig } from "@/kernel/lib/next-auth/next-auth-config";
import NextAuth from "next-auth/next";

const authHandler = NextAuth(nextAuthConfig);
Expand Down
13 changes: 13 additions & 0 deletions src/app/api/trpc/[trpc]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { coursesListController } from "@/features/courses-list/controller";
import { createContext, sharedRouter, t } from "@/kernel/lib/trpc/server";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";

const handler = (req: Request) =>
fetchRequestHandler({
endpoint: "/api/trpc",
req,
router: t.mergeRouters(sharedRouter, coursesListController),
createContext: createContext,
});

export { handler as GET, handler as POST };
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { coursesRepository } from "../_repositories/course";

type GetCoursesList = {};

export class GetCoursesListUseCase {
export class GetCoursesListService {
async exec(data?: GetCoursesList) {
return coursesRepository.getCoursesList();
}
}

export const getCoursesListUseCase = new GetCoursesListUseCase();
export const getCoursesListService = new GetCoursesListService();
2 changes: 1 addition & 1 deletion src/entities/course/course.server.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { getCoursesListUseCase } from "./_use-cases/get-courses-list";
export { getCoursesListService } from "./_services/get-courses-list";
6 changes: 3 additions & 3 deletions src/entities/user/_actions/get-user-profile.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use server";
import { z } from "zod";
import { getUserUseCase } from "../_use-cases/get-user";
import { getAppSessionStrictServer } from "../session.server";
import { getUserService } from "../_services/get-user";
import { getAppSessionStrictServer } from "../../../kernel/lib/next-auth/server";
import { profileSchema } from "../_domain/schema";

const propsSchema = z.object({
Expand All @@ -19,7 +19,7 @@ export const getUserProfileAction = async (

const session = await getAppSessionStrictServer();

const user = await getUserUseCase.exec({
const user = await getUserService.exec({
session,
userId,
});
Expand Down
6 changes: 3 additions & 3 deletions src/entities/user/_domain/ability.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ROLES, SessionEntity, UserId } from "./types";
import { SharedSession, UserId, ROLES } from "@/kernel/domain/user";

export const createUserAbility = (session: SessionEntity) => ({
export const createUserAbility = (session: SharedSession) => ({
canGetUser: (userId: UserId) =>
session.user.id === userId || session.user.role === ROLES.ADMIN,
});

export const createProfileAbility = (session: SessionEntity) => ({
export const createProfileAbility = (session: SharedSession) => ({
canUpdateProfile: (userId: UserId) =>
session.user.id === userId || session.user.role === ROLES.ADMIN,
});
30 changes: 0 additions & 30 deletions src/entities/user/_domain/types.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,3 @@
export type UserId = string;
export type Role = "ADMIN" | "USER";

export const ROLES: Record<Role, Role> = {
ADMIN: "ADMIN",
USER: "USER",
};

export type UserEntity = {
id: UserId;
email: string;
role: Role;
emailVerified?: Date | null;
name?: string | null;
image?: string | null;
};

export type SessionEntity = {
user: {
id: UserId;
email: string;
role: Role;
name?: string | null;
image?: string | null;
};
expires: string;
};

// Projections

export type Profile = {
email: string;
name?: string | null;
Expand Down
9 changes: 0 additions & 9 deletions src/entities/user/_next-auth.d.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/entities/user/_queries/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UserId } from "../_domain/types";
import { UserId } from "@/kernel/domain/user";
import { getUserProfileAction } from "../_actions/get-user-profile";
import { useQueryClient } from "@tanstack/react-query";

Expand Down
3 changes: 2 additions & 1 deletion src/entities/user/_repositories/profile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { dbClient } from "@/shared/lib/db";
import { Profile, UserId } from "../_domain/types";
import { Profile } from "../_domain/types";
import { UserId } from "@/kernel/domain/user";

export class ProfileRepository {
async update(userId: UserId, data: Partial<Profile>): Promise<Profile> {
Expand Down
10 changes: 2 additions & 8 deletions src/entities/user/_repositories/user.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { UserId, SharedUser } from "@/kernel/domain/user";
import { dbClient } from "@/shared/lib/db";
import { UserEntity, UserId } from "../_domain/types";

export class UserRepository {
async getUserById(userId: UserId): Promise<UserEntity> {
async getUserById(userId: UserId): Promise<SharedUser> {
return dbClient.user.findUniqueOrThrow({
where: {
id: userId,
},
});
}

async createUser(user: UserEntity): Promise<UserEntity> {
return await dbClient.user.create({
data: user,
});
}
}

export const userRepository = new UserRepository();
Loading

0 comments on commit c74ff1d

Please sign in to comment.