From 557ed86abbcd3a6fb6c65735cd0cd233ac399696 Mon Sep 17 00:00:00 2001 From: Dylan Decrulle <81740200+ddecrulle@users.noreply.github.com> Date: Wed, 29 May 2024 15:42:40 +0200 Subject: [PATCH] breakpoint --- openApi.json | 74 ++++++++++++--- src/api/endpoints/default.ts | 84 ++++++++++++++--- src/api/model/index.ts | 5 +- src/api/model/putTodo200.ts | 11 +++ src/api/model/putTodoBody.ts | 11 +++ src/api/model/putTodoIdBody.ts | 12 +++ src/api/model/putTodoIdParams.ts | 2 +- src/api/model/todo.ts | 2 +- src/oidc.ts | 20 +++-- src/routeTree.gen.ts | 150 +++++++++++++++---------------- src/routes/account.tsx | 19 +++- src/routes/todo/index.tsx | 91 ++++++++++++------- src/routes/todo/route.tsx | 4 +- yarn.lock | 8 +- 14 files changed, 345 insertions(+), 148 deletions(-) create mode 100644 src/api/model/putTodo200.ts create mode 100644 src/api/model/putTodoBody.ts create mode 100644 src/api/model/putTodoIdBody.ts diff --git a/openApi.json b/openApi.json index cf520f4..3d58ae3 100644 --- a/openApi.json +++ b/openApi.json @@ -1,6 +1,6 @@ { "openapi": "3.0.0", - "info": { "version": "1.0.8", "title": "My API" }, + "info": { "version": "2.0.1", "title": "My API" }, "components": { "schemas": { "Todo": { @@ -24,21 +24,26 @@ "required": true, "name": "id", "in": "path" - }, - { - "schema": { "type": "string", "minLength": 1, "example": "Clean my room" }, - "required": true, - "name": "text", - "in": "query" - }, - { - "schema": { "type": "boolean", "example": false }, - "required": true, - "name": "isDone", - "in": "query" } ], - "responses": { "200": { "description": "Create or update a todo item" } } + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "text": { + "type": "string", + "minLength": 1, + "example": "Clean my room" + }, + "isDone": { "type": "boolean", "example": false } + } + } + } + } + }, + "responses": { "200": { "description": "Update an existing todo item" } } }, "delete": { "parameters": [ @@ -52,6 +57,47 @@ "responses": { "200": { "description": "Deleted a todo item" } } } }, + "/todo": { + "put": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "text": { + "type": "string", + "minLength": 1, + "example": "Clean my room" + } + }, + "required": ["text"] + } + } + } + }, + "responses": { + "200": { + "description": "Create a new todo item returns the newly created todo item's id", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The id of the newly created todo item", + "example": "123" + } + }, + "required": ["id"] + } + } + } + } + } + } + }, "/todos": { "get": { "responses": { diff --git a/src/api/endpoints/default.ts b/src/api/endpoints/default.ts index ceb8502..04b3791 100644 --- a/src/api/endpoints/default.ts +++ b/src/api/endpoints/default.ts @@ -2,7 +2,7 @@ * Generated by orval v6.29.1 🍺 * Do not edit manually. * My API - * OpenAPI spec version: 1.0.6 + * OpenAPI spec version: 2.0.1 */ import { useMutation, useQuery } from "@tanstack/react-query"; import type { @@ -14,63 +14,71 @@ import type { UseQueryOptions, UseQueryResult } from "@tanstack/react-query"; -import type { PutTodoIdParams, Todo } from "../model"; +import type { PutTodo200, PutTodoBody, PutTodoIdBody, Todo } from "../model"; import { customInstance } from "../mutator/customInstance"; type SecondParameter any> = Parameters[1]; export const putTodoId = ( id: string, - params: PutTodoIdParams, + putTodoIdBody: PutTodoIdBody, options?: SecondParameter ) => { - return customInstance({ url: `/todo/${id}`, method: "PUT", params }, options); + return customInstance( + { + url: `/todo/${id}`, + method: "PUT", + headers: { "Content-Type": "application/json" }, + data: putTodoIdBody + }, + options + ); }; export const getPutTodoIdMutationOptions = (options?: { mutation?: UseMutationOptions< Awaited>, TError, - { id: string; params: PutTodoIdParams }, + { id: string; data: PutTodoIdBody }, TContext >; request?: SecondParameter; }): UseMutationOptions< Awaited>, TError, - { id: string; params: PutTodoIdParams }, + { id: string; data: PutTodoIdBody }, TContext > => { const { mutation: mutationOptions, request: requestOptions } = options ?? {}; const mutationFn: MutationFunction< Awaited>, - { id: string; params: PutTodoIdParams } + { id: string; data: PutTodoIdBody } > = props => { - const { id, params } = props ?? {}; + const { id, data } = props ?? {}; - return putTodoId(id, params, requestOptions); + return putTodoId(id, data, requestOptions); }; return { mutationFn, ...mutationOptions }; }; export type PutTodoIdMutationResult = NonNullable>>; - +export type PutTodoIdMutationBody = PutTodoIdBody; export type PutTodoIdMutationError = unknown; export const usePutTodoId = (options?: { mutation?: UseMutationOptions< Awaited>, TError, - { id: string; params: PutTodoIdParams }, + { id: string; data: PutTodoIdBody }, TContext >; request?: SecondParameter; }): UseMutationResult< Awaited>, TError, - { id: string; params: PutTodoIdParams }, + { id: string; data: PutTodoIdBody }, TContext > => { const mutationOptions = getPutTodoIdMutationOptions(options); @@ -121,6 +129,58 @@ export const useDeleteTodoId = (options?: return useMutation(mutationOptions); }; +export const putTodo = (putTodoBody: PutTodoBody, options?: SecondParameter) => { + return customInstance( + { + url: `/todo`, + method: "PUT", + headers: { "Content-Type": "application/json" }, + data: putTodoBody + }, + options + ); +}; + +export const getPutTodoMutationOptions = (options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data: PutTodoBody }, + TContext + >; + request?: SecondParameter; +}): UseMutationOptions>, TError, { data: PutTodoBody }, TContext> => { + const { mutation: mutationOptions, request: requestOptions } = options ?? {}; + + const mutationFn: MutationFunction< + Awaited>, + { data: PutTodoBody } + > = props => { + const { data } = props ?? {}; + + return putTodo(data, requestOptions); + }; + + return { mutationFn, ...mutationOptions }; +}; + +export type PutTodoMutationResult = NonNullable>>; +export type PutTodoMutationBody = PutTodoBody; +export type PutTodoMutationError = unknown; + +export const usePutTodo = (options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data: PutTodoBody }, + TContext + >; + request?: SecondParameter; +}): UseMutationResult>, TError, { data: PutTodoBody }, TContext> => { + const mutationOptions = getPutTodoMutationOptions(options); + + return useMutation(mutationOptions); +}; export const getTodos = (options?: SecondParameter, signal?: AbortSignal) => { return customInstance({ url: `/todos`, method: "GET", signal }, options); }; diff --git a/src/api/model/index.ts b/src/api/model/index.ts index 0f98f6e..804cea3 100644 --- a/src/api/model/index.ts +++ b/src/api/model/index.ts @@ -2,8 +2,11 @@ * Generated by orval v6.29.1 🍺 * Do not edit manually. * My API - * OpenAPI spec version: 1.0.6 + * OpenAPI spec version: 2.0.1 */ +export * from "./putTodo200"; export * from "./putTodoIdParams"; export * from "./todo"; +export * from "./putTodoBody"; +export * from "./putTodoIdBody"; diff --git a/src/api/model/putTodo200.ts b/src/api/model/putTodo200.ts new file mode 100644 index 0000000..ab95b09 --- /dev/null +++ b/src/api/model/putTodo200.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v6.29.1 🍺 + * Do not edit manually. + * My API + * OpenAPI spec version: 2.0.1 + */ + +export type PutTodo200 = { + /** The id of the newly created todo item */ + id: string; +}; diff --git a/src/api/model/putTodoBody.ts b/src/api/model/putTodoBody.ts new file mode 100644 index 0000000..707418b --- /dev/null +++ b/src/api/model/putTodoBody.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v6.29.1 🍺 + * Do not edit manually. + * My API + * OpenAPI spec version: 2.0.1 + */ + +export type PutTodoBody = { + /** @minLength 1 */ + text: string; +}; diff --git a/src/api/model/putTodoIdBody.ts b/src/api/model/putTodoIdBody.ts new file mode 100644 index 0000000..2881392 --- /dev/null +++ b/src/api/model/putTodoIdBody.ts @@ -0,0 +1,12 @@ +/** + * Generated by orval v6.29.1 🍺 + * Do not edit manually. + * My API + * OpenAPI spec version: 2.0.1 + */ + +export type PutTodoIdBody = { + isDone?: boolean; + /** @minLength 1 */ + text?: string; +}; diff --git a/src/api/model/putTodoIdParams.ts b/src/api/model/putTodoIdParams.ts index 7f0dc17..c3ad443 100644 --- a/src/api/model/putTodoIdParams.ts +++ b/src/api/model/putTodoIdParams.ts @@ -2,7 +2,7 @@ * Generated by orval v6.29.1 🍺 * Do not edit manually. * My API - * OpenAPI spec version: 1.0.6 + * OpenAPI spec version: 1.0.8 */ export type PutTodoIdParams = { diff --git a/src/api/model/todo.ts b/src/api/model/todo.ts index 3066d13..b032931 100644 --- a/src/api/model/todo.ts +++ b/src/api/model/todo.ts @@ -2,7 +2,7 @@ * Generated by orval v6.29.1 🍺 * Do not edit manually. * My API - * OpenAPI spec version: 1.0.6 + * OpenAPI spec version: 2.0.1 */ export interface Todo { diff --git a/src/oidc.ts b/src/oidc.ts index 4d34488..85c8eb5 100644 --- a/src/oidc.ts +++ b/src/oidc.ts @@ -2,17 +2,27 @@ import { createReactOidc } from "oidc-spa/react"; import { createMockReactOidc } from "oidc-spa/mock/react"; import { z } from "zod"; +const decodedIdTokenSchema = z.object({ + sub: z.string(), + preferred_username: z.string() +}); + export const { OidcProvider, useOidc, prOidc } = import.meta.env.VITE_OIDC_ISSUER ? createReactOidc({ issuerUri: import.meta.env.VITE_OIDC_ISSUER, clientId: import.meta.env.VITE_OIDC_CLIENT_ID, publicUrl: import.meta.env.BASE_URL, - decodedIdTokenSchema: z.object({ - sub: z.string(), - preferred_username: z.string() - }) + decodedIdTokenSchema: decodedIdTokenSchema }) - : createMockReactOidc({ isUserInitiallyLoggedIn: false }); + : createMockReactOidc({ + isUserInitiallyLoggedIn: false, + mockedTokens: { + decodedIdToken: { + sub: "123", + preferred_username: "john doe" + } satisfies z.infer + } + }); export const protectedLoader = async () => { const oidc = await prOidc; diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 4bd4ebb..cd8dede 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -8,109 +8,109 @@ // This file is auto-generated by TanStack Router -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute } from '@tanstack/react-router' // Import Routes -import { Route as rootRoute } from "./routes/__root"; -import { Route as AccountImport } from "./routes/account"; -import { Route as TodoRouteImport } from "./routes/todo/route"; -import { Route as TodoIndexImport } from "./routes/todo/index"; -import { Route as TodoEditImport } from "./routes/todo/edit"; +import { Route as rootRoute } from './routes/__root' +import { Route as AccountImport } from './routes/account' +import { Route as TodoRouteImport } from './routes/todo/route' +import { Route as TodoIndexImport } from './routes/todo/index' +import { Route as TodoEditImport } from './routes/todo/edit' // Create Virtual Routes -const MuiLazyImport = createFileRoute("/mui")(); -const IndexLazyImport = createFileRoute("/")(); +const MuiLazyImport = createFileRoute('/mui')() +const IndexLazyImport = createFileRoute('/')() // Create/Update Routes const MuiLazyRoute = MuiLazyImport.update({ - path: "/mui", - getParentRoute: () => rootRoute -} as any).lazy(() => import("./routes/mui.lazy").then(d => d.Route)); + path: '/mui', + getParentRoute: () => rootRoute, +} as any).lazy(() => import('./routes/mui.lazy').then((d) => d.Route)) const AccountRoute = AccountImport.update({ - path: "/account", - getParentRoute: () => rootRoute -} as any); + path: '/account', + getParentRoute: () => rootRoute, +} as any) const TodoRouteRoute = TodoRouteImport.update({ - path: "/todo", - getParentRoute: () => rootRoute -} as any); + path: '/todo', + getParentRoute: () => rootRoute, +} as any) const IndexLazyRoute = IndexLazyImport.update({ - path: "/", - getParentRoute: () => rootRoute -} as any).lazy(() => import("./routes/index.lazy").then(d => d.Route)); + path: '/', + getParentRoute: () => rootRoute, +} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route)) const TodoIndexRoute = TodoIndexImport.update({ - path: "/", - getParentRoute: () => TodoRouteRoute -} as any); + path: '/', + getParentRoute: () => TodoRouteRoute, +} as any) const TodoEditRoute = TodoEditImport.update({ - path: "/edit", - getParentRoute: () => TodoRouteRoute -} as any); + path: '/edit', + getParentRoute: () => TodoRouteRoute, +} as any) // Populate the FileRoutesByPath interface -declare module "@tanstack/react-router" { - interface FileRoutesByPath { - "/": { - id: "/"; - path: "/"; - fullPath: "/"; - preLoaderRoute: typeof IndexLazyImport; - parentRoute: typeof rootRoute; - }; - "/todo": { - id: "/todo"; - path: "/todo"; - fullPath: "/todo"; - preLoaderRoute: typeof TodoRouteImport; - parentRoute: typeof rootRoute; - }; - "/account": { - id: "/account"; - path: "/account"; - fullPath: "/account"; - preLoaderRoute: typeof AccountImport; - parentRoute: typeof rootRoute; - }; - "/mui": { - id: "/mui"; - path: "/mui"; - fullPath: "/mui"; - preLoaderRoute: typeof MuiLazyImport; - parentRoute: typeof rootRoute; - }; - "/todo/edit": { - id: "/todo/edit"; - path: "/edit"; - fullPath: "/todo/edit"; - preLoaderRoute: typeof TodoEditImport; - parentRoute: typeof TodoRouteImport; - }; - "/todo/": { - id: "/todo/"; - path: "/"; - fullPath: "/todo/"; - preLoaderRoute: typeof TodoIndexImport; - parentRoute: typeof TodoRouteImport; - }; +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexLazyImport + parentRoute: typeof rootRoute } + '/todo': { + id: '/todo' + path: '/todo' + fullPath: '/todo' + preLoaderRoute: typeof TodoRouteImport + parentRoute: typeof rootRoute + } + '/account': { + id: '/account' + path: '/account' + fullPath: '/account' + preLoaderRoute: typeof AccountImport + parentRoute: typeof rootRoute + } + '/mui': { + id: '/mui' + path: '/mui' + fullPath: '/mui' + preLoaderRoute: typeof MuiLazyImport + parentRoute: typeof rootRoute + } + '/todo/edit': { + id: '/todo/edit' + path: '/edit' + fullPath: '/todo/edit' + preLoaderRoute: typeof TodoEditImport + parentRoute: typeof TodoRouteImport + } + '/todo/': { + id: '/todo/' + path: '/' + fullPath: '/todo/' + preLoaderRoute: typeof TodoIndexImport + parentRoute: typeof TodoRouteImport + } + } } // Create and export the route tree export const routeTree = rootRoute.addChildren({ - IndexLazyRoute, - TodoRouteRoute: TodoRouteRoute.addChildren({ TodoEditRoute, TodoIndexRoute }), - AccountRoute, - MuiLazyRoute -}); + IndexLazyRoute, + TodoRouteRoute: TodoRouteRoute.addChildren({ TodoEditRoute, TodoIndexRoute }), + AccountRoute, + MuiLazyRoute, +}) /* prettier-ignore-end */ diff --git a/src/routes/account.tsx b/src/routes/account.tsx index 5ee2c7e..fe476b6 100644 --- a/src/routes/account.tsx +++ b/src/routes/account.tsx @@ -1,7 +1,22 @@ +import Button from "@codegouvfr/react-dsfr/Button"; import { createFileRoute } from "@tanstack/react-router"; -import { protectedLoader } from "oidc"; +import { protectedLoader, useOidc } from "oidc"; export const Route = createFileRoute("/account")({ - component: () =>
Hello account!
, + component: Account, beforeLoad: protectedLoader }); + +function Account() { + const { oidcTokens, renewTokens } = useOidc({ assertUserLoggedIn: true }); + + return ( + <> +

Hello {oidcTokens.decodedIdToken.preferred_username}

+
+

{JSON.stringify(oidcTokens.accessToken)}

+ +
+ + ); +} diff --git a/src/routes/todo/index.tsx b/src/routes/todo/index.tsx index 9bd1730..7186f95 100644 --- a/src/routes/todo/index.tsx +++ b/src/routes/todo/index.tsx @@ -1,6 +1,11 @@ import { useSuspenseQuery } from "@tanstack/react-query"; import { createFileRoute } from "@tanstack/react-router"; -import { getGetTodosQueryOptions } from "api/endpoints/default"; +import { + getGetTodosQueryOptions, + useDeleteTodoId, + usePutTodo, + usePutTodoId +} from "api/endpoints/default"; import { TodoApp } from "components/TodoApp"; export const Route = createFileRoute("/todo/")({ @@ -13,40 +18,62 @@ export const Route = createFileRoute("/todo/")({ function TodoIndex() { const todoQuery = useSuspenseQuery(getGetTodosQueryOptions()); - const todo = todoQuery.data; - - const test = (params: unknown) => console.log(params); - - const todos = [ - { - id: "1", - text: "test1", - isDone: false - }, - - { - id: "2", - text: "test2", - isDone: false - }, - { - id: "3", - text: "test3", - isDone: true - }, - { - id: "4", - text: "test4", - isDone: true - } - ]; + const todos = todoQuery.data; + + const mutationPutTodo = usePutTodoId(); + const mutationAddTodo = usePutTodo(); + const mutationDeleteTodo = useDeleteTodoId(); + + const addTodo = (text: string) => + mutationAddTodo.mutate({ + data: { text } + }); + + const deleteTodo = (id: string) => mutationDeleteTodo.mutate({ id }); + + const toggleTodo = (id: string) => + mutationPutTodo.mutate({ + id, + data: { isDone: true } + }); + + const updateTodo = (id: string, text: string) => + mutationPutTodo.mutate({ + id, + data: { text } + }); + return ( ); } + +const mockTodos = [ + { + id: "1", + text: "test1", + isDone: false + }, + + { + id: "2", + text: "test2", + isDone: false + }, + { + id: "3", + text: "test3", + isDone: true + }, + { + id: "4", + text: "test4", + isDone: true + } +]; diff --git a/src/routes/todo/route.tsx b/src/routes/todo/route.tsx index c964e5b..75f8687 100644 --- a/src/routes/todo/route.tsx +++ b/src/routes/todo/route.tsx @@ -3,7 +3,9 @@ import { protectedLoader } from "oidc"; export const Route = createFileRoute("/todo")({ component: Layout, - beforeLoad: protectedLoader + beforeLoad: protectedLoader, + errorComponent: () => <>An error occurred, + pendingComponent: () => <>Loading ... }); function Layout() { diff --git a/yarn.lock b/yarn.lock index 5055a8c..96e2cef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3687,10 +3687,10 @@ oidc-client-ts@2.4.0: crypto-js "^4.2.0" jwt-decode "^3.1.2" -oidc-spa@^4.6.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-4.6.1.tgz#ddf2e090aab5b1c1ab48766d4a34c6e23ebf0e69" - integrity sha512-QWT2SpVDGNNiSo6eQ2kL1wgCbPhq5ZlH4wPvo0y9rxyVsHV+5um2TnBf5xJEKcCQCzFNDzfqZ3vVh2bRVm6J0A== +oidc-spa@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-4.6.2.tgz#0683e328f227a9de4bc225f6dd6ddc808724c600" + integrity sha512-meT8Jits+4AkQvWByc+PyHn+CZ19bD2osYuxQySOwqSWtbCyZPmj6KrLkv1iSvZpe4wOjbRdVVETK6FbYMlLfw== dependencies: jwt-decode "^3.1.2" oidc-client-ts "2.4.0"