cables_dev/cables_electron/src/utils/files_util.js
- import { SharedFilesUtil, utilProvider } from "cables-shared-api";
- import fs from "fs";
- import path from "path";
- import chokidar from "chokidar";
- import helper from "./helper_util.js";
- import cables from "../cables.js";
- import opsUtil from "./ops_util.js";
- import electronApp from "../electron/main.js";
- import projectsUtil from "./projects_util.js";
- import settings from "../electron/electron_settings.js";
-
- class FilesUtil extends SharedFilesUtil
- {
- constructor(provider)
- {
- super(provider);
-
- const watcherOptions = {
- "ignored": /(^|[\/\\])\../,
- "ignorePermissionErrors": true,
- "ignoreInitial": true,
- "persistent": true,
- "followSymlinks": true,
- "disableGlobbing": true,
- "awaitWriteFinish": {
- "stabilityThreshold": 200
- }
- };
-
- this._opChangeWatcher = chokidar.watch([], watcherOptions);
- this._opChangeWatcher.on("change", (fileName) =>
- {
- const opName = opsUtil.getOpNameByAbsoluteFileName(fileName);
- if (opName)
- {
- const opId = opsUtil.getOpIdByObjName(opName);
- const code = opsUtil.getOpCode(opName);
- electronApp.sendTalkerMessage("executeOp", { "name": opName, "forceReload": true, "id": opId, "code": code });
- }
- });
-
- this._opChangeWatcher.on("unlink", (fileName) =>
- {
- const opName = opsUtil.getOpNameByAbsoluteFileName(fileName);
- if (opName)
- {
- electronApp.sendTalkerMessage("deleteOp", { "name": opName });
- }
- });
-
- this._assetChangeWatcher = chokidar.watch([], watcherOptions);
- this._assetChangeWatcher.on("change", (fileName) =>
- {
- electronApp.sendTalkerMessage("fileUpdated", { "filename": helper.pathToFileURL(fileName) });
- });
-
- this._assetChangeWatcher.on("unlink", (fileName) =>
- {
- electronApp.sendTalkerMessage("fileDeleted", { "fileName": helper.pathToFileURL(fileName) });
- });
- }
-
- registerAssetChangeListeners(project, removeOthers = false)
- {
- if (!project || !project.ops) return;
- if (removeOthers) this._assetChangeWatcher.removeAllListeners();
- const fileNames = projectsUtil.getUsedAssetFilenames(project, true);
- this._assetChangeWatcher.add(fileNames);
- }
-
- registerOpChangeListeners(opNames, removeOthers = false)
- {
- if (!opNames) return;
- if (removeOthers) this._opChangeWatcher.removeAllListeners();
- const fileNames = [];
- opNames.forEach((opName) =>
- {
- if (opsUtil.isOpNameValid(opName))
- {
- const opFile = opsUtil.getOpAbsoluteFileName(opName);
- if (opFile)
- {
- fileNames.push(opFile);
- }
- }
- });
- this._opChangeWatcher.add(fileNames);
- }
-
- unregisterOpChangeListeners(opNames)
- {
- if (!opNames) return;
- const fileNames = [];
- opNames.forEach((opName) =>
- {
- if (opsUtil.isOpNameValid(opName))
- {
- const opFile = opsUtil.getOpAbsoluteFileName(opName);
- if (opFile)
- {
- fileNames.push(opFile);
- }
- }
- });
- this._opChangeWatcher.unwatch(fileNames);
- }
-
- async unregisterChangeListeners()
- {
- await this._assetChangeWatcher.close();
- await this._opChangeWatcher.close();
- }
-
- getFileDb(filePath, user, project, cachebuster = "")
- {
- const stats = fs.statSync(filePath);
- const fileName = path.basename(filePath);
- const suffix = path.extname(fileName);
- return {
- "_id": helper.generateRandomId(),
- "name": fileName,
- "type": this.getFileType(fileName),
- "suffix": suffix,
- "fileName": fileName,
- "projectId": project._id,
- "userId": user._id,
- "updated": stats.mtime,
- "created": stats.ctime,
- "cachebuster": cachebuster,
- "isLibraryFile": filePath.includes(cables.getAssetLibraryPath()),
- "__v": 0,
- "size": stats.size,
- "path": filePath
- };
- }
-
- getFileAssetLocation(fileDb)
- {
- return fileDb.path;
- }
-
- getFileAssetUrlPath(fileDb)
- {
- if (!fileDb) return "";
- let assetDir = "";
- let assetFilePath = fileDb.path;
- if (fileDb.isLibraryFile)
- {
- assetDir = cables.getAssetLibraryPath();
- assetFilePath = path.join(assetDir, this.getAssetFileName(fileDb));
- }
- else if (!assetFilePath)
- {
- assetFilePath = path.join(assetDir, this.getAssetFileName(fileDb));
- }
- return helper.pathToFileURL(assetFilePath);
- }
-
- getLibraryFiles()
- {
- const p = cables.getAssetLibraryPath();
- return this.readAssetDir(0, p, p);
- }
-
- getFileIconName(fileDb)
- {
- let icon = "file";
-
- if (fileDb.type === "SVG") icon = "pen-tool";
- else if (fileDb.type === "image") icon = "image";
- else if (fileDb.type === "gltf" || fileDb.type === "3d json") icon = "cube";
- else if (fileDb.type === "video") icon = "film";
- else if (fileDb.type === "font") icon = "type";
- else if (fileDb.type === "JSON") icon = "code";
- else if (fileDb.type === "audio") icon = "headphones";
-
- return icon;
- }
-
- readAssetDir(lvl, filePath, origPath, urlPrefix = "")
- {
- const arr = [];
- if (!fs.existsSync(filePath))
- {
- this._log.error("could not find library assets at", filePath, "check your cables_env_local.json");
- return arr;
- }
- const files = fs.readdirSync(filePath);
- for (const i in files)
- {
- const fullPath = path.join(filePath, "/", files[i]);
- const urlPath = helper.pathToFileURL(fullPath);
-
- if (files[i] && !files[i].startsWith("."))
- {
- const s = fs.statSync(fullPath);
- if (s.isDirectory() && fs.readdirSync(fullPath).length > 0)
- {
- arr.push({
- "d": true,
- "n": files[i],
- "t": "dir",
- "l": lvl,
- "c": this.readAssetDir(lvl + 1, path.join(fullPath, "/"), origPath, urlPrefix),
- "p": urlPath,
- "isLibraryFile": true
- });
- }
- else if (files[i].toLowerCase().endsWith(".fileinfo.json")) continue;
- else
- {
- let type = "unknown";
- if (files[i].endsWith("jpg") || files[i].endsWith("png") || files[i].endsWith("jpeg")) type = "image";
- else if (files[i].endsWith("mp3") || files[i].endsWith("ogg") || files[i].endsWith("wav")) type = "audio";
- else if (files[i].endsWith("3d.json")) type = "3d json";
- else if (files[i].endsWith("json")) type = "json";
- else if (files[i].endsWith("mp4")) type = "video";
-
- const fileData = {
- "d": false,
- "n": files[i],
- "t": type,
- "l": lvl,
- "p": urlPath,
- "type": type,
- "updated": "bla",
- "isLibraryFile": true
- };
- fileData.icon = this.getFileIconName(fileData);
- let stats = fs.statSync(fullPath);
- if (stats && stats.mtime)
- {
- fileData.updated = new Date(stats.mtime).getTime();
- }
-
- arr.push(fileData);
- }
- }
- }
- return arr;
- }
-
- getPatchFiles()
- {
- const arr = [];
- const fileHierarchy = {};
-
- const project = settings.getCurrentProject();
- if (!project) return arr;
-
- const projectDir = settings.getCurrentProjectDir();
- const fileNames = projectsUtil.getUsedAssetFilenames(project);
- fileNames.forEach((fileName) =>
- {
- let type = "unknown";
- if (fileName.endsWith("jpg") || fileName.endsWith("png") || fileName.endsWith("jpeg")) type = "image";
- else if (fileName.endsWith("mp3") || fileName.endsWith("ogg") || fileName.endsWith("wav")) type = "audio";
- else if (fileName.endsWith("3d.json")) type = "3d json";
- else if (fileName.endsWith("json")) type = "json";
- else if (fileName.endsWith("mp4")) type = "video";
-
- let dirName = path.join(path.dirname(fileName), "/");
- dirName = dirName.replaceAll("\\", "/");
-
- if (!fileHierarchy.hasOwnProperty(dirName)) fileHierarchy[dirName] = [];
- const fileUrl = helper.pathToFileURL(fileName);
-
- const fileData = {
- "d": false,
- "n": path.basename(fileUrl),
- "t": type,
- "l": 0,
- "p": fileUrl,
- "type": type,
- "updated": "bla",
- "isReference": true
- };
- fileData.icon = this.getFileIconName(fileData);
-
- let stats = fs.statSync(fileName);
- if (stats && stats.mtime)
- {
- fileData.updated = new Date(stats.mtime).getTime();
- }
- fileHierarchy[dirName].push(fileData);
- });
- const dirNames = Object.keys(fileHierarchy);
- for (let dirName of dirNames)
- {
- let displayName = path.join(dirName, "/");
-
- arr.push({
- "d": true,
- "n": displayName,
- "t": "dir",
- "l": 1,
- "c": fileHierarchy[dirName],
- "p": dirName
- });
- }
- return arr;
- }
-
- isAssetLibraryLocation(filePath)
- {
- if (!filePath) return false;
- return filePath.toLowerCase().includes(cables.getAssetLibraryPath());
- }
- }
-
- export default new FilesUtil(utilProvider);