fileSystemStore.ts80 lines · main
1import type { Dirent } from 'node:fs'
2import { readdir, stat } from 'node:fs/promises'
3import path from 'node:path'
4import { pathToFileURL } from 'node:url'
5
6import { FunctionArtifact, FunctionFileEntry } from './types'
7
8export class FileSystemFunctionsArtifactStore {
9 constructor(private folderPath: string) {}
10
11 async getFunctions(): Promise<FunctionArtifact[]> {
12 const dirEntries = await readdir(this.folderPath, { withFileTypes: true })
13
14 const functionsFolders = dirEntries.filter((dir) => dir.isDirectory() && dir.name !== 'main')
15 const functionsArtifacts = await Promise.all(
16 functionsFolders.map(parseFolderToFunctionArtifact)
17 )
18
19 return functionsArtifacts.filter((f) => f !== undefined)
20 }
21
22 async getFunctionBySlug(slug: string): Promise<FunctionArtifact | undefined> {
23 const dirEntries = await readdir(this.folderPath, { withFileTypes: true })
24
25 const functionFolder = dirEntries.find(
26 (dir) => dir.isDirectory() && dir.name !== 'main' && dir.name === slug
27 )
28 if (!functionFolder) return
29
30 return parseFolderToFunctionArtifact(functionFolder)
31 }
32
33 async getFileEntriesBySlug(slug: string): Promise<Array<FunctionFileEntry>> {
34 if (slug === 'main') return []
35
36 const functionFolderPath = path.resolve(this.folderPath, slug)
37 if (!functionFolderPath.startsWith(path.resolve(this.folderPath) + path.sep)) return []
38
39 const entries = await readdir(functionFolderPath, {
40 recursive: true,
41 withFileTypes: true,
42 })
43
44 const fileEntries = await Promise.all(
45 entries
46 .filter((entry) => entry.isFile())
47 .map(async (entry) => {
48 const absolutePath = path.join(entry.parentPath, entry.name)
49 const fileStat = await stat(absolutePath)
50 return {
51 absolutePath,
52 relativePath: path.relative(functionFolderPath, absolutePath),
53 size: fileStat.size,
54 }
55 })
56 )
57
58 return fileEntries
59 }
60}
61
62async function parseFolderToFunctionArtifact(
63 folder: Dirent
64): Promise<FunctionArtifact | undefined> {
65 const folderPath = path.join(folder.parentPath, folder.name)
66 const files = await readdir(folderPath, { withFileTypes: true })
67 const entrypoint = files.find((file) => file.isFile() && file.name.startsWith('index'))
68
69 if (!entrypoint) return
70
71 const entrypointPath = path.join(folderPath, entrypoint.name)
72 const entrypointStat = await stat(entrypointPath)
73
74 return {
75 slug: folder.name,
76 entrypoint_path: pathToFileURL(entrypointPath).href,
77 created_at: entrypointStat.birthtimeMs,
78 updated_at: entrypointStat.mtimeMs,
79 }
80}