mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-03-09 21:18:11 +00:00
Stop storing bag and revision details as tiddler fields
Instead we store them as dictionary tiddlers
This commit is contained in:
parent
eaebeb87c9
commit
3aa5607a3a
@ -13,7 +13,9 @@ A sync adaptor module for synchronising with MultiWikiServer-compatible servers
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var CONFIG_HOST_TIDDLER = "$:/config/multiwikiclient/host",
|
var CONFIG_HOST_TIDDLER = "$:/config/multiwikiclient/host",
|
||||||
DEFAULT_HOST_TIDDLER = "$protocol$//$host$/";
|
DEFAULT_HOST_TIDDLER = "$protocol$//$host$/",
|
||||||
|
BAG_STATE_TIDDLER = "$:/state/federatial/xememex/tiddlers/bag",
|
||||||
|
REVISION_STATE_TIDDLER = "$:/state/federatial/xememex/tiddlers/revision";
|
||||||
|
|
||||||
function MultiWikiClientAdaptor(options) {
|
function MultiWikiClientAdaptor(options) {
|
||||||
this.wiki = options.wiki;
|
this.wiki = options.wiki;
|
||||||
@ -52,14 +54,32 @@ MultiWikiClientAdaptor.prototype.getHost = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MultiWikiClientAdaptor.prototype.getTiddlerInfo = function(tiddler) {
|
MultiWikiClientAdaptor.prototype.getTiddlerInfo = function(tiddler) {
|
||||||
return {
|
var title = tiddler.fields.title,
|
||||||
bag: tiddler.fields.bag
|
revision = this.wiki.extractTiddlerDataItem(REVISION_STATE_TIDDLER,title),
|
||||||
};
|
bag = this.wiki.extractTiddlerDataItem(BAG_STATE_TIDDLER,title);
|
||||||
|
if(revision && bag) {
|
||||||
|
return {
|
||||||
|
title: title,
|
||||||
|
revision: revision,
|
||||||
|
bag: bag
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MultiWikiClientAdaptor.prototype.getTiddlerRevision = function(title) {
|
MultiWikiClientAdaptor.prototype.getTiddlerRevision = function(title) {
|
||||||
var tiddler = this.wiki.getTiddler(title);
|
return this.wiki.extractTiddlerDataItem(REVISION_STATE_TIDDLER,title);
|
||||||
return tiddler.fields.revision;
|
};
|
||||||
|
|
||||||
|
MultiWikiClientAdaptor.prototype.setTiddlerInfo = function(title,revision,bag) {
|
||||||
|
this.wiki.setText(BAG_STATE_TIDDLER,null,title,revision,{suppressTimestamp: true});
|
||||||
|
this.wiki.setText(REVISION_STATE_TIDDLER,null,title,bag,{suppressTimestamp: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiWikiClientAdaptor.prototype.removeTiddlerInfo = function(title) {
|
||||||
|
this.wiki.setText(BAG_STATE_TIDDLER,null,title,undefined,{suppressTimestamp: true});
|
||||||
|
this.wiki.setText(REVISION_STATE_TIDDLER,null,title,undefined,{suppressTimestamp: true});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -157,11 +177,7 @@ MultiWikiClientAdaptor.prototype.getSkinnyTiddlers = function(callback) {
|
|||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
// Process the tiddlers to make sure the revision is a string
|
var tiddlers = $tw.utils.parseJSONSafe(data);
|
||||||
var tiddlers = JSON.parse(data);
|
|
||||||
for(var t=0; t<tiddlers.length; t++) {
|
|
||||||
tiddlers[t] = self.convertTiddlerFromTiddlyWebFormat(tiddlers[t]);
|
|
||||||
}
|
|
||||||
// Invoke the callback with the skinny tiddlers
|
// Invoke the callback with the skinny tiddlers
|
||||||
callback(null,tiddlers);
|
callback(null,tiddlers);
|
||||||
// If Browswer Storage tiddlers were cached on reloading the wiki, add them after sync from server completes in the above callback.
|
// If Browswer Storage tiddlers were cached on reloading the wiki, add them after sync from server completes in the above callback.
|
||||||
@ -186,7 +202,7 @@ MultiWikiClientAdaptor.prototype.saveTiddler = function(tiddler,callback,options
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-type": "application/json"
|
"Content-type": "application/json"
|
||||||
},
|
},
|
||||||
data: this.convertTiddlerToTiddlyWebFormat(tiddler),
|
data: JSON.stringify(tiddler.getFieldStrings()),
|
||||||
callback: function(err,data,request) {
|
callback: function(err,data,request) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -220,7 +236,7 @@ MultiWikiClientAdaptor.prototype.loadTiddler = function(title,callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
// Invoke the callback
|
// Invoke the callback
|
||||||
callback(null,self.convertTiddlerFromTiddlyWebFormat(JSON.parse(data)));
|
callback(null,$tw.utils.parseJSONSafe(data));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -254,64 +270,6 @@ MultiWikiClientAdaptor.prototype.deleteTiddler = function(title,callback,options
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Convert a tiddler to a field set suitable for PUTting to TiddlyWeb
|
|
||||||
*/
|
|
||||||
MultiWikiClientAdaptor.prototype.convertTiddlerToTiddlyWebFormat = function(tiddler) {
|
|
||||||
var result = {},
|
|
||||||
knownFields = [
|
|
||||||
"bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri"
|
|
||||||
];
|
|
||||||
if(tiddler) {
|
|
||||||
$tw.utils.each(tiddler.fields,function(fieldValue,fieldName) {
|
|
||||||
var fieldString = fieldName === "tags" ?
|
|
||||||
tiddler.fields.tags :
|
|
||||||
tiddler.getFieldString(fieldName); // Tags must be passed as an array, not a string
|
|
||||||
|
|
||||||
if(knownFields.indexOf(fieldName) !== -1) {
|
|
||||||
// If it's a known field, just copy it across
|
|
||||||
result[fieldName] = fieldString;
|
|
||||||
} else {
|
|
||||||
// If it's unknown, put it in the "fields" field
|
|
||||||
result.fields = result.fields || {};
|
|
||||||
result.fields[fieldName] = fieldString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Default the content type
|
|
||||||
result.type = result.type || "text/vnd.tiddlywiki";
|
|
||||||
return JSON.stringify(result,null,$tw.config.preferences.jsonSpaces);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Convert a field set in TiddlyWeb format into ordinary TiddlyWiki5 format
|
|
||||||
*/
|
|
||||||
MultiWikiClientAdaptor.prototype.convertTiddlerFromTiddlyWebFormat = function(tiddlerFields) {
|
|
||||||
var self = this,
|
|
||||||
result = {};
|
|
||||||
// Transfer the fields, pulling down the `fields` hashmap
|
|
||||||
$tw.utils.each(tiddlerFields,function(element,title,object) {
|
|
||||||
if(title === "fields") {
|
|
||||||
$tw.utils.each(element,function(element,subTitle,object) {
|
|
||||||
result[subTitle] = element;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
result[title] = tiddlerFields[title];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Make sure the revision is expressed as a string
|
|
||||||
if(typeof result.revision === "number") {
|
|
||||||
result.revision = result.revision.toString();
|
|
||||||
}
|
|
||||||
// Some unholy freaking of content types
|
|
||||||
if(result.type === "text/javascript") {
|
|
||||||
result.type = "application/javascript";
|
|
||||||
} else if(!result.type || result.type === "None") {
|
|
||||||
result.type = "text/x-tiddlywiki";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Split an MWS Etag into its constituent parts. For example:
|
Split an MWS Etag into its constituent parts. For example:
|
||||||
|
|
||||||
|
@ -28,23 +28,10 @@ exports.handler = function(request,response,state) {
|
|||||||
if(tiddlerInfo && tiddlerInfo.tiddler) {
|
if(tiddlerInfo && tiddlerInfo.tiddler) {
|
||||||
// If application/json is requested then this is an API request, and gets the response in JSON
|
// If application/json is requested then this is an API request, and gets the response in JSON
|
||||||
if(request.headers.accept && request.headers.accept.indexOf("application/json") !== -1) {
|
if(request.headers.accept && request.headers.accept.indexOf("application/json") !== -1) {
|
||||||
var tiddlerFields = {},
|
|
||||||
knownFields = [
|
|
||||||
"bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri"
|
|
||||||
];
|
|
||||||
$tw.utils.each(tiddlerInfo.tiddler,function(value,name) {
|
|
||||||
if(knownFields.indexOf(name) !== -1) {
|
|
||||||
tiddlerFields[name] = value;
|
|
||||||
} else {
|
|
||||||
tiddlerFields.fields = tiddlerFields.fields || {};
|
|
||||||
tiddlerFields.fields[name] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
|
||||||
state.sendResponse(200,{
|
state.sendResponse(200,{
|
||||||
Etag: state.makeTiddlerEtag(tiddlerInfo),
|
Etag: state.makeTiddlerEtag(tiddlerInfo),
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},JSON.stringify(tiddlerFields),"utf8");
|
},JSON.stringify(tiddlerInfo.tiddler),"utf8");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// This is not a JSON API request, we should return the raw tiddler content
|
// This is not a JSON API request, we should return the raw tiddler content
|
||||||
|
@ -28,23 +28,10 @@ exports.handler = function(request,response,state) {
|
|||||||
if(tiddlerInfo && tiddlerInfo.tiddler) {
|
if(tiddlerInfo && tiddlerInfo.tiddler) {
|
||||||
// If application/json is requested then this is an API request, and gets the response in JSON
|
// If application/json is requested then this is an API request, and gets the response in JSON
|
||||||
if(request.headers.accept && request.headers.accept.indexOf("application/json") !== -1) {
|
if(request.headers.accept && request.headers.accept.indexOf("application/json") !== -1) {
|
||||||
var tiddlerFields = {},
|
|
||||||
knownFields = [
|
|
||||||
"bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri"
|
|
||||||
];
|
|
||||||
$tw.utils.each(tiddlerInfo.tiddler,function(value,name) {
|
|
||||||
if(knownFields.indexOf(name) !== -1) {
|
|
||||||
tiddlerFields[name] = value;
|
|
||||||
} else {
|
|
||||||
tiddlerFields.fields = tiddlerFields.fields || {};
|
|
||||||
tiddlerFields.fields[name] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
|
||||||
state.sendResponse(200,{
|
state.sendResponse(200,{
|
||||||
Etag: state.makeTiddlerEtag(tiddlerInfo),
|
Etag: state.makeTiddlerEtag(tiddlerInfo),
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},JSON.stringify(tiddlerFields),"utf8");
|
},JSON.stringify(tiddlerInfo.tiddler),"utf8");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// This is not a JSON API request, we should return the raw tiddler content
|
// This is not a JSON API request, we should return the raw tiddler content
|
||||||
|
@ -64,12 +64,12 @@ exports.handler = function(request,response,state) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
writeTiddler({
|
writeTiddler({
|
||||||
title: "$:/config/multiwikiclient/tiddlers/bag",
|
title: "$:/state/multiwikiclient/tiddlers/bag",
|
||||||
text: JSON.stringify(bagInfo),
|
text: JSON.stringify(bagInfo),
|
||||||
type: "application/json"
|
type: "application/json"
|
||||||
});
|
});
|
||||||
writeTiddler({
|
writeTiddler({
|
||||||
title: "$:/config/multiwikiclient/tiddlers/revision",
|
title: "$:/state/multiwikiclient/tiddlers/revision",
|
||||||
text: JSON.stringify(revisionInfo),
|
text: JSON.stringify(revisionInfo),
|
||||||
type: "application/json"
|
type: "application/json"
|
||||||
});
|
});
|
||||||
|
@ -21,20 +21,7 @@ exports.handler = function(request,response,state) {
|
|||||||
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
title = $tw.utils.decodeURIComponentSafe(state.params[1]),
|
title = $tw.utils.decodeURIComponentSafe(state.params[1]),
|
||||||
fields = $tw.utils.parseJSONSafe(state.data);
|
fields = $tw.utils.parseJSONSafe(state.data);
|
||||||
// Pull up any subfields in the `fields` object
|
if(recipe_name && title === fields.title) {
|
||||||
if(typeof fields.fields === "object") {
|
|
||||||
$tw.utils.each(fields.fields,function(field,name) {
|
|
||||||
fields[name] = field;
|
|
||||||
});
|
|
||||||
delete fields.fields;
|
|
||||||
}
|
|
||||||
// Stringify any array fields
|
|
||||||
$tw.utils.each(fields,function(value,name) {
|
|
||||||
if($tw.utils.isArray(value)) {
|
|
||||||
fields[name] = $tw.utils.stringifyList(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if(recipe_name) {
|
|
||||||
var result = $tw.mws.store.saveRecipeTiddler(fields,recipe_name);
|
var result = $tw.mws.store.saveRecipeTiddler(fields,recipe_name);
|
||||||
if(result) {
|
if(result) {
|
||||||
response.writeHead(204, "OK",{
|
response.writeHead(204, "OK",{
|
||||||
|
@ -86,15 +86,18 @@ Given tiddler fields, tiddler_id and a bag_name, return the tiddler fields after
|
|||||||
- Apply the bag_name as the bag field
|
- Apply the bag_name as the bag field
|
||||||
*/
|
*/
|
||||||
SqlTiddlerStore.prototype.processOutgoingTiddler = function(tiddlerFields,tiddler_id,bag_name,attachment_blob) {
|
SqlTiddlerStore.prototype.processOutgoingTiddler = function(tiddlerFields,tiddler_id,bag_name,attachment_blob) {
|
||||||
const fields = Object.assign({},tiddlerFields,{
|
|
||||||
revision: "" + tiddler_id,
|
|
||||||
bag: bag_name
|
|
||||||
});
|
|
||||||
if(attachment_blob !== null) {
|
if(attachment_blob !== null) {
|
||||||
delete fields.text;
|
return $tw.utils.extend(
|
||||||
fields._canonical_uri = `/bags/${encodeURIComponent(bag_name)}/tiddlers/${encodeURIComponent(tiddlerFields.title)}/blob`;
|
{},
|
||||||
|
tiddlerFields,
|
||||||
|
{
|
||||||
|
text: undefined,
|
||||||
|
_canonical_uri: `/bags/${encodeURIComponent(bag_name)}/tiddlers/${encodeURIComponent(tiddlerFields.title)}/blob`
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return tiddlerFields;
|
||||||
}
|
}
|
||||||
return fields;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user