fileSystemStore.ts 2.6 KB

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