Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/library/src/server/dirtree/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,37 @@ describe("dirtree", () => {
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>"
`)
})

it("creates an empty schema when the directory cannot be read", async () => {
const tree = getDirectoryTree("nonexistent")
const result = await buildSchemaForDirectoryTree(tree, "MyDirectoryTree")
expect(result).toMatchInlineSnapshot(`
"
// Note: This file is autogenerated. Do not edit it directly.
//
// Describes the contents of the test directory, which is a blueprint for
// files and directories. Tests can create a unique, safe environment for
// interacting with the contents of such a directory.
//
// Having strong typing for the test directory contents ensures that tests can
// be written with confidence that the files and directories they expect are
// actually found. Otherwise the tests are brittle and can break easily.

import { z } from "zod"

export const MyDirectoryTreeSchema = z.object({
type: z.literal("directory"),
name: z.literal("root"),
contents: z.object({}),
})

export const MyDirectoryTreeContentsSchema = MyDirectoryTreeSchema.shape.contents
export type MyDirectoryTreeContentsSchemaType = z.infer<typeof MyDirectoryTreeSchema>

export type MyDirectoryTree = MyDirectoryTreeContentsSchemaType["contents"]

export const testDirectoryFiles = z.enum([])
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>"
`)
})
})
20 changes: 11 additions & 9 deletions packages/library/src/server/dirtree/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import assert from "assert"
import type { Dree } from "dree"
import { scan, Type } from "dree"
import { format, resolveConfig } from "prettier"
import { fileURLToPath } from "url"
import { jsonToZod } from "./json-to-zod.js"

type TreeResult = { dree: Dree; allFiles: Dree[] }
type TreeResult = { dree: Dree | undefined; allFiles: Dree[] }

/** Convert a directory tree to a TypeScript type. This is useful for testing
* as the initial state of the test directory is fully known in tests. */
Expand All @@ -25,9 +24,9 @@ export function getDirectoryTree(path: string): TreeResult {
dir => {
allFiles.push(dir)
}
)
) as Dree | null // https://github.com/euberdeveloper/dree/pull/51

return { dree: result, allFiles }
return { dree: result ?? undefined, allFiles }
}

type FileNode = {
Expand All @@ -42,7 +41,11 @@ type DirectoryNode = {

type TreeNode = FileNode | DirectoryNode

export function convertDree(root: Dree): TreeNode {
export function convertDree(root: Dree | undefined): TreeNode {
if (!root) {
return { type: Type.DIRECTORY, name: "root", contents: {} }
}

if (root.type === Type.FILE) {
return {
name: root.name,
Expand All @@ -63,10 +66,9 @@ export function convertDree(root: Dree): TreeNode {
}

export async function buildSchemaForDirectoryTree(result: TreeResult, name: string): Promise<string> {
const root = result.dree
assert(root.type === Type.DIRECTORY)
const node = convertDree(root)
const schema = (await jsonToZod(node, `${name}Schema`)).split("\n")
const root = convertDree(result.dree)

const schema = (await jsonToZod(root, `${name}Schema`)).split("\n")

const lines = `
// Note: This file is autogenerated. Do not edit it directly.
Expand Down