chore: update reservation platform to newest codebase
This commit is contained in:
29
packages/reservation-platform/src/utils/drizzle.ts
Normal file
29
packages/reservation-platform/src/utils/drizzle.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import type * as schema from "@/server/db/schema";
|
||||
import type { BuildQueryResult, DBQueryConfig, ExtractTablesWithRelations } from "drizzle-orm";
|
||||
|
||||
type Schema = typeof schema;
|
||||
type TSchema = ExtractTablesWithRelations<Schema>;
|
||||
|
||||
/**
|
||||
* Infer the relation type of a table.
|
||||
*/
|
||||
export type IncludeRelation<TableName extends keyof TSchema> = DBQueryConfig<
|
||||
"one" | "many",
|
||||
boolean,
|
||||
TSchema,
|
||||
TSchema[TableName]
|
||||
>["with"];
|
||||
|
||||
/**
|
||||
* Infer the result type of a query with optional relations.
|
||||
*/
|
||||
export type InferResultType<
|
||||
TableName extends keyof TSchema,
|
||||
With extends IncludeRelation<TableName> | undefined = undefined,
|
||||
> = BuildQueryResult<
|
||||
TSchema,
|
||||
TSchema[TableName],
|
||||
{
|
||||
with: With;
|
||||
}
|
||||
>;
|
13
packages/reservation-platform/src/utils/env.ts
Normal file
13
packages/reservation-platform/src/utils/env.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* Environment variables
|
||||
*/
|
||||
export const env = {
|
||||
RUNTIME_ENVIRONMENT: z.enum(["prod", "dev"]).parse(process.env.RUNTIME_ENVIRONMENT),
|
||||
DB_PATH: "db/sqlite.db", // As drizzle-kit currently can't load env variables, use a hardcoded value
|
||||
OAUTH: {
|
||||
CLIENT_ID: z.string().parse(process.env.OAUTH_CLIENT_ID),
|
||||
CLIENT_SECRET: z.string().parse(process.env.OAUTH_CLIENT_SECRET),
|
||||
},
|
||||
};
|
59
packages/reservation-platform/src/utils/errors.ts
Normal file
59
packages/reservation-platform/src/utils/errors.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import strings from "@/utils/strings";
|
||||
|
||||
/**
|
||||
* Base error class.
|
||||
*/
|
||||
class BaseError extends Error {
|
||||
constructor(message?: string) {
|
||||
// Pass the message to the Error constructor
|
||||
super(message);
|
||||
|
||||
// Set the name of the error
|
||||
this.name = this.constructor.name;
|
||||
|
||||
// Capture the stack trace
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
} else {
|
||||
this.stack = new Error(message).stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission error class.
|
||||
*/
|
||||
export class PermissionError extends BaseError {
|
||||
constructor() {
|
||||
super(strings.ERROR.PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication error class.
|
||||
*/
|
||||
export class AuthenticationError extends BaseError {
|
||||
constructor() {
|
||||
super(strings.ERROR.NO_SESSION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation error class.
|
||||
*/
|
||||
export class ValidationError extends BaseError {
|
||||
constructor() {
|
||||
super(strings.ERROR.VALIDATION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not found error class.
|
||||
*/
|
||||
export class NotFoundError extends BaseError {
|
||||
constructor() {
|
||||
super(strings.ERROR.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseError;
|
1
packages/reservation-platform/src/utils/fetch.ts
Normal file
1
packages/reservation-platform/src/utils/fetch.ts
Normal file
@ -0,0 +1 @@
|
||||
export const fetcher = (url: string) => fetch(url).then((response) => response.json());
|
35
packages/reservation-platform/src/utils/guard.ts
Normal file
35
packages/reservation-platform/src/utils/guard.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import type { UserRole } from "@/server/auth/permissions";
|
||||
import type { users } from "@/server/db/schema";
|
||||
import type { InferSelectModel } from "drizzle-orm";
|
||||
import type { RegisteredDatabaseUserAttributes } from "lucia";
|
||||
|
||||
// Constants for better readability
|
||||
export const IS = false;
|
||||
export const IS_NOT = true;
|
||||
|
||||
/**
|
||||
* Checks if a user has the required role(s).
|
||||
* @param user - The user to check.
|
||||
* @param negate - Whether to negate the result.
|
||||
* @param roleRequirements - The required role(s).
|
||||
* @returns Whether the user has the required role(s).
|
||||
*/
|
||||
export function guard(
|
||||
user: RegisteredDatabaseUserAttributes | InferSelectModel<typeof users> | undefined | null,
|
||||
negate: boolean,
|
||||
roleRequirements: UserRole | UserRole[],
|
||||
) {
|
||||
// Early return for unauthenticated users
|
||||
if (!user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Normalize roleRequirements to an array
|
||||
const requiredRoles = Array.isArray(roleRequirements) ? roleRequirements : [roleRequirements];
|
||||
|
||||
// Check if the user's role is in the required roles
|
||||
const userHasRequiredRole = requiredRoles.includes(user.role as UserRole);
|
||||
|
||||
// Return the result, negated if necessary
|
||||
return negate ? !userHasRequiredRole : userHasRequiredRole;
|
||||
}
|
33
packages/reservation-platform/src/utils/heimdall.ts
Normal file
33
packages/reservation-platform/src/utils/heimdall.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import type { UserRole } from "@/server/auth/permissions";
|
||||
import type { users } from "@/server/db/schema";
|
||||
import type { InferSelectModel } from "drizzle-orm";
|
||||
import type { RegisteredDatabaseUserAttributes } from "lucia";
|
||||
|
||||
// Helpers to improve readability of the guard function
|
||||
export const is = false;
|
||||
export const is_not = true;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export function guard(
|
||||
user: RegisteredDatabaseUserAttributes | InferSelectModel<typeof users> | undefined | null,
|
||||
negate: boolean,
|
||||
roleRequirements: UserRole | UserRole[],
|
||||
) {
|
||||
if (!user) {
|
||||
return true; // Guard against unauthenticated users
|
||||
}
|
||||
|
||||
const hasRole = Array.isArray(roleRequirements)
|
||||
? roleRequirements.includes(user?.role as UserRole)
|
||||
: user?.role === roleRequirements;
|
||||
|
||||
return negate ? !hasRole : hasRole;
|
||||
}
|
||||
|
||||
export class PermissionError extends Error {
|
||||
constructor() {
|
||||
super("Du besitzt nicht die erforderlichen Berechtigungen um diese Aktion auszuführen.");
|
||||
}
|
||||
}
|
41
packages/reservation-platform/src/utils/printers.ts
Normal file
41
packages/reservation-platform/src/utils/printers.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import type { InferResultType } from "@/utils/drizzle";
|
||||
|
||||
export enum PrinterStatus {
|
||||
IDLE = 0,
|
||||
OUT_OF_ORDER = 1,
|
||||
RESERVED = 2,
|
||||
}
|
||||
|
||||
export function derivePrinterStatus(
|
||||
printer: InferResultType<"printers", { printJobs: true }>,
|
||||
) {
|
||||
if (printer.status === PrinterStatus.OUT_OF_ORDER) {
|
||||
return PrinterStatus.OUT_OF_ORDER;
|
||||
}
|
||||
|
||||
const activePrintJob = printer.printJobs[0];
|
||||
|
||||
if (!activePrintJob || activePrintJob.aborted) {
|
||||
return PrinterStatus.IDLE;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const startAt = new Date(activePrintJob.startAt).getTime();
|
||||
const endAt = startAt + activePrintJob.durationInMinutes * 60 * 1000;
|
||||
if (now < endAt) {
|
||||
return PrinterStatus.RESERVED;
|
||||
}
|
||||
|
||||
return PrinterStatus.IDLE;
|
||||
}
|
||||
|
||||
export function translatePrinterStatus(status: PrinterStatus) {
|
||||
switch (status) {
|
||||
case PrinterStatus.IDLE:
|
||||
return "Verfügbar";
|
||||
case PrinterStatus.OUT_OF_ORDER:
|
||||
return "Außer Betrieb";
|
||||
case PrinterStatus.RESERVED:
|
||||
return "Reserviert";
|
||||
}
|
||||
}
|
11
packages/reservation-platform/src/utils/strings.ts
Normal file
11
packages/reservation-platform/src/utils/strings.ts
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Contains all strings used in the application.
|
||||
*/
|
||||
export default {
|
||||
ERROR: {
|
||||
PERMISSION: "Du besitzt nicht die erforderlichen Berechtigungen um diese Aktion auszuführen.",
|
||||
VALIDATION: "Die Eingabe ist ungültig.",
|
||||
NOT_FOUND: "Die angeforderten Daten konnten nicht gefunden werden.",
|
||||
NO_SESSION: "Du bist nicht angemeldet.",
|
||||
},
|
||||
};
|
11
packages/reservation-platform/src/utils/styles.ts
Normal file
11
packages/reservation-platform/src/utils/styles.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
/**
|
||||
* Utility function to merge classes with tailwindcss.
|
||||
* @param inputs Classes to merge
|
||||
* @returns classes
|
||||
*/
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
Reference in New Issue
Block a user