Template
1
0

feat: checkpoint

This commit is contained in:
2025-11-23 22:57:43 +01:00
parent 7df57522d2
commit 5d45e273ee
160 changed files with 10160 additions and 1476 deletions

12
api/config.ts Normal file
View File

@@ -0,0 +1,12 @@
import { getEnvironmentVariable } from "@platform/config";
import z from "zod";
export const config = {
name: "@valkyr/boilerplate",
host: getEnvironmentVariable({ key: "API_HOST", type: z.ipv4(), fallback: "0.0.0.0" }),
port: getEnvironmentVariable({
key: "API_PORT",
type: z.coerce.number(),
fallback: "8370",
}),
};

12
api/package.json Normal file
View File

@@ -0,0 +1,12 @@
{
"private": true,
"scripts": {
"start": "deno --allow-all --watch-hmr=routes/ server.ts"
},
"dependencies": {
"@modules/identity": "workspace:*",
"@module/workspace": "workspace:*",
"@platform/config": "workspace:*",
"zod": "4.1.12"
}
}

73
api/server.ts Normal file
View File

@@ -0,0 +1,73 @@
import { logger } from "@platform/logger";
import { context } from "@platform/relay";
import { Api } from "@platform/server/api.ts";
import server from "@platform/server/server.ts";
import socket from "@platform/socket/server.ts";
import { storage } from "@platform/storage";
import { config } from "./config.ts";
import session from "./session.ts";
const log = logger.prefix("Server");
/*
|--------------------------------------------------------------------------------
| Bootstrap
|--------------------------------------------------------------------------------
*/
// ### Platform
await server.bootstrap();
await socket.bootstrap();
await session.bootstrap();
// ### Modules
// await workspace.bootstrap();
/*
|--------------------------------------------------------------------------------
| Service
|--------------------------------------------------------------------------------
*/
const api = new Api([
/*...identity.routes, ...workspace.routes*/
]);
/*
|--------------------------------------------------------------------------------
| Server
|--------------------------------------------------------------------------------
*/
Deno.serve(
{
port: config.port,
hostname: config.host,
onListen({ port, hostname }) {
logger.prefix("Server").info(`Listening at http://${hostname}:${port}`);
},
},
async (request) =>
storage.run({}, async () => {
const url = new URL(request.url);
// ### Storage Context
// Resolve storage context for all dependent modules.
await server.resolve(request);
await socket.resolve();
await session.resolve(request);
// ### Fetch
// Execute fetch against the api instance.
return api.fetch(request).finally(() => {
log.info(
`${request.method} ${url.pathname} [${((Date.now() - context.info.start) / 1000).toLocaleString()} seconds]`,
);
});
}),
);

111
api/session.ts Normal file
View File

@@ -0,0 +1,111 @@
import { context, UnauthorizedError } from "@platform/relay";
import { storage } from "@platform/storage";
const IDENTITY_RESOLVE_HEADER = "x-identity-resolver";
export default {
bootstrap: async () => {
bootstrapSessionContext();
},
resolve: async (request: Request) => {
await resolvePrincipalSession(request);
},
};
function bootstrapSessionContext() {
Object.defineProperties(context, {
/**
* TODO ...
*/
isAuthenticated: {
get() {
return storage.getStore()?.principal !== undefined;
},
},
/**
* TODO ...
*/
session: {
get() {
const session = storage.getStore()?.session;
if (session === undefined) {
throw new UnauthorizedError();
}
return session;
},
},
/**
* TODO ...
*/
principal: {
get() {
const principal = storage.getStore()?.principal;
if (principal === undefined) {
throw new UnauthorizedError();
}
return principal;
},
},
/**
* TODO ...
*/
access: {
get() {
const access = storage.getStore()?.access;
if (access === undefined) {
throw new UnauthorizedError();
}
return access;
},
},
});
}
async function resolvePrincipalSession(request: Request) {
// ### Resolver
// Check if the incoming request is tagged as a resolver check.
// If it is a resolver we break out of the session resolution
// to avoid an infinite resolution loop.
const isResolver = request.headers.get(IDENTITY_RESOLVE_HEADER) !== null;
if (isResolver) {
return;
}
// ### Cookie
// Check for the existence of cookie to pass onto the session
// resolver.
const cookie = request.headers.get("cookie");
if (cookie === null) {
return;
}
// ### Session
// Fetch session from identity module and tag it as a resolution
// call so it can break out of a resolution loop.
const session = await getPrincipalSession({
headers: new Headers({
cookie,
[IDENTITY_RESOLVE_HEADER]: "true",
}),
});
// ### Populate Context
// On successfull resolution we build the request identity context.
if (session !== undefined) {
const context = storage.getStore();
if (context === undefined) {
return;
}
context.session = session.session;
context.principal = session.principal;
context.access = identity.access;
}
}