Skip to content

Commit

Permalink
fix a few things for release
Browse files Browse the repository at this point in the history
  • Loading branch information
Arlen22 committed Jun 10, 2023
1 parent 6d60fd4 commit 2052a66
Show file tree
Hide file tree
Showing 10 changed files with 548 additions and 504 deletions.
48 changes: 26 additions & 22 deletions build.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
var $tw = require("tiddlywiki").TiddlyWiki();
var path = require("path");
var fs = require("fs");

// Pass the command line arguments to the boot kernel
$tw.boot.argv = ["."];
// we only need the first phase of startup
$tw.boot.initStartup({});
// get the bundle output path
var output = path.resolve("plugins/sse/plugin.info");
// create the directory tree
if(!fs.existsSync(path.dirname(output))) {
fs.mkdirSync(path.dirname(output),{recursive: true});
}
// load the plugin from the dist folder
var plugin = $tw.loadPluginFolder(path.join(__dirname,"dist"));
// put the plugin tiddlers back into the tiddlers field
$tw.utils.extend(plugin,JSON.parse(plugin.text));
// remove the text field
delete plugin.text;
// write the bundled plugin to file
fs.writeFileSync(output,JSON.stringify(plugin,null,"\t"));
var $tw = require("tiddlywiki").TiddlyWiki();
var path = require("path");
var fs = require("fs");

// Pass the command line arguments to the boot kernel
$tw.boot.argv = ["."];
// we only need the first phase of startup
$tw.boot.initStartup({});
// get the bundle output path
var output = [path.resolve("plugins/sse/plugin.info"), path.resolve("plugins/sse/plugin.json")];

// load the plugin from the dist folder
var plugin = $tw.loadPluginFolder(path.join(__dirname, "dist"));
// put the plugin tiddlers back into the tiddlers field
$tw.utils.extend(plugin, JSON.parse(plugin.text));
// remove the text field
delete plugin.text;
// write the bundled plugin to file
output.forEach(output => {
// create the directory tree
if (!fs.existsSync(path.dirname(output))) {
fs.mkdirSync(path.dirname(output), { recursive: true });
}
fs.writeFileSync(output, JSON.stringify(plugin, null, "\t"));
})

18 changes: 9 additions & 9 deletions dist/plugin.info
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"title": "$:/plugins/twcloud/tiddlyweb-sse",
"name": "TiddlyWeb SSE",
"description": "Sync changes immediately from the browser to TW5 (node.js) using SSE",
"list": "readme",
"plugin-priority": 10,
"license": "MIT - Copyright Arlen Beiler 2021",
"version": "1.0.1"
}
{
"title": "$:/plugins/twcloud/tiddlyweb-sse",
"name": "TiddlyWeb SSE",
"description": "Sync changes immediately from the browser to TW5 (node.js) using SSE",
"list": "readme",
"plugin-priority": 10,
"license": "MIT - Copyright Arlen Beiler 2021",
"version": "1.0.2"
}
6 changes: 3 additions & 3 deletions dist/server-sent-events.js.meta
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
title: $:/core/modules/server/server-sent-events.js
type: application/javascript
module-type: library
title: $:/core/modules/server/server-sent-events.js
type: application/javascript
module-type: library
162 changes: 81 additions & 81 deletions dist/sse-client.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,81 @@
/*\
title: $:/plugins/twcloud/tiddlyweb-sse/sse-client.js
type: application/javascript
module-type: startup
Miscellaneous startup logic for both the client and server.
\*/
(function() {

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var checks = [
"$:/status/IsLoggedIn",
"$:/status/UserName",
"$:/status/IsAnonymous",
"$:/status/IsReadOnly"
];
// Export name and synchronous status
exports.name = "tiddlyweb-sse-hook";
exports.after = ["startup"];
exports.platforms = ["browser"];
exports.synchronous = true;
exports.startup = function() {
var source = null;
if(!$tw.syncer || !$tw.syncer.syncadaptor || $tw.syncer.syncadaptor.name !== "tiddlyweb") {return;}
$tw.wiki.addEventListener("change",function(changes) {
if(checks.filter(e => changes[e]).length === 0) {return;}
// check if we have a previous one and close it if we do
if(source && source.readyState !== source.CLOSED) {source.close();}
// Get the mount point in case a path prefix is used
var host = $tw.syncer.syncadaptor.getHost();
// Make sure it ends with a slash (it usually does)
if(host[host.length - 1] !== "/") {host += "/";}
// get the endpoint
var endpoint = host + "events/plugins/twcloud/tiddlyweb-sse/wiki-change";
// set the syncer poll to one hour
$tw.syncer.pollTimerInterval = 1000 * 60 * 60;
// Setup the event listener
source = exports.setupSSE(endpoint,$tw.syncer);
});
}

function debounce(interval,callback) {
var timeout = null;
return function() {
clearTimeout(timeout);
timeout = setTimeout(callback,interval);
};
}

exports.setupSSE = function setupSSE(endpoint,syncer,refresh) {
if(window.EventSource) {
var source = new EventSource(endpoint,{withCredentials: true});
var debouncedSync = debounce(syncer.throttleInterval,syncer.syncFromServer.bind(syncer));
source.addEventListener("change",debouncedSync);
source.onerror = function() {
// return if we're reconnecting because that's handled automatically
if(source.readyState === source.CONNECTING) {return;}
// wait for the errorRetryInterval
setTimeout(function() {
//call this function to set everything up again
exports.setupSSE(endpoint,syncer,true);
},syncer.errorRetryInterval);
};
source.onopen = function() {
// only run this on first open, not on auto reconnect
source.onopen = function() {};
// once we've properly opened, disable polling
syncer.wiki.addTiddler({title: syncer.titleSyncDisablePolling,text: "yes"});
//sync from server manually here to make sure we stay up to date
if(refresh) {syncer.syncFromServer();}
}
return source;
} else {
return null;
}
}

})();
/*\
title: $:/plugins/twcloud/tiddlyweb-sse/sse-client.js
type: application/javascript
module-type: startup
Miscellaneous startup logic for both the client and server.
\*/
(function() {

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var checks = [
"$:/status/IsLoggedIn",
"$:/status/UserName",
"$:/status/IsAnonymous",
"$:/status/IsReadOnly"
];
// Export name and synchronous status
exports.name = "tiddlyweb-sse-hook";
exports.after = ["startup"];
exports.platforms = ["browser"];
exports.synchronous = true;
exports.startup = function() {
var source = null;
if(!$tw.syncer || !$tw.syncer.syncadaptor || $tw.syncer.syncadaptor.name !== "tiddlyweb") {return;}
$tw.wiki.addEventListener("change",function(changes) {
if(checks.filter(e => changes[e]).length === 0) {return;}
// check if we have a previous one and close it if we do
if(source && source.readyState !== source.CLOSED) {source.close();}
// Get the mount point in case a path prefix is used
var host = $tw.syncer.syncadaptor.getHost();
// Make sure it ends with a slash (it usually does)
if(host[host.length - 1] !== "/") {host += "/";}
// get the endpoint
var endpoint = host + "events/plugins/twcloud/tiddlyweb-sse/wiki-change";
// set the syncer poll to one hour
$tw.syncer.pollTimerInterval = 1000 * 60 * 60;
// Setup the event listener
source = exports.setupSSE(endpoint,$tw.syncer);
});
}

function debounce(interval,callback) {
var timeout = null;
return function() {
clearTimeout(timeout);
timeout = setTimeout(callback,interval);
};
}

exports.setupSSE = function setupSSE(endpoint,syncer,refresh) {
if(window.EventSource) {
var source = new EventSource(endpoint,{withCredentials: true});
var debouncedSync = debounce(syncer.throttleInterval,syncer.syncFromServer.bind(syncer));
source.addEventListener("change",debouncedSync);
source.onerror = function() {
// return if we're reconnecting because that's handled automatically
if(source.readyState === source.CONNECTING) {return;}
// wait for the errorRetryInterval
setTimeout(function() {
//call this function to set everything up again
exports.setupSSE(endpoint,syncer,true);
},syncer.errorRetryInterval);
};
source.onopen = function() {
// only run this on first open, not on auto reconnect
source.onopen = function() {};
// once we've properly opened, disable polling
syncer.wiki.addTiddler({title: syncer.titleSyncDisablePolling,text: "yes"});
//sync from server manually here to make sure we stay up to date
if(refresh) {syncer.syncFromServer();}
}
return source;
} else {
return null;
}
}

})();
152 changes: 76 additions & 76 deletions dist/sse-server.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,77 @@
/*\
title: $:/plugins/twcloud/tiddlyweb-sse/sse-server.js
type: application/javascript
module-type: route
GET /events/plugins/twcloud/tiddlyweb/(channel)
\*/
(function() {

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var wikis = [];

// Import the Journal class
var Journal = require("$:/core/modules/server/server-sent-events.js").Journal;

/*
Setup up the array for this wiki and add the change listener
*/
function setupWiki(wiki) {
function filter(conn) {
return conn.state.wiki === wiki;
}
// Listen to change events for this wiki
wiki.addEventListener("change",function(changes) {
var jsonChanges = JSON.stringify(changes);
eventServer.emitEvent("wiki-change","change",jsonChanges,filter);
});
wikis.push(wiki);
}

/*
Setup this particular wiki if we haven't seen it before
*/
function ensureChannelSetup(channel,wiki) {
// setup wikis for the wiki-change channel
if(channel === "wiki-change" && wikis.indexOf(wiki) === -1) { setupWiki(wiki); }
}
/** @type {import('../server-sent-events').Journal} */
var eventServer = new Journal();

// this filter is called for the emitter route, which recieves
// messages from clients and forwards them to all listeners. It
// does not affect messages sent directly by the server.
// We don't use it in tiddlyweb so just set it to false
eventServer.emitterFilter = function(sender) {
// do not allow clients to broadcast
// they can't anyway unless a route is specified
return function() { return false; };
}

if(!$tw.wiki.getTiddler("$:/plugins/tiddlywiki/tiddlyweb")) {
$tw.utils.warning("Warning: Plugin \"twcloud/tiddlyweb-sse\" specified but \"tiddlywiki/tiddlyweb\" is missing");
}

// Export the route definition for this server sent events handler.
// We don't need an emitter route, otherwise we could put the common
// instance in a library tiddler export and require it in both files.

module.exports = eventServer.handlerExports(
"plugins/twcloud/tiddlyweb-sse",
function(request,response,state) {
if(state.params[0] !== "wiki-change") {
response.writeHead(404);
response.end();
return;
}
// remove the socket timeout
request.setTimeout(0);
ensureChannelSetup(state.params[0],state.wiki);
eventServer.handler(request,response,state);
}
);
/*\
title: $:/plugins/twcloud/tiddlyweb-sse/sse-server.js
type: application/javascript
module-type: route
GET /events/plugins/twcloud/tiddlyweb/(channel)
\*/
(function() {

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var wikis = [];

// Import the Journal class
var Journal = require("$:/core/modules/server/server-sent-events.js").Journal;

/*
Setup up the array for this wiki and add the change listener
*/
function setupWiki(wiki) {
function filter(conn) {
return conn.state.wiki === wiki;
}
// Listen to change events for this wiki
wiki.addEventListener("change",function(changes) {
var jsonChanges = JSON.stringify(changes);
eventServer.emitEvent("wiki-change","change",jsonChanges,filter);
});
wikis.push(wiki);
}

/*
Setup this particular wiki if we haven't seen it before
*/
function ensureChannelSetup(channel,wiki) {
// setup wikis for the wiki-change channel
if(channel === "wiki-change" && wikis.indexOf(wiki) === -1) { setupWiki(wiki); }
}
/** @type {import('../server-sent-events').Journal} */
var eventServer = new Journal();

// this filter is called for the emitter route, which recieves
// messages from clients and forwards them to all listeners. It
// does not affect messages sent directly by the server.
// We don't use it in tiddlyweb so just set it to false
eventServer.emitterFilter = function(sender) {
// do not allow clients to broadcast
// they can't anyway unless a route is specified
return function() { return false; };
}

if(!$tw.wiki.getTiddler("$:/plugins/tiddlywiki/tiddlyweb")) {
$tw.utils.warning("Warning: Plugin \"twcloud/tiddlyweb-sse\" specified but \"tiddlywiki/tiddlyweb\" is missing");
}

// Export the route definition for this server sent events handler.
// We don't need an emitter route, otherwise we could put the common
// instance in a library tiddler export and require it in both files.

module.exports = eventServer.handlerExports(
"plugins/twcloud/tiddlyweb-sse",
function(request,response,state) {
if(state.params[0] !== "wiki-change") {
response.writeHead(404);
response.end();
return;
}
// remove the socket timeout
request.setTimeout(0);
ensureChannelSetup(state.params[0],state.wiki);
eventServer.handler(request,response,state);
}
);
})();
Loading

0 comments on commit 2052a66

Please sign in to comment.