mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 08:45:38 +02:00
## Description This attempts to connect the Steam account to user account... for easier management <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced user profiles and account views now display integrated Steam account details and enriched team associations for a more comprehensive experience. - **Chores** - Backend and database refinements have been implemented to improve system stability, data integrity, and overall performance. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
155 lines
5.8 KiB
TypeScript
155 lines
5.8 KiB
TypeScript
import { z } from "zod";
|
|
import { Common } from "../common";
|
|
import { createID, fn } from "../utils";
|
|
import { Examples } from "../examples";
|
|
import { machineTable } from "./machine.sql";
|
|
import { getTableColumns, eq, sql, and, isNull } from "../drizzle";
|
|
import { createTransaction, useTransaction } from "../drizzle/transaction";
|
|
|
|
export namespace Machine {
|
|
export const Info = z
|
|
.object({
|
|
id: z.string().openapi({
|
|
description: Common.IdDescription,
|
|
example: Examples.Machine.id,
|
|
}),
|
|
// userID: z.string().nullable().openapi({
|
|
// description: "The userID of the user who owns this machine, in the case of BYOG",
|
|
// example: Examples.Machine.userID
|
|
// }),
|
|
country: z.string().openapi({
|
|
description: "The fullname of the country this machine is running in",
|
|
example: Examples.Machine.country
|
|
}),
|
|
fingerprint: z.string().openapi({
|
|
description: "The fingerprint of this machine, deduced from the host machine's machine id - /etc/machine-id",
|
|
example: Examples.Machine.fingerprint
|
|
}),
|
|
location: z.object({ longitude: z.number(), latitude: z.number() }).openapi({
|
|
description: "This is the 2d location of this machine, they might not be accurate",
|
|
example: Examples.Machine.location
|
|
}),
|
|
countryCode: z.string().openapi({
|
|
description: "This is the 2 character country code of the country this machine [ISO 3166-1 alpha-2] ",
|
|
example: Examples.Machine.countryCode
|
|
}),
|
|
timezone: z.string().openapi({
|
|
description: "The IANA timezone formatted string of the timezone of the location where the machine is running",
|
|
example: Examples.Machine.timezone
|
|
})
|
|
})
|
|
.openapi({
|
|
ref: "Machine",
|
|
description: "Represents a hosted or BYOG machine connected to Nestri",
|
|
example: Examples.Machine,
|
|
});
|
|
|
|
export type Info = z.infer<typeof Info>;
|
|
|
|
export const create = fn(Info.partial({ id: true }), async (input) =>
|
|
createTransaction(async (tx) => {
|
|
const id = input.id ?? createID("machine");
|
|
await tx.insert(machineTable).values({
|
|
id,
|
|
country: input.country,
|
|
timezone: input.timezone,
|
|
fingerprint: input.fingerprint,
|
|
countryCode: input.countryCode,
|
|
// userID: input.userID,
|
|
location: { x: input.location.longitude, y: input.location.latitude },
|
|
})
|
|
|
|
// await afterTx(() =>
|
|
// bus.publish(Resource.Bus, Events.Created, {
|
|
// teamID: id,
|
|
// }),
|
|
// );
|
|
return id;
|
|
})
|
|
)
|
|
|
|
// export const fromUserID = fn(z.string(), async (userID) =>
|
|
// useTransaction(async (tx) =>
|
|
// tx
|
|
// .select()
|
|
// .from(machineTable)
|
|
// .where(and(eq(machineTable.userID, userID), isNull(machineTable.timeDeleted)))
|
|
// .then((rows) => rows.map(serialize))
|
|
// )
|
|
// )
|
|
|
|
// export const list = fn(z.void(), async () =>
|
|
// useTransaction(async (tx) =>
|
|
// tx
|
|
// .select()
|
|
// .from(machineTable)
|
|
// // Show only hosted machines, not BYOG machines
|
|
// .where(and(isNull(machineTable.userID), isNull(machineTable.timeDeleted)))
|
|
// .then((rows) => rows.map(serialize))
|
|
// )
|
|
// )
|
|
|
|
export const fromID = fn(Info.shape.id, async (id) =>
|
|
useTransaction(async (tx) =>
|
|
tx
|
|
.select()
|
|
.from(machineTable)
|
|
.where(and(eq(machineTable.id, id), isNull(machineTable.timeDeleted)))
|
|
.then((rows) => rows.map(serialize).at(0))
|
|
)
|
|
)
|
|
|
|
export const fromFingerprint = fn(Info.shape.fingerprint, async (fingerprint) =>
|
|
useTransaction(async (tx) =>
|
|
tx
|
|
.select()
|
|
.from(machineTable)
|
|
.where(and(eq(machineTable.fingerprint, fingerprint), isNull(machineTable.timeDeleted)))
|
|
.execute()
|
|
.then((rows) => rows.map(serialize).at(0))
|
|
)
|
|
)
|
|
|
|
export const remove = fn(Info.shape.id, (id) =>
|
|
useTransaction(async (tx) => {
|
|
await tx
|
|
.update(machineTable)
|
|
.set({
|
|
timeDeleted: sql`now()`,
|
|
})
|
|
.where(and(eq(machineTable.id, id)))
|
|
.execute();
|
|
return id;
|
|
}),
|
|
);
|
|
|
|
export const fromLocation = fn(Info.shape.location, async (location) =>
|
|
useTransaction(async (tx) => {
|
|
const sqlDistance = sql`location <-> point(${location.longitude}, ${location.latitude})`;
|
|
return tx
|
|
.select({
|
|
...getTableColumns(machineTable),
|
|
distance: sql`round((${sqlDistance})::numeric, 2)`
|
|
})
|
|
.from(machineTable)
|
|
.where(isNull(machineTable.timeDeleted))
|
|
.orderBy(sqlDistance)
|
|
.limit(3)
|
|
.then((rows) => rows.map(serialize))
|
|
})
|
|
)
|
|
|
|
export function serialize(
|
|
input: typeof machineTable.$inferSelect,
|
|
): z.infer<typeof Info> {
|
|
return {
|
|
id: input.id,
|
|
// userID: input.userID,
|
|
country: input.country,
|
|
timezone: input.timezone,
|
|
fingerprint: input.fingerprint,
|
|
countryCode: input.countryCode,
|
|
location: { latitude: input.location.y, longitude: input.location.x },
|
|
};
|
|
}
|
|
} |