TiddlyWiki5/plugins/tiddlywiki/filesystem/filesystemadaptor.js
Mario Pietsch 8aa558eb2c
Remove module function wrapper and add matching configurations for dprint and eslint (#7596)
* remove blks first try

* dprint.json seems to be OK, some forgotten functions

* add some more space-after-keyword settings

* server remove blks

* add **/files to dprint exclude

* dprint.js fixes a typo

* add boot.js and bootprefix.js to dprint exclude

* dprint change dprint.json

* add dprint fmt as script

* remove jslint comments

* fix whitespace

* fix whitespace

* remove function-wrapper from geospatial plugin

* fix whitespace

* add function wrapper to dyannotate-startup

* remove dpring.json
2025-03-21 17:22:57 +00:00

166 lines
5.5 KiB
JavaScript

/*\
title: $:/plugins/tiddlywiki/filesystem/filesystemadaptor.js
type: application/javascript
module-type: syncadaptor
A sync adaptor module for synchronising with the local filesystem via node.js APIs
\*/
"use strict";
// Get a reference to the file system
var fs = $tw.node ? require("fs") : null,
path = $tw.node ? require("path") : null;
function FileSystemAdaptor(options) {
var self = this;
this.wiki = options.wiki;
this.boot = options.boot || $tw.boot;
this.logger = new $tw.utils.Logger("filesystem",{colour: "blue"});
// Create the <wiki>/tiddlers folder if it doesn't exist
if(this.boot.wikiTiddlersPath) {
$tw.utils.createDirectory(this.boot.wikiTiddlersPath);
}
}
FileSystemAdaptor.prototype.name = "filesystem";
FileSystemAdaptor.prototype.supportsLazyLoading = false;
FileSystemAdaptor.prototype.isReady = function() {
// The file system adaptor is always ready
return true;
};
FileSystemAdaptor.prototype.getTiddlerInfo = function(tiddler) {
//Returns the existing fileInfo for the tiddler. To regenerate, call getTiddlerFileInfo().
var title = tiddler.fields.title;
return this.boot.files[title];
};
/*
Return a fileInfo object for a tiddler, creating it if necessary:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler -- see below)
hasMetaFile: true if the file also has a companion .meta file
The boot process populates this.boot.files for each of the tiddler files that it loads.
The type is found by looking up the extension in $tw.config.fileExtensionInfo (eg "application/x-tiddler" for ".tid" files).
It is the responsibility of the filesystem adaptor to update this.boot.files for new files that are created.
*/
FileSystemAdaptor.prototype.getTiddlerFileInfo = function(tiddler,callback) {
// Error if we don't have a this.boot.wikiTiddlersPath
if(!this.boot.wikiTiddlersPath) {
return callback("filesystemadaptor requires a valid wiki folder");
}
// Always generate a fileInfo object when this fuction is called
var title = tiddler.fields.title, newInfo, pathFilters, extFilters,
fileInfo = this.boot.files[title];
if(this.wiki.tiddlerExists("$:/config/FileSystemPaths")) {
pathFilters = this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n");
}
if(this.wiki.tiddlerExists("$:/config/FileSystemExtensions")) {
extFilters = this.wiki.getTiddlerText("$:/config/FileSystemExtensions","").split("\n");
}
newInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
directory: this.boot.wikiTiddlersPath,
pathFilters: pathFilters,
extFilters: extFilters,
wiki: this.wiki,
fileInfo: fileInfo
});
callback(null,newInfo);
};
/*
Save a tiddler and invoke the callback with (err,adaptorInfo,revision)
*/
FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback,options) {
var self = this;
var syncerInfo = options.tiddlerInfo || {};
this.getTiddlerFileInfo(tiddler,function(err,fileInfo) {
if(err) {
return callback(err);
}
$tw.utils.saveTiddlerToFile(tiddler,fileInfo,function(err,fileInfo) {
if(err) {
if((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "open") {
fileInfo = fileInfo || self.boot.files[tiddler.fields.title];
fileInfo.writeError = true;
self.boot.files[tiddler.fields.title] = fileInfo;
$tw.syncer.logger.log("Sync failed for \""+tiddler.fields.title+"\" and will be retried with encoded filepath",encodeURIComponent(fileInfo.filepath));
return callback(err);
} else {
return callback(err);
}
}
// Store new boot info only after successful writes
self.boot.files[tiddler.fields.title] = fileInfo;
// Cleanup duplicates if the file moved or changed extensions
var options = {
adaptorInfo: syncerInfo.adaptorInfo || {},
bootInfo: fileInfo || {},
title: tiddler.fields.title
};
$tw.utils.cleanupTiddlerFiles(options,function(err,fileInfo) {
if(err) {
return callback(err);
}
return callback(null,fileInfo);
});
});
});
};
/*
Load a tiddler and invoke the callback with (err,tiddlerFields)
We don't need to implement loading for the file system adaptor, because all the tiddler files will have been loaded during the boot process.
*/
FileSystemAdaptor.prototype.loadTiddler = function(title,callback) {
callback(null,null);
};
/*
Delete a tiddler and invoke the callback with (err)
*/
FileSystemAdaptor.prototype.deleteTiddler = function(title,callback,options) {
var self = this,
fileInfo = this.boot.files[title];
// Only delete the tiddler if we have writable information for the file
if(fileInfo) {
$tw.utils.deleteTiddlerFile(fileInfo,function(err,fileInfo) {
if(err) {
if((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") {
// Error deleting the file on disk, should fail gracefully
$tw.syncer.displayError("Server desynchronized. Error deleting file for deleted tiddler \"" + title + "\"",err);
return callback(null,fileInfo);
} else {
return callback(err);
}
}
// Remove the tiddler from self.boot.files & return null adaptorInfo
self.removeTiddlerFileInfo(title);
return callback(null,null);
});
} else {
callback(null,null);
}
};
/*
Delete a tiddler in cache, without modifying file system.
*/
FileSystemAdaptor.prototype.removeTiddlerFileInfo = function(title) {
// Only delete the tiddler info if we have writable information for the file
if(this.boot.files[title]) {
delete this.boot.files[title];
};
};
if(fs) {
exports.adaptorClass = FileSystemAdaptor;
}