checkpoint

pull/134/head
Alex Kern 1 year ago
parent 3c17d2604f
commit def5707932
No known key found for this signature in database
GPG Key ID: EF051FACCACBEE25

@ -24,8 +24,6 @@
"autoprefixer": "^10.4.20",
"debug": "^4.3.6",
"express": "^4.19.2",
"fp-ts": "^2.16.9",
"io-ts": "^2.2.21",
"ioredis": "^4.28.5",
"next": "^14.2.8",
"nodemon": "^1.19.4",
@ -42,7 +40,8 @@
"twilio": "^2.11.1",
"use-http": "^1.0.28",
"web-streams-polyfill": "^3.3.3",
"webrtcsupport": "^2.2.0"
"webrtcsupport": "^2.2.0",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/debug": "^4.1.12",

@ -74,6 +74,9 @@ dependencies:
webrtcsupport:
specifier: ^2.2.0
version: 2.2.0
zod:
specifier: ^3.23.8
version: 3.23.8
devDependencies:
'@types/debug':
@ -9401,3 +9404,7 @@ packages:
/yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
/zod@3.23.8:
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
dev: false

@ -10,7 +10,7 @@ import {
mobileVendor,
mobileModel,
} from 'react-device-detect'
import * as t from 'io-ts'
import { z } from 'zod' // Add this import
import { ChunkMessage, decodeMessage, Message, MessageType } from '../messages'
import { createZipStream } from '../zip-stream'
import { DataConnection } from 'peerjs'
@ -110,7 +110,7 @@ export default function Downloader({
type: string
}> | null>(null)
const processChunk = useRef<
((message: t.TypeOf<typeof ChunkMessage>) => void) | null
((message: z.infer<typeof ChunkMessage>) => void) | null
>(null)
const [shouldAttemptConnection, setShouldAttemptConnection] = useState(false)
const [open, setOpen] = useState(false)
@ -133,7 +133,7 @@ export default function Downloader({
const handleOpen = () => {
setOpen(true)
const request: t.TypeOf<typeof Message> = {
const request: z.infer<typeof Message> = {
type: MessageType.RequestInfo,
browserName: browserName,
browserVersion: browserVersion,
@ -149,7 +149,7 @@ export default function Downloader({
const handleData = (data: unknown) => {
try {
const message = decodeMessage(data)
const message = Message.parse(data) // Use Zod's parse method
switch (message.type) {
case MessageType.Info:
setFilesInfo(message.files)
@ -248,7 +248,7 @@ export default function Downloader({
return
}
const request: t.TypeOf<typeof Message> = {
const request: z.infer<typeof Message> = {
type: MessageType.Start,
fileName: filesInfo[nextFileIndex].fileName,
offset: 0,
@ -257,7 +257,7 @@ export default function Downloader({
nextFileIndex++
}
const processChunkFunc = (message: t.TypeOf<typeof ChunkMessage>): void => {
const processChunkFunc = (message: z.infer<typeof ChunkMessage>): void => {
const fileStream = fileStreamByPath[message.fileName]
if (!fileStream) {
console.error('no stream found for ' + message.fileName)
@ -291,7 +291,7 @@ export default function Downloader({
downloadPromise
.then(() => {
const request: t.TypeOf<typeof Message> = {
const request: z.infer<typeof Message> = {
type: MessageType.Done,
}
dataConnection.send(request)

@ -6,7 +6,6 @@ import {
UploaderConnectionStatus,
} from '../types'
import { decodeMessage, Message, MessageType } from '../messages'
import * as t from 'io-ts'
import { getFileName } from '../fs'
// TODO(@kern): Test for better values
@ -59,7 +58,7 @@ export function useUploaderConnections(
switch (message.type) {
case MessageType.RequestInfo: {
if (message.password !== password) {
const request: t.TypeOf<typeof Message> = {
const request: Message = {
type: MessageType.Error,
error: 'Invalid password',
}
@ -105,13 +104,13 @@ export function useUploaderConnections(
const fileInfo = files.map((f) => {
return {
fileName: f.fileName ?? f.name ?? '',
fileName: getFileName(f),
size: f.size,
type: f.type,
}
})
const request: t.TypeOf<typeof Message> = {
const request: Message = {
type: MessageType.Info,
files: fileInfo,
}
@ -142,7 +141,7 @@ export function useUploaderConnections(
const end = Math.min(file.size, offset + MAX_CHUNK_SIZE)
const chunkSize = end - offset
const final = chunkSize < MAX_CHUNK_SIZE
const request: t.TypeOf<typeof Message> = {
const request: Message = {
type: MessageType.Chunk,
fileName,
offset,

@ -1,82 +1,70 @@
import * as t from 'io-ts'
import { pipe } from 'fp-ts/function'
import { fold } from 'fp-ts/Either'
import { z } from 'zod'
export enum MessageType {
RequestInfo = 'REQUEST_INFO',
Info = 'INFO',
Pause = 'PAUSE',
Start = 'START',
Chunk = 'CHUNK',
Done = 'DONE',
Error = 'ERROR',
RequestInfo = 'RequestInfo',
Info = 'Info',
Start = 'Start',
Chunk = 'Chunk',
Done = 'Done',
Error = 'Error',
}
export const RequestInfoMessage = t.type({
type: t.literal(MessageType.RequestInfo),
browserName: t.string,
browserVersion: t.string,
osName: t.string,
osVersion: t.string,
mobileVendor: t.string,
mobileModel: t.string,
password: t.string,
export const RequestInfoMessage = z.object({
type: z.literal(MessageType.RequestInfo),
browserName: z.string(),
browserVersion: z.string(),
osName: z.string(),
osVersion: z.string(),
mobileVendor: z.string(),
mobileModel: z.string(),
password: z.string(),
})
export const InfoMessage = t.type({
type: t.literal(MessageType.Info),
files: t.array(
t.type({
fileName: t.string,
size: t.number,
type: t.string,
export const InfoMessage = z.object({
type: z.literal(MessageType.Info),
files: z.array(
z.object({
fileName: z.string(),
size: z.number(),
type: z.string(),
}),
),
})
export const StartMessage = t.type({
type: t.literal(MessageType.Start),
fileName: t.string,
offset: t.number,
export const StartMessage = z.object({
type: z.literal(MessageType.Start),
fileName: z.string(),
offset: z.number(),
})
export const ChunkMessage = t.type({
type: t.literal(MessageType.Chunk),
fileName: t.string,
offset: t.number,
bytes: t.unknown,
final: t.boolean,
export const ChunkMessage = z.object({
type: z.literal(MessageType.Chunk),
fileName: z.string(),
offset: z.number(),
bytes: z.unknown(),
final: z.boolean(),
})
export const PauseMessage = t.type({
type: t.literal(MessageType.Pause),
export const DoneMessage = z.object({
type: z.literal(MessageType.Done),
})
export const DoneMessage = t.type({
type: t.literal(MessageType.Done),
export const ErrorMessage = z.object({
type: z.literal(MessageType.Error),
error: z.string(),
})
export const ErrorMessage = t.type({
type: t.literal(MessageType.Error),
error: t.string,
})
export const Message = t.union([
export const Message = z.discriminatedUnion('type', [
RequestInfoMessage,
InfoMessage,
PauseMessage,
StartMessage,
ChunkMessage,
DoneMessage,
ErrorMessage,
])
export function decodeMessage(data: any): t.TypeOf<typeof Message> {
const onFailure = (errors: t.Errors): t.TypeOf<typeof Message> => {
throw new Error(`${errors.length} error(s) found`)
}
const onSuccess = (mesg: t.TypeOf<typeof Message>) => mesg
export type Message = z.infer<typeof Message>
return pipe(Message.decode(data), fold(onFailure, onSuccess))
export function decodeMessage(data: unknown): Message {
return Message.parse(data)
}

Loading…
Cancel
Save