@dpkit/file
Version:
Fast TypeScript data management framework built on top of the Data Package standard and Polars DataFrames
87 lines (72 loc) • 2.29 kB
text/typescript
import type { Resource } from "@dpkit/core"
import {
denormalizePath,
denormalizeResource,
getFilename,
isRemotePath,
} from "@dpkit/core"
import invariant from "tiny-invariant"
export type SaveFile = (options: {
propertyName: string
propertyIndex: number
normalizedPath: string
denormalizedPath: string
}) => Promise<string>
export async function saveResourceFiles(
resource: Resource,
options: {
saveFile: SaveFile
basepath?: string
withRemote?: boolean
withoutFolders?: boolean
},
) {
const { basepath, withRemote, withoutFolders } = options
const descriptor = denormalizeResource(resource, { basepath })
const dedupIndexes = new Map<string, number>()
const saveFile = async (path: string, name: string, index: number) => {
const isRemote = isRemotePath(path)
// Denormalized path always uses "/" as the path separator
let denormalizedPath = denormalizePath(path, { basepath })
const normalizedPath = path
if (isRemote) {
if (!withRemote) return path
const filename = getFilename(path)
if (!filename) return path
denormalizedPath = filename
} else if (withoutFolders) {
denormalizedPath = denormalizedPath.replaceAll("/", "-")
}
const dedupIndex = dedupIndexes.get(denormalizedPath) ?? 0
dedupIndexes.set(denormalizedPath, dedupIndex + 1)
if (dedupIndex) {
denormalizedPath = denormalizedPath.replace(
/^(.*?)([^\/]+?)(\.[^\/]+(?:\.[^\/]+)*)$/,
`$1$2-${dedupIndex}$3`,
)
}
denormalizedPath = await options.saveFile({
propertyName: name,
propertyIndex: index,
normalizedPath,
denormalizedPath,
})
return denormalizedPath
}
if (typeof resource.path === "string") {
descriptor.path = await saveFile(resource.path, "path", 0)
}
if (Array.isArray(resource.path)) {
invariant(Array.isArray(descriptor.path), "Multipart as resource.path")
for (const [index, path] of resource.path.entries()) {
descriptor.path[index] = await saveFile(path, "path", index)
}
}
for (const name of ["dialect", "schema"] as const) {
const path = resource[name]
if (typeof path === "string") {
descriptor[name] = await saveFile(path, name, 0)
}
}
return descriptor
}