Skip to content

Commit

Permalink
refactor: 🎨 use pathPrefix in contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
ArnaudTA committed Sep 25, 2024
1 parent 96758a3 commit 9cdaffc
Show file tree
Hide file tree
Showing 24 changed files with 112 additions and 108 deletions.
2 changes: 1 addition & 1 deletion apps/client/cypress/e2e/specs/home.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Header', () => {
it('Should display app version and swagger', () => {
cy.visit('/')
cy.getByDataTestid('swaggerUrl')
.should('have.attr', 'href', `${window?.location?.origin}/api/v1/swagger-ui/static/index.html`)
.should('have.attr', 'href', '/api/v1/swagger-ui')
cy.getByDataTestid('appVersionUrl')
.contains('vpr-')
.invoke('attr', 'href')
Expand Down
18 changes: 5 additions & 13 deletions apps/client/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { apiPrefix } from '@cpn-console/shared'
import { swaggerUiPath } from '@cpn-console/shared'
import { getKeycloak } from './utils/keycloak/keycloak.js'
import { useSnackbarStore } from './stores/snackbar.js'
import { useSystemSettingsStore } from './stores/system-settings.js'
Expand All @@ -10,20 +10,16 @@ const snackbarStore = useSnackbarStore()
const systemStore = useSystemSettingsStore()
const isLoggedIn = ref<boolean | undefined>(keycloak.authenticated)
const label = ref(isLoggedIn.value ? 'Se déconnecter' : 'Se connecter')
const to = ref(isLoggedIn.value ? '/logout' : '/login')
const appVersion: string = process.env.APP_VERSION ? `v${process.env.APP_VERSION}` : 'vpr-dev'
const quickLinks = ref([{
label,
to,
const quickLinks = computed(() => [{
label: isLoggedIn.value ? 'Se déconnecter' : 'Se connecter',
to: isLoggedIn.value ? '/logout' : '/login',
icon: 'ri:account-circle-line',
iconRight: true,
}])
const getSwaggerUrl = () => `${window?.location?.origin}${apiPrefix}/swagger-ui/static/index.html`
onErrorCaptured((error) => {
if (error instanceof Error) {
snackbarStore.setMessage(error?.message, 'error')
Expand All @@ -34,10 +30,6 @@ onErrorCaptured((error) => {
return false
})
watch(label, (label: string) => {
quickLinks.value[0].label = label
})
const serviceStore = useServiceStore()
onBeforeMount(() => {
serviceStore.startHealthPolling()
Expand Down Expand Up @@ -78,7 +70,7 @@ onBeforeMount(() => {
>
<a
data-testid="swaggerUrl"
:href="getSwaggerUrl()"
:href="swaggerUiPath"
title="accéder au swagger"
>
swagger
Expand Down
11 changes: 0 additions & 11 deletions apps/server/src/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,6 @@ describe('app', () => {
await app.close()
})

it('should respond with the version', async () => {
const response = await app.inject()
.get(`${apiPrefix}/version`)
expect(JSON.parse(response.body).version).toBe('dev')
})

it('should respond with the healthz', async () => {
const response = await app.inject()
.get(`${apiPrefix}/healthz`)
expect(JSON.parse(response.body).status).toBe('OK')
})
it('should respond 404 on unknown route', async () => {
const response = await app.inject()
.get(`${apiPrefix}/miss`)
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/resources/system/router.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { describe, expect, it, vi } from 'vitest'
import { apiPrefix } from '@cpn-console/shared'
import { systemContract } from '@cpn-console/shared'
import app from '../../app.js'

vi.mock('fastify-keycloak-adapter', (await import('../../utils/mocks.js')).mockSessionPlugin)

describe('system - router', () => {
it('should send application version', async () => {
const response = await app.inject()
.get(`${apiPrefix}/version`)
.get(systemContract.getVersion.path)
.end()

expect(response.statusCode).toBe(200)
Expand All @@ -16,7 +16,7 @@ describe('system - router', () => {

it('should send application health with status OK', async () => {
const response = await app.inject()
.get(`${apiPrefix}/healthz`)
.get(systemContract.getHealth.path)
.end()

expect(response.statusCode).toBe(200)
Expand Down
12 changes: 7 additions & 5 deletions apps/server/src/utils/fastify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { randomUUID } from 'node:crypto'
import type { FastifyServerOptions } from 'fastify'
import type { FastifySwaggerUiOptions } from '@fastify/swagger-ui/types'
import type { generateOpenApi } from '@ts-rest/open-api'
import { apiPrefix } from '@cpn-console/shared'
import { swaggerUiPath } from '@cpn-console/shared'
import { loggerConf } from './logger.js'
import { NODE_ENV } from './env.js'
import { NODE_ENV, keycloakRedirectUri } from './env.js'

export const fastifyConf: FastifyServerOptions = {
maxParamLength: 5000,
Expand All @@ -26,14 +26,16 @@ export const swaggerConf: Parameters<typeof generateOpenApi>[1] = {

externalDocs,
servers: [
// { url: keycloakRedirectUri?.includes('://') ? keycloakRedirectUri.split('://')[1] : 'localhost' }, // TODO: replace with app url
{
url: keycloakRedirectUri,
},
],
}

export const swaggerUiConf: FastifySwaggerUiOptions = {
routePrefix: `${apiPrefix}/swagger-ui`,
routePrefix: swaggerUiPath,
uiConfig: {
docExpansion: 'list',
deepLinking: true,
deepLinking: false,
},
}
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@cpn-console/shared",
"type": "module",
"version": "1.1.4",
"version": "1.1.5",
"private": false,
"description": "",
"main": "dist/index.js",
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/api-client.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ApiFetcher } from '@ts-rest/core'
import { initClient, initContract } from '@ts-rest/core'

export const contractInstance: ReturnType<typeof initContract> = initContract()

export const apiPrefix: string = '/api/v1'

export const contractInstance: ReturnType<typeof initContract> = initContract()

export async function getContract() {
return contractInstance.router(
{
Expand Down
11 changes: 6 additions & 5 deletions packages/shared/src/contracts/admin-role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ErrorSchema, baseHeaders } from './_utils.js'
export const adminRoleContract = contractInstance.router({
listAdminRoles: {
method: 'GET',
path: `${apiPrefix}/admin/roles`,
path: '',
responses: {
200: AdminRoleSchema.array(),
400: ErrorSchema,
Expand All @@ -17,7 +17,7 @@ export const adminRoleContract = contractInstance.router({

createAdminRole: {
method: 'POST',
path: `${apiPrefix}/admin/roles`,
path: '',
body: AdminRoleSchema.pick({ name: true }),
responses: {
200: AdminRoleSchema,
Expand All @@ -30,7 +30,7 @@ export const adminRoleContract = contractInstance.router({

patchAdminRoles: {
method: 'PATCH',
path: `${apiPrefix}/admin/roles`,
path: '',
body: AdminRoleSchema.partial({ name: true, permissions: true, position: true, oidcGroup: true }).array(),
responses: {
200: AdminRoleSchema.array(),
Expand All @@ -43,7 +43,7 @@ export const adminRoleContract = contractInstance.router({

adminRoleMemberCounts: {
method: 'GET',
path: `${apiPrefix}/admin/roles/member-counts`,
path: `/member-counts`,
responses: {
200: z.record(z.number().min(0)), // Record<role uuid, number of member>
400: ErrorSchema,
Expand All @@ -55,7 +55,7 @@ export const adminRoleContract = contractInstance.router({

deleteAdminRole: {
method: 'DELETE',
path: `${apiPrefix}/admin/roles/:roleId`,
path: `/:roleId`,
pathParams: z.object({
roleId: z.string().uuid(),
}),
Expand All @@ -70,4 +70,5 @@ export const adminRoleContract = contractInstance.router({
},
}, {
baseHeaders,
pathPrefix: `${apiPrefix}/admin/roles`,
})
7 changes: 4 additions & 3 deletions packages/shared/src/contracts/admin-token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ErrorSchema, baseHeaders } from './_utils.js'
export const adminTokenContract = contractInstance.router({
listAdminTokens: {
method: 'GET',
path: `${apiPrefix}/admin/tokens`,
path: '',
query: z.object({
withRevoked: CoerceBooleanSchema
.optional(),
Expand All @@ -22,7 +22,7 @@ export const adminTokenContract = contractInstance.router({

createAdminToken: {
method: 'POST',
path: `${apiPrefix}/admin/tokens`,
path: '',
body: AdminTokenSchema.pick({ name: true, permissions: true, expirationDate: true }).required(),
responses: {
201: ExposedAdminTokenSchema,
Expand All @@ -35,7 +35,7 @@ export const adminTokenContract = contractInstance.router({

deleteAdminToken: {
method: 'DELETE',
path: `${apiPrefix}/admin/tokens/:tokenId`,
path: `/:tokenId`,
pathParams: z.object({ tokenId: z.string().uuid() }),
body: null,
responses: {
Expand All @@ -48,4 +48,5 @@ export const adminTokenContract = contractInstance.router({
},
}, {
baseHeaders,
pathPrefix: `${apiPrefix}/admin/tokens`,
})
13 changes: 7 additions & 6 deletions packages/shared/src/contracts/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ClusterParams = z.object({
export const clusterContract = contractInstance.router({
listClusters: {
method: 'GET',
path: `${apiPrefix}/clusters`,
path: '',
summary: 'Get clusters',
description: 'Retrieve clusters authorized for user',
responses: {
Expand All @@ -30,7 +30,7 @@ export const clusterContract = contractInstance.router({

createCluster: {
method: 'POST',
path: `${apiPrefix}/clusters`,
path: '',
contentType: 'application/json',
summary: 'Create cluster',
description: 'Create new cluster.',
Expand All @@ -45,7 +45,7 @@ export const clusterContract = contractInstance.router({

getClusterDetails: {
method: 'GET',
path: `${apiPrefix}/clusters/:clusterId`,
path: `/:clusterId`,
summary: 'Get cluster details',
description: 'Retrieved details of a cluster.',
pathParams: ClusterParams,
Expand All @@ -59,7 +59,7 @@ export const clusterContract = contractInstance.router({

getClusterEnvironments: {
method: 'GET',
path: `${apiPrefix}/clusters/:clusterId/environments`,
path: `/:clusterId/environments`,
summary: 'Get cluster envs',
description: 'Retrieved environments linked to a cluster.',
pathParams: ClusterParams,
Expand All @@ -79,7 +79,7 @@ export const clusterContract = contractInstance.router({

updateCluster: {
method: 'PUT',
path: `${apiPrefix}/clusters/:clusterId`,
path: `/:clusterId`,
summary: 'Update cluster',
description: 'Update a cluster by its ID.',
pathParams: ClusterParams,
Expand All @@ -95,7 +95,7 @@ export const clusterContract = contractInstance.router({

deleteCluster: {
method: 'DELETE',
path: `${apiPrefix}/clusters/:clusterId`,
path: `/:clusterId`,
summary: 'Delete cluster',
description: 'Delete a cluster by its ID.',
query: z.object({ force: CoerceBooleanSchema.optional() }),
Expand All @@ -112,6 +112,7 @@ export const clusterContract = contractInstance.router({
},
}, {
baseHeaders,
pathPrefix: `${apiPrefix}/clusters`,
})

export type ClusterAssociatedEnvironments = ClientInferResponseBody<typeof clusterContract.getClusterEnvironments, 200>
Expand Down
9 changes: 5 additions & 4 deletions packages/shared/src/contracts/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ErrorSchema, baseHeaders } from './_utils.js'
export const environmentContract = contractInstance.router({
createEnvironment: {
method: 'POST',
path: `${apiPrefix}/environments`,
path: '',
contentType: 'application/json',
summary: 'Create environment',
description: 'Create new environment.',
Expand All @@ -24,7 +24,7 @@ export const environmentContract = contractInstance.router({

listEnvironments: {
method: 'GET',
path: `${apiPrefix}/environments`,
path: '',
summary: 'Get environments',
description: 'Retrieved project environments.',
query: z.object({
Expand All @@ -43,7 +43,7 @@ export const environmentContract = contractInstance.router({

updateEnvironment: {
method: 'PUT',
path: `${apiPrefix}/environments/:environmentId`,
path: `/:environmentId`,
summary: 'Update environment',
description: 'Update a environment by its ID.',
pathParams: z.object({
Expand All @@ -63,7 +63,7 @@ export const environmentContract = contractInstance.router({

deleteEnvironment: {
method: 'DELETE',
path: `${apiPrefix}/environments/:environmentId`,
path: `/:environmentId`,
summary: 'Delete environment',
description: 'Delete a environment by its ID.',
body: null,
Expand All @@ -82,6 +82,7 @@ export const environmentContract = contractInstance.router({
},
}, {
baseHeaders,
pathPrefix: `${apiPrefix}/environments`,
})

export type CreateEnvironmentBody = ClientInferRequest<typeof environmentContract.createEnvironment>['body']
Expand Down
3 changes: 2 additions & 1 deletion packages/shared/src/contracts/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export type AdminLogsQuery = Zod.infer<typeof adminLogsQuery>
export const logContract = contractInstance.router({
getLogs: {
method: 'GET',
path: `${apiPrefix}/logs`,
path: '',
query: adminLogsQuery,
summary: 'Get logs',
description: 'Retrieved all logs.',
Expand All @@ -40,6 +40,7 @@ export const logContract = contractInstance.router({
},
}, {
baseHeaders,
pathPrefix: `${apiPrefix}/logs`,
})

export type GetLogsQuery = ClientInferRequest<typeof logContract.getLogs>['query']
Expand Down
Loading

0 comments on commit 9cdaffc

Please sign in to comment.