mirror of
https://github.com/fergalmoran/kidarr-server.git
synced 2025-12-22 09:17:51 +00:00
Initial trpc calls done
This commit is contained in:
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
61
.idea/codeStyles/Project.xml
generated
Normal file
61
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,61 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<HTMLCodeStyleSettings>
|
||||
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
<option name="HTML_KEEP_WHITESPACES_INSIDE" value="" />
|
||||
</HTMLCodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
</JSCodeStyleSettings>
|
||||
<TypeScriptCodeStyleSettings version="0">
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
</TypeScriptCodeStyleSettings>
|
||||
<VueCodeStyleSettings>
|
||||
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
||||
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
||||
</VueCodeStyleSettings>
|
||||
<codeStyleSettings language="HTML">
|
||||
<option name="SOFT_MARGINS" value="80" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="SOFT_MARGINS" value="80" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="TypeScript">
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="SOFT_MARGINS" value="80" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Vue">
|
||||
<option name="SOFT_MARGINS" value="80" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
12
.idea/dataSources.xml
generated
Normal file
12
.idea/dataSources.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="parentgrine@localhost" uuid="da0ccf76-47f7-499f-8f35-82c39250995f">
|
||||
<driver-ref>postgresql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:postgresql://localhost:5432/parentgrine</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/parentgrine-server.iml" filepath="$PROJECT_DIR$/.idea/parentgrine-server.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/parentgrine-server.iml
generated
Normal file
12
.idea/parentgrine-server.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,9 +1,10 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import DashboardPage from "@/components/pages/dashboard-page";
|
||||
import React from 'react';
|
||||
import DashboardPage from '@/components/pages/dashboard-page';
|
||||
import { api } from '@/trpc/server';
|
||||
|
||||
const Dashboard = () => {
|
||||
return <DashboardPage />;
|
||||
const Dashboard = async () => {
|
||||
const kids = await api.child.mine.query();
|
||||
return <DashboardPage kids={kids} />;
|
||||
};
|
||||
|
||||
export default Dashboard;
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { newChildSchema } from '@/lib/validations/child';
|
||||
import { getServerAuthSession } from '@/lib/services/auth/config';
|
||||
import { createApiKey } from '@/lib/services/auth/api';
|
||||
|
||||
import { NextResponse } from 'next/server';
|
||||
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
|
||||
import {db} from '@/server/db';
|
||||
import { db } from '@/server/db';
|
||||
|
||||
import { child } from '@/server/db/schema';
|
||||
import { users } from '@/server/db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { device } from '@/server/db/schema';
|
||||
import { getServerAuthSession } from '@/server/auth';
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const session = await getServerAuthSession();
|
||||
if (!session || !session.user?.email)
|
||||
if (!session?.user?.email)
|
||||
return NextResponse.next({
|
||||
statusText: getReasonPhrase(StatusCodes.UNAUTHORIZED),
|
||||
status: StatusCodes.UNAUTHORIZED,
|
||||
@@ -36,7 +35,7 @@ export async function POST(req: Request) {
|
||||
const newChild = await db
|
||||
.insert(child)
|
||||
.values({
|
||||
parentId: user[0].id.toString(),
|
||||
parentId: "asdkfjhsa",
|
||||
name,
|
||||
})
|
||||
.returning();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from "@/server/db";
|
||||
import { child } from "@/server/db/schema";
|
||||
import { StatusCodes, getReasonPhrase } from "http-status-codes";
|
||||
import { NextResponse } from "next/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { getServerAuthSession } from "@/server/auth";
|
||||
import { db } from '@/server/db';
|
||||
import { child } from '@/server/db/schema';
|
||||
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
|
||||
import { NextResponse } from 'next/server';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { getServerAuthSession } from '@/server/auth';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const session = await getServerAuthSession();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -7,35 +7,25 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import axios from 'axios'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { env } from '@/env'
|
||||
} from '@/components/ui/select';
|
||||
import axios from 'axios';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { env } from '@/env';
|
||||
import ChildModel from '@/lib/models/child';
|
||||
|
||||
const ChildSelectList = () => {
|
||||
const { data, isLoading, isError } = useQuery({
|
||||
queryKey: ['user-children'],
|
||||
queryFn: async () => {
|
||||
const { data } = await axios.get(
|
||||
`${env.NEXT_PUBLIC_BASE_URL}/child`,
|
||||
{
|
||||
withCredentials: true,
|
||||
},
|
||||
)
|
||||
return data as ChildModel[]
|
||||
},
|
||||
})
|
||||
if (isLoading) return <div>Loading....</div>
|
||||
if (isError) return <div>Error loading</div>
|
||||
type ChildSelectListProps = {
|
||||
kids: ChildModel[];
|
||||
}
|
||||
const ChildSelectList: React.FC<ChildSelectListProps> = ({ kids }) => {
|
||||
return (
|
||||
<Select defaultValue={'____all____'}>
|
||||
<SelectTrigger className='w-[180px]'>
|
||||
<SelectValue placeholder='Choose child' />
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Choose child" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value='____all____'>(All Children)</SelectItem>
|
||||
{data?.map((r) => (
|
||||
<SelectItem value="____all____">(All Children)</SelectItem>
|
||||
{kids?.map((r) => (
|
||||
<SelectItem
|
||||
key={r.name}
|
||||
value={r.name.toLowerCase()}
|
||||
@@ -46,7 +36,7 @@ const ChildSelectList = () => {
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ChildSelectList
|
||||
export default ChildSelectList;
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import React from 'react'
|
||||
import ChildSelectList from './child-select-list'
|
||||
import React from 'react';
|
||||
import ChildSelectList from './child-select-list';
|
||||
|
||||
import AddChildComponent from './add-child-component'
|
||||
import AddChildComponent from './add-child-component';
|
||||
import ChildModel from '@/lib/models/child';
|
||||
|
||||
const ChildrenFilter = async () => {
|
||||
type ChildrenFilterProps = {
|
||||
kids: ChildModel[];
|
||||
}
|
||||
const ChildrenFilter: React.FC<ChildrenFilterProps> = async ({ kids }) => {
|
||||
return (
|
||||
<div className='flex flex-row space-x-2 justify-center items-center'>
|
||||
<ChildSelectList />
|
||||
<div className="flex flex-row space-x-2 justify-center items-center">
|
||||
<ChildSelectList kids={kids} />
|
||||
<AddChildComponent />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ChildrenFilter
|
||||
export default ChildrenFilter;
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import React from "react";
|
||||
import ChildrenFilter from "@/components/children/children-filter";
|
||||
import dynamic from "next/dynamic";
|
||||
import React from 'react';
|
||||
import ChildrenFilter from '@/components/children/children-filter';
|
||||
import dynamic from 'next/dynamic';
|
||||
import ChildModel from '@/lib/models/child';
|
||||
|
||||
const DashboardPage: React.FC = () => {
|
||||
type DashboardPageProps = {
|
||||
kids: ChildModel[];
|
||||
}
|
||||
const DashboardPage: React.FC<DashboardPageProps> = ({ kids }) => {
|
||||
//this needs to be a dynamic import
|
||||
//otherwise it causes window not found errors
|
||||
const Map = dynamic(() => import("@/components/maps/main-map"), {
|
||||
const Map = dynamic(() => import('@/components/maps/main-map'), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="z-10">
|
||||
<ChildrenFilter />
|
||||
<ChildrenFilter kids={kids} />
|
||||
</div>
|
||||
<div className="z-0 mt-4">
|
||||
<Map />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
interface ChildModel {
|
||||
export default interface ChildModel {
|
||||
id: string;
|
||||
name: string;
|
||||
recentLocations: Location[];
|
||||
// recentLocations: Location[];
|
||||
}
|
||||
|
||||
@@ -1,37 +1,33 @@
|
||||
import { z } from "zod";
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
createTRPCRouter,
|
||||
protectedProcedure,
|
||||
publicProcedure,
|
||||
} from "@/server/api/trpc";
|
||||
import { child } from "@/server/db/schema";
|
||||
} from '@/server/api/trpc';
|
||||
import { child } from '@/server/db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
export const childRouter = createTRPCRouter({
|
||||
hello: publicProcedure
|
||||
.input(z.object({ text: z.string() }))
|
||||
.query(({ input }) => {
|
||||
return {
|
||||
greeting: `Hello ${input.text}`,
|
||||
};
|
||||
}),
|
||||
|
||||
create: protectedProcedure
|
||||
.input(z.object({ name: z.string().min(1) }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
await ctx.db.insert(child).values({
|
||||
const c = {
|
||||
parentId: ctx.session.user.id,
|
||||
name,
|
||||
});
|
||||
name: input.name,
|
||||
};
|
||||
await ctx.db.insert(child).values(c);
|
||||
}),
|
||||
|
||||
getLatest: publicProcedure.query(({ ctx }) => {
|
||||
return ctx.db.query.child.findFirst({
|
||||
mine: protectedProcedure.query(async ({ ctx }) => {
|
||||
return ctx.db.query.child.findMany({
|
||||
orderBy: (posts, { asc }) => [asc(child.name)],
|
||||
where: eq(child.parentId, ctx.session.user.id),
|
||||
with: {
|
||||
devices: {
|
||||
with: { pings: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
}),
|
||||
|
||||
getSecretMessage: protectedProcedure.query(() => {
|
||||
return "you can now see this secret message!";
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -8,60 +8,61 @@ import {
|
||||
varchar,
|
||||
pgSchema,
|
||||
doublePrecision,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import type { AdapterAccount } from "@auth/core/adapters";
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
} from 'drizzle-orm/pg-core';
|
||||
import type { AdapterAccount } from '@auth/core/adapters';
|
||||
import { relations, sql } from 'drizzle-orm';
|
||||
|
||||
//#region auth
|
||||
//TODO: use this schema once https://github.com/drizzle-team/drizzle-orm/issues/636 is fixed
|
||||
const authSchema = pgSchema("auth");
|
||||
export const users = pgTable("user", {
|
||||
id: uuid("id")
|
||||
const authSchema = pgSchema('auth');
|
||||
export const users = pgTable('user', {
|
||||
id: uuid('id')
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.default(sql`gen_random_uuid()`),
|
||||
name: text("name"),
|
||||
email: text("email").notNull(),
|
||||
emailVerified: timestamp("emailVerified", { mode: "date" }),
|
||||
image: text("image"),
|
||||
.default(sql`gen_random_uuid
|
||||
()`),
|
||||
name: text('name'),
|
||||
email: text('email').notNull(),
|
||||
emailVerified: timestamp('emailVerified', { mode: 'date' }),
|
||||
image: text('image'),
|
||||
});
|
||||
|
||||
export const accounts = pgTable(
|
||||
"account",
|
||||
'account',
|
||||
{
|
||||
userId: uuid("userId")
|
||||
userId: uuid('userId')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
type: text("type").$type<AdapterAccount["type"]>().notNull(),
|
||||
provider: text("provider").notNull(),
|
||||
providerAccountId: text("providerAccountId").notNull(),
|
||||
refresh_token: text("refresh_token"),
|
||||
access_token: text("access_token"),
|
||||
expires_at: integer("expires_at"),
|
||||
token_type: text("token_type"),
|
||||
scope: text("scope"),
|
||||
id_token: text("id_token"),
|
||||
session_state: text("session_state"),
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
type: text('type').$type<AdapterAccount['type']>().notNull(),
|
||||
provider: text('provider').notNull(),
|
||||
providerAccountId: text('providerAccountId').notNull(),
|
||||
refresh_token: text('refresh_token'),
|
||||
access_token: text('access_token'),
|
||||
expires_at: integer('expires_at'),
|
||||
token_type: text('token_type'),
|
||||
scope: text('scope'),
|
||||
id_token: text('id_token'),
|
||||
session_state: text('session_state'),
|
||||
},
|
||||
(account) => ({
|
||||
compoundKey: primaryKey(account.provider, account.providerAccountId),
|
||||
}),
|
||||
);
|
||||
|
||||
export const sessions = pgTable("session", {
|
||||
sessionToken: text("sessionToken").notNull().primaryKey(),
|
||||
userId: uuid("userId")
|
||||
export const sessions = pgTable('session', {
|
||||
sessionToken: text('sessionToken').notNull().primaryKey(),
|
||||
userId: uuid('userId')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
expires: timestamp("expires", { mode: "date" }).notNull(),
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
||||
});
|
||||
|
||||
export const verificationTokens = pgTable(
|
||||
"verification_token",
|
||||
'verification_token',
|
||||
{
|
||||
identifier: varchar("identifier", { length: 255 }).notNull(),
|
||||
token: varchar("token", { length: 255 }).notNull(),
|
||||
expires: timestamp("expires", { mode: "date" }).notNull(),
|
||||
identifier: varchar('identifier', { length: 255 }).notNull(),
|
||||
token: varchar('token', { length: 255 }).notNull(),
|
||||
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
||||
},
|
||||
(vt) => ({
|
||||
compoundKey: primaryKey(vt.identifier, vt.token),
|
||||
@@ -74,15 +75,16 @@ export const userRelations = relations(users, ({ many }) => ({
|
||||
}));
|
||||
|
||||
//#region child
|
||||
export const child = pgTable("child", {
|
||||
id: uuid("id")
|
||||
export const child = pgTable('child', {
|
||||
id: uuid('id')
|
||||
.primaryKey()
|
||||
.default(sql`gen_random_uuid()`),
|
||||
name: varchar("name", { length: 256 }),
|
||||
email: varchar("email", { length: 256 }),
|
||||
phone: varchar("phone", { length: 256 }),
|
||||
apiKey: varchar("key", { length: 256 }),
|
||||
parentId: uuid("parent_id").notNull(),
|
||||
.default(sql`gen_random_uuid
|
||||
()`),
|
||||
name: varchar('name', { length: 256 }).notNull(),
|
||||
email: varchar('email', { length: 256 }),
|
||||
phone: varchar('phone', { length: 256 }),
|
||||
apiKey: varchar('key', { length: 256 }),
|
||||
parentId: uuid('parent_id').notNull(),
|
||||
});
|
||||
export const childRelations = relations(child, ({ one, many }) => ({
|
||||
parent: one(users, {
|
||||
@@ -92,17 +94,18 @@ export const childRelations = relations(child, ({ one, many }) => ({
|
||||
devices: many(device),
|
||||
}));
|
||||
|
||||
export const device = pgTable("device", {
|
||||
id: uuid("id")
|
||||
export const device = pgTable('device', {
|
||||
id: uuid('id')
|
||||
.primaryKey()
|
||||
.default(sql`gen_random_uuid()`),
|
||||
deviceId: varchar("device_id").notNull().unique(),
|
||||
childId: uuid("child_id").notNull(),
|
||||
apiKey: varchar("api_key").notNull().unique(),
|
||||
.default(sql`gen_random_uuid
|
||||
()`),
|
||||
deviceId: varchar('device_id').notNull().unique(),
|
||||
childId: uuid('child_id').notNull(),
|
||||
apiKey: varchar('api_key').notNull().unique(),
|
||||
//TODO: make the device request/pin a separate table and enforce the expiry
|
||||
pin: integer("pin").notNull(),
|
||||
expires: timestamp("expires").default(sql`now
|
||||
()
|
||||
pin: integer('pin').notNull(),
|
||||
expires: timestamp('expires').default(sql`now
|
||||
()
|
||||
+ interval '1 hour'`),
|
||||
});
|
||||
export const deviceRelations = relations(device, ({ one, many }) => ({
|
||||
@@ -113,14 +116,15 @@ export const deviceRelations = relations(device, ({ one, many }) => ({
|
||||
pings: many(ping),
|
||||
}));
|
||||
|
||||
export const ping = pgTable("ping", {
|
||||
id: uuid("id")
|
||||
export const ping = pgTable('ping', {
|
||||
id: uuid('id')
|
||||
.primaryKey()
|
||||
.default(sql`gen_random_uuid()`),
|
||||
deviceId: uuid("device_id").notNull(),
|
||||
latitude: doublePrecision("latitude").notNull(),
|
||||
longitude: doublePrecision("longitude").notNull(),
|
||||
timestamp: timestamp("timestamp").notNull(),
|
||||
.default(sql`gen_random_uuid
|
||||
()`),
|
||||
deviceId: uuid('device_id').notNull(),
|
||||
latitude: doublePrecision('latitude').notNull(),
|
||||
longitude: doublePrecision('longitude').notNull(),
|
||||
timestamp: timestamp('timestamp').notNull(),
|
||||
});
|
||||
export const pingRelations = relations(ping, ({ one, many }) => ({
|
||||
device: one(device, {
|
||||
|
||||
Reference in New Issue
Block a user