Design Prot Merge #1
@@ -30,3 +30,15 @@ npm run check # svelte-check — debe salir 0 errores antes de cerrar un camb
|
|||||||
`hooks.server.ts` valida la cookie de sesión cifrada (`mf_session`), refresca el `access_token` y puebla `locals.user` / `locals.accessToken`. Para proteger una ruta, comprueba `locals.user` en su `load` y redirige a `/login?returnTo=…`. Para el backend, envía `locals.accessToken` como Bearer hacia `API_BASE_URL`.
|
`hooks.server.ts` valida la cookie de sesión cifrada (`mf_session`), refresca el `access_token` y puebla `locals.user` / `locals.accessToken`. Para proteger una ruta, comprueba `locals.user` en su `load` y redirige a `/login?returnTo=…`. Para el backend, envía `locals.accessToken` como Bearer hacia `API_BASE_URL`.
|
||||||
|
|
||||||
Variables de entorno en `.env` (ver `.env.example`): `ZITADEL_*`, `AUTH_REDIRECT_URI`, `AUTH_POST_LOGOUT_URI`, `SESSION_SECRET`, `API_BASE_URL`.
|
Variables de entorno en `.env` (ver `.env.example`): `ZITADEL_*`, `AUTH_REDIRECT_URI`, `AUTH_POST_LOGOUT_URI`, `SESSION_SECRET`, `API_BASE_URL`.
|
||||||
|
|
||||||
|
## Backend API
|
||||||
|
|
||||||
|
Cliente tipado con `openapi-fetch` sobre el OpenAPI de `Musify.Api`. En un `load`/action server:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { createApiClient } from '$lib/server/api';
|
||||||
|
const api = createApiClient({ fetch, accessToken: locals.accessToken ?? undefined });
|
||||||
|
const { data, error: err } = await api.GET('/tracks');
|
||||||
|
```
|
||||||
|
|
||||||
|
Devuelve `{ data, error }` (estilo ErrorOr), no lanza. Los tipos viven en `src/lib/api/schema.d.ts` y se regeneran con `npm run gen:api` (requiere la API dev levantada en `API_BASE_URL`, que expone `/openapi/v1.json` solo en Development).
|
||||||
|
|||||||
Generated
+16
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/adapter-node": "^5.5.7",
|
"@sveltejs/adapter-node": "^5.5.7",
|
||||||
"jose": "^6.2.3",
|
"jose": "^6.2.3",
|
||||||
|
"openapi-fetch": "^0.17.0",
|
||||||
"openid-client": "^6.8.4"
|
"openid-client": "^6.8.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1834,6 +1835,21 @@
|
|||||||
"node": ">=12.20.0"
|
"node": ">=12.20.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/openapi-fetch": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-PsbZR1wAPcG91eEthKhN+Zn92FMHxv+/faECIwjXdxfTODGSGegYv0sc1Olz+HYPvKOuoXfp+0pA2XVt2cI0Ig==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"openapi-typescript-helpers": "^0.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/openapi-typescript-helpers": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/openid-client": {
|
"node_modules/openid-client": {
|
||||||
"version": "6.8.4",
|
"version": "6.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.4.tgz",
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"prepare": "svelte-kit sync || echo ''",
|
"prepare": "svelte-kit sync || echo ''",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
|
"gen:api": "npx -y openapi-typescript@7 http://localhost:5111/openapi/v1.json -o src/lib/api/schema.d.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^7.0.1",
|
"@sveltejs/adapter-auto": "^7.0.1",
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/adapter-node": "^5.5.7",
|
"@sveltejs/adapter-node": "^5.5.7",
|
||||||
"jose": "^6.2.3",
|
"jose": "^6.2.3",
|
||||||
|
"openapi-fetch": "^0.17.0",
|
||||||
"openid-client": "^6.8.4"
|
"openid-client": "^6.8.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
export type paths = Record<string, never>;
|
||||||
|
export type webhooks = Record<string, never>;
|
||||||
|
export type components = Record<string, never>;
|
||||||
|
export type operations = Record<string, never>;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import createClient from 'openapi-fetch';
|
||||||
|
import type { paths } from '$lib/api/schema';
|
||||||
|
import { apiConfig } from '$lib/server/config';
|
||||||
|
|
||||||
|
interface ApiClientOptions {
|
||||||
|
fetch: typeof fetch;
|
||||||
|
accessToken?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createApiClient({ fetch, accessToken }: ApiClientOptions) {
|
||||||
|
return createClient<paths>({
|
||||||
|
baseUrl: apiConfig.baseUrl,
|
||||||
|
fetch,
|
||||||
|
headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -45,3 +45,9 @@ export const authConfig = {
|
|||||||
return env.AUTH_ALLOW_INSECURE_HTTP === 'true';
|
return env.AUTH_ALLOW_INSECURE_HTTP === 'true';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const apiConfig = {
|
||||||
|
get baseUrl() {
|
||||||
|
return (env.API_BASE_URL ?? '').replace(/\/+$/, '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user