You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
4.7 KiB

const uuid = require('uuid').v4
const { Model } = require('flitter-orm')
const { NodeDescriptorType } = require('../../enum')
class Node extends Model {
static get services() {
return [...super.services, 'models']
}
static get schema() {
return {
uuid: { type: String, default: uuid },
pied_name: String,
pied_parent_path: { type: String, default: '/' },
overlay_name: { type: String, default: 'mainline' },
mtime: { type: Date, default: () => new Date },
atime: { type: Date, default: () => new Date },
ctime: { type: Date, default: () => new Date },
mode: { type: Number, default: 33188 },
size: { type: Number, default: 0 },
descriptor_type: { type: String, default: NodeDescriptorType.File },
uploaded_file_id: String,
deleted: { type: Boolean, default: false },
root: { type: Boolean, default: false },
}
}
static path_parts(path) {
const path_parts = path.split('/')
const pied_name = path_parts.pop()
let pied_parent_path = path_parts.join('/')
if ( !pied_parent_path.startsWith('/') ) pied_parent_path = `/${pied_parent_path}`
return [pied_parent_path, pied_name]
}
static async get_root() {
let root = await this.findOne({
deleted: false, root: true, pied_parent_path: '/', pied_name: '/',
})
if ( !root ) {
root = new this({
pied_name: '/',
mode: 16877,
root: true,
descriptor_type: NodeDescriptorType.Directory,
})
await root.save()
}
return root
}
static async get_path(path, workspace = 'mainline') {
const [pied_parent_path, pied_name] = this.path_parts(path)
const nodes = await this.find({
pied_name,
pied_parent_path,
overlay_name: {
$in: [workspace, 'mainline'],
},
deleted: false,
root: false,
})
if ( nodes.length === 1 ) {
return nodes[0]
}
if ( nodes.length === 2 ) {
return nodes.find(x => x.overlay_name === workspace)
}
}
static async list_path(path, workspace = 'mainline') {
const nodes = await this.find({
pied_parent_path: path,
overlay_name: workspace,
// deleted: false,
root: false,
})
const mainline_nodes = await this.find({
pied_name: {
$nin: nodes.map(x => x.pied_name),
},
pied_parent_path: path,
overlay_name: 'mainline',
deleted: false,
root: false,
})
return [...nodes, ...mainline_nodes].filter(x => !x.deleted)
}
async uploaded_file() {
if ( !this.uploaded_file_id ) return;
const File = this.models.get('upload::File')
return File.findById(this.uploaded_file_id)
}
async all_descendants(workspace = 'mainline') {
const formatted_parent = `${this.pied_parent_path === '/' ? '/' : this.pied_parent_path + '/'}${this.pied_name}`
const nodes = await this.constructor.find({
pied_parent_path: {
$regex: this.root ? `/.*` : `(?:${formatted_parent}/.*)|(?:${formatted_parent}$)`,
},
overlay_name: workspace,
root: false,
// deleted: false,
})
const mainline_nodes = await this.constructor.find({
$and: [
{
pied_parent_path: {
$regex: this.root ? `/.*` : `(?:${formatted_parent}/.*)|(?:${formatted_parent}$)`,
},
overlay_name: 'mainline',
root: false,
deleted: false,
},
...nodes.map(node => {
return {
pied_parent_path: {
$ne: node.pied_parent_path,
},
pied_name: {
$ne: node.pied_name,
},
}
})
],
})
return [...nodes, ...mainline_nodes].filter(x => !x.deleted)
}
to_api() {
return {
pied_name: this.pied_name,
mtime: this.mtime,
atime: this.atime,
ctime: this.ctime,
mode: this.mode,
nlink: 1,
uid: 0, // TODO
gid: 0, // TODO
size: this.size,
}
}
}
module.exports = exports = Node