diff --git a/.gitignore b/.gitignore index e31ebce..5553dce 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ temp.json temp.md .dragonshoard/ + +certificates \ No newline at end of file diff --git a/actions/Schemas/index.ts b/actions/Schemas/index.ts index b26ef46..6118710 100644 --- a/actions/Schemas/index.ts +++ b/actions/Schemas/index.ts @@ -3,33 +3,70 @@ import { auth } from "@/auth"; import { isEmailVerified } from "@/util/isEmailVerified"; import { redirect } from "next/navigation"; import { prisma } from "@/prisma/prismaClient"; +import { Schema } from "@/types"; -export const saveSchemaDb = async (s: Schema) => { +export const saveSchemaDb = async (s: Schema, version: number) => { const sesh = await auth(); if (!sesh?.user?.id) return; - const { id } = await prisma.schema.upsert({ + const { id, SchemaRevision } = await prisma.schema.upsert({ // data: { // ...s, // }, create: { - ...s, - version: 0, + name: s.name, + SchemaRevision: { + create: { + fields: s.fields, + types: s.types, + }, + }, authorId: sesh.user.id, id: undefined, }, - update: s, + update: { + name: s.name, + }, where: { id: s.id, }, - select: { - id: true, + include: { + // id: true, + SchemaRevision: { + where: { + version: s.version, + }, + select: { + version: true, + isFinal: true, + }, + }, }, }); + + // const schema2 = await prisma.schema.findUnique({where:{id}}) + if ( + !SchemaRevision.at(0) || + SchemaRevision[0].version < version || + SchemaRevision[0].isFinal + ) { + await prisma.schemaRevision.create({ + data: { + schemaId: id, + types: s.types, + fields: s.fields, + version, + }, + }); + } + redirect(`/game-systems/${s.gameSystemId}/schema/${id}`); }; -export const findSchema = async (id: string): Promise => { +export const findSchema = async ( + id: string, + version: number, +): Promise => { const schema = await prisma.schema.findFirst({ where: { id, @@ -42,17 +79,33 @@ export const findSchema = async (id: string): Promise => { // }, // }, // }, - select: { - id: true, - name: true, - schema: true, - types: true, + include: { + SchemaRevision: { + where: { + version, + }, + select: { + version: true, + fields: true, + types: true, + }, + }, }, + // select: { + // id: true, + // name: true, + // }, }); - if (!schema) return null; + if (!schema?.SchemaRevision[0]) return null; - return schema as Schema; + return { + fields: schema.SchemaRevision[0].fields, + types: schema.SchemaRevision[0].types, + id: schema.id, + gameSystemId: schema.gameSystemId, + name: schema.name, + } as Schema; }; export const createSchema = async (form: FormData) => { @@ -67,9 +120,6 @@ export const createSchema = async (form: FormData) => { const { id } = await prisma.schema.create({ data: { name, - schema: "{}", - types: "{}", - version: 0, gameSystemId: gsId, authorId: session.user.id, }, diff --git a/auth/index.ts b/auth/index.ts index eab44a6..bc3b27b 100644 --- a/auth/index.ts +++ b/auth/index.ts @@ -20,6 +20,8 @@ export const { handlers, signIn, signOut, auth } = NextAuth(async () => { Discord({ clientId, clientSecret, + // redirectProxyUrl: + // "https://bottomsurgery.local:3000/api/auth/callback/discord", }), Credentials({ credentials: { diff --git a/components/schema/field-type-input.tsx b/components/schema/field-type-input.tsx index baa30d8..67ecd2e 100644 --- a/components/schema/field-type-input.tsx +++ b/components/schema/field-type-input.tsx @@ -1,15 +1,14 @@ -// import { useRecoilValue } from "recoil"; import { SchemaEditAtom } from "../../recoil/atoms/schema"; import { TEMPLATE_TYPES } from "../../constants/TemplateTypes"; import { FC, PropsWithChildren } from "react"; import { useAtom } from "jotai"; +import { InputBinder } from "@/types"; interface IProps { bind: InputBinder; } export const FieldTypeInput: FC> = ({ bind }) => { - // const schema = useRecoilValue(SchemaEditAtom); const [schema] = useAtom(SchemaEditAtom); return ( diff --git a/components/schema/index.tsx b/components/schema/index.tsx index ec0fee0..8a62c71 100644 --- a/components/schema/index.tsx +++ b/components/schema/index.tsx @@ -14,10 +14,10 @@ import { FieldTypes } from "./fieldtypes"; import { findSchema, saveSchemaDb } from "@/actions/Schemas/index"; import { useToast } from "../toast"; import { useAtom } from "jotai"; -import { Schema } from "@/types"; +import { Schema, TypeType } from "@/types"; export const SchemaBuilder: FC = () => { - const [schema, setSchema] = useAtom(SchemaEditAtom); + const [schema, setSchema] = useAtom(SchemaEditAtom); // const resetSchema = useResetRecoilState(SchemaEditAtom); const { createToast } = useToast(); const { update: updateSchema, bindProperty: bindSchemaProperty } = @@ -30,7 +30,7 @@ export const SchemaBuilder: FC = () => { useEffect(() => { if (schemaId !== "create" && schemaId !== schema.id) - findSchema(schemaId).then((sc) => { + findSchema(schemaId, 0).then((sc) => { if (!sc) return; setSchema(sc); }); @@ -70,7 +70,7 @@ export const SchemaBuilder: FC = () => { const saveSchema = useCallback(async () => { createToast({ msg: "Saving Schema", fading: true }); - await saveSchemaDb(schema); + await saveSchemaDb(schema, schema.version); }, [createToast, schema]); const selectTypeForEdit = useCallback((typeKey: string) => { diff --git a/components/signIn.tsx b/components/signIn.tsx index 9b8acc0..2453e8e 100644 --- a/components/signIn.tsx +++ b/components/signIn.tsx @@ -17,6 +17,13 @@ export default function SignIn() { type="password" name="password" /> +
@@ -24,7 +31,10 @@ export default function SignIn() {
- diff --git a/lib/tcmd/Resolver.tsx b/lib/tcmd/Resolver.tsx index 46ba71b..e59fdbf 100644 --- a/lib/tcmd/Resolver.tsx +++ b/lib/tcmd/Resolver.tsx @@ -1,10 +1,10 @@ import { PublicationAtom } from "@/recoil/atoms/publication"; import { useState, useEffect, useCallback, useRef, ReactNode } from "react"; -import { useRecoilValue } from "recoil"; import { TTCQueryResolver } from "../ttcQuery/TTCResolvers"; +import { useAtom } from "jotai"; export function Resolver({ resolver }: { resolver: string }) { - const parser = useRecoilValue(PublicationAtom); + const [parser] = useAtom(PublicationAtom); const [res] = useState(new TTCQueryResolver(parser)); const [content, setContent] = useState(""); useEffect(() => { @@ -15,7 +15,7 @@ export function Resolver({ resolver }: { resolver: string }) { ) : ( resolved?.display - ) + ), ); }, [resolver, res]); return {content}; @@ -31,7 +31,7 @@ export function OnDemandResolver({ template: string; title?: string; }) { - const parser = useRecoilValue(PublicationAtom); + const [parser] = useAtom(PublicationAtom); const res = useRef(new TTCQueryResolver(parser)); const [content, setContent] = useState(""); const generateContent = useCallback(() => { diff --git a/lib/tcmd/TokenIdentifiers.tsx b/lib/tcmd/TokenIdentifiers.tsx index 0b65dd6..a5b321b 100644 --- a/lib/tcmd/TokenIdentifiers.tsx +++ b/lib/tcmd/TokenIdentifiers.tsx @@ -5,11 +5,13 @@ import { Poppable } from "../poppables/components/poppable"; import { Accordion, AccordionContent } from "../accordion"; import { OnDemandResolver, Resolver } from "./Resolver"; +// import "crypto"; + export const TokenRenderers = new Map>(); export function buildIdentifierMap(): [ TokenIdentifierMap, - IdentifierRegistration + IdentifierRegistration, ] { const TokenIdentifiers = new Map>(); @@ -17,7 +19,7 @@ export function buildIdentifierMap(): [ type: string, match: RegExp, parseFunction: (s: string, rx: RegExp) => IdentifiedToken, - renderFunction: TokenRenderer + renderFunction: TokenRenderer, ): void; function registerIdentifier( type: string, @@ -25,7 +27,7 @@ export function buildIdentifierMap(): [ parseFunction: (s: string, rx: RegExp) => IdentifiedToken, renderFunction: TokenRenderer, openTagRx: RegExp, - closeTagRx: RegExp + closeTagRx: RegExp, ): void; function registerIdentifier>( type: string, @@ -33,7 +35,7 @@ export function buildIdentifierMap(): [ parseFunction: (s: string, rx: RegExp) => IdentifiedToken, renderFunction: TokenRenderer, openTagRx?: RegExp, - closeTagRx?: RegExp + closeTagRx?: RegExp, ) { TokenIdentifiers.set(type, { rx: match, @@ -54,7 +56,7 @@ export function buildIdentifierMap(): [ start, end, new RegExp(openTagRx, "g"), - new RegExp(closeTagRx, "g") + new RegExp(closeTagRx, "g"), ); } : undefined, @@ -125,7 +127,7 @@ export const buildOnlyDefaultElements = () => { ); }, /(? { ); }, /\[\[/g, - /\]\]/g + /\]\]/g, ); // fenced code block @@ -192,7 +194,7 @@ export const buildOnlyDefaultElements = () => { {token.content} ); - } + }, ); // list @@ -231,7 +233,7 @@ export const buildOnlyDefaultElements = () => { ); - } + }, ); // ordered-list @@ -271,7 +273,7 @@ export const buildOnlyDefaultElements = () => { ); - } + }, ); // ordered list-item @@ -300,7 +302,7 @@ export const buildOnlyDefaultElements = () => { ))} ); - } + }, ); // heading @@ -336,7 +338,7 @@ export const buildOnlyDefaultElements = () => { {token.content} ); - } + }, ); // image @@ -373,7 +375,7 @@ export const buildOnlyDefaultElements = () => { } // eslint-disable-next-line @next/next/no-img-element return {token.content}; - } + }, ); // anchor @@ -417,7 +419,7 @@ export const buildOnlyDefaultElements = () => { {token.content} ); - } + }, ); // inline-code @@ -440,7 +442,7 @@ export const buildOnlyDefaultElements = () => { {token.content} ); - } + }, ); // bold @@ -458,7 +460,7 @@ export const buildOnlyDefaultElements = () => { }, (token) => { return {token.content}; - } + }, ); // italic @@ -477,7 +479,7 @@ export const buildOnlyDefaultElements = () => { }, (token) => { return {token.content}; - } + }, ); // popover @@ -513,7 +515,7 @@ export const buildOnlyDefaultElements = () => { ); - } + }, ); // accordion @@ -543,7 +545,7 @@ export const buildOnlyDefaultElements = () => { ); - } + }, ); // paragraph @@ -569,7 +571,7 @@ export const buildOnlyDefaultElements = () => { })} ); - } + }, ); // horizontal rule @@ -587,7 +589,7 @@ export const buildOnlyDefaultElements = () => { }, () => { return
; - } + }, ); // comment @@ -605,7 +607,7 @@ export const buildOnlyDefaultElements = () => { }, () => { return <>; - } + }, ); // frontmatter @@ -624,7 +626,7 @@ export const buildOnlyDefaultElements = () => { }, (token) => { return <>{token.raw}; - } + }, ); // table @@ -655,8 +657,8 @@ export const buildOnlyDefaultElements = () => { r .split("|") .map((c) => c.trim()) - .filter((c) => !!c) - ) + .filter((c) => !!c), + ), ); let headerRows: string[][] = [], @@ -679,7 +681,7 @@ export const buildOnlyDefaultElements = () => { } const maxColumns = Math.max( - ...[...headerRows, ...bodyRows, ...footerRows].map((r) => r.length) + ...[...headerRows, ...bodyRows, ...footerRows].map((r) => r.length), ); return { @@ -770,7 +772,7 @@ export const buildOnlyDefaultElements = () => { )} ); - } + }, ); // resolver @@ -797,7 +799,7 @@ export const buildOnlyDefaultElements = () => { if (t.content.startsWith("Error")) return {t.content}; return ; - } + }, ); // on-demand resolver @@ -839,7 +841,7 @@ export const buildOnlyDefaultElements = () => { title={t.metadata.title} /> ); - } + }, ); return TokenIdentifiers; @@ -848,7 +850,7 @@ export const buildOnlyDefaultElements = () => { function findMatchingClosedParenthesis( str: string, openRegex: RegExp, - closedRegex: RegExp + closedRegex: RegExp, ): number | null { let openings = 0; let closings = 0; @@ -904,7 +906,7 @@ function search( start: number, end: number, openRx: RegExp, - closeRx: RegExp + closeRx: RegExp, ): SearchResult { const oldEnd = end; @@ -912,7 +914,7 @@ function search( s, // s.substring(0, end - start), openRx, - closeRx + closeRx, ); if (newEnd === null) diff --git a/recoil/atoms/publication.ts b/recoil/atoms/publication.ts index fa81829..435c6a9 100644 --- a/recoil/atoms/publication.ts +++ b/recoil/atoms/publication.ts @@ -1,9 +1,14 @@ import { TTCQueryParser } from "@/lib/ttcQuery/TTCQueryParser"; -import { atom } from "recoil"; +import { atom } from "jotai"; +// import { atom } from "recoil"; -export const PublicationAtom = atom({ - key: "publication", - default: new TTCQueryParser({ - path: { to: { dice: "2d6" } }, - }), -}); +// export const PublicationAtom = atom({ +// key: "publication", +// default: new TTCQueryParser({ +// path: { to: { dice: "2d6" } }, +// }), +// }); + +export const PublicationAtom = atom( + new TTCQueryParser({ path: { to: { dice: "2d6" } } }), +); diff --git a/recoil/atoms/schema.ts b/recoil/atoms/schema.ts index c029ea0..eed47e4 100644 --- a/recoil/atoms/schema.ts +++ b/recoil/atoms/schema.ts @@ -1,5 +1,6 @@ // import { atom } from "recoil"; +import { Schema } from "@/types"; import { atom } from "jotai"; // export const SchemaEditAtom = atom({ @@ -12,4 +13,5 @@ export const SchemaEditAtom = atom({ id: "", types: {}, fields: {}, + version: 0, }); diff --git a/tsconfig.json b/tsconfig.json index 833b4a8..1afe11f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,6 @@ { "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -22,23 +18,11 @@ } ], "paths": { - "@/*": [ - "./*" - ] + "@/*": ["./*"] }, "target": "es2022" }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - ], - "exclude": [ - "node_modules" - ], - "files": [ - "global.d.ts", - "./components/mdeditor/TextEditor.tsx" - ] -} \ No newline at end of file + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"], + "files": ["global.d.ts", "types.d.ts", "./components/mdeditor/TextEditor.tsx"] +} diff --git a/types.d.ts b/types.d.ts index eb5bbd3..fc882f6 100644 --- a/types.d.ts +++ b/types.d.ts @@ -87,7 +87,8 @@ type Schema = { name: string; fields: SchemaFields; types: SchemaTypes; - gameSystemId?: string; + version: number; + gameSystemId?: string | null; }; // Input Binder