- Add GETTING_STARTED.md with quick start guide and development modes - Add INSTALL.sh automated installation script - Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md - Add QUICK_REFERENCE.md for common commands - Add SETUP_GUIDE.md with detailed setup instructions - Update README.md with improved project overview - Add did-wallet app dependencies and node_modules
124 lines
3.2 KiB
TypeScript
124 lines
3.2 KiB
TypeScript
import { DirFlat } from './dir-flat.js'
|
|
import { Dir } from './dir.js'
|
|
import { flatToShard } from './flat-to-shard.js'
|
|
import { toPathComponents } from './utils/to-path-components.js'
|
|
import type { ImportResult, InProgressImportResult, TreeBuilder, WritableStorage } from './index.js'
|
|
import type { PersistOptions } from './utils/persist.js'
|
|
|
|
export interface AddToTreeOptions extends PersistOptions {
|
|
shardSplitThresholdBytes: number
|
|
}
|
|
|
|
async function addToTree (elem: InProgressImportResult, tree: Dir, options: AddToTreeOptions): Promise<Dir> {
|
|
const pathElems = toPathComponents(elem.path ?? '')
|
|
const lastIndex = pathElems.length - 1
|
|
let parent = tree
|
|
let currentPath = ''
|
|
|
|
for (let i = 0; i < pathElems.length; i++) {
|
|
const pathElem = pathElems[i]
|
|
|
|
currentPath += `${currentPath !== '' ? '/' : ''}${pathElem}`
|
|
|
|
const last = (i === lastIndex)
|
|
parent.dirty = true
|
|
parent.cid = undefined
|
|
parent.size = undefined
|
|
|
|
if (last) {
|
|
await parent.put(pathElem, elem)
|
|
tree = await flatToShard(null, parent, options.shardSplitThresholdBytes, options)
|
|
} else {
|
|
let dir = await parent.get(pathElem)
|
|
|
|
if ((dir == null) || !(dir instanceof Dir)) {
|
|
dir = new DirFlat({
|
|
root: false,
|
|
dir: true,
|
|
parent,
|
|
parentKey: pathElem,
|
|
path: currentPath,
|
|
dirty: true,
|
|
flat: true,
|
|
mtime: dir?.unixfs?.mtime,
|
|
mode: dir?.unixfs?.mode
|
|
}, options)
|
|
}
|
|
|
|
await parent.put(pathElem, dir)
|
|
|
|
parent = dir
|
|
}
|
|
}
|
|
|
|
return tree
|
|
}
|
|
|
|
async function * flushAndYield (tree: Dir | InProgressImportResult, blockstore: WritableStorage): AsyncGenerator<ImportResult> {
|
|
if (!(tree instanceof Dir)) {
|
|
if (tree.unixfs?.isDirectory() === true) {
|
|
yield tree
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
yield * tree.flush(blockstore)
|
|
}
|
|
|
|
export interface TreeBuilderOptions extends AddToTreeOptions {
|
|
wrapWithDirectory: boolean
|
|
}
|
|
|
|
export function defaultTreeBuilder (options: TreeBuilderOptions): TreeBuilder {
|
|
return async function * treeBuilder (source, block) {
|
|
let tree: Dir = new DirFlat({
|
|
root: true,
|
|
dir: true,
|
|
path: '',
|
|
dirty: true,
|
|
flat: true
|
|
}, options)
|
|
|
|
let rootDir: string | undefined
|
|
let singleRoot = false
|
|
|
|
for await (const entry of source) {
|
|
if (entry == null) {
|
|
continue
|
|
}
|
|
|
|
// if all paths are from the same root directory, we should
|
|
// wrap them all in that root directory
|
|
const dir = `${entry.originalPath ?? ''}`.split('/')[0]
|
|
|
|
if (dir != null && dir !== '') {
|
|
if (rootDir == null) {
|
|
rootDir = dir
|
|
singleRoot = true
|
|
} else if (rootDir !== dir) {
|
|
singleRoot = false
|
|
}
|
|
}
|
|
|
|
tree = await addToTree(entry, tree, options)
|
|
|
|
if (entry.unixfs == null || !entry.unixfs.isDirectory()) {
|
|
yield entry
|
|
}
|
|
}
|
|
|
|
if (options.wrapWithDirectory || (singleRoot && tree.childCount() > 1)) {
|
|
yield * flushAndYield(tree, block)
|
|
} else {
|
|
for await (const unwrapped of tree.eachChildSeries()) {
|
|
if (unwrapped == null) {
|
|
continue
|
|
}
|
|
|
|
yield * flushAndYield(unwrapped.child, block)
|
|
}
|
|
}
|
|
}
|
|
}
|