diff --git a/plugins/tiddlywiki/multiwikiserver/modules/route-get-bag-tiddler.js b/plugins/tiddlywiki/multiwikiserver/modules/route-get-bag-tiddler.js index 8fe738518..e3ce8ef51 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/route-get-bag-tiddler.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/route-get-bag-tiddler.js @@ -23,15 +23,15 @@ exports.handler = function(request,response,state) { var bag_name = $tw.utils.decodeURIComponentSafe(state.params[0]), bag_name_2 = $tw.utils.decodeURIComponentSafe(state.params[1]), title = $tw.utils.decodeURIComponentSafe(state.params[2]), - tiddler = bag_name === bag_name_2 && $tw.sqlTiddlerStore.getBagTiddler(title,bag_name); - if(bag_name === bag_name_2 && tiddler) { + result = bag_name === bag_name_2 && $tw.sqlTiddlerStore.getBagTiddler(title,bag_name); + if(bag_name === bag_name_2 && result) { // 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) { var tiddlerFields = {}, knownFields = [ "bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri" ]; - $tw.utils.each(tiddler,function(value,name) { + $tw.utils.each(result.tiddler,function(value,name) { if(knownFields.indexOf(name) !== -1) { tiddlerFields[name] = value; } else { @@ -39,17 +39,17 @@ exports.handler = function(request,response,state) { tiddlerFields.fields[name] = value; } }); - tiddlerFields.revision = "0"; + tiddlerFields.revision = "" + result.tiddler_id; tiddlerFields.bag = bag_name; tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki"; state.sendResponse(200,{"Content-Type": "application/json"},JSON.stringify(tiddlerFields),"utf8"); } else { // This is not a JSON API request, we should return the raw tiddler content - var type = tiddler.type || "text/plain"; + var type = result.tiddler.type || "text/plain"; response.writeHead(200, "OK",{ "Content-Type": type }); - response.write(tiddler.text || "",($tw.config.contentTypeInfo[type] ||{encoding: "utf8"}).encoding); + response.write(result.tiddler.text || "",($tw.config.contentTypeInfo[type] ||{encoding: "utf8"}).encoding); response.end();; } } else { diff --git a/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddler.js b/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddler.js index e3815fdf5..b34075759 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddler.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddler.js @@ -39,7 +39,7 @@ exports.handler = function(request,response,state) { tiddlerFields.fields[name] = value; } }); - tiddlerFields.revision = "0"; + tiddlerFields.revision = "" + tiddlerInfo.tiddler_id; tiddlerFields.bag = tiddlerInfo.bag_name; tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki"; state.sendResponse(200,{"Content-Type": "application/json"},JSON.stringify(tiddlerFields),"utf8"); diff --git a/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddlers-json.js b/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddlers-json.js index 4e69ee87b..f8d81173b 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddlers-json.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe-tiddlers-json.js @@ -29,7 +29,7 @@ exports.handler = function(request,response,state) { var tiddlers = []; $tw.utils.each(recipeTiddlers,function(recipeTiddlerInfo) { var tiddlerInfo = $tw.sqlTiddlerStore.getRecipeTiddler(recipeTiddlerInfo.title,recipe_name); - tiddlers.push(Object.assign({},tiddlerInfo.tiddler,{text: undefined, revision: "0", bag: recipeTiddlerInfo.bag_name})); + tiddlers.push(Object.assign({},tiddlerInfo.tiddler,{text: undefined, revision: "" + tiddlerInfo.tiddler_id, bag: recipeTiddlerInfo.bag_name})); }); var text = JSON.stringify(tiddlers); state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8"); diff --git a/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe.js b/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe.js index 7126b8470..d77cbf5f7 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/route-get-recipe.js @@ -53,14 +53,14 @@ exports.handler = function(request,response,state) { var tiddlerInfo = $tw.sqlTiddlerStore.getRecipeTiddler(recipeTiddlerInfo.title,recipe_name); if((tiddlerInfo.tiddler.text || "").length > 10 * 1024 * 1024) { response.write(JSON.stringify(Object.assign({},tiddlerInfo.tiddler,{ - revision: "0", + revision: "" + tiddlerInfo.tiddler_id, bag: recipeTiddlerInfo.bag_name, text: undefined, _canonical_uri: `/wiki/${recipe_name}/recipes/${recipe_name}/tiddlers/${title}` }))); } else { response.write(JSON.stringify(Object.assign({},tiddlerInfo.tiddler,{ - revision: "0", + revision: "" + tiddlerInfo.tiddler_id, bag: recipeTiddlerInfo.bag_name }))); } diff --git a/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js b/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js index 455f9f794..c5ca2dd52 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js @@ -39,9 +39,9 @@ exports.handler = function(request,response,state) { }); // Require the recipe names to match if(recipe_name === recipe_name_2) { - var bag_name = $tw.sqlTiddlerStore.saveRecipeTiddler(fields,recipe_name); + var result = $tw.sqlTiddlerStore.saveRecipeTiddler(fields,recipe_name); response.writeHead(204, "OK",{ - Etag: "\"" + bag_name + "/" + encodeURIComponent(title) + "/" + 2222 + ":\"", + Etag: "\"" + result.bag_name + "/" + encodeURIComponent(title) + "/" + result.tiddler_id + ":\"", "Content-Type": "text/plain" }); response.end(); diff --git a/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js b/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js index 84b688e2b..e63951c2f 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js @@ -32,7 +32,7 @@ SqlTiddlerStore.prototype.close = function() { SqlTiddlerStore.prototype.runStatement = function(sql,params) { params = params || {}; const statement = this.db.prepare(sql); - statement.run(params); + return statement.run(params); }; SqlTiddlerStore.prototype.runStatementGet = function(sql,params) { @@ -81,14 +81,14 @@ SqlTiddlerStore.prototype.createTables = function() { this.runStatements([` -- Bags have names and access control settings CREATE TABLE IF NOT EXISTS bags ( - bag_id INTEGER PRIMARY KEY, + bag_id INTEGER PRIMARY KEY AUTOINCREMENT, bag_name TEXT UNIQUE, accesscontrol TEXT ) `,` -- Recipes have names... CREATE TABLE IF NOT EXISTS recipes ( - recipe_id INTEGER PRIMARY KEY, + recipe_id INTEGER PRIMARY KEY AUTOINCREMENT, recipe_name TEXT UNIQUE ) `,` @@ -104,7 +104,7 @@ SqlTiddlerStore.prototype.createTables = function() { `,` -- Tiddlers are contained in bags and have titles CREATE TABLE IF NOT EXISTS tiddlers ( - tiddler_id INTEGER PRIMARY KEY, + tiddler_id INTEGER PRIMARY KEY AUTOINCREMENT, bag_id INTEGER, title TEXT, FOREIGN KEY (bag_id) REFERENCES bags(bag_id) ON UPDATE CASCADE ON DELETE CASCADE, @@ -212,9 +212,12 @@ SqlTiddlerStore.prototype.createRecipe = function(recipename,bagnames) { }); }; +/* +Returns {tiddler_id:} +*/ SqlTiddlerStore.prototype.saveBagTiddler = function(tiddlerFields,bagname) { // Update the tiddlers table - this.runStatement(` + var info = this.runStatement(` INSERT OR REPLACE INTO tiddlers (bag_id, title) VALUES ( (SELECT bag_id FROM bags WHERE bag_name = $bag_name), @@ -246,8 +249,14 @@ SqlTiddlerStore.prototype.saveBagTiddler = function(tiddlerFields,bagname) { bag_name: bagname, field_values: JSON.stringify(Object.assign({},tiddlerFields,{title: undefined})) }); + return { + tiddler_id: info.lastInsertRowid + } }; +/* +Returns {tiddler_id:,bag_name:} +*/ SqlTiddlerStore.prototype.saveRecipeTiddler = function(tiddlerFields,recipename) { // Find the topmost bag in the recipe var row = this.runStatementGet(` @@ -269,8 +278,11 @@ SqlTiddlerStore.prototype.saveRecipeTiddler = function(tiddlerFields,recipename) recipe_name: recipename }); // Save the tiddler to the topmost bag - this.saveBagTiddler(tiddlerFields,row.bag_name); - return row.bag_name; + var info = this.saveBagTiddler(tiddlerFields,row.bag_name); + return { + tiddler_id: info.tiddler_id, + bag_name: row.bag_name + }; }; SqlTiddlerStore.prototype.deleteTiddler = function(title,bagname) { @@ -300,9 +312,12 @@ SqlTiddlerStore.prototype.deleteTiddler = function(title,bagname) { }); }; +/* +returns {tiddler_id:,tiddler:} +*/ SqlTiddlerStore.prototype.getBagTiddler = function(title,bagname) { const rows = this.runStatementGetAll(` - SELECT field_name, field_value + SELECT field_name, field_value, tiddler_id FROM fields WHERE tiddler_id = ( SELECT t.tiddler_id @@ -317,15 +332,18 @@ SqlTiddlerStore.prototype.getBagTiddler = function(title,bagname) { if(rows.length === 0) { return null; } else { - return rows.reduce((accumulator,value) => { - accumulator[value["field_name"]] = value.field_value; - return accumulator; - },{title: title}); + return { + tiddler_id: rows[0].tiddler_id, + tiddler: rows.reduce((accumulator,value) => { + accumulator[value["field_name"]] = value.field_value; + return accumulator; + },{title: title}) + }; } }; /* -Returns {bag_name:, tiddler: {fields}} +Returns {bag_name:, tiddler: {fields}, tiddler_id:} */ SqlTiddlerStore.prototype.getRecipeTiddler = function(title,recipename) { const rowTiddlerId = this.runStatementGet(` @@ -356,6 +374,7 @@ SqlTiddlerStore.prototype.getRecipeTiddler = function(title,recipename) { }); return { bag_name: rowTiddlerId.bag_name, + tiddler_id: rowTiddlerId.tiddler_id, tiddler: rows.reduce((accumulator,value) => { accumulator[value["field_name"]] = value.field_value; return accumulator; diff --git a/plugins/tiddlywiki/multiwikiserver/modules/tests-sql-tiddler-store.js b/plugins/tiddlywiki/multiwikiserver/modules/tests-sql-tiddler-store.js index b0f9a20e7..7523ac092 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/tests-sql-tiddler-store.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/tests-sql-tiddler-store.js @@ -71,7 +71,7 @@ describe("SQL tiddler store", function() { expect(sqlTiddlerStore.getRecipeTiddlers("recipe-rho")).toEqual([ { title: 'Hello There', bag_name: 'bag-alpha' } ]); expect(sqlTiddlerStore.getRecipeTiddlers("recipe-sigma")).toEqual([ { title: 'Hello There', bag_name: 'bag-gamma' } ]); // Save a recipe tiddler - sqlTiddlerStore.saveRecipeTiddler({title: "More", text: "None"},"recipe-rho"); + expect(sqlTiddlerStore.saveRecipeTiddler({title: "More", text: "None"},"recipe-rho")).toEqual({tiddler_id: 5, bag_name: 'bag-beta'}); expect(sqlTiddlerStore.getRecipeTiddler("More","recipe-rho").tiddler).toEqual({title: "More", text: "None"}); });