refactor: update collection type using zod

This commit is contained in:
nivedin
2023-12-11 17:33:06 +05:30
committed by Andrew Bastin
parent b6f3b24b9e
commit 79a8bc669e
4 changed files with 127 additions and 33 deletions

View File

@@ -1,37 +1,47 @@
import {
GQL_REQ_SCHEMA_VERSION,
HoppGQLRequest,
translateToGQLRequest,
} from "../graphql"
import { HoppRESTRequest, translateToNewRequest } from "../rest"
import { InferredEntity, createVersionedEntity } from "verzod"
const CURRENT_COLL_SCHEMA_VER = 1
import V1_VERSION from "./v/1"
import V2_VERSION from "./v/2"
type SupportedReqTypes = HoppRESTRequest | HoppGQLRequest
import { z } from "zod"
import { translateToNewRequest } from "../rest"
import { translateToGQLRequest } from "../graphql"
export type HoppCollection<T extends SupportedReqTypes> = {
v: number
name: string
folders: HoppCollection<T>[]
requests: T[]
const versionedObject = z.object({
// v is a stringified number
v: z.string().regex(/^\d+$/).transform(Number),
})
auth: T["auth"]
headers: T["headers"]
export const HoppCollection = createVersionedEntity({
latestVersion: 2,
versionMap: {
1: V1_VERSION,
2: V2_VERSION,
},
getVersion(data) {
const versionCheck = versionedObject.safeParse(data)
id?: string // For Firestore ID data
}
if (versionCheck.success) return versionCheck.data.v
// For V1 we have to check the schema
const result = V1_VERSION.schema.safeParse(data)
return result.success ? 0 : null
},
})
export type HoppCollection = InferredEntity<typeof HoppCollection>
export const CollectionSchemaVersion = 2
/**
* Generates a Collection object. This ignores the version number object
* so it can be incremented independently without updating it everywhere
* @param x The Collection Data
* @returns The final collection
*/
export function makeCollection<T extends SupportedReqTypes>(
x: Omit<HoppCollection<T>, "v">
): HoppCollection<T> {
export function makeCollection(x: Omit<HoppCollection, "v">): HoppCollection {
return {
v: CURRENT_COLL_SCHEMA_VER,
v: CollectionSchemaVersion,
...x,
}
}
@@ -41,20 +51,18 @@ export function makeCollection<T extends SupportedReqTypes>(
* @param x The collection object to load
* @returns The proper new collection format
*/
export function translateToNewRESTCollection(
x: any
): HoppCollection<HoppRESTRequest> {
if (x.v && x.v === 1) return x
export function translateToNewRESTCollection(x: any): HoppCollection {
if (x.v && x.v === CollectionSchemaVersion) return x
// Legacy
const name = x.name ?? "Untitled"
const folders = (x.folders ?? []).map(translateToNewRESTCollection)
const requests = (x.requests ?? []).map(translateToNewRequest)
const auth = x.auth ?? "None"
const auth = x.auth ?? { authType: "inherit", authActive: true }
const headers = x.headers ?? []
const obj = makeCollection<HoppRESTRequest>({
const obj = makeCollection({
name,
folders,
requests,
@@ -72,10 +80,8 @@ export function translateToNewRESTCollection(
* @param x The collection object to load
* @returns The proper new collection format
*/
export function translateToNewGQLCollection(
x: any
): HoppCollection<HoppGQLRequest> {
if (x.v && x.v === GQL_REQ_SCHEMA_VERSION) return x
export function translateToNewGQLCollection(x: any): HoppCollection {
if (x.v && x.v === CollectionSchemaVersion) return x
// Legacy
const name = x.name ?? "Untitled"
@@ -85,7 +91,7 @@ export function translateToNewGQLCollection(
const auth = x.auth ?? { authType: "inherit", authActive: true }
const headers = x.headers ?? []
const obj = makeCollection<HoppGQLRequest>({
const obj = makeCollection({
name,
folders,
requests,

View File

@@ -0,0 +1,33 @@
import { defineVersion, entityReference } from "verzod"
import { z } from "zod"
import { HoppRESTRequest } from "../../rest"
import { HoppGQLRequest } from "../../graphql"
const baseCollectionSchema = z.object({
v: z.literal(1),
id: z.optional(z.string()), // For Firestore ID data
name: z.string(),
requests: z.array(
z.lazy(() =>
z.union([
entityReference(HoppRESTRequest),
entityReference(HoppGQLRequest),
])
)
),
})
type Collection = z.infer<typeof baseCollectionSchema> & {
folders: Collection[]
}
//@ts-expect-error ~ Recursive type
export const V1_SCHEMA: z.ZodType<Collection> = baseCollectionSchema.extend({
folders: z.lazy(() => z.array(V1_SCHEMA)),
})
export default defineVersion({
initial: true,
schema: V1_SCHEMA,
})

View File

@@ -0,0 +1,54 @@
import { defineVersion, entityReference } from "verzod"
import { z } from "zod"
import { HoppRESTRequest, HoppRESTAuth } from "../../rest"
import { HoppGQLRequest, HoppGQLAuth, GQLHeader } from "../../graphql"
import { V1_SCHEMA } from "./1"
import { HoppRESTHeaders } from "../../rest/v/1"
const baseCollectionSchema = z.object({
v: z.literal(2),
id: z.optional(z.string()), // For Firestore ID data
name: z.string(),
requests: z.array(
z.lazy(() =>
z.union([
entityReference(HoppRESTRequest),
entityReference(HoppGQLRequest),
])
)
),
auth: z.union([HoppRESTAuth, HoppGQLAuth]),
headers: z.array(z.union([HoppRESTHeaders, GQLHeader])),
})
type Collection = z.infer<typeof baseCollectionSchema> & {
folders: Collection[]
}
// @ts-expect-error ~ Recursive type
export const V2_SCHEMA: z.ZodType<Collection> = baseCollectionSchema.extend({
folders: z.lazy(() => z.array(V2_SCHEMA)),
})
export default defineVersion({
initial: false,
schema: V2_SCHEMA,
up(old: z.infer<typeof V1_SCHEMA>) {
// @ts-expect-error
const result: z.infer<typeof V2_SCHEMA> = {
...old,
v: 2,
auth: {
authActive: true,
authType: "inherit",
},
headers: [],
}
if (old.id) result.id = old.id
return result
},
})

View File

@@ -25,6 +25,7 @@ export {
HoppRESTAuthNone,
HoppRESTAuthOAuth2,
HoppRESTReqBody,
HoppRESTHeaders,
} from "./v/1"
const versionedObject = z.object({